diff options
1341 files changed, 24391 insertions, 14625 deletions
diff --git a/.clang-tidy b/.clang-tidy index d65027687bb..b51555b55dd 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -39,9 +39,8 @@ Checks: > -modernize-use-nodiscard, -modernize-loop-convert, -modernize-pass-by-value, - -modernize-use-default-member-init, - -modernize-raw-string-literal, - -modernize-avoid-bind, - -modernize-use-transparent-functors, WarningsAsErrors: '*' +CheckOptions: + - key: modernize-use-default-member-init.UseAssignment + value: 1 diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d864e08c953..0cad9be4693 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -10,8 +10,9 @@ # Changes that belong here: # - Massive comment, doxy-sections, or spelling corrections. # - Clang-format, PEP8 or other automated changes which are *strictly* "no functional change". -# - Several smaller commits should be added to this list at once, because adding -# one extra commit (to edit this file) after every small cleanup is noisy. +# - Several commits should be added to this list at once, because adding +# one extra commit (to edit this file) after every cleanup is noisy. +# - No clang-tidy changes. # # Note: # - The comment above the SHA should be the first line of the commit. @@ -92,78 +93,12 @@ c42a6b77b52560d257279de2cb624b4ef2c0d24c # Cleanup: use doxy sections for imbuf c207f7c22e1439e0b285fba5d2c072bdae23f981 -# Cleanup: Clang-Tidy, modernize-use-bool-literals -af35ada2f3fa8da4d46b3a71de724d353d716820 - -# Cleanup: Use nullptr everywhere in fluid code -311031ecd03dbfbf43e1df672a395f24b2e7d4d3 - -# Cleanup: Clang-Tidy, modernize-redundant-void-arg -a331d5c99299c4514ca33c843b1c79b872f2728d - -# Cleanup: Clang-Tidy modernize-use-nullptr -16732def37c5a66f3ea28dbe247b09cc6bca6677 - -# Cleanup: Clang-tidy, modernize-concat-nested-namespaces -4525049aa0cf818f6483dce589ac9791eb562338 - -# Cleanup: Clang-tidy else-after-return -ae342ed4511cf2e144dcd27ce2c635d3d536f9ad - -# Cleanup: Clang-Tidy, readability-redundant-member-init -190170d4cc92ff34abe1744a10474ac4f1074086 - -# Cleanup: use 'filepath' instead of 'name' for ImBuf utilities -99f56b4c16323f96c0cbf54e392fb509fcac5bda - # Cleanup: clang-format c4d8f6a4a8ddc29ed27311ed7578b3c8c31399d2 b5d310b569e07a937798a2d38539cfd290149f1c 8c846cccd6bdfd3e90a695fabbf05f53e5466a57 -40d4a4cb1a6b4c3c2a486e8f2868f547530e0811 4eac03d821fa17546f562485f7d073813a5e5943 +1166110a9d66af9c5a47cee2be591f50fdc445e8 -# Cleanup: use preprocessor version check for PyTypeObject declaration -cd9acfed4f7674b84be965d469a367aef96f8af3 - -# Cycles: fix compilation of OSL shaders following API change -b980cd163a9d5d77eeffc2e353333e739fa9e719 - -# Cleanup: clang-tidy suppress warnings for PyTypeObject.tp_print -efd71aad4f22ec0073d80b8dd296015d3f395aa8 - -# Cleanup: fix wrong merge, remove extra unique_ptr. -6507449e54a167c63a72229e4d0119dd2af68ae5 - -# Cleanup: fix some clang tidy issues -525a042c5c7513c41240b118acca002f6c60cc12 - -# Fix T82520: error building freestyle with Python3.8 -e118426e4695a97d67e65d69677f3c4e2db50a56 - -# Cleanup: Clang-tidy, readability-else-after-return -7be47dadea5066ae095c644e0b4f1f10d75f5ab3 - -# Cleanup: Add `r_` to return parameter -45dca05b1cd2a5ead59144c93d790fdfe7c35ee6 - -# Cleanup: Typo in `print_default_info` function name. -41a73909dec716642f044e60b40a28335c9fdb10 - -# Cleanup: Reduce indentation -1cc3a0e2cf73a5ff4f9e0a7f5338eda77266b300 - -# Build-system: Force C linkage for all DNA type headers -ad4b7741dba45a2be210942c18af6b6e4438f129 - -# Cleanup: Move function to proper section -c126e27cdc8b28365a9d5f9fafc4d521d1eb83df - -# Cleanup: remove break after return statements -bbdfeb751e16d939482d2e4b95c4d470f53f18a5 - -# Cleanup: clang-tidy -af013ff76feef7e8b8ba642279c62a5dc275d59f - -# Cleanup: Make panel type flag names more clear -9d28353b525ecfbcca1501be72e4276dfb2bbc2a +# Cleanup: clang-format. +40d4a4cb1a6b4c3c2a486e8f2868f547530e0811 diff --git a/CMakeLists.txt b/CMakeLists.txt index 035cf81e1b3..78f49942a13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build_files/cmake/platform") # avoid having empty buildtype if(NOT DEFINED CMAKE_BUILD_TYPE_INIT) set(CMAKE_BUILD_TYPE_INIT "Release") + # Internal logic caches this variable, avoid showing it by default + # since it's easy to accidentally set instead of the build type. + mark_as_advanced(CMAKE_BUILD_TYPE_INIT) endif() # Omit superfluous "Up-to-date" messages. @@ -164,10 +167,6 @@ if(APPLE) endif() option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON) -if(${CMAKE_VERSION} VERSION_LESS 2.8.8) - # add_library OBJECT arg unsupported - set(WITH_BUILDINFO OFF) -endif() set(BUILDINFO_OVERRIDE_DATE "" CACHE STRING "Use instead of the current date for reproducible builds (empty string disables this option)") set(BUILDINFO_OVERRIDE_TIME "" CACHE STRING "Use instead of the current time for reproducible builds (empty string disables this option)") set(CPACK_OVERRIDE_PACKAGENAME "" CACHE STRING "Use instead of the standard packagename (empty string disables this option)") @@ -205,6 +204,7 @@ option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF) mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE) option(WITH_NANOVDB "Enable usage of NanoVDB data structure for rendering on the GPU" ON) +option(WITH_HARU "Enable features relying on Libharu (Grease pencil PDF export)" ON) # GHOST Windowing Library Options option(WITH_GHOST_DEBUG "Enable debugging output for the GHOST library" OFF) @@ -613,6 +613,7 @@ endif() if(UNIX) # See WITH_WINDOWS_SCCACHE for Windows. option(WITH_COMPILER_CCACHE "Use ccache to improve rebuild times (Works with Ninja, Makefiles and Xcode)" OFF) + mark_as_advanced(WITH_COMPILER_CCACHE) endif() # The following only works with the Ninja generator in CMake >= 3.0. @@ -730,6 +731,9 @@ set_and_warn_dependency(WITH_OPENVDB WITH_NANOVDB OFF) # OpenVDB uses 'half' type from OpenEXR & fails to link without OpenEXR enabled. set_and_warn_dependency(WITH_IMAGE_OPENEXR WITH_OPENVDB OFF) +# Haru needs `TIFFFaxBlackCodes` & `TIFFFaxWhiteCodes` symbols from TIFF. +set_and_warn_dependency(WITH_IMAGE_TIFF WITH_HARU OFF) + # auto enable openimageio for cycles if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) @@ -1018,6 +1022,9 @@ if(WITH_OPENVDB) list(APPEND OPENVDB_DEFINITIONS -DOPENVDB_3_ABI_COMPATIBLE) endif() + # OpenVDB headers use deprecated TBB headers, silence warning. + list(APPEND OPENVDB_DEFINITIONS -DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) + list(APPEND OPENVDB_INCLUDE_DIRS ${BOOST_INCLUDE_DIR} ${TBB_INCLUDE_DIRS} @@ -1433,6 +1440,7 @@ if(CMAKE_COMPILER_IS_GNUCC) # gcc 4.2 gives annoying warnings on every file with this if(NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "4.3") ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNINITIALIZED -Wuninitialized) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNINITIALIZED -Wuninitialized) endif() # versions before gcc4.6 give many BLI_math warnings @@ -1497,11 +1505,13 @@ if(CMAKE_COMPILER_IS_GNUCC) ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_FORMAT -Wno-format) ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_SWITCH -Wno-switch) ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable) + ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized) ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_CLASS_MEMACCESS -Wno-class-memaccess) ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_COMMENT -Wno-comment) ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_TYPEDEFS -Wno-unused-local-typedefs) ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-unused-variable) + ADD_CHECK_CXX_COMPILER_FLAG(CXX_REMOVE_STRICT_FLAGS CXX_WARN_NO_UNUSED_VARIABLE -Wno-uninitialized) if(CMAKE_COMPILER_IS_GNUCC AND (NOT "${CMAKE_C_COMPILER_VERSION}" VERSION_LESS "7.0")) ADD_CHECK_C_COMPILER_FLAG(C_REMOVE_STRICT_FLAGS C_WARN_NO_IMPLICIT_FALLTHROUGH -Wno-implicit-fallthrough) @@ -1849,6 +1859,7 @@ if(FIRST_RUN) info_cfg_option(WITH_FFTW3) info_cfg_option(WITH_FREESTYLE) info_cfg_option(WITH_GMP) + info_cfg_option(WITH_HARU) info_cfg_option(WITH_IK_ITASC) info_cfg_option(WITH_IK_SOLVER) info_cfg_option(WITH_INPUT_NDOF) diff --git a/GNUmakefile b/GNUmakefile index 3b5b9d65521..98463891407 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -183,8 +183,13 @@ endif ifndef DEPS_INSTALL_DIR DEPS_INSTALL_DIR:=$(shell dirname "$(BLENDER_DIR)")/lib/$(OS_NCASE) - ifneq ($(OS_NCASE),darwin) - # Add processor type to directory name + # Add processor type to directory name, except for darwin x86_64 + # which by convention does not have it. + ifeq ($(OS_NCASE),darwin) + ifneq ($(CPU),x86_64) + DEPS_INSTALL_DIR:=$(DEPS_INSTALL_DIR)_$(CPU) + endif + else DEPS_INSTALL_DIR:=$(DEPS_INSTALL_DIR)_$(CPU) endif endif @@ -198,7 +203,7 @@ endif # in libraries, or python 2 for running make update to get it. ifeq ($(OS_NCASE),darwin) ifeq (, $(shell command -v $(PYTHON))) - PYTHON:=../lib/darwin/python/bin/python3.7m + PYTHON:=$(DEPS_INSTALL_DIR)/python/bin/python3.7m ifeq (, $(shell command -v $(PYTHON))) PYTHON:=python endif @@ -520,7 +525,7 @@ format: .FORCE # Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation. doc_py: .FORCE - ASAN_OPTIONS=halt_on_error=0 \ + ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \ $(BLENDER_BIN) --background -noaudio --factory-startup \ --python doc/python_api/sphinx_doc_gen.py sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt index dfbb0e824a0..672f5820a16 100644 --- a/build_files/build_environment/CMakeLists.txt +++ b/build_files/build_environment/CMakeLists.txt @@ -92,6 +92,7 @@ include(cmake/package_python.cmake) include(cmake/numpy.cmake) include(cmake/usd.cmake) include(cmake/potrace.cmake) +include(cmake/haru.cmake) # Boost needs to be included after python.cmake due to the PYTHON_BINARY variable being needed. include(cmake/boost.cmake) include(cmake/pugixml.cmake) diff --git a/build_files/build_environment/cmake/haru.cmake b/build_files/build_environment/cmake/haru.cmake new file mode 100644 index 00000000000..7382095f459 --- /dev/null +++ b/build_files/build_environment/cmake/haru.cmake @@ -0,0 +1,46 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ***** END GPL LICENSE BLOCK ***** + +set(HARU_EXTRA_ARGS + -DLIBHPDF_SHARED=OFF + -DLIBHPDF_STATIC=ON + -DLIBHPDF_EXAMPLES=OFF + -DLIBHPDF_ENABLE_EXCEPTIONS=ON +) + +ExternalProject_Add(external_haru + URL ${HARU_URI} + DOWNLOAD_DIR ${DOWNLOAD_DIR} + URL_HASH MD5=${HARU_HASH} + PREFIX ${BUILD_DIR}/haru + PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/haru/src/external_haru < ${PATCH_DIR}/haru.diff + CMAKE_ARGS + -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=${LIBDIR}/haru + ${DEFAULT_CMAKE_FLAGS} ${HARU_EXTRA_ARGS} + INSTALL_DIR ${LIBDIR}/haru +) + +if(WIN32) + if(BUILD_MODE STREQUAL Release) + ExternalProject_Add_Step(external_haru after_install + COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/haru/include ${HARVEST_TARGET}/haru/include + COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/haru/lib/libhpdfs.lib ${HARVEST_TARGET}/haru/lib/libhpdfs.lib + DEPENDEES install + ) + endif() +endif() diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake index 536907f563d..308cb77144c 100644 --- a/build_files/build_environment/cmake/harvest.cmake +++ b/build_files/build_environment/cmake/harvest.cmake @@ -162,7 +162,7 @@ harvest(png/include png/include "*.h") harvest(png/lib png/lib "*.a") harvest(pugixml/include pugixml/include "*.hpp") harvest(pugixml/lib pugixml/lib "*.a") -harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}m") +harvest(python/bin python/bin "python${PYTHON_SHORT_VERSION}") harvest(python/include python/include "*h") harvest(python/lib python/lib "*") harvest(sdl/include/SDL2 sdl/include "*.h") @@ -187,6 +187,8 @@ harvest(usd/lib/usd usd/lib/usd "*") harvest(usd/plugin usd/plugin "*") harvest(potrace/include potrace/include "*.h") harvest(potrace/lib potrace/lib "*.a") +harvest(haru/include haru/include "*.h") +harvest(haru/lib haru/lib "*.a") if(UNIX AND NOT APPLE) harvest(libglu/lib mesa/lib "*.so*") diff --git a/build_files/build_environment/cmake/numpy.cmake b/build_files/build_environment/cmake/numpy.cmake index 03316a8fc63..7a1b00895f4 100644 --- a/build_files/build_environment/cmake/numpy.cmake +++ b/build_files/build_environment/cmake/numpy.cmake @@ -47,4 +47,5 @@ ExternalProject_Add(external_numpy add_dependencies( external_numpy external_python + external_python_site_packages ) diff --git a/build_files/build_environment/cmake/opencolorio.cmake b/build_files/build_environment/cmake/opencolorio.cmake index e8b0043edf7..4ad401800d0 100644 --- a/build_files/build_environment/cmake/opencolorio.cmake +++ b/build_files/build_environment/cmake/opencolorio.cmake @@ -32,8 +32,8 @@ set(OPENCOLORIO_EXTRA_ARGS if(APPLE AND NOT("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64")) set(OPENCOLORIO_EXTRA_ARGS - ${OPENCOLORIO_EXTRA_ARGS} - -DOCIO_USE_SSE=OFF + ${OPENCOLORIO_EXTRA_ARGS} + -DOCIO_USE_SSE=OFF ) endif() diff --git a/build_files/build_environment/cmake/python.cmake b/build_files/build_environment/cmake/python.cmake index bfb318f9939..5731a0e0ae8 100644 --- a/build_files/build_environment/cmake/python.cmake +++ b/build_files/build_environment/cmake/python.cmake @@ -43,7 +43,7 @@ if(WIN32) PREFIX ${BUILD_DIR}/python CONFIGURE_COMMAND "" BUILD_COMMAND cd ${BUILD_DIR}/python/src/external_python/pcbuild/ && set IncludeTkinter=false && call build.bat -e -p x64 -c ${BUILD_MODE} - INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-underpth --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python + INSTALL_COMMAND ${PYTHON_BINARY_INTERNAL} ${PYTHON_SRC}/PC/layout/main.py -b ${PYTHON_SRC}/PCbuild/amd64 -s ${PYTHON_SRC} -t ${PYTHON_SRC}/tmp/ --include-stable --include-pip --include-dev --include-launchers --include-venv --include-symbols ${PYTHON_EXTRA_INSTLAL_FLAGS} --copy ${LIBDIR}/python ) else() @@ -74,12 +74,11 @@ else() endif() set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV} && ${PYTHON_FUNC_CONFIGS}) set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python.exe) - set(PYTHON_PATCH ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_macos.diff) else() set(PYTHON_CONFIGURE_ENV ${CONFIGURE_ENV}) set(PYTHON_BINARY ${BUILD_DIR}/python/src/external_python/python) set(PYTHON_PATCH ${PATCH_CMD} --verbose -p1 -d ${BUILD_DIR}/python/src/external_python < ${PATCH_DIR}/python_linux.diff) - endif() + endif() set(PYTHON_CONFIGURE_EXTRA_ARGS "--with-openssl=${LIBDIR}/ssl") set(PYTHON_CFLAGS "-I${LIBDIR}/sqlite/include -I${LIBDIR}/bzip2/include -I${LIBDIR}/lzma/include -I${LIBDIR}/zlib/include") diff --git a/build_files/build_environment/cmake/python_site_packages.cmake b/build_files/build_environment/cmake/python_site_packages.cmake index d17f65a152b..a3b9c3bf796 100644 --- a/build_files/build_environment/cmake/python_site_packages.cmake +++ b/build_files/build_environment/cmake/python_site_packages.cmake @@ -16,12 +16,16 @@ # # ***** END GPL LICENSE BLOCK ***** +if(WIN32 AND BUILD_MODE STREQUAL Debug) + set(SITE_PACKAGES_EXTRA --global-option build --global-option --debug) +endif() + ExternalProject_Add(external_python_site_packages DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" PREFIX ${BUILD_DIR}/site_packages - INSTALL_COMMAND ${PYTHON_BINARY} -m pip install idna==${IDNA_VERSION} chardet==${CHARDET_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} --no-binary :all: + INSTALL_COMMAND ${PYTHON_BINARY} -m pip install ${SITE_PACKAGES_EXTRA} cython==${CYTHON_VERSION} idna==${IDNA_VERSION} chardet==${CHARDET_VERSION} urllib3==${URLLIB3_VERSION} certifi==${CERTIFI_VERSION} requests==${REQUESTS_VERSION} --no-binary :all: ) add_dependencies( diff --git a/build_files/build_environment/cmake/ssl.cmake b/build_files/build_environment/cmake/ssl.cmake index e1c168817f4..e6741ebb385 100644 --- a/build_files/build_environment/cmake/ssl.cmake +++ b/build_files/build_environment/cmake/ssl.cmake @@ -20,7 +20,7 @@ set(SSL_CONFIGURE_COMMAND ./Configure) set(SSL_PATCH_CMD echo .) if(APPLE) - set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}") + set(SSL_OS_COMPILER "blender-darwin-${CMAKE_OSX_ARCHITECTURES}") else() if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(SSL_EXTRA_ARGS enable-ec_nistp_64_gcc_128) diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake index d4a2c715ecc..76417b59bb3 100644 --- a/build_files/build_environment/cmake/versions.cmake +++ b/build_files/build_environment/cmake/versions.cmake @@ -138,11 +138,11 @@ set(OSL_VERSION 1.10.10) set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz) set(OSL_HASH 00dec08a93c8084e53848b9ad047889f) -set(PYTHON_VERSION 3.7.7) -set(PYTHON_SHORT_VERSION 3.7) -set(PYTHON_SHORT_VERSION_NO_DOTS 37) +set(PYTHON_VERSION 3.9.1) +set(PYTHON_SHORT_VERSION 3.9) +set(PYTHON_SHORT_VERSION_NO_DOTS 39) set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz) -set(PYTHON_HASH 172c650156f7bea68ce31b2fd01fa766) +set(PYTHON_HASH 61981498e75ac8f00adcb908281fadb6) set(TBB_VERSION 2019_U9) set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz) @@ -156,16 +156,17 @@ set(NANOVDB_GIT_UID e62f7a0bf1e27397223c61ddeaaf57edf111b77f) set(NANOVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_GIT_UID}.tar.gz) set(NANOVDB_HASH 90919510bc6ccd630fedc56f748cb199) -set(IDNA_VERSION 2.9) -set(CHARDET_VERSION 3.0.4) -set(URLLIB3_VERSION 1.25.9) -set(CERTIFI_VERSION 2020.4.5.2) -set(REQUESTS_VERSION 2.23.0) +set(IDNA_VERSION 2.10) +set(CHARDET_VERSION 4.0.0) +set(URLLIB3_VERSION 1.26.3) +set(CERTIFI_VERSION 2020.12.5) +set(REQUESTS_VERSION 2.25.1) +set(CYTHON_VERSION 0.29.21) -set(NUMPY_VERSION 1.17.5) -set(NUMPY_SHORT_VERSION 1.17) +set(NUMPY_VERSION 1.19.5) +set(NUMPY_SHORT_VERSION 1.19) set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}/numpy-${NUMPY_VERSION}.zip) -set(NUMPY_HASH 763a5646fa6eef7a22f4895bca0524f2) +set(NUMPY_HASH f6a1b48717c552bbc18f1adc3cc1fe0e) set(LAME_VERSION 3.100) set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz) @@ -265,7 +266,7 @@ set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar. set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd) set(FLEXBISON_VERSION 2.5.5) -set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison//win_flex_bison-2.5.5.zip) +set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison/win_flex_bison-2.5.5.zip) set(FLEXBISON_HASH d87a3938194520d904013abef3df10ce) # Libraries to keep Python modules static on Linux. @@ -309,7 +310,7 @@ set(LIBGLU_URI ftp://ftp.freedesktop.org/pub/mesa/glu/glu-${LIBGLU_VERSION}.tar. set(LIBGLU_HASH 151aef599b8259efe9acd599c96ea2a3) set(MESA_VERSION 18.3.1) -set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa//mesa-${MESA_VERSION}.tar.xz) +set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa/mesa-${MESA_VERSION}.tar.xz) set(MESA_HASH d60828056d77bfdbae0970f9b15fb1be) set(NASM_VERSION 2.15.02) @@ -331,3 +332,7 @@ set(GMP_HASH a325e3f09e6d91e62101e59f9bda3ec1) set(POTRACE_VERSION 1.16) set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz) set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69) + +set(HARU_VERSION 2_3_0) +set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz) +set(HARU_HASH 4f916aa49c3069b3a10850013c507460) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 671417214d8..da2a6535142 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -53,15 +53,15 @@ getopt \ --long source:,install:,tmp:,info:,threads:,help,show-deps,no-sudo,no-build,no-confirm,\ with-all,with-opencollada,with-jack,with-embree,with-oidn,with-nanovdb,\ ver-ocio:,ver-oiio:,ver-llvm:,ver-osl:,ver-osd:,ver-openvdb:,ver-xr-openxr:,\ -force-all,force-python,force-numpy,force-boost,force-tbb,\ +force-all,force-python,force-boost,force-tbb,\ force-ocio,force-openexr,force-oiio,force-llvm,force-osl,force-osd,force-openvdb,\ force-ffmpeg,force-opencollada,force-alembic,force-embree,force-oidn,force-usd,\ force-xr-openxr,\ -build-all,build-python,build-numpy,build-boost,build-tbb,\ +build-all,build-python,build-boost,build-tbb,\ build-ocio,build-openexr,build-oiio,build-llvm,build-osl,build-osd,build-openvdb,\ build-ffmpeg,build-opencollada,build-alembic,build-embree,build-oidn,build-usd,\ build-xr-openxr,\ -skip-python,skip-numpy,skip-boost,skip-tbb,\ +skip-python,skip-boost,skip-tbb,\ skip-ocio,skip-openexr,skip-oiio,skip-llvm,skip-osl,skip-osd,skip-openvdb,\ skip-ffmpeg,skip-opencollada,skip-alembic,skip-embree,skip-oidn,skip-usd,\ skip-xr-openxr \ @@ -188,9 +188,6 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --build-python Force the build of Python. - --build-numpy - Force the build of NumPy. - --build-boost Force the build of Boost. @@ -255,9 +252,6 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --force-python Force the rebuild of Python. - --force-numpy - Force the rebuild of NumPy. - --force-boost Force the rebuild of Boost. @@ -315,9 +309,6 @@ ARGUMENTS_INFO="\"COMMAND LINE ARGUMENTS: --skip-python Unconditionally skip Python installation/building. - --skip-numpy - Unconditionally skip NumPy installation/building. - --skip-boost Unconditionally skip Boost installation/building. @@ -385,36 +376,80 @@ USE_CXX11=true CLANG_FORMAT_VERSION_MIN="6.0" CLANG_FORMAT_VERSION_MAX="10.0" -PYTHON_VERSION="3.7.7" -PYTHON_VERSION_SHORT="3.7" +PYTHON_VERSION="3.9.1" +PYTHON_VERSION_SHORT="3.9" PYTHON_VERSION_MIN="3.7" -PYTHON_VERSION_MAX="3.9" -PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_MIN +PYTHON_VERSION_MAX="3.10" +PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT PYTHON_FORCE_BUILD=false PYTHON_FORCE_REBUILD=false PYTHON_SKIP=false -NUMPY_VERSION="1.17.5" -NUMPY_VERSION_SHORT="1.17" -NUMPY_VERSION_MIN="1.8" -NUMPY_VERSION_MAX="2.0" -NUMPY_FORCE_BUILD=false -NUMPY_FORCE_REBUILD=false -NUMPY_SKIP=false +# Additional Python modules. +PYTHON_IDNA_VERSION="2.9" +PYTHON_IDNA_VERSION_MIN="2.0" +PYTHON_IDNA_VERSION_MAX="3.0" +PYTHON_IDNA_NAME="idna" + +PYTHON_CHARDET_VERSION="3.0.4" +PYTHON_CHARDET_VERSION_MIN="3.0" +PYTHON_CHARDET_VERSION_MAX="5.0" +PYTHON_CHARDET_NAME="chardet" + +PYTHON_URLLIB3_VERSION="1.25.9" +PYTHON_URLLIB3_VERSION_MIN="1.0" +PYTHON_URLLIB3_VERSION_MAX="2.0" +PYTHON_URLLIB3_NAME="urllib3" + +PYTHON_CERTIFI_VERSION="2020.4.5.2" +PYTHON_CERTIFI_VERSION_MIN="2020.0" +PYTHON_CERTIFI_VERSION_MAX="2021.0" +PYTHON_CERTIFI_NAME="certifi" + +PYTHON_REQUESTS_VERSION="2.23.0" +PYTHON_REQUESTS_VERSION_MIN="2.0" +PYTHON_REQUESTS_VERSION_MAX="3.0" +PYTHON_REQUESTS_NAME="requests" + +PYTHON_NUMPY_VERSION="1.19.5" +PYTHON_NUMPY_VERSION_MIN="1.14" +PYTHON_NUMPY_VERSION_MAX="2.0" +PYTHON_NUMPY_NAME="numpy" + +# As package-ready parameters (only used with distro packages). +PYTHON_MODULES_PACKAGES=( + "$PYTHON_IDNA_NAME $PYTHON_IDNA_VERSION_MIN $PYTHON_IDNA_VERSION_MAX" + "$PYTHON_CHARDET_NAME $PYTHON_CHARDET_VERSION_MIN $PYTHON_CHARDET_VERSION_MAX" + "$PYTHON_URLLIB3_NAME $PYTHON_URLLIB3_VERSION_MIN $PYTHON_URLLIB3_VERSION_MAX" + "$PYTHON_CERTIFI_NAME $PYTHON_CERTIFI_VERSION_MIN $PYTHON_CERTIFI_VERSION_MAX" + "$PYTHON_REQUESTS_NAME $PYTHON_REQUESTS_VERSION_MIN $PYTHON_REQUESTS_VERSION_MAX" + "$PYTHON_NUMPY_NAME $PYTHON_NUMPY_VERSION_MIN $PYTHON_NUMPY_VERSION_MAX" +) -BOOST_VERSION="1.70.0" -BOOST_VERSION_SHORT="1.70" +# As pip-ready parameters (only used when building python). +PYTHON_MODULES_PIP=( + "$PYTHON_IDNA_NAME==$PYTHON_IDNA_VERSION" + "$PYTHON_CHARDET_NAME==$PYTHON_CHARDET_VERSION" + "$PYTHON_URLLIB3_NAME==$PYTHON_URLLIB3_VERSION" + "$PYTHON_CERTIFI_NAME==$PYTHON_CERTIFI_VERSION" + "$PYTHON_REQUESTS_NAME==$PYTHON_REQUESTS_VERSION" + "$PYTHON_NUMPY_NAME==$PYTHON_NUMPY_VERSION" +) + + +BOOST_VERSION="1.73.0" +BOOST_VERSION_SHORT="1.73" BOOST_VERSION_MIN="1.49" BOOST_VERSION_MAX="2.0" BOOST_FORCE_BUILD=false BOOST_FORCE_REBUILD=false BOOST_SKIP=false -TBB_VERSION="2019" -TBB_VERSION_SHORT="2019" -TBB_VERSION_UPDATE="_U9" # Used for source packages... +TBB_VERSION="2020" +TBB_VERSION_SHORT="2020" +TBB_VERSION_UPDATE="_U2" # Used for source packages... TBB_VERSION_MIN="2018" -TBB_VERSION_MAX="2021" +TBB_VERSION_MAX="2022" TBB_FORCE_BUILD=false TBB_FORCE_REBUILD=false TBB_SKIP=false @@ -439,7 +474,7 @@ _with_built_openexr=false OIIO_VERSION="2.1.15.0" OIIO_VERSION_SHORT="2.1" OIIO_VERSION_MIN="2.1.12" -OIIO_VERSION_MAX="3.0" +OIIO_VERSION_MAX="2.2.10" OIIO_FORCE_BUILD=false OIIO_FORCE_REBUILD=false OIIO_SKIP=false @@ -447,16 +482,16 @@ OIIO_SKIP=false LLVM_VERSION="9.0.1" LLVM_VERSION_SHORT="9.0" LLVM_VERSION_MIN="6.0" -LLVM_VERSION_MAX="11.0" +LLVM_VERSION_MAX="12.0" LLVM_VERSION_FOUND="" LLVM_FORCE_BUILD=false LLVM_FORCE_REBUILD=false LLVM_SKIP=false # OSL needs to be compiled for now! -OSL_VERSION="1.10.10" -OSL_VERSION_SHORT="1.10" -OSL_VERSION_MIN="1.10" +OSL_VERSION="1.11.10.0" +OSL_VERSION_SHORT="1.11" +OSL_VERSION_MIN="1.11" OSL_VERSION_MAX="2.0" OSL_FORCE_BUILD=false OSL_FORCE_REBUILD=false @@ -474,16 +509,16 @@ OSD_SKIP=false # OpenVDB needs to be compiled for now OPENVDB_BLOSC_VERSION="1.5.0" -OPENVDB_VERSION="7.0.0" -OPENVDB_VERSION_SHORT="7.0" -OPENVDB_VERSION_MIN="7.0" -OPENVDB_VERSION_MAX="7.1" +OPENVDB_VERSION="8.0.1" +OPENVDB_VERSION_SHORT="8.0" +OPENVDB_VERSION_MIN="8.0" +OPENVDB_VERSION_MAX="8.1" OPENVDB_FORCE_BUILD=false OPENVDB_FORCE_REBUILD=false OPENVDB_SKIP=false # Alembic needs to be compiled for now -ALEMBIC_VERSION="1.7.12" +ALEMBIC_VERSION="1.7.16" ALEMBIC_VERSION_SHORT="1.7" ALEMBIC_VERSION_MIN="1.7" ALEMBIC_VERSION_MAX="2.0" @@ -491,10 +526,10 @@ ALEMBIC_FORCE_BUILD=false ALEMBIC_FORCE_REBUILD=false ALEMBIC_SKIP=false -USD_VERSION="20.05" -USD_VERSION_SHORT="20.05" +USD_VERSION="20.08" +USD_VERSION_SHORT="20.08" USD_VERSION_MIN="20.05" -USD_VERSION_MAX="20.06" +USD_VERSION_MAX="21.00" USD_FORCE_BUILD=false USD_FORCE_REBUILD=false USD_SKIP=false @@ -515,10 +550,10 @@ EMBREE_FORCE_BUILD=false EMBREE_FORCE_REBUILD=false EMBREE_SKIP=false -OIDN_VERSION="1.2.3" -OIDN_VERSION_SHORT="1.2" -OIDN_VERSION_MIN="1.2.0" -OIDN_VERSION_MAX="1.3" +OIDN_VERSION="1.3.0" +OIDN_VERSION_SHORT="1.3" +OIDN_VERSION_MIN="1.3.0" +OIDN_VERSION_MAX="1.4" OIDN_FORCE_BUILD=false OIDN_FORCE_REBUILD=false OIDN_SKIP=false @@ -534,7 +569,7 @@ FFMPEG_FORCE_REBUILD=false FFMPEG_SKIP=false _ffmpeg_list_sep=";" -XR_OPENXR_VERSION="1.0.8" +XR_OPENXR_VERSION="1.0.14" XR_OPENXR_VERSION_SHORT="1.0" XR_OPENXR_VERSION_MIN="1.0.8" XR_OPENXR_VERSION_MAX="2.0" @@ -730,7 +765,6 @@ while true; do ;; --build-all) PYTHON_FORCE_BUILD=true - NUMPY_FORCE_BUILD=true BOOST_FORCE_BUILD=true TBB_FORCE_BUILD=true OCIO_FORCE_BUILD=true @@ -751,12 +785,6 @@ while true; do ;; --build-python) PYTHON_FORCE_BUILD=true - NUMPY_FORCE_BUILD=true - shift; continue - ;; - --build-numpy) - PYTHON_FORCE_BUILD=true - NUMPY_FORCE_BUILD=true shift; continue ;; --build-boost) @@ -809,7 +837,6 @@ while true; do ;; --force-all) PYTHON_FORCE_REBUILD=true - NUMPY_FORCE_REBUILD=true BOOST_FORCE_REBUILD=true TBB_FORCE_REBUILD=true OCIO_FORCE_REBUILD=true @@ -830,12 +857,8 @@ while true; do ;; --force-python) PYTHON_FORCE_REBUILD=true - NUMPY_FORCE_REBUILD=true shift; continue ;; - --force-numpy) - NUMPY_FORCE_REBUILD=true; shift; continue - ;; --force-boost) BOOST_FORCE_REBUILD=true; shift; continue ;; @@ -887,9 +910,6 @@ while true; do --skip-python) PYTHON_SKIP=true; shift; continue ;; - --skip-numpy) - NUMPY_SKIP=true; shift; continue - ;; --skip-boost) BOOST_SKIP=true; shift; continue ;; @@ -990,11 +1010,10 @@ PRINT "" # This has to be done here, because user might force some versions... PYTHON_SOURCE=( "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz" ) -NUMPY_SOURCE=( "https://github.com/numpy/numpy/releases/download/v$NUMPY_VERSION/numpy-$NUMPY_VERSION.tar.gz" ) _boost_version_nodots=`echo "$BOOST_VERSION" | sed -r 's/\./_/g'` BOOST_SOURCE=( "https://dl.bintray.com/boostorg/release/$BOOST_VERSION/source/boost_$_boost_version_nodots.tar.bz2" ) -BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options" +BOOST_BUILD_MODULES="--with-system --with-filesystem --with-thread --with-regex --with-locale --with-date_time --with-wave --with-iostreams --with-python --with-program_options --with-serialization --with-atomic" TBB_SOURCE=( "https://github.com/oneapi-src/oneTBB/archive/$TBB_VERSION$TBB_VERSION_UPDATE.tar.gz" ) TBB_SOURCE_CMAKE=( "https://raw.githubusercontent.com/wjakob/tbb/master/CMakeLists.txt" ) @@ -1082,8 +1101,8 @@ FFMPEG_SOURCE=( "http://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2" ) XR_OPENXR_USE_REPO=false XR_OPENXR_SOURCE=("https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_VERSION}.tar.gz") -#~ XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK-Source.git") -#~ XR_OPENXR_REPO_UID="5292e57fda47561e672fba0a4b6e545c0f25dd8d" +#~ XR_OPENXR_SOURCE_REPO=("https://github.com/KhronosGroup/OpenXR-SDK.git") +#~ XR_OPENXR_REPO_UID="5900c51562769b03bea699dc0352cae56acb6419d" #~ XR_OPENXR_REPO_BRANCH="master" # C++11 is required now @@ -1103,7 +1122,7 @@ Those libraries should be available as packages in all recent distributions (opt * libjpeg, libpng, libtiff, [openjpeg2], [libopenal]. * libx11, libxcursor, libxi, libxrandr, libxinerama (and other libx... as needed). * libsqlite3, libbz2, libssl, libfftw3, libxml2, libtinyxml, yasm, libyaml-cpp. - * libsdl2, libglew, libpugixml, libpotrace, [libgmp], [libglewmx], fontconfig.\"" + * libsdl2, libglew, libpugixml, libpotrace, [libgmp], [libglewmx], fontconfig, [libharu/libhpdf].\"" DEPS_SPECIFIC_INFO="\"BUILDABLE DEPENDENCIES: @@ -1112,19 +1131,24 @@ The following libraries will probably not all be available as packages in your d You can force install_deps to build those with '--build-all' or relevant 'build-foo' options, see '--help' message. You may also want to build them yourself (optional ones are [between brackets]): - * Python $PYTHON_VERSION_MIN (from $PYTHON_SOURCE). - * [NumPy $NUMPY_VERSION_MIN] (from $NUMPY_SOURCE). - * Boost $BOOST_VERSION_MIN (from $BOOST_SOURCE, modules: $BOOST_BUILD_MODULES). - * TBB $TBB_VERSION_MIN (from $TBB_SOURCE). - * [FFMpeg $FFMPEG_VERSION_MIN (needs libvorbis, libogg, libtheora, libx264, libmp3lame, libxvidcore, libvpx, ...)] (from $FFMPEG_SOURCE). - * [OpenColorIO $OCIO_VERSION_MIN] (from $OCIO_SOURCE). - * ILMBase $OPENEXR_VERSION_MIN (from $OPENEXR_SOURCE). - * OpenEXR $OPENEXR_VERSION_MIN (from $OPENEXR_SOURCE). - * OpenImageIO $OIIO_VERSION_MIN (from $OIIO_SOURCE). - * [LLVM $LLVM_VERSION_MIN (with clang)] (from $LLVM_SOURCE, and $LLVM_CLANG_SOURCE). - * [OpenShadingLanguage $OSL_VERSION_MIN] (from $OSL_SOURCE_REPO, branch $OSL_SOURCE_REPO_BRANCH, commit $OSL_SOURCE_REPO_UID). - * [OpenSubDiv $OSD_VERSION_MIN] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID). - * [OpenVDB $OPENVDB_VERSION_MIN] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE). + * Python $PYTHON_VERSION (from $PYTHON_SOURCE). + ** [IDNA $PYTHON_IDNA_VERSION] (use pip). + ** [Chardet $PYTHON_CHARDET_VERSION] (use pip). + ** [Urllib3 $PYTHON_URLLIB3_VERSION] (use pip). + ** [Certifi $PYTHON_CERTIFI_VERSION] (use pip). + ** [Requests $PYTHON_REQUESTS_VERSION] (use pip). + ** [NumPy $PYTHON_NUMPY_VERSION] (use pip). + * Boost $BOOST_VERSION (from $BOOST_SOURCE, modules: $BOOST_BUILD_MODULES). + * TBB $TBB_VERSION (from $TBB_SOURCE). + * [FFMpeg $FFMPEG_VERSION (needs libvorbis, libogg, libtheora, libx264, libmp3lame, libxvidcore, libvpx, ...)] (from $FFMPEG_SOURCE). + * [OpenColorIO $OCIO_VERSION] (from $OCIO_SOURCE). + * ILMBase $OPENEXR_VERSION (from $OPENEXR_SOURCE). + * OpenEXR $OPENEXR_VERSION (from $OPENEXR_SOURCE). + * OpenImageIO $OIIO_VERSION (from $OIIO_SOURCE). + * [LLVM $LLVM_VERSION (with clang)] (from $LLVM_SOURCE, and $LLVM_CLANG_SOURCE). + * [OpenShadingLanguage $OSL_VERSION] (from $OSL_SOURCE_REPO, branch $OSL_SOURCE_REPO_BRANCH, commit $OSL_SOURCE_REPO_UID). + * [OpenSubDiv $OSD_VERSION] (from $OSD_SOURCE_REPO, branch $OSD_SOURCE_REPO_BRANCH, commit $OSD_SOURCE_REPO_UID). + * [OpenVDB $OPENVDB_VERSION] (from $OPENVDB_SOURCE), [Blosc $OPENVDB_BLOSC_VERSION] (from $OPENVDB_BLOSC_SOURCE). * [OpenCollada $OPENCOLLADA_VERSION] (from $OPENCOLLADA_SOURCE). * [Embree $EMBREE_VERSION] (from $EMBREE_SOURCE). * [OpenImageDenoise $OIDN_VERSION] (from $OIDN_SOURCE). @@ -1309,18 +1333,22 @@ magic_compile_set() { # Note: should clean nicely in $INST, but not in $SRC, when we switch to a new version of a lib... _clean() { - rm -rf `readlink -f $_inst_shortcut` + if [ $_inst_shortcut ]; then + rm -rf `readlink -f $_inst_shortcut` + rm -rf $_inst_shortcut + fi # Only remove $_src dir when not using git repo (avoids to re-clone the whole repo every time!!!). if [ $_git == false ]; then rm -rf $_src fi rm -rf $_inst - rm -rf $_inst_shortcut } _create_inst_shortcut() { - rm -f $_inst_shortcut - ln -s $_inst $_inst_shortcut + if [ $_inst_shortcut ]; then + rm -f $_inst_shortcut + ln -s $_inst $_inst_shortcut + fi } # ldconfig @@ -1350,14 +1378,19 @@ _init_python() { } _update_deps_python() { - : + if [ "$1" = true ]; then + BOOST_FORCE_BUILD=true + fi + if [ "$2" = true ]; then + BOOST_FORCE_REBUILD=true + fi } clean_Python() { - clean_Numpy _init_python if [ -d $_inst ]; then - _update_deps_python + # Force rebuilding the dependencies if needed. + _update_deps_python false true fi _clean } @@ -1369,9 +1402,12 @@ compile_Python() { fi # To be changed each time we make edits that would modify the compiled result! - py_magic=1 + py_magic=3 _init_python + # Force having own builds for the dependencies. + _update_deps_python true false + # Clean install if needed! magic_compile_check python-$PYTHON_VERSION $py_magic if [ $? -eq 1 -o "$PYTHON_FORCE_REBUILD" = true ]; then @@ -1380,10 +1416,9 @@ compile_Python() { if [ ! -d $_inst ]; then INFO "Building Python-$PYTHON_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_python + # Force rebuilding the dependencies. + _update_deps_python true true prepare_inst @@ -1413,96 +1448,25 @@ compile_Python() { magic_compile_set python-$PYTHON_VERSION $py_magic + PYTHON_VERSION_INSTALLED=$PYTHON_VERSION_SHORT + cd $CWD INFO "Done compiling Python-$PYTHON_VERSION!" - _is_building=false else INFO "Own Python-$PYTHON_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-python option." fi run_ldconfig "python-$PYTHON_VERSION_SHORT" -} - -# ---------------------------------------------------------------------------- -# Build Numpy - -_init_numpy() { - _src=$SRC/numpy-$NUMPY_VERSION - _git=false - _inst=$INST/numpy-$NUMPY_VERSION - _python=$INST/python-$PYTHON_VERSION_SHORT - _site=lib/python$PYTHON_VERSION_SHORT/site-packages - _inst_shortcut=$_python/$_site/numpy -} - -_update_deps_numpy() { - : -} - -clean_Numpy() { - _init_numpy - if [ -d $_inst ]; then - _update_deps_numpy - fi - _clean -} -compile_Numpy() { - if [ "$NO_BUILD" = true ]; then - WARNING "--no-build enabled, Numpy will not be compiled!" - return - fi - - # To be changed each time we make edits that would modify the compiled result! - numpy_magic=0 - _init_numpy - - # Clean install if needed! - magic_compile_check numpy-$NUMPY_VERSION $numpy_magic - if [ $? -eq 1 -o "$NUMPY_FORCE_REBUILD" = true ]; then - clean_Numpy - fi - - if [ ! -d $_inst ]; then - INFO "Building Numpy-$NUMPY_VERSION" - _is_building=true - - # Rebuild dependencies as well! - _update_deps_numpy - - prepare_inst - - if [ ! -d $_src ]; then - mkdir -p $SRC - download NUMPY_SOURCE[@] $_src.tar.gz - - INFO "Unpacking Numpy-$NUMPY_VERSION" - tar -C $SRC -xf $_src.tar.gz - fi - - cd $_src - - $_python/bin/python3 setup.py install --old-and-unmanageable --prefix=$_inst - - if [ -d $_inst ]; then - # Can't use _create_inst_shortcut here... - rm -f $_inst_shortcut - ln -s $_inst/$_site/numpy $_inst_shortcut - else - ERROR "Numpy-$NUMPY_VERSION failed to compile, exiting" - exit 1 - fi - - magic_compile_set numpy-$NUMPY_VERSION $numpy_magic - - cd $CWD - INFO "Done compiling Numpy-$NUMPY_VERSION!" - _is_building=false - else - INFO "Own Numpy-$NUMPY_VERSION is up to date, nothing to do!" - INFO "If you want to force rebuild of this lib, use the --force-numpy option." - fi + # Extra step: install required modules with pip. + _python="$_inst/bin/python3" + $_python -m pip install --upgrade pip + for module in "${PYTHON_MODULES_PIP[@]}" + do + PRINT "" + $_python -m pip install $module --no-binary :all: + done } # ---------------------------------------------------------------------------- @@ -1516,22 +1480,25 @@ _init_boost() { } _update_deps_boost() { - OIIO_FORCE_REBUILD=true - OSL_FORCE_REBUILD=true - OPENVDB_FORCE_REBUILD=true - ALEMBIC_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OIIO_FORCE_BUILD=true OSL_FORCE_BUILD=true OPENVDB_FORCE_BUILD=true ALEMBIC_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OIIO_FORCE_REBUILD=true + OSL_FORCE_REBUILD=true + OPENVDB_FORCE_REBUILD=true + ALEMBIC_FORCE_REBUILD=true + fi } clean_Boost() { _init_boost if [ -d $_inst ]; then - _update_deps_boost + # Force rebuilding the dependencies if needed. + _update_deps_boost false true fi _clean } @@ -1543,10 +1510,13 @@ compile_Boost() { fi # To be changed each time we make edits that would modify the compiled result! - boost_magic=11 + boost_magic=14 _init_boost + # Force having own builds for the dependencies. + _update_deps_boost true false + # Clean install if needed! magic_compile_check boost-$BOOST_VERSION $boost_magic if [ $? -eq 1 -o "$BOOST_FORCE_REBUILD" = true ]; then @@ -1555,10 +1525,9 @@ compile_Boost() { if [ ! -d $_inst ]; then INFO "Building Boost-$BOOST_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_boost + # Force rebuilding the dependencies. + _update_deps_boost true true prepare_inst @@ -1571,7 +1540,11 @@ compile_Boost() { cd $_src if [ ! -f $_src/b2 ]; then - ./bootstrap.sh + if [ -d $INST/python-$PYTHON_VERSION_INSTALLED ]; then + ./bootstrap.sh --with-python-root="$INST/python-$PYTHON_VERSION_INSTALLED" + else + ./bootstrap.sh + fi fi ./b2 -j$THREADS -a $BOOST_BUILD_MODULES \ --prefix=$_inst --disable-icu boost.locale.icu=off install @@ -1588,7 +1561,6 @@ compile_Boost() { cd $CWD INFO "Done compiling Boost-$BOOST_VERSION!" - _is_building=false else INFO "Own Boost-$BOOST_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-boost option." @@ -1609,24 +1581,27 @@ _init_tbb() { } _update_deps_tbb() { - OSD_FORCE_REBUILD=true - OPENVDB_FORCE_REBUILD=true - USD_FORCE_REBUILD=true - EMBREE_FORCE_REBUILD=true - OIDN_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OSD_FORCE_BUILD=true OPENVDB_FORCE_BUILD=true USD_FORCE_BUILD=true EMBREE_FORCE_BUILD=true OIDN_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OSD_FORCE_REBUILD=true + OPENVDB_FORCE_REBUILD=true + USD_FORCE_REBUILD=true + EMBREE_FORCE_REBUILD=true + OIDN_FORCE_REBUILD=true + fi } clean_TBB() { _init_tbb if [ -d $_inst ]; then - _update_deps_tbb + # Force rebuilding the dependencies if needed. + _update_deps_tbb false true fi _clean } @@ -1641,6 +1616,9 @@ compile_TBB() { tbb_magic=0 _init_tbb + # Force having own builds for the dependencies. + _update_deps_tbb true false + # Clean install if needed! magic_compile_check tbb-$TBB_VERSION $tbb_magic if [ $? -eq 1 -o "$TBB_FORCE_REBUILD" = true ]; then @@ -1649,10 +1627,9 @@ compile_TBB() { if [ ! -d $_inst ]; then INFO "Building TBB-$TBB_VERSION$TBB_VERSION_UPDATE" - _is_building=true - # Rebuild dependencies as well! - _update_deps_tbb + # Force rebuilding the dependencies. + _update_deps_tbb true true prepare_inst @@ -1713,7 +1690,6 @@ compile_TBB() { cd $CWD INFO "Done compiling TBB-$TBB_VERSION$TBB_VERSION_UPDATE!" - _is_building=false else INFO "Own TBB-$TBB_VERSION$TBB_VERSION_UPDATE is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-tbb option." @@ -1743,7 +1719,8 @@ _update_deps_ocio() { clean_OCIO() { _init_ocio if [ -d $_inst ]; then - _update_deps_ocio + # Force rebuilding the dependencies if needed. + _update_deps_ocio false true fi _clean } @@ -1758,6 +1735,9 @@ compile_OCIO() { ocio_magic=2 _init_ocio + # Force having own builds for the dependencies. + _update_deps_ocio true false + # Clean install if needed! magic_compile_check ocio-$OCIO_VERSION $ocio_magic if [ $? -eq 1 -o "$OCIO_FORCE_REBUILD" = true ]; then @@ -1766,10 +1746,9 @@ compile_OCIO() { if [ ! -d $_inst ]; then INFO "Building OpenColorIO-$OCIO_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_ocio + # Force rebuilding the dependencies. + _update_deps_ocio true true prepare_inst @@ -1842,7 +1821,6 @@ compile_OCIO() { cd $CWD INFO "Done compiling OpenColorIO-$OCIO_VERSION!" - _is_building=false else INFO "Own OpenColorIO-$OCIO_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-ocio option." @@ -1862,18 +1840,21 @@ _init_openexr() { } _update_deps_openexr() { - OIIO_FORCE_REBUILD=true - ALEMBIC_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OIIO_FORCE_BUILD=true ALEMBIC_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OIIO_FORCE_REBUILD=true + ALEMBIC_FORCE_REBUILD=true + fi } clean_OPENEXR() { _init_openexr if [ -d $_inst ]; then - _update_deps_openexr + # Force rebuilding the dependencies if needed. + _update_deps_openexr false true fi _clean } @@ -1886,6 +1867,10 @@ compile_OPENEXR() { # To be changed each time we make edits that would modify the compiled result! openexr_magic=15 + _init_openexr + + # Force having own builds for the dependencies. + _update_deps_openexr true false # Clean install if needed! magic_compile_check openexr-$OPENEXR_VERSION $openexr_magic @@ -1894,14 +1879,12 @@ compile_OPENEXR() { fi PRINT "" - _init_openexr if [ ! -d $_inst ]; then INFO "Building ILMBase-$OPENEXR_VERSION and OpenEXR-$OPENEXR_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_openexr + # Force rebuilding the dependencies. + _update_deps_openexr true true prepare_inst @@ -1969,7 +1952,6 @@ compile_OPENEXR() { cd $CWD INFO "Done compiling OpenEXR-$OPENEXR_VERSION!" - _is_building=false else INFO "Own OpenEXR-$OPENEXR_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-openexr option." @@ -1992,16 +1974,19 @@ _init_oiio() { } _update_deps_oiio() { - OSL_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OSL_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OSL_FORCE_REBUILD=true + fi } clean_OIIO() { _init_oiio if [ -d $_inst ]; then - _update_deps_oiio + # Force rebuilding the dependencies if needed. + _update_deps_oiio false true fi _clean } @@ -2016,6 +2001,9 @@ compile_OIIO() { oiio_magic=17 _init_oiio + # Force having own builds for the dependencies. + _update_deps_oiio true false + # Clean install if needed! magic_compile_check oiio-$OIIO_VERSION $oiio_magic if [ $? -eq 1 -o "$OIIO_FORCE_REBUILD" = true ]; then @@ -2024,10 +2012,9 @@ compile_OIIO() { if [ ! -d $_inst ]; then INFO "Building OpenImageIO-$OIIO_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_oiio + # Force rebuilding the dependencies. + _update_deps_oiio true true prepare_inst @@ -2064,7 +2051,6 @@ compile_OIIO() { cmake_d="$cmake_d -D CMAKE_PREFIX_PATH=$_inst" cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" cmake_d="$cmake_d -D STOP_ON_WARNING=OFF" - cmake_d="$cmake_d -D BUILDSTATIC=OFF" cmake_d="$cmake_d -D LINKSTATIC=OFF" cmake_d="$cmake_d -D USE_SIMD=sse2" @@ -2092,16 +2078,13 @@ compile_OIIO() { #cmake_d="$cmake_d -D CMAKE_VERBOSE_MAKEFILE=ON" if [ -d $INST/boost ]; then - cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON -D Boost_NO_BOOST_CMAKE=ON" fi # Looks like we do not need ocio in oiio for now... # if [ -d $INST/ocio ]; then # cmake_d="$cmake_d -D OCIO_PATH=$INST/ocio" # fi - cmake_d="$cmake_d -D USE_OCIO=OFF" - - cmake_d="$cmake_d -D OIIO_BUILD_CPP11=ON" if file /bin/cp | grep -q '32-bit'; then cflags="-fPIC -m32 -march=i686" @@ -2125,7 +2108,6 @@ compile_OIIO() { cd $CWD INFO "Done compiling OpenImageIO-$OIIO_VERSION!" - _is_building=false else INFO "Own OpenImageIO-$OIIO_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-oiio option." @@ -2147,16 +2129,19 @@ _init_llvm() { } _update_deps_llvm() { - OSL_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OSL_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OSL_FORCE_REBUILD=true + fi } clean_LLVM() { _init_llvm if [ -d $_inst ]; then - _update_deps_llvm + # Force rebuilding the dependencies if needed. + _update_deps_llvm false true fi _clean } @@ -2171,6 +2156,9 @@ compile_LLVM() { llvm_magic=3 _init_llvm + # Force having own builds for the dependencies. + _update_deps_llvm true false + # Clean install if needed! magic_compile_check llvm-$LLVM_VERSION $llvm_magic if [ $? -eq 1 -o "$LLVM_FORCE_REBUILD" = true ]; then @@ -2179,10 +2167,9 @@ compile_LLVM() { if [ ! -d $_inst ]; then INFO "Building LLVM-$LLVM_VERSION (CLANG included!)" - _is_building=true - # Rebuild dependencies as well! - _update_deps_llvm + # Force rebuilding the dependencies. + _update_deps_llvm true true prepare_inst @@ -2241,7 +2228,6 @@ compile_LLVM() { cd $CWD INFO "Done compiling LLVM-$LLVM_VERSION (CLANG included)!" - _is_building=false else INFO "Own LLVM-$LLVM_VERSION (CLANG included) is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-llvm option." @@ -2265,7 +2251,8 @@ _update_deps_osl() { clean_OSL() { _init_osl if [ -d $_inst ]; then - _update_deps_osl + # Force rebuilding the dependencies if needed. + _update_deps_osl false true fi _clean } @@ -2280,6 +2267,9 @@ compile_OSL() { osl_magic=21 _init_osl + # Force having own builds for the dependencies. + _update_deps_osl true false + # Clean install if needed! magic_compile_check osl-$OSL_VERSION $osl_magic if [ $? -eq 1 -o "$OSL_FORCE_REBUILD" = true ]; then @@ -2289,10 +2279,9 @@ compile_OSL() { if [ ! -d $_inst ]; then INFO "Building OpenShadingLanguage-$OSL_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_osl + # Force rebuilding the dependencies. + _update_deps_osl true true prepare_inst @@ -2331,7 +2320,6 @@ compile_OSL() { cmake_d="$cmake_d -D CMAKE_INSTALL_PREFIX=$_inst" cmake_d="$cmake_d -D BUILD_TESTING=OFF" cmake_d="$cmake_d -D STOP_ON_WARNING=OFF" - cmake_d="$cmake_d -D BUILDSTATIC=OFF" cmake_d="$cmake_d -D OSL_BUILD_PLUGINS=OFF" cmake_d="$cmake_d -D OSL_BUILD_TESTS=OFF" cmake_d="$cmake_d -D USE_SIMD=sse2" @@ -2339,6 +2327,9 @@ compile_OSL() { cmake_d="$cmake_d -D USE_PARTIO=OFF" cmake_d="$cmake_d -D OSL_BUILD_MATERIALX=OFF" cmake_d="$cmake_d -D USE_QT=OFF" + cmake_d="$cmake_d -D USE_PYTHON=OFF" + + cmake_d="$cmake_d -D CMAKE_CXX_STANDARD=14" #~ cmake_d="$cmake_d -D ILMBASE_VERSION=$ILMBASE_VERSION" @@ -2350,11 +2341,14 @@ compile_OSL() { fi if [ -d $INST/boost ]; then - cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON" + cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost -D Boost_NO_SYSTEM_PATHS=ON -D Boost_NO_BOOST_CMAKE=ON" fi if [ -d $INST/oiio ]; then cmake_d="$cmake_d -D OPENIMAGEIO_ROOT_DIR=$INST/oiio" + # HACK! SIC!!!! + # Quiet incredible, but if root dir is given, path to lib is found, but not path to include... + cmake_d="$cmake_d -D OPENIMAGEIO_INCLUDE_DIR=$INST/oiio/include" fi if [ ! -z $LLVM_VERSION_FOUND ]; then @@ -2384,7 +2378,6 @@ compile_OSL() { cd $CWD INFO "Done compiling OpenShadingLanguage-$OSL_VERSION!" - _is_building=false else INFO "Own OpenShadingLanguage-$OSL_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-osl option." @@ -2410,7 +2403,8 @@ _update_deps_osd() { clean_OSD() { _init_osd if [ -d $_inst ]; then - _update_deps_osd + # Force rebuilding the dependencies if needed. + _update_deps_osd false true fi _clean } @@ -2425,6 +2419,9 @@ compile_OSD() { osd_magic=2 _init_osd + # Force having own builds for the dependencies. + _update_deps_osd true false + # Clean install if needed! magic_compile_check osd-$OSD_VERSION $osd_magic if [ $? -eq 1 -o "$OSD_FORCE_REBUILD" = true ]; then @@ -2433,10 +2430,9 @@ compile_OSD() { if [ ! -d $_inst ]; then INFO "Building OpenSubdiv-$OSD_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_osd + # Force rebuilding the dependencies. + _update_deps_osd true true prepare_inst @@ -2498,7 +2494,6 @@ compile_OSD() { cd $CWD INFO "Done compiling OpenSubdiv-$OSD_VERSION!" - _is_building=false else INFO "Own OpenSubdiv-$OSD_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-osd option." @@ -2518,16 +2513,19 @@ _init_blosc() { } _update_deps_blosc() { - OPENVDB_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OPENVDB_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OPENVDB_FORCE_REBUILD=true + fi } clean_BLOSC() { _init_blosc if [ -d $_inst ]; then - _update_deps_blosc + # Force rebuilding the dependencies if needed. + _update_deps_blosc false true fi _clean } @@ -2542,6 +2540,9 @@ compile_BLOSC() { blosc_magic=0 _init_blosc + # Force having own builds for the dependencies. + _update_deps_blosc true false + # Clean install if needed! magic_compile_check blosc-$OPENVDB_BLOSC_VERSION $blosc_magic if [ $? -eq 1 -o "$OPENVDB_FORCE_REBUILD" = true ]; then @@ -2551,10 +2552,9 @@ compile_BLOSC() { if [ ! -d $_inst ]; then INFO "Building Blosc-$OPENVDB_BLOSC_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_blosc + # Force rebuilding the dependencies. + _update_deps_blosc true true prepare_inst @@ -2596,7 +2596,6 @@ compile_BLOSC() { fi cd $CWD INFO "Done compiling Blosc-$OPENVDB_BLOSC_VERSION!" - _is_building=false else INFO "Own Blosc-$OPENVDB_BLOSC_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib (and openvdb), use the --force-openvdb option." @@ -2623,7 +2622,8 @@ _update_deps_nanovdb() { clean_nanovdb() { _init_nanovdb if [ -d $_inst ]; then - _update_deps_nanovdb + # Force rebuilding the dependencies if needed. + _update_deps_nanovdb false true fi _git=true # Mere trick to prevent clean from removing $_src... _clean @@ -2634,6 +2634,9 @@ install_NanoVDB() { nanovdb_magic=1 _init_nanovdb + # Force having own builds for the dependencies. + _update_deps_nanovdb true false + # Clean install if needed! magic_compile_check nanovdb-$OPENVDB_VERSION $nanovdb_magic if [ $? -eq 1 ]; then @@ -2642,10 +2645,9 @@ install_NanoVDB() { if [ ! -d $_inst ]; then INFO "Installing NanoVDB v$OPENVDB_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_nanovdb + # Force rebuilding the dependencies. + _update_deps_nanovdb true true prepare_inst @@ -2702,7 +2704,6 @@ install_NanoVDB() { cd $CWD INFO "Done compiling NanoVDB-v$OPENVDB_VERSION!" - _is_building=false else INFO "Own NanoVDB-v$OPENVDB_VERSION is up to date, nothing to do!" fi @@ -2728,7 +2729,8 @@ _update_deps_openvdb() { clean_OPENVDB() { _init_openvdb if [ -d $_inst ]; then - _update_deps_openvdb + # Force rebuilding the dependencies if needed. + _update_deps_openvdb false true fi _clean } @@ -2746,6 +2748,9 @@ compile_OPENVDB() { openvdb_magic=2 _init_openvdb + # Force having own builds for the dependencies. + _update_deps_openvdb true false + # Clean install if needed! magic_compile_check openvdb-$OPENVDB_VERSION $openvdb_magic if [ $? -eq 1 -o "$OPENVDB_FORCE_REBUILD" = true ]; then @@ -2754,10 +2759,9 @@ compile_OPENVDB() { if [ ! -d $_inst ]; then INFO "Building OpenVDB-$OPENVDB_VERSION (with NanoVDB: $WITH_NANOVDB)" - _is_building=true - # Rebuild dependencies as well! - _update_deps_openvdb + # Force rebuilding the dependencies. + _update_deps_openvdb true true prepare_inst @@ -2802,6 +2806,7 @@ compile_OPENVDB() { cmake_d="$cmake_d -D Boost_USE_MULTITHREADED=ON" cmake_d="$cmake_d -D Boost_NO_SYSTEM_PATHS=ON" cmake_d="$cmake_d -D Boost_NO_BOOST_CMAKE=ON" + cmake_d="$cmake_d -D Boost_NO_BOOST_CMAKE=ON" fi if [ -d $INST/tbb ]; then cmake_d="$cmake_d -D TBB_ROOT=$INST/tbb" @@ -2832,7 +2837,6 @@ compile_OPENVDB() { cd $CWD INFO "Done compiling OpenVDB-$OPENVDB_VERSION!" - _is_building=false else INFO "Own OpenVDB-$OPENVDB_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-openvdb option." @@ -2862,7 +2866,8 @@ _update_deps_alembic() { clean_ALEMBIC() { _init_alembic if [ -d $_inst ]; then - _update_deps_alembic + # Force rebuilding the dependencies if needed. + _update_deps_alembic false true fi _clean } @@ -2877,6 +2882,9 @@ compile_ALEMBIC() { alembic_magic=2 _init_alembic + # Force having own builds for the dependencies. + _update_deps_alembic true false + # Clean install if needed! magic_compile_check alembic-$ALEMBIC_VERSION $alembic_magic if [ $? -eq 1 -o "$ALEMBIC_FORCE_REBUILD" = true ]; then @@ -2885,10 +2893,9 @@ compile_ALEMBIC() { if [ ! -d $_inst ]; then INFO "Building Alembic-$ALEMBIC_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_alembic + # Force rebuilding the dependencies. + _update_deps_alembic true true prepare_inst @@ -2943,7 +2950,6 @@ compile_ALEMBIC() { cd $CWD INFO "Done compiling Alembic-$ALEMBIC_VERSION!" - _is_building=false else INFO "Own Alembic-$ALEMBIC_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-alembic option." @@ -2967,7 +2973,8 @@ _update_deps_usd() { clean_USD() { _init_usd if [ -d $_inst ]; then - _update_deps_usd + # Force rebuilding the dependencies if needed. + _update_deps_usd false true fi _clean } @@ -2982,6 +2989,9 @@ compile_USD() { usd_magic=1 _init_usd + # Force having own builds for the dependencies. + _update_deps_usd true false + # Clean install if needed! magic_compile_check usd-$USD_VERSION $usd_magic if [ $? -eq 1 -o "$USD_FORCE_REBUILD" = true ]; then @@ -2990,10 +3000,9 @@ compile_USD() { if [ ! -d $_inst ]; then INFO "Building USD-$USD_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_usd + # Force rebuilding the dependencies. + _update_deps_usd true true prepare_inst @@ -3041,7 +3050,6 @@ compile_USD() { cd $CWD INFO "Done compiling USD-$USD_VERSION!" - _is_building=false else INFO "Own USD-$USD_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-usd option." @@ -3066,7 +3074,8 @@ _update_deps_collada() { clean_OpenCOLLADA() { _init_opencollada if [ -d $_inst ]; then - _update_deps_collada + # Force rebuilding the dependencies if needed. + _update_deps_collada false true fi _clean } @@ -3081,6 +3090,9 @@ compile_OpenCOLLADA() { opencollada_magic=9 _init_opencollada + # Force having own builds for the dependencies. + _update_deps_opencollada true false + # Clean install if needed! magic_compile_check opencollada-$OPENCOLLADA_VERSION $opencollada_magic if [ $? -eq 1 -o "$OPENCOLLADA_FORCE_REBUILD" = true ]; then @@ -3089,10 +3101,9 @@ compile_OpenCOLLADA() { if [ ! -d $_inst ]; then INFO "Building OpenCOLLADA-$OPENCOLLADA_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_collada + # Force rebuilding the dependencies. + _update_deps_collada true true prepare_inst @@ -3148,7 +3159,6 @@ compile_OpenCOLLADA() { cd $CWD INFO "Done compiling OpenCOLLADA-$OPENCOLLADA_VERSION!" - _is_building=false else INFO "Own OpenCOLLADA-$OPENCOLLADA_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-opencollada option." @@ -3172,7 +3182,8 @@ _update_deps_embree() { clean_Embree() { _init_embree if [ -d $_inst ]; then - _update_deps_embree + # Force rebuilding the dependencies if needed. + _update_deps_embree false true fi _clean } @@ -3187,6 +3198,9 @@ compile_Embree() { embree_magic=10 _init_embree + # Force having own builds for the dependencies. + _update_deps_embree true false + # Clean install if needed! magic_compile_check embree-$EMBREE_VERSION $embree_magic if [ $? -eq 1 -o "$EMBREE_FORCE_REBUILD" = true ]; then @@ -3195,10 +3209,9 @@ compile_Embree() { if [ ! -d $_inst ]; then INFO "Building Embree-$EMBREE_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_embree + # Force rebuilding the dependencies. + _update_deps_embree true true prepare_inst @@ -3261,7 +3274,6 @@ compile_Embree() { cd $CWD INFO "Done compiling Embree-$EMBREE_VERSION!" - _is_building=false else INFO "Own Embree-$EMBREE_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-embree option." @@ -3278,16 +3290,19 @@ _init_ispc() { } _update_deps_ispc() { - OIDN_FORCE_REBUILD=true - if [ "$_is_building" = true ]; then + if [ "$1" = true ]; then OIDN_FORCE_BUILD=true fi + if [ "$2" = true ]; then + OIDN_FORCE_REBUILD=true + fi } clean_ispc() { _init_ispc if [ -d $_inst ]; then - _update_deps_ispc + # Force rebuilding the dependencies if needed. + _update_deps_ispc false true fi _clean } @@ -3297,6 +3312,9 @@ install_ISPC() { ispc_magic=0 _init_ispc + # Force having own builds for the dependencies. + _update_deps_ispc true false + # Clean install if needed! magic_compile_check ispc-$ISPC_VERSION $ispc_magic if [ $? -eq 1 ]; then @@ -3305,10 +3323,9 @@ install_ISPC() { if [ ! -d $_inst ]; then INFO "Installing Implicit SPMD Program Compiler v$ISPC_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_ispc + # Force rebuilding the dependencies. + _update_deps_ispc true true prepare_inst @@ -3334,7 +3351,6 @@ install_ISPC() { cd $CWD INFO "Done compiling ISPC-v$ISPC_VERSION!" - _is_building=false else INFO "Own ISPC-v$ISPC_VERSION is up to date, nothing to do!" fi @@ -3358,7 +3374,8 @@ _update_deps_oidn() { clean_oidn() { _init_oidn if [ -d $_inst ]; then - _update_deps_oidn + # Force rebuilding the dependencies if needed. + _update_deps_oidn false true fi _clean } @@ -3376,6 +3393,9 @@ compile_OIDN() { oidn_magic=9 _init_oidn + # Force having own builds for the dependencies. + _update_deps_oidn true false + # Clean install if needed! magic_compile_check oidn-$OIDN_VERSION $oidn_magic if [ $? -eq 1 -o "$OIDN_FORCE_REBUILD" = true ]; then @@ -3384,10 +3404,9 @@ compile_OIDN() { if [ ! -d $_inst ]; then INFO "Building OpenImageDenoise-$OIDN_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_oidn + # Force rebuilding the dependencies. + _update_deps_oidn true true prepare_inst @@ -3446,7 +3465,6 @@ compile_OIDN() { cd $CWD INFO "Done compiling OpenImageDenoise-$OIDN_VERSION!" - _is_building=false else INFO "Own OpenImageDenoise-$OIDN_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-oidn option." @@ -3471,7 +3489,8 @@ _update_deps_ffmpeg() { clean_FFmpeg() { _init_ffmpeg if [ -d $_inst ]; then - _update_deps_ffmpeg + # Force rebuilding the dependencies if needed. + _update_deps_ffmpeg false true fi _clean } @@ -3486,6 +3505,9 @@ compile_FFmpeg() { ffmpeg_magic=5 _init_ffmpeg + # Force having own builds for the dependencies. + _update_deps_ffmpeg true false + # Clean install if needed! magic_compile_check ffmpeg-$FFMPEG_VERSION $ffmpeg_magic if [ $? -eq 1 -o "$FFMPEG_FORCE_REBUILD" = true ]; then @@ -3494,10 +3516,9 @@ compile_FFmpeg() { if [ ! -d $_inst ]; then INFO "Building ffmpeg-$FFMPEG_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_ffmpeg + # Force rebuilding the dependencies. + _update_deps_ffmpeg true true prepare_inst @@ -3576,7 +3597,6 @@ compile_FFmpeg() { cd $CWD INFO "Done compiling ffmpeg-$FFMPEG_VERSION!" - _is_building=false else INFO "Own ffmpeg-$FFMPEG_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-ffmpeg option." @@ -3600,7 +3620,8 @@ _update_deps_xr_openxr_sdk() { clean_XR_OpenXR_SDK() { _init_xr_openxr_sdk if [ -d $_inst ]; then - _update_deps_xr_openxr_sdk + # Force rebuilding the dependencies if needed. + _update_deps_xr_openxr_sdk false true fi _clean } @@ -3615,6 +3636,9 @@ compile_XR_OpenXR_SDK() { xr_openxr_magic=2 _init_xr_openxr_sdk + # Force having own builds for the dependencies. + _update_deps_xr_openxr_sdk true false + # Clean install if needed! magic_compile_check xr-openxr-$XR_OPENXR_VERSION $xr_openxr_magic if [ $? -eq 1 -o "$XR_OPENXR_FORCE_REBUILD" = true ]; then @@ -3623,10 +3647,9 @@ compile_XR_OpenXR_SDK() { if [ ! -d $_inst ]; then INFO "Building XR-OpenXR-SDK-$XR_OPENXR_VERSION" - _is_building=true - # Rebuild dependencies as well! - _update_deps_xr_openxr_sdk + # Force rebuilding the dependencies. + _update_deps_xr_openxr_sdk true true prepare_inst @@ -3687,7 +3710,6 @@ compile_XR_OpenXR_SDK() { cd $CWD INFO "Done compiling XR-OpenXR-SDK-$XR_OPENXR_VERSION!" - _is_building=false else INFO "Own XR-OpenXR-SDK-$XR_OPENXR_VERSION is up to date, nothing to do!" INFO "If you want to force rebuild of this lib, use the --force-xr-openxr option." @@ -3798,7 +3820,7 @@ install_DEB() { libbz2-dev libncurses5-dev libssl-dev liblzma-dev libreadline-dev \ libopenal-dev libglew-dev yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV \ libsdl2-dev libfftw3-dev patch bzip2 libxml2-dev libtinyxml-dev libjemalloc-dev \ - libgmp-dev libpugixml-dev libpotrace-dev" + libgmp-dev libpugixml-dev libpotrace-dev libhpdf-dev" # libglewmx-dev (broken in deb testing currently...) VORBIS_USE=true @@ -3949,9 +3971,9 @@ install_DEB() { PRINT "" _do_compile_python=false if [ "$PYTHON_SKIP" = true ]; then - WARNING "Skipping Python/NumPy installation, as requested..." + WARNING "Skipping Python installation, as requested..." elif [ "$PYTHON_FORCE_BUILD" = true ]; then - INFO "Forced Python/NumPy building, as requested..." + INFO "Forced Python building, as requested..." _do_compile_python=true else check_package_version_ge_lt_DEB python3-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX @@ -3961,17 +3983,21 @@ install_DEB() { install_packages_DEB python3-dev clean_Python PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - check_package_DEB python3-numpy + + for module in "${PYTHON_MODULES_PACKAGES[@]}" + do + module=($module) + package="python3-${module[0]}" + package_vmin=${module[1]} + package_vmax=${module[2]} + check_package_version_ge_lt_DEB "$package" $package_vmin $package_vmax if [ $? -eq 0 ]; then - install_packages_DEB python3-numpy + install_packages_DEB "$package" else - WARNING "Sorry, using python package but no valid numpy package available!" \ - " Use --build-numpy to force building of both Python and NumPy." + WARNING "Sorry, using python package but no valid $package package available!" \ + " Use --build-python to force building of Python and use pip to get the packages." fi - fi + done else _do_compile_python=true fi @@ -3980,12 +4006,6 @@ install_DEB() { if $_do_compile_python; then install_packages_DEB libffi-dev compile_Python - PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - compile_Numpy - fi fi @@ -4092,7 +4112,7 @@ install_DEB() { else check_package_version_ge_lt_DEB llvm-dev $LLVM_VERSION_MIN $LLVM_VERSION_MAX if [ $? -eq 0 ]; then - install_packages_DEB llvm-dev clang + install_packages_DEB llvm-dev clang libclang-dev have_llvm=true LLVM_VERSION=`llvm-config --version` LLVM_VERSION_FOUND=$LLVM_VERSION @@ -4465,7 +4485,7 @@ install_RPM() { wget ncurses-devel readline-devel $OPENJPEG_DEV openal-soft-devel \ glew-devel yasm $THEORA_DEV $VORBIS_DEV $OGG_DEV patch \ libxml2-devel yaml-cpp-devel tinyxml-devel jemalloc-devel \ - gmp-devel pugixml-devel potrace-devel" + gmp-devel pugixml-devel potrace-devel libharu-devel" OPENJPEG_USE=true VORBIS_USE=true @@ -4585,7 +4605,7 @@ install_RPM() { if [ "$PYTHON_SKIP" = true ]; then WARNING "Skipping Python installation, as requested..." elif [ "$PYTHON_FORCE_BUILD" = true ]; then - INFO "Forced Python/NumPy building, as requested..." + INFO "Forced Python building, as requested..." _do_compile_python=true else check_package_version_ge_lt_RPM python3-devel $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX @@ -4594,18 +4614,21 @@ install_RPM() { install_packages_RPM python3-devel clean_Python - PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - check_package_version_ge_lt_RPM python3-numpy $NUMPY_VERSION_MIN $NUMPY_VERSION_MAX + + for module in "${PYTHON_MODULES_PACKAGES[@]}" + do + module=($module) + package="python3-${module[0]}" + package_vmin=${module[1]} + package_vmax=${module[2]} + check_package_version_ge_lt_RPM "$package" $package_vmin $package_vmax if [ $? -eq 0 ]; then - install_packages_RPM python3-numpy + install_packages_RPM "$package" else - WARNING "Sorry, using python package but no valid numpy package available!" \ - " Use --build-numpy to force building of both Python and NumPy." + WARNING "Sorry, using python package but no valid $package package available!" \ + " Use --build-python to force building of Python and use pip to get the packages." fi - fi + done else _do_compile_python=true fi @@ -4614,12 +4637,6 @@ install_RPM() { if [ "$_do_compile_python" = true ]; then install_packages_RPM libffi-devel compile_Python - PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - compile_Numpy - fi fi @@ -5041,7 +5058,7 @@ install_ARCH() { _packages="$BASE_DEVEL git cmake fontconfig \ libxi libxcursor libxrandr libxinerama glew libpng libtiff wget openal \ $OPENJPEG_DEV $VORBIS_DEV $OGG_DEV $THEORA_DEV yasm sdl2 fftw \ - libxml2 yaml-cpp tinyxml python-requests jemalloc gmp potrace pugixml" + libxml2 yaml-cpp tinyxml python-requests jemalloc gmp potrace pugixml libharu" OPENJPEG_USE=true VORBIS_USE=true @@ -5126,7 +5143,7 @@ install_ARCH() { if [ "$PYTHON_SKIP" = true ]; then WARNING "Skipping Python installation, as requested..." elif [ "$PYTHON_FORCE_BUILD" = true ]; then - INFO "Forced Python/NumPy building, as requested..." + INFO "Forced Python building, as requested..." _do_compile_python=true else check_package_version_ge_lt_ARCH python $PYTHON_VERSION_MIN $PYTHON_VERSION_MAX @@ -5136,17 +5153,21 @@ install_ARCH() { install_packages_ARCH python clean_Python PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - check_package_version_ge_ARCH python-numpy $NUMPY_VERSION_MIN $NUMPY_VERSION_MAX + + for module in "${PYTHON_MODULES_PACKAGES[@]}" + do + module=($module) + package="python-${module[0]}" + package_vmin=${module[1]} + package_vmax=${module[2]} + check_package_version_ge_lt_ARCH "$package" $package_vmin $package_vmax if [ $? -eq 0 ]; then - install_packages_ARCH python-numpy + install_packages_ARCH "$package" else - WARNING "Sorry, using python package but no valid numpy package available!" \ - "Use --build-numpy to force building of both Python and NumPy." + WARNING "Sorry, using python package but no valid $package package available!" \ + " Use --build-python to force building of Python and use pip to get the packages." fi - fi + done else _do_compile_python=true fi @@ -5155,12 +5176,6 @@ install_ARCH() { if [ "$_do_compile_python" = true ]; then install_packages_ARCH libffi compile_Python - PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - compile_Numpy - fi fi @@ -5493,16 +5508,10 @@ install_OTHER() { PRINT "" if [ "$PYTHON_SKIP" = true ]; then - WARNING "Skipping Python/NumPy installation, as requested..." + WARNING "Skipping Python installation, as requested..." elif [ "$PYTHON_FORCE_BUILD" = true ]; then - INFO "Forced Python/NumPy building, as requested..." + INFO "Forced Python building, as requested..." compile_Python - PRINT "" - if [ "$NUMPY_SKIP" = true ]; then - WARNING "Skipping NumPy installation, as requested..." - else - compile_Numpy - fi fi @@ -5736,9 +5745,11 @@ print_info() { if [ -d $INST/boost ]; then _1="-D BOOST_ROOT=$INST/boost" _2="-D Boost_NO_SYSTEM_PATHS=ON" + _3="-D Boost_NO_BOOST_CMAKE=ON" PRINT " $_1" PRINT " $_2" - _buildargs="$_buildargs $_1 $_2" + PRINT " $_3" + _buildargs="$_buildargs $_1 $_2 $_3" fi if [ -d $INST/tbb ]; then diff --git a/build_files/build_environment/patches/haru.diff b/build_files/build_environment/patches/haru.diff new file mode 100644 index 00000000000..fed551b4bf0 --- /dev/null +++ b/build_files/build_environment/patches/haru.diff @@ -0,0 +1,12 @@ +diff --git a/src/hpdf_image_ccitt.c b/src/hpdf_image_ccitt.c +index 8672763..9be531a 100644 +--- a/src/hpdf_image_ccitt.c ++++ b/src/hpdf_image_ccitt.c +@@ -21,7 +21,6 @@ + #include <memory.h> + #include <assert.h> + +-#define G3CODES + #include "t4.h" + + typedef unsigned int uint32; diff --git a/build_files/build_environment/patches/python_linux.diff b/build_files/build_environment/patches/python_linux.diff index 24d625c7ceb..a9baae8ce32 100644 --- a/build_files/build_environment/patches/python_linux.diff +++ b/build_files/build_environment/patches/python_linux.diff @@ -2,23 +2,23 @@ diff --git a/setup.py.orig b/setup.py index a97a755..07ce853 100644 --- a/setup.py.orig +++ b/setup.py -@@ -1422,13 +1422,13 @@ class PyBuildExt(build_ext): +@@ -1603,13 +1603,13 @@ version = line.split()[2] break if version >= version_req: -- if (self.compiler.find_library_file(lib_dirs, 'z')): -+ if (self.compiler.find_library_file(lib_dirs, 'z_pic')): - if host_platform == "darwin": +- if (self.compiler.find_library_file(self.lib_dirs, 'z')): ++ if (self.compiler.find_library_file(self.lib_dirs, 'z_pic')): + if MACOS: zlib_extra_link_args = ('-Wl,-search_paths_first',) else: zlib_extra_link_args = () - exts.append( Extension('zlib', ['zlibmodule.c'], -- libraries = ['z'], -+ libraries = ['z_pic'], - extra_link_args = zlib_extra_link_args)) + self.add(Extension('zlib', ['zlibmodule.c'], +- libraries=['z'], ++ libraries=['z_pic'], + extra_link_args=zlib_extra_link_args)) have_zlib = True else: -@@ -1442,7 +1442,7 @@ class PyBuildExt(build_ext): +@@ -1623,7 +1623,7 @@ # crc32 if we have it. Otherwise binascii uses its own. if have_zlib: extra_compile_args = ['-DUSE_ZLIB_CRC32'] @@ -27,12 +27,12 @@ index a97a755..07ce853 100644 extra_link_args = zlib_extra_link_args else: extra_compile_args = [] -@@ -1991,7 +1991,7 @@ class PyBuildExt(build_ext): +@@ -2168,7 +2168,7 @@ + ffi_inc = None print('Header file {} does not exist'.format(ffi_h)) - ffi_lib = None - if ffi_inc is not None: + if ffi_lib is None and ffi_inc: - for lib_name in ('ffi', 'ffi_pic'): + for lib_name in ('ffi_pic', ): - if (self.compiler.find_library_file(lib_dirs, lib_name)): + if (self.compiler.find_library_file(self.lib_dirs, lib_name)): ffi_lib = lib_name break diff --git a/build_files/build_environment/patches/python_macos.diff b/build_files/build_environment/patches/python_macos.diff deleted file mode 100644 index 22ccbebee2f..00000000000 --- a/build_files/build_environment/patches/python_macos.diff +++ /dev/null @@ -1,289 +0,0 @@ -diff -ru a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst ---- a/Doc/library/ctypes.rst 2020-03-10 07:11:12.000000000 +0100 -+++ b/Doc/library/ctypes.rst 2020-07-14 08:10:10.000000000 +0200 -@@ -1551,6 +1551,13 @@ - value usable as argument (integer, string, ctypes instance). This allows - defining adapters that can adapt custom objects as function parameters. - -+ .. attribute:: variadic -+ -+ Assign a boolean to specify that the function takes a variable number of -+ arguments. This does not matter on most platforms, but for Apple arm64 -+ platforms variadic functions have a different calling convention than -+ normal functions. -+ - .. attribute:: errcheck - - Assign a Python function or another callable to this attribute. The -diff -ru a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c ---- a/Modules/_ctypes/_ctypes.c 2020-03-10 07:11:12.000000000 +0100 -+++ b/Modules/_ctypes/_ctypes.c 2020-07-14 08:14:41.000000000 +0200 -@@ -3175,6 +3175,35 @@ - } - - static int -+PyCFuncPtr_set_variadic(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored)) -+{ -+ StgDictObject *dict = PyObject_stgdict((PyObject *)self); -+ assert(dict); -+ int r = PyObject_IsTrue(ob); -+ if (r == 1) { -+ dict->flags |= FUNCFLAG_VARIADIC; -+ return 0; -+ } else if (r == 0) { -+ dict->flags &= ~FUNCFLAG_VARIADIC; -+ return 0; -+ } else { -+ return -1; -+ } -+} -+ -+static PyObject * -+PyCFuncPtr_get_variadic(PyCFuncPtrObject *self, void *Py_UNUSED(ignored)) -+{ -+ StgDictObject *dict = PyObject_stgdict((PyObject *)self); -+ assert(dict); /* Cannot be NULL for PyCFuncPtrObject instances */ -+ if (dict->flags & FUNCFLAG_VARIADIC) -+ Py_RETURN_TRUE; -+ else -+ Py_RETURN_FALSE; -+} -+ -+ -+static int - PyCFuncPtr_set_argtypes(PyCFuncPtrObject *self, PyObject *ob, void *Py_UNUSED(ignored)) - { - PyObject *converters; -@@ -5632,6 +5661,7 @@ - PyModule_AddObject(m, "FUNCFLAG_USE_ERRNO", PyLong_FromLong(FUNCFLAG_USE_ERRNO)); - PyModule_AddObject(m, "FUNCFLAG_USE_LASTERROR", PyLong_FromLong(FUNCFLAG_USE_LASTERROR)); - PyModule_AddObject(m, "FUNCFLAG_PYTHONAPI", PyLong_FromLong(FUNCFLAG_PYTHONAPI)); -+ PyModule_AddObject(m, "FUNCFLAG_VARIADIC", PyLong_FromLong(FUNCFLAG_VARIADIC)); - PyModule_AddStringConstant(m, "__version__", "1.1.0"); - - PyModule_AddObject(m, "_memmove_addr", PyLong_FromVoidPtr(memmove)); -diff -ru a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c ---- a/Modules/_ctypes/callproc.c 2020-03-10 07:11:12.000000000 +0100 -+++ b/Modules/_ctypes/callproc.c 2020-07-14 08:18:33.000000000 +0200 -@@ -767,7 +767,8 @@ - ffi_type **atypes, - ffi_type *restype, - void *resmem, -- int argcount) -+ int argcount, -+ int argtypecount) - { - PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ - PyObject *error_object = NULL; -@@ -793,15 +794,38 @@ - if ((flags & FUNCFLAG_CDECL) == 0) - cc = FFI_STDCALL; - #endif -- if (FFI_OK != ffi_prep_cif(&cif, -- cc, -- argcount, -- restype, -- atypes)) { -- PyErr_SetString(PyExc_RuntimeError, -- "ffi_prep_cif failed"); -- return -1; -- } -+#if HAVE_FFI_PREP_CIF_VAR -+ /* Everyone SHOULD set f.variadic=True on variadic function pointers, but -+ * lots of existing code will not. If there's at least one arg and more -+ * args are passed than are defined in the prototype, then it must be a -+ * variadic function. */ -+ if ((flags & FUNCFLAG_VARIADIC) || -+ (argtypecount != 0 && argcount > argtypecount)) -+ { -+ if (FFI_OK != ffi_prep_cif_var(&cif, -+ cc, -+ argtypecount, -+ argcount, -+ restype, -+ atypes)) { -+ PyErr_SetString(PyExc_RuntimeError, -+ "ffi_prep_cif_var failed"); -+ return -1; -+ } -+ } else { -+#endif -+ if (FFI_OK != ffi_prep_cif(&cif, -+ cc, -+ argcount, -+ restype, -+ atypes)) { -+ PyErr_SetString(PyExc_RuntimeError, -+ "ffi_prep_cif failed"); -+ return -1; -+ } -+#if HAVE_FFI_PREP_CIF_VAR -+ } -+#endif - - if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { - error_object = _ctypes_get_errobj(&space); -@@ -1185,9 +1209,8 @@ - - if (-1 == _call_function_pointer(flags, pProc, avalues, atypes, - rtype, resbuf, -- Py_SAFE_DOWNCAST(argcount, -- Py_ssize_t, -- int))) -+ Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int), -+ Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int))) - goto cleanup; - - #ifdef WORDS_BIGENDIAN -diff -ru a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h ---- a/Modules/_ctypes/ctypes.h 2020-03-10 07:11:12.000000000 +0100 -+++ b/Modules/_ctypes/ctypes.h 2020-07-14 08:30:53.000000000 +0200 -@@ -285,6 +285,7 @@ - #define FUNCFLAG_PYTHONAPI 0x4 - #define FUNCFLAG_USE_ERRNO 0x8 - #define FUNCFLAG_USE_LASTERROR 0x10 -+#define FUNCFLAG_VARIADIC 0x20 - - #define TYPEFLAG_ISPOINTER 0x100 - #define TYPEFLAG_HASPOINTER 0x200 -diff -ru a/configure b/configure ---- a/configure 2020-03-10 07:11:12.000000000 +0100 -+++ b/configure 2020-07-14 08:03:27.000000000 +0200 -@@ -3374,7 +3374,7 @@ - # has no effect, don't bother defining them - Darwin/[6789].*) - define_xopen_source=no;; -- Darwin/1[0-9].*) -+ Darwin/[12][0-9].*) - define_xopen_source=no;; - # On AIX 4 and 5.1, mbstate_t is defined only when _XOPEN_SOURCE == 500 but - # used in wcsnrtombs() and mbsnrtowcs() even if _XOPEN_SOURCE is not defined -@@ -9251,6 +9251,9 @@ - ppc) - MACOSX_DEFAULT_ARCH="ppc64" - ;; -+ arm64) -+ MACOSX_DEFAULT_ARCH="arm64" -+ ;; - *) - as_fn_error $? "Unexpected output of 'arch' on OSX" "$LINENO" 5 - ;; -diff -ru a/configure.ac b/configure.ac ---- a/configure.ac 2020-03-10 07:11:12.000000000 +0100 -+++ b/configure.ac 2020-07-14 08:03:27.000000000 +0200 -@@ -2456,6 +2456,9 @@ - ppc) - MACOSX_DEFAULT_ARCH="ppc64" - ;; -+ arm64) -+ MACOSX_DEFAULT_ARCH="arm64" -+ ;; - *) - AC_MSG_ERROR([Unexpected output of 'arch' on OSX]) - ;; -diff -ru a/setup.py b/setup.py ---- a/setup.py 2020-03-10 07:11:12.000000000 +0100 -+++ b/setup.py 2020-07-14 08:28:12.000000000 +0200 -@@ -141,6 +141,13 @@ - os.unlink(tmpfile) - - return MACOS_SDK_ROOT -+ -+def is_macosx_at_least(vers): -+ if host_platform == 'darwin': -+ dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') -+ if dep_target: -+ return tuple(map(int, dep_target.split('.'))) >= vers -+ return False - - def is_macosx_sdk_path(path): - """ -@@ -150,6 +157,13 @@ - or path.startswith('/System/') - or path.startswith('/Library/') ) - -+def grep_headers_for(function, headers): -+ for header in headers: -+ with open(header, 'r') as f: -+ if function in f.read(): -+ return True -+ return False -+ - def find_file(filename, std_dirs, paths): - """Searches for the directory where a given file is located, - and returns a possibly-empty list of additional directories, or None -@@ -1972,7 +1986,11 @@ - return True - - def detect_ctypes(self, inc_dirs, lib_dirs): -- self.use_system_libffi = False -+ if not sysconfig.get_config_var("LIBFFI_INCLUDEDIR") and is_macosx_at_least((10,15)): -+ self.use_system_libffi = True -+ else: -+ self.use_system_libffi = '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS") -+ - include_dirs = [] - extra_compile_args = [] - extra_link_args = [] -@@ -2016,32 +2034,48 @@ - ext_test = Extension('_ctypes_test', - sources=['_ctypes/_ctypes_test.c'], - libraries=['m']) -+ ffi_inc = sysconfig.get_config_var("LIBFFI_INCLUDEDIR") -+ ffi_lib = None -+ - self.extensions.extend([ext, ext_test]) - - if host_platform == 'darwin': -- if '--with-system-ffi' not in sysconfig.get_config_var("CONFIG_ARGS"): -+ if not self.use_system_libffi: - return -- # OS X 10.5 comes with libffi.dylib; the include files are -- # in /usr/include/ffi -- inc_dirs.append('/usr/include/ffi') -- -- ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] -- if not ffi_inc or ffi_inc[0] == '': -- ffi_inc = find_file('ffi.h', [], inc_dirs) -- if ffi_inc is not None: -- ffi_h = ffi_inc[0] + '/ffi.h' -+ ffi_in_sdk = os.path.join(macosx_sdk_root(), "usr/include/ffi") -+ if os.path.exists(ffi_in_sdk): -+ ffi_inc = ffi_in_sdk -+ ffi_lib = 'ffi' -+ else: -+ # OS X 10.5 comes with libffi.dylib; the include files are -+ # in /usr/include/ffi -+ ffi_inc_dirs.append('/usr/include/ffi') -+ -+ if not ffi_inc: -+ found = find_file('ffi.h', [], ffi_inc_dirs) -+ if found: -+ ffi_inc = found[0] -+ if ffi_inc: -+ ffi_h = ffi_inc + '/ffi.h' - if not os.path.exists(ffi_h): - ffi_inc = None - print('Header file {} does not exist'.format(ffi_h)) -- ffi_lib = None -- if ffi_inc is not None: -+ if ffi_lib is None and ffi_inc: - for lib_name in ('ffi', 'ffi_pic'): - if (self.compiler.find_library_file(lib_dirs, lib_name)): - ffi_lib = lib_name - break - - if ffi_inc and ffi_lib: -- ext.include_dirs.extend(ffi_inc) -+ ffi_headers = glob(os.path.join(ffi_inc, '*.h')) -+ if grep_headers_for('ffi_closure_alloc', ffi_headers): -+ try: -+ sources.remove('_ctypes/malloc_closure.c') -+ except ValueError: -+ pass -+ if grep_headers_for('ffi_prep_cif_var', ffi_headers): -+ ext.extra_compile_args.append("-DHAVE_FFI_PREP_CIF_VAR=1") -+ ext.include_dirs.append(ffi_inc) - ext.libraries.append(ffi_lib) - self.use_system_libffi = True - diff --git a/build_files/cmake/Modules/FindAudaspace.cmake b/build_files/cmake/Modules/FindAudaspace.cmake index 07ce2ba33d0..d4a68461d32 100644 --- a/build_files/cmake/Modules/FindAudaspace.cmake +++ b/build_files/cmake/Modules/FindAudaspace.cmake @@ -19,7 +19,7 @@ #============================================================================= IF(NOT AUDASPACE_ROOT_DIR AND NOT $ENV{AUDASPACE_ROOT_DIR} STREQUAL "") - SET(AUDASPACE_ROOT_DIR $ENV{AUDASPACE_ROOT_DIR}) + SET(AUDASPACE_ROOT_DIR $ENV{AUDASPACE_ROOT_DIR}) ENDIF() SET(_audaspace_SEARCH_DIRS diff --git a/build_files/cmake/Modules/FindClangTidy.cmake b/build_files/cmake/Modules/FindClangTidy.cmake index 04c5dfda448..4cf416e67d7 100644 --- a/build_files/cmake/Modules/FindClangTidy.cmake +++ b/build_files/cmake/Modules/FindClangTidy.cmake @@ -34,6 +34,8 @@ set(_clang_tidy_SEARCH_DIRS # TODO(sergey): Find more reliable way of finding the latest clang-tidy. find_program(CLANG_TIDY_EXECUTABLE NAMES + clang-tidy-12 + clang-tidy-11 clang-tidy-10 clang-tidy-9 clang-tidy-8 diff --git a/build_files/cmake/Modules/FindEmbree.cmake b/build_files/cmake/Modules/FindEmbree.cmake index 0716f47ca52..af545cee00c 100644 --- a/build_files/cmake/Modules/FindEmbree.cmake +++ b/build_files/cmake/Modules/FindEmbree.cmake @@ -59,14 +59,14 @@ FOREACH(COMPONENT ${_embree_FIND_COMPONENTS}) PATH_SUFFIXES lib64 lib ) - IF (NOT EMBREE_${UPPERCOMPONENT}_LIBRARY) - IF (EMBREE_EMBREE3_LIBRARY) + IF(NOT EMBREE_${UPPERCOMPONENT}_LIBRARY) + IF(EMBREE_EMBREE3_LIBRARY) # If we can't find all the static libraries, try to fall back to the shared library if found. # This allows building with a shared embree library SET(_embree_LIBRARIES ${EMBREE_EMBREE3_LIBRARY}) BREAK() - ENDIF () - ENDIF () + ENDIF() + ENDIF() LIST(APPEND _embree_LIBRARIES "${EMBREE_${UPPERCOMPONENT}_LIBRARY}") ENDFOREACH() diff --git a/build_files/cmake/Modules/FindHaru.cmake b/build_files/cmake/Modules/FindHaru.cmake new file mode 100644 index 00000000000..5774f83b8c5 --- /dev/null +++ b/build_files/cmake/Modules/FindHaru.cmake @@ -0,0 +1,64 @@ +# - Find HARU library +# Find the native Haru includes and library +# This module defines +# HARU_INCLUDE_DIRS, where to find hpdf.h, set when +# HARU_INCLUDE_DIR is found. +# HARU_LIBRARIES, libraries to link against to use Haru. +# HARU_ROOT_DIR, The base directory to search for Haru. +# This can also be an environment variable. +# HARU_FOUND, If false, do not try to use Haru. +# +# also defined, but not for general use are +# HARU_LIBRARY, where to find the Haru library. + +#============================================================================= +# Copyright 2021 Blender Foundation. +# +# Distributed under the OSI-approved BSD 3-Clause License, +# see accompanying file BSD-3-Clause-license.txt for details. +#============================================================================= + +# If HARU_ROOT_DIR was defined in the environment, use it. +if(NOT HARU_ROOT_DIR AND NOT $ENV{HARU_ROOT_DIR} STREQUAL "") + set(HARU_ROOT_DIR $ENV{HARU_ROOT_DIR}) +endif() + +set(_haru_SEARCH_DIRS + ${HARU_ROOT_DIR} + /opt/lib/haru +) + +find_path(HARU_INCLUDE_DIR + NAMES + hpdf.h + HINTS + ${_haru_SEARCH_DIRS} + PATH_SUFFIXES + include/haru +) + +find_library(HARU_LIBRARY + NAMES + hpdfs + HINTS + ${_haru_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib +) + +# Handle the QUIETLY and REQUIRED arguments and set HARU_FOUND to TRUE if +# all listed variables are TRUE. +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Haru DEFAULT_MSG HARU_LIBRARY HARU_INCLUDE_DIR) + +if(HARU_FOUND) + set(HARU_LIBRARIES ${HARU_LIBRARY}) + set(HARU_INCLUDE_DIRS ${HARU_INCLUDE_DIR}) +endif() + +mark_as_advanced( + HARU_INCLUDE_DIR + HARU_LIBRARY +) + +unset(_haru_SEARCH_DIRS) diff --git a/build_files/cmake/Modules/GTest.cmake b/build_files/cmake/Modules/GTest.cmake index d32e49d2145..4faa47452b1 100644 --- a/build_files/cmake/Modules/GTest.cmake +++ b/build_files/cmake/Modules/GTest.cmake @@ -272,7 +272,7 @@ cmake_policy(SET CMP0057 NEW) # if IN_LIST #------------------------------------------------------------------------------ function(gtest_add_tests) - if (ARGC LESS 1) + if(ARGC LESS 1) message(FATAL_ERROR "No arguments supplied to gtest_add_tests()") endif() @@ -298,7 +298,7 @@ function(gtest_add_tests) set(autoAddSources YES) else() # Non-keyword syntax, convert to keyword form - if (ARGC LESS 3) + if(ARGC LESS 3) message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments") endif() set(ARGS_TARGET "${ARGV0}") diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake index 70f48fc33ea..0c78111eaaf 100644 --- a/build_files/cmake/Modules/GTestTesting.cmake +++ b/build_files/cmake/Modules/GTestTesting.cmake @@ -99,7 +99,9 @@ macro(BLENDER_SRC_GTEST_EX) # Don't fail tests on leaks since these often happen in external libraries # that we can't fix. - set_tests_properties(${TARGET_NAME} PROPERTIES ENVIRONMENT LSAN_OPTIONS=exitcode=0) + set_tests_properties(${TARGET_NAME} PROPERTIES + ENVIRONMENT LSAN_OPTIONS=exitcode=0:$ENV{LSAN_OPTIONS} + ) endif() if(WIN32) set_target_properties(${TARGET_NAME} PROPERTIES VS_GLOBAL_VcpkgEnabled "false") diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index aab997ab453..75f78befb60 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -19,6 +19,7 @@ set(WITH_DRACO ON CACHE BOOL "" FORCE) set(WITH_FFTW3 ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) set(WITH_GMP ON CACHE BOOL "" FORCE) +set(WITH_HARU ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index 480548abca7..680734aba6e 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -24,6 +24,7 @@ set(WITH_DRACO OFF CACHE BOOL "" FORCE) set(WITH_FFTW3 OFF CACHE BOOL "" FORCE) set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE) set(WITH_GMP OFF CACHE BOOL "" FORCE) +set(WITH_HARU OFF CACHE BOOL "" FORCE) set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE) set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE) diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index 96101ee7bcc..973d6cdb34e 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -20,6 +20,7 @@ set(WITH_DRACO ON CACHE BOOL "" FORCE) set(WITH_FFTW3 ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) set(WITH_GMP ON CACHE BOOL "" FORCE) +set(WITH_HARU ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index d1f51b99c67..aebcd25e3b6 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -389,7 +389,7 @@ function(blender_add_lib endfunction() function(blender_add_test_suite) - if (ARGC LESS 1) + if(ARGC LESS 1) message(FATAL_ERROR "No arguments supplied to blender_add_test_suite()") endif() @@ -1209,9 +1209,9 @@ function(find_python_package site-packages dist-packages vendor-packages - NO_DEFAULT_PATH - DOC - "Path to python site-packages or dist-packages containing '${package}' module" + NO_DEFAULT_PATH + DOC + "Path to python site-packages or dist-packages containing '${package}' module" ) mark_as_advanced(PYTHON_${_upper_package}_PATH) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 31da5292eaf..8a7792bd886 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -72,7 +72,11 @@ if(WITH_JACK) endif() if(NOT DEFINED LIBDIR) - set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin) + if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "x86_64") + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin) + else() + set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin_${CMAKE_OSX_ARCHITECTURES}) + endif() else() message(STATUS "Using pre-compiled LIBDIR: ${LIBDIR}") endif() @@ -428,6 +432,14 @@ if(WITH_GMP) endif() endif() +if(WITH_HARU) + find_package(Haru) + if(NOT HARU_FOUND) + message(WARNING "Haru not found, disabling WITH_HARU") + set(WITH_HARU OFF) + endif() +endif() + if(EXISTS ${LIBDIR}) without_system_libs_end() endif() diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake index a2448829206..fed70c5b8b2 100644 --- a/build_files/cmake/platform/platform_unix.cmake +++ b/build_files/cmake/platform/platform_unix.cmake @@ -353,7 +353,7 @@ endif() if(WITH_PUGIXML) find_package_wrapper(PugiXML) - if (NOT PUGIXML_FOUND) + if(NOT PUGIXML_FOUND) set(WITH_PUGIXML OFF) message(STATUS "PugiXML not found, disabling WITH_PUGIXML") endif() @@ -470,6 +470,14 @@ if(WITH_POTRACE) endif() endif() +if(WITH_HARU) + find_package_wrapper(Haru) + if(NOT HARU_FOUND) + message(WARNING "Haru not found, disabling WITH_HARU") + set(WITH_HARU OFF) + endif() +endif() + if(EXISTS ${LIBDIR}) without_system_libs_end() endif() diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index 016ae58fde4..69a78ba7ca6 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -800,3 +800,15 @@ if(WITH_POTRACE) set(POTRACE_LIBRARIES ${LIBDIR}/potrace/lib/potrace.lib) set(POTRACE_FOUND On) endif() + +if(WITH_HARU) + if(EXISTS ${LIBDIR}/haru) + set(HARU_FOUND On) + set(HARU_ROOT_DIR ${LIBDIR}/haru) + set(HARU_INCLUDE_DIRS ${HARU_ROOT_DIR}/include) + set(HARU_LIBRARIES ${HARU_ROOT_DIR}/lib/libhpdfs.lib) + else() + message(WARNING "Haru was not found, disabling WITH_HARU") + set(WITH_HARU OFF) + endif() +endif() diff --git a/build_files/utils/make_update.py b/build_files/utils/make_update.py index 53f6b3d447f..2b8c7af98fb 100755 --- a/build_files/utils/make_update.py +++ b/build_files/utils/make_update.py @@ -8,6 +8,7 @@ import argparse import os +import platform import shutil import sys @@ -49,7 +50,12 @@ def svn_update(args, release_version): # Checkout precompiled libraries if sys.platform == 'darwin': - lib_platform = "darwin" + if platform.machine() == 'x86_64': + lib_platform = "darwin" + elif platform.machine() == 'arm64': + lib_platform = "darwin_arm64" + else: + lib_platform = None elif sys.platform == 'win32': # Windows checkout is usually handled by bat scripts since python3 to run # this script is bundled as part of the precompiled libraries. However it diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 772fac56f63..f9055f02bcf 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = Blender # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = "V2.92" +PROJECT_NUMBER = "V2.93" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/manpage/blender.1.py b/doc/manpage/blender.1.py index da83abe8442..150548072d5 100755 --- a/doc/manpage/blender.1.py +++ b/doc/manpage/blender.1.py @@ -52,10 +52,11 @@ outfilename = sys.argv[2] cmd = [blender_bin, "--help"] print(" executing:", " ".join(cmd)) +ASAN_OPTIONS = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") blender_help = subprocess.run( - cmd, env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8") + cmd, env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8") blender_version = subprocess.run( - [blender_bin, "--version"], env={"ASAN_OPTIONS": "exitcode=0"}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip() + [blender_bin, "--version"], env={"ASAN_OPTIONS": ASAN_OPTIONS}, check=True, stdout=subprocess.PIPE).stdout.decode(encoding="utf-8").strip() blender_version, blender_date = (blender_version.split("build") + [None, None])[0:2] blender_version = blender_version.rstrip().partition(" ")[2] # remove 'Blender' prefix. if blender_date is None: diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh index 590de594875..26c3701f3e0 100755 --- a/doc/python_api/sphinx_doc_gen.sh +++ b/doc/python_api/sphinx_doc_gen.sh @@ -55,7 +55,7 @@ if $DO_EXE_BLENDER ; then # Don't delete existing docs, now partial updates are used for quick builds. # # Disable ASAN error halt since it results in nonzero exit code on any minor issue. - ASAN_OPTIONS=halt_on_error=0 \ + ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \ $BLENDER_BIN \ --background \ -noaudio \ diff --git a/extern/mantaflow/CMakeLists.txt b/extern/mantaflow/CMakeLists.txt index 82bf95a9742..c1fa13420b8 100644 --- a/extern/mantaflow/CMakeLists.txt +++ b/extern/mantaflow/CMakeLists.txt @@ -75,6 +75,8 @@ endif() if(WITH_OPENVDB) add_definitions(-DOPENVDB=1) + # OpenVDB headers use deprecated TBB headers, silence warning. + add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) endif() if(WITH_OPENVDB_BLOSC) diff --git a/extern/quadriflow/CMakeLists.txt b/extern/quadriflow/CMakeLists.txt index e24151d8bf6..1ab2322f73b 100644 --- a/extern/quadriflow/CMakeLists.txt +++ b/extern/quadriflow/CMakeLists.txt @@ -102,7 +102,7 @@ set(SRC ) set(LIB - ${BOOST_LIBRARIES} + ${BOOST_LIBRARIES} ) blender_add_lib(extern_quadriflow "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/intern/cycles/app/cycles_cubin_cc.cpp b/intern/cycles/app/cycles_cubin_cc.cpp index 7631cb9bed5..e5d256dd113 100644 --- a/intern/cycles/app/cycles_cubin_cc.cpp +++ b/intern/cycles/app/cycles_cubin_cc.cpp @@ -103,7 +103,7 @@ static bool compile_cuda(CompilationSettings &settings) return false; } - /* Tranfer options to a classic C array. */ + /* Transfer options to a classic C array. */ vector<const char *> opts(options.size()); for (size_t i = 0; i < options.size(); i++) { opts[i] = options[i].c_str(); diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 3ab352e52a2..b1deb5cb64e 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -59,6 +59,7 @@ class CyclesRender(bpy.types.RenderEngine): bl_use_exclude_layers = True bl_use_save_buffers = True bl_use_spherical_stereo = True + bl_use_custom_freestyle = True def __init__(self): self.session = None diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 964241e9904..4fb5c7f57d1 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -67,11 +67,10 @@ static bool ObtainCacheParticleData( Transform tfm = get_transform(b_ob->matrix_world()); Transform itfm = transform_quick_inverse(tfm); - BL::Object::modifiers_iterator b_mod; - for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && - (background ? b_mod->show_render() : b_mod->show_viewport())) { - BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + for (BL::Modifier &b_mod : b_ob->modifiers) { + if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) && + (background ? b_mod.show_render() : b_mod.show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr); BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); @@ -163,11 +162,10 @@ static bool ObtainCacheParticleUV(Hair *hair, CData->curve_uv.clear(); - BL::Object::modifiers_iterator b_mod; - for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && - (background ? b_mod->show_render() : b_mod->show_viewport())) { - BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + for (BL::Modifier &b_mod : b_ob->modifiers) { + if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) && + (background ? b_mod.show_render() : b_mod.show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr); BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); @@ -226,11 +224,10 @@ static bool ObtainCacheParticleVcol(Hair *hair, CData->curve_vcol.clear(); - BL::Object::modifiers_iterator b_mod; - for (b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) { - if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && - (background ? b_mod->show_render() : b_mod->show_viewport())) { - BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + for (BL::Modifier &b_mod : b_ob->modifiers) { + if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) && + (background ? b_mod.show_render() : b_mod.show_viewport())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr); BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); @@ -510,11 +507,10 @@ static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int bool BlenderSync::object_has_particle_hair(BL::Object b_ob) { /* Test if the object has a particle modifier with hair. */ - BL::Object::modifiers_iterator b_mod; - for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { - if ((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && - (preview ? b_mod->show_viewport() : b_mod->show_render())) { - BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr); + for (BL::Modifier &b_mod : b_ob.modifiers) { + if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) && + (preview ? b_mod.show_viewport() : b_mod.show_render())) { + BL::ParticleSystemModifier psmd((const PointerRNA)b_mod.ptr); BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr); BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr); @@ -678,9 +674,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair) /* Export curves and points. */ vector<float> points_length; - BL::Hair::curves_iterator b_curve_iter; - for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) { - BL::HairCurve b_curve = *b_curve_iter; + for (BL::HairCurve &b_curve : b_hair.curves) { const int first_point_index = b_curve.first_point_index(); const int num_points = b_curve.num_points(); @@ -748,9 +742,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st int num_motion_keys = 0; int curve_index = 0; - BL::Hair::curves_iterator b_curve_iter; - for (b_hair.curves.begin(b_curve_iter); b_curve_iter != b_hair.curves.end(); ++b_curve_iter) { - BL::HairCurve b_curve = *b_curve_iter; + for (BL::HairCurve &b_curve : b_hair.curves) { const int first_point_index = b_curve.first_point_index(); const int num_points = b_curve.num_points(); @@ -855,10 +847,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha hair->set_value(socket, new_hair, socket); } - hair->attributes.clear(); - foreach (Attribute &attr, new_hair.attributes.attributes) { - hair->attributes.attributes.push_back(std::move(attr)); - } + hair->attributes.update(std::move(new_hair.attributes)); /* tag update */ diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp index 3ec77719bea..d51b31de638 100644 --- a/intern/cycles/blender/blender_device.cpp +++ b/intern/cycles/blender/blender_device.cpp @@ -47,11 +47,9 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen /* Find cycles preferences. */ PointerRNA cpreferences; - BL::Preferences::addons_iterator b_addon_iter; - for (b_preferences.addons.begin(b_addon_iter); b_addon_iter != b_preferences.addons.end(); - ++b_addon_iter) { - if (b_addon_iter->module() == "cycles") { - cpreferences = b_addon_iter->preferences().ptr; + for (BL::Addon &b_addon : b_preferences.addons) { + if (b_addon.module() == "cycles") { + cpreferences = b_addon.preferences().ptr; break; } } diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp index bd2f0731030..a009018f357 100644 --- a/intern/cycles/blender/blender_geometry.cpp +++ b/intern/cycles/blender/blender_geometry.cpp @@ -42,32 +42,20 @@ static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_ha return Geometry::MESH; } -Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, - BL::Object &b_ob_instance, - bool object_updated, - bool use_particle_hair, - TaskPool *task_pool) +array<Node *> BlenderSync::find_used_shaders(BL::Object &b_ob) { - /* Test if we can instance or if the object is modified. */ - BL::ID b_ob_data = b_ob.data(); - BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; BL::Material material_override = view_layer.material_override; Shader *default_shader = (b_ob.type() == BL::Object::type_VOLUME) ? scene->default_volume : scene->default_surface; - Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair); - GeometryKey key(b_key_id.ptr.data, geom_type); - /* Find shader indices. */ array<Node *> used_shaders; - BL::Object::material_slots_iterator slot; - for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) { + for (BL::MaterialSlot &b_slot : b_ob.material_slots) { if (material_override) { find_shader(material_override, used_shaders, default_shader); } else { - BL::ID b_material(slot->material()); + BL::ID b_material(b_slot.material()); find_shader(b_material, used_shaders, default_shader); } } @@ -79,6 +67,25 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, used_shaders.push_back_slow(default_shader); } + return used_shaders; +} + +Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, + BL::Object &b_ob, + BL::Object &b_ob_instance, + bool object_updated, + bool use_particle_hair, + TaskPool *task_pool) +{ + /* Test if we can instance or if the object is modified. */ + BL::ID b_ob_data = b_ob.data(); + BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; + Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair); + GeometryKey key(b_key_id.ptr.data, geom_type); + + /* Find shader indices. */ + array<Node *> used_shaders = find_used_shaders(b_ob); + /* Ensure we only sync instanced geometry once. */ Geometry *geom = geometry_map.find(key); if (geom) { @@ -124,7 +131,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, foreach (Node *node, geom->get_used_shaders()) { Shader *shader = static_cast<Shader *>(node); - if (shader->need_update_geometry) { + if (shader->need_update_geometry()) { attribute_recalc = true; } } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 3420025f472..7edf797e096 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -285,12 +285,10 @@ static void attr_create_sculpt_vertex_color(Scene *scene, BL::Mesh &b_mesh, bool subdivision) { - BL::Mesh::sculpt_vertex_colors_iterator l; - - for (b_mesh.sculpt_vertex_colors.begin(l); l != b_mesh.sculpt_vertex_colors.end(); ++l) { - const bool active_render = l->active_render(); + for (BL::MeshVertColorLayer &l : b_mesh.sculpt_vertex_colors) { + const bool active_render = l.active_render(); AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE; - ustring vcol_name = ustring(l->name().c_str()); + ustring vcol_name = ustring(l.name().c_str()); const bool need_vcol = mesh->need_attribute(scene, vcol_name) || mesh->need_attribute(scene, vcol_std); @@ -307,7 +305,7 @@ static void attr_create_sculpt_vertex_color(Scene *scene, int numverts = b_mesh.vertices.length(); for (int i = 0; i < numverts; i++) { - *(cdata++) = get_float4(l->data[i].color()); + *(cdata++) = get_float4(l.data[i].color()); } } } @@ -315,12 +313,10 @@ static void attr_create_sculpt_vertex_color(Scene *scene, /* Create vertex color attributes. */ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) { - BL::Mesh::vertex_colors_iterator l; - - for (b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) { - const bool active_render = l->active_render(); + for (BL::MeshLoopColorLayer &l : b_mesh.vertex_colors) { + const bool active_render = l.active_render(); AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE; - ustring vcol_name = ustring(l->name().c_str()); + ustring vcol_name = ustring(l.name().c_str()); const bool need_vcol = mesh->need_attribute(scene, vcol_name) || mesh->need_attribute(scene, vcol_std); @@ -339,13 +335,12 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, vcol_attr = mesh->subd_attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); } - BL::Mesh::polygons_iterator p; uchar4 *cdata = vcol_attr->data_uchar4(); - for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); + for (BL::MeshPolygon &p : b_mesh.polygons) { + int n = p.loop_total(); for (int i = 0; i < n; i++) { - float4 color = get_float4(l->data[p->loop_start() + i].color()); + float4 color = get_float4(l.data[p.loop_start() + i].color()); /* Compress/encode vertex color using the sRGB curve. */ *(cdata++) = color_float4_to_uchar4(color); } @@ -359,14 +354,13 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, vcol_attr = mesh->attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); } - BL::Mesh::loop_triangles_iterator t; uchar4 *cdata = vcol_attr->data_uchar4(); - for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - int3 li = get_int3(t->loops()); - float4 c1 = get_float4(l->data[li[0]].color()); - float4 c2 = get_float4(l->data[li[1]].color()); - float4 c3 = get_float4(l->data[li[2]].color()); + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + int3 li = get_int3(t.loops()); + float4 c1 = get_float4(l.data[li[0]].color()); + float4 c2 = get_float4(l.data[li[1]].color()); + float4 c3 = get_float4(l.data[li[2]].color()); /* Compress/encode vertex color using the sRGB curve. */ cdata[0] = color_float4_to_uchar4(c1); @@ -383,14 +377,12 @@ static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) { if (b_mesh.uv_layers.length() != 0) { - BL::Mesh::uv_layers_iterator l; - - for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l) { - const bool active_render = l->active_render(); + for (BL::MeshUVLoopLayer &l : b_mesh.uv_layers) { + const bool active_render = l.active_render(); AttributeStandard uv_std = (active_render) ? ATTR_STD_UV : ATTR_STD_NONE; - ustring uv_name = ustring(l->name().c_str()); + ustring uv_name = ustring(l.name().c_str()); AttributeStandard tangent_std = (active_render) ? ATTR_STD_UV_TANGENT : ATTR_STD_NONE; - ustring tangent_name = ustring((string(l->name().c_str()) + ".tangent").c_str()); + ustring tangent_name = ustring((string(l.name().c_str()) + ".tangent").c_str()); /* Denotes whether UV map was requested directly. */ const bool need_uv = mesh->need_attribute(scene, uv_name) || @@ -412,14 +404,13 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) uv_attr = mesh->attributes.add(uv_name, TypeFloat2, ATTR_ELEMENT_CORNER); } - BL::Mesh::loop_triangles_iterator t; float2 *fdata = uv_attr->data_float2(); - for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - int3 li = get_int3(t->loops()); - fdata[0] = get_float2(l->data[li[0]].uv()); - fdata[1] = get_float2(l->data[li[1]].uv()); - fdata[2] = get_float2(l->data[li[2]].uv()); + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + int3 li = get_int3(t.loops()); + fdata[0] = get_float2(l.data[li[0]].uv()); + fdata[1] = get_float2(l.data[li[1]].uv()); + fdata[2] = get_float2(l.data[li[2]].uv()); fdata += 3; } } @@ -427,10 +418,10 @@ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) /* UV tangent */ if (need_tangent) { AttributeStandard sign_std = (active_render) ? ATTR_STD_UV_TANGENT_SIGN : ATTR_STD_NONE; - ustring sign_name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str()); + ustring sign_name = ustring((string(l.name().c_str()) + ".tangent_sign").c_str()); bool need_sign = (mesh->need_attribute(scene, sign_name) || mesh->need_attribute(scene, sign_std)); - mikk_compute_tangents(b_mesh, l->name().c_str(), mesh, need_sign, active_render); + mikk_compute_tangents(b_mesh, l.name().c_str(), mesh, need_sign, active_render); } /* Remove temporarily created UV attribute. */ if (!need_uv && uv_attr != NULL) { @@ -480,13 +471,12 @@ static void attr_create_subd_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, uv_attr->flags |= ATTR_SUBDIVIDED; } - BL::Mesh::polygons_iterator p; float2 *fdata = uv_attr->data_float2(); - for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); + for (BL::MeshPolygon &p : b_mesh.polygons) { + int n = p.loop_total(); for (int j = 0; j < n; j++) { - *(fdata++) = get_float2(l->data[p->loop_start() + j].uv()); + *(fdata++) = get_float2(l->data[p.loop_start() + j].uv()); } } } @@ -706,9 +696,8 @@ static void attr_create_random_per_island(Scene *scene, DisjointSet vertices_sets(number_of_vertices); - BL::Mesh::edges_iterator e; - for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { - vertices_sets.join(e->vertices()[0], e->vertices()[1]); + for (BL::MeshEdge &e : b_mesh.edges) { + vertices_sets.join(e.vertices()[0], e.vertices()[1]); } AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes; @@ -716,15 +705,13 @@ static void attr_create_random_per_island(Scene *scene, float *data = attribute->data_float(); if (!subdivision) { - BL::Mesh::loop_triangles_iterator t; - for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - data[t->index()] = hash_uint_to_float(vertices_sets.find(t->vertices()[0])); + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + data[t.index()] = hash_uint_to_float(vertices_sets.find(t.vertices()[0])); } } else { - BL::Mesh::polygons_iterator p; - for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - data[p->index()] = hash_uint_to_float(vertices_sets.find(p->vertices()[0])); + for (BL::MeshPolygon &p : b_mesh.polygons) { + data[p.index()] = hash_uint_to_float(vertices_sets.find(p.vertices()[0])); } } } @@ -756,10 +743,9 @@ static void create_mesh(Scene *scene, numtris = numfaces; } else { - BL::Mesh::polygons_iterator p; - for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - numngons += (p->loop_total() == 4) ? 0 : 1; - numcorners += p->loop_total(); + for (BL::MeshPolygon &p : b_mesh.polygons) { + numngons += (p.loop_total() == 4) ? 0 : 1; + numcorners += p.loop_total(); } } @@ -803,17 +789,15 @@ static void create_mesh(Scene *scene, /* create faces */ if (!subdivision) { - BL::Mesh::loop_triangles_iterator t; - - for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) { - BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()]; - int3 vi = get_int3(t->vertices()); + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + BL::MeshPolygon p = b_mesh.polygons[t.polygon_index()]; + int3 vi = get_int3(t.vertices()); int shader = clamp(p.material_index(), 0, used_shaders.size() - 1); bool smooth = p.use_smooth() || use_loop_normals; if (use_loop_normals) { - BL::Array<float, 9> loop_normals = t->split_normals(); + BL::Array<float, 9> loop_normals = t.split_normals(); for (int i = 0; i < 3; i++) { N[vi[i]] = make_float3( loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]); @@ -828,18 +812,17 @@ static void create_mesh(Scene *scene, } } else { - BL::Mesh::polygons_iterator p; vector<int> vi; - for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) { - int n = p->loop_total(); - int shader = clamp(p->material_index(), 0, used_shaders.size() - 1); - bool smooth = p->use_smooth() || use_loop_normals; + for (BL::MeshPolygon &p : b_mesh.polygons) { + int n = p.loop_total(); + int shader = clamp(p.material_index(), 0, used_shaders.size() - 1); + bool smooth = p.use_smooth() || use_loop_normals; vi.resize(n); for (int i = 0; i < n; i++) { /* NOTE: Autosmooth is already taken care about. */ - vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index(); + vi[i] = b_mesh.loops[p.loop_start() + i].vertex_index(); } /* create subd faces */ @@ -891,19 +874,18 @@ static void create_subd_mesh(Scene *scene, /* export creases */ size_t num_creases = 0; - BL::Mesh::edges_iterator e; - for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { - if (e->crease() != 0.0f) { + for (BL::MeshEdge &e : b_mesh.edges) { + if (e.crease() != 0.0f) { num_creases++; } } mesh->reserve_subd_creases(num_creases); - for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e) { - if (e->crease() != 0.0f) { - mesh->add_crease(e->vertices()[0], e->vertices()[1], e->crease()); + for (BL::MeshEdge &e : b_mesh.edges) { + if (e.crease() != 0.0f) { + mesh->add_crease(e.vertices()[0], e.vertices()[1], e.crease()); } } @@ -1075,15 +1057,8 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me mesh->set_value(socket, new_mesh, socket); } - mesh->attributes.clear(); - foreach (Attribute &attr, new_mesh.attributes.attributes) { - mesh->attributes.attributes.push_back(std::move(attr)); - } - - mesh->subd_attributes.clear(); - foreach (Attribute &attr, new_mesh.subd_attributes.attributes) { - mesh->subd_attributes.attributes.push_back(std::move(attr)); - } + mesh->attributes.update(std::move(new_mesh.attributes)); + mesh->subd_attributes.update(std::move(new_mesh.subd_attributes)); mesh->set_num_subd_faces(new_mesh.get_num_subd_faces()); diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 5261fbcee07..f0460b129c2 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -51,10 +51,11 @@ bool BlenderSync::BKE_object_is_modified(BL::Object &b_ob) } else { /* object level material links */ - BL::Object::material_slots_iterator slot; - for (b_ob.material_slots.begin(slot); slot != b_ob.material_slots.end(); ++slot) - if (slot->link() == BL::MaterialSlot::link_OBJECT) + for (BL::MaterialSlot &b_slot : b_ob.material_slots) { + if (b_slot.link() == BL::MaterialSlot::link_OBJECT) { return true; + } + } } return false; @@ -243,9 +244,6 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* holdout */ object->set_use_holdout(use_holdout); - if (object->use_holdout_is_modified()) { - scene->object_manager->tag_update(scene); - } object->set_visibility(visibility); diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index ca221b229b4..ae43dae4dc1 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -31,7 +31,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, BL::DepsgraphObjectInstance &b_instance, Object *object) { - /* test if this dupli was generated from a particle sytem */ + /* Test if this dupli was generated from a particle system. */ BL::ParticleSystem b_psys = b_instance.particle_system(); if (!b_psys) return false; @@ -57,7 +57,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, /* no update needed? */ if (!need_update && !object->get_geometry()->is_modified() && - !scene->object_manager->need_update) + !scene->object_manager->need_update()) return true; /* first time used in this sync loop? clear and tag update */ @@ -85,7 +85,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob, object->set_particle_index(psys->particles.size() - 1); if (object->particle_index_is_modified()) - scene->object_manager->tag_update(scene); + scene->object_manager->tag_update(scene, ObjectManager::PARTICLE_MODIFIED); /* return that this object has particle data */ return true; diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 525525e1047..5646bd5b2eb 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -597,22 +597,19 @@ static PyObject *osl_update_node_func(PyObject * /*self*/, PyObject *args) bool removed; do { - BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; - removed = false; - for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { - if (used_sockets.find(b_input->ptr.data) == used_sockets.end()) { - b_node.inputs.remove(b_data, *b_input); + for (BL::NodeSocket &b_input : b_node.inputs) { + if (used_sockets.find(b_input.ptr.data) == used_sockets.end()) { + b_node.inputs.remove(b_data, b_input); removed = true; break; } } - for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { - if (used_sockets.find(b_output->ptr.data) == used_sockets.end()) { - b_node.outputs.remove(b_data, *b_output); + for (BL::NodeSocket &b_output : b_node.outputs) { + if (used_sockets.find(b_output.ptr.data) == used_sockets.end()) { + b_node.outputs.remove(b_data, b_output); removed = true; break; } diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 8566d0e7ed5..ae13310789e 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -358,11 +358,7 @@ void BlenderSession::do_write_update_render_tile(RenderTile &rtile, if (do_read_only) { /* copy each pass */ - BL::RenderLayer::passes_iterator b_iter; - - for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { - BL::RenderPass b_pass(*b_iter); - + for (BL::RenderPass &b_pass : b_rlay.passes) { /* find matching pass type */ PassType pass_type = BlenderSync::get_pass_type(b_pass); int components = b_pass.channels(); @@ -552,7 +548,6 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_) int seed = scene->integrator->get_seed(); seed += hash_uint2(seed, hash_uint2(view_index * 0xdeadbeef, 0)); scene->integrator->set_seed(seed); - scene->integrator->tag_update(scene); } /* Update number of samples per layer. */ @@ -736,10 +731,7 @@ void BlenderSession::do_write_update_render_result(BL::RenderLayer &b_rlay, if (!do_update_only) { /* copy each pass */ - BL::RenderLayer::passes_iterator b_iter; - - for (b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) { - BL::RenderPass b_pass(*b_iter); + for (BL::RenderPass &b_pass : b_rlay.passes) { int components = b_pass.channels(); /* Copy pixels from regular render passes. */ @@ -1116,10 +1108,6 @@ void BlenderSession::update_resumable_tile_manager(int num_samples) scene->integrator->set_start_sample(rounded_range_start_sample); - if (scene->integrator->is_modified()) { - scene->integrator->tag_update(scene); - } - session->tile_manager.range_start_sample = rounded_range_start_sample; session->tile_manager.range_num_samples = rounded_range_num_samples; } diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 68db8a2fb58..d967b81c854 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -136,7 +136,7 @@ class BlenderSession { /* ** Resumable render ** */ - /* Overall number of chunks in which the sample range is to be devided. */ + /* Overall number of chunks in which the sample range is to be divided. */ static int num_resumable_chunks; /* Current resumable chunk index to render. */ diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index ac86cf3345c..02a6638b083 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -148,15 +148,13 @@ BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_r static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name) { - BL::Node::outputs_iterator b_out; - - for (b_node.outputs.begin(b_out); b_out != b_node.outputs.end(); ++b_out) - if (b_out->name() == name) - return *b_out; - + for (BL::NodeSocket &b_out : b_node.outputs) { + if (b_out.name() == name) { + return b_out; + } + } assert(0); - - return *b_out; + return *b_node.outputs.begin(); } static float3 get_node_output_rgba(BL::Node &b_node, const string &name) @@ -723,9 +721,8 @@ static ShaderNode *add_node(Scene *scene, image->set_alpha_type(get_image_alpha_type(b_image)); array<int> tiles; - BL::Image::tiles_iterator b_iter; - for (b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) { - tiles.push_back_slow(b_iter->number()); + for (BL::UDIMTile &b_tile : b_image.tiles) { + tiles.push_back_slow(b_tile.number()); } image->set_tiles(tiles); @@ -885,7 +882,7 @@ static ShaderNode *add_node(Scene *scene, sky->set_sun_intensity(b_sky_node.sun_intensity()); sky->set_sun_elevation(b_sky_node.sun_elevation()); sky->set_sun_rotation(b_sky_node.sun_rotation()); - sky->set_altitude(1000.0f * b_sky_node.altitude()); + sky->set_altitude(b_sky_node.altitude()); sky->set_air_density(b_sky_node.air_density()); sky->set_dust_density(b_sky_node.dust_density()); sky->set_ozone_density(b_sky_node.ozone_density()); @@ -1012,18 +1009,18 @@ static ShaderInput *node_find_input_by_name(ShaderNode *node, string name = b_socket.name(); if (node_use_modified_socket_name(node)) { - BL::Node::inputs_iterator b_input; bool found = false; int counter = 0, total = 0; - for (b_node.inputs.begin(b_input); b_input != b_node.inputs.end(); ++b_input) { - if (b_input->name() == name) { - if (!found) + for (BL::NodeSocket &b_input : b_node.inputs) { + if (b_input.name() == name) { + if (!found) { counter++; + } total++; } - if (b_input->ptr.data == b_socket.ptr.data) + if (b_input.ptr.data == b_socket.ptr.data) found = true; } @@ -1045,19 +1042,20 @@ static ShaderOutput *node_find_output_by_name(ShaderNode *node, string name = b_socket.name(); if (node_use_modified_socket_name(node)) { - BL::Node::outputs_iterator b_output; bool found = false; int counter = 0, total = 0; - for (b_node.outputs.begin(b_output); b_output != b_node.outputs.end(); ++b_output) { - if (b_output->name() == name) { - if (!found) + for (BL::NodeSocket &b_output : b_node.outputs) { + if (b_output.name() == name) { + if (!found) { counter++; + } total++; } - if (b_output->ptr.data == b_socket.ptr.data) + if (b_output.ptr.data == b_socket.ptr.data) { found = true; + } } /* rename if needed */ @@ -1082,25 +1080,19 @@ static void add_nodes(Scene *scene, const ProxyMap &proxy_output_map) { /* add nodes */ - BL::ShaderNodeTree::nodes_iterator b_node; PtrInputMap input_map; PtrOutputMap output_map; - BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; - /* find the node to use for output if there are multiple */ BL::ShaderNode output_node = b_ntree.get_output_node( BL::ShaderNodeOutputMaterial::target_CYCLES); /* add nodes */ - for (b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { - if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) { + for (BL::Node &b_node : b_ntree.nodes) { + if (b_node.mute() || b_node.is_a(&RNA_NodeReroute)) { /* replace muted node with internal links */ - BL::Node::internal_links_iterator b_link; - for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); - ++b_link) { - BL::NodeSocket to_socket(b_link->to_socket()); + for (BL::NodeLink &b_link : b_node.internal_links) { + BL::NodeSocket to_socket(b_link.to_socket()); SocketType::Type to_socket_type = convert_socket_type(to_socket); if (to_socket_type == SocketType::UNDEFINED) { continue; @@ -1108,22 +1100,22 @@ static void add_nodes(Scene *scene, ConvertNode *proxy = graph->create_node<ConvertNode>(to_socket_type, to_socket_type, true); - input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; - output_map[b_link->to_socket().ptr.data] = proxy->outputs[0]; + input_map[b_link.from_socket().ptr.data] = proxy->inputs[0]; + output_map[b_link.to_socket().ptr.data] = proxy->outputs[0]; graph->add(proxy); } } - else if (b_node->is_a(&RNA_ShaderNodeGroup) || b_node->is_a(&RNA_NodeCustomGroup) || - b_node->is_a(&RNA_ShaderNodeCustomGroup)) { + else if (b_node.is_a(&RNA_ShaderNodeGroup) || b_node.is_a(&RNA_NodeCustomGroup) || + b_node.is_a(&RNA_ShaderNodeCustomGroup)) { BL::ShaderNodeTree b_group_ntree(PointerRNA_NULL); - if (b_node->is_a(&RNA_ShaderNodeGroup)) - b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(*b_node)).node_tree()); - else if (b_node->is_a(&RNA_NodeCustomGroup)) - b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(*b_node)).node_tree()); + if (b_node.is_a(&RNA_ShaderNodeGroup)) + b_group_ntree = BL::ShaderNodeTree(((BL::NodeGroup)(b_node)).node_tree()); + else if (b_node.is_a(&RNA_NodeCustomGroup)) + b_group_ntree = BL::ShaderNodeTree(((BL::NodeCustomGroup)(b_node)).node_tree()); else - b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(*b_node)).node_tree()); + b_group_ntree = BL::ShaderNodeTree(((BL::ShaderNodeCustomGroup)(b_node)).node_tree()); ProxyMap group_proxy_input_map, group_proxy_output_map; @@ -1131,8 +1123,8 @@ static void add_nodes(Scene *scene, * Do this even if the node group has no internal tree, * so that links have something to connect to and assert won't fail. */ - for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - SocketType::Type input_type = convert_socket_type(*b_input); + for (BL::NodeSocket &b_input : b_node.inputs) { + SocketType::Type input_type = convert_socket_type(b_input); if (input_type == SocketType::UNDEFINED) { continue; } @@ -1141,14 +1133,14 @@ static void add_nodes(Scene *scene, graph->add(proxy); /* register the proxy node for internal binding */ - group_proxy_input_map[b_input->identifier()] = proxy; + group_proxy_input_map[b_input.identifier()] = proxy; - input_map[b_input->ptr.data] = proxy->inputs[0]; + input_map[b_input.ptr.data] = proxy->inputs[0]; - set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree); + set_default_value(proxy->inputs[0], b_input, b_data, b_ntree); } - for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - SocketType::Type output_type = convert_socket_type(*b_output); + for (BL::NodeSocket &b_output : b_node.outputs) { + SocketType::Type output_type = convert_socket_type(b_output); if (output_type == SocketType::UNDEFINED) { continue; } @@ -1157,9 +1149,9 @@ static void add_nodes(Scene *scene, graph->add(proxy); /* register the proxy node for internal binding */ - group_proxy_output_map[b_output->identifier()] = proxy; + group_proxy_output_map[b_output.identifier()] = proxy; - output_map[b_output->ptr.data] = proxy->outputs[0]; + output_map[b_output.ptr.data] = proxy->outputs[0]; } if (b_group_ntree) { @@ -1174,30 +1166,30 @@ static void add_nodes(Scene *scene, group_proxy_output_map); } } - else if (b_node->is_a(&RNA_NodeGroupInput)) { + else if (b_node.is_a(&RNA_NodeGroupInput)) { /* map each socket to a proxy node */ - for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier()); + for (BL::NodeSocket &b_output : b_node.outputs) { + ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output.identifier()); if (proxy_it != proxy_input_map.end()) { ConvertNode *proxy = proxy_it->second; - output_map[b_output->ptr.data] = proxy->outputs[0]; + output_map[b_output.ptr.data] = proxy->outputs[0]; } } } - else if (b_node->is_a(&RNA_NodeGroupOutput)) { - BL::NodeGroupOutput b_output_node(*b_node); + else if (b_node.is_a(&RNA_NodeGroupOutput)) { + BL::NodeGroupOutput b_output_node(b_node); /* only the active group output is used */ if (b_output_node.is_active_output()) { /* map each socket to a proxy node */ - for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier()); + for (BL::NodeSocket &b_input : b_node.inputs) { + ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input.identifier()); if (proxy_it != proxy_output_map.end()) { ConvertNode *proxy = proxy_it->second; - input_map[b_input->ptr.data] = proxy->inputs[0]; + input_map[b_input.ptr.data] = proxy->inputs[0]; - set_default_value(proxy->inputs[0], *b_input, b_data, b_ntree); + set_default_value(proxy->inputs[0], b_input, b_data, b_ntree); } } } @@ -1205,52 +1197,49 @@ static void add_nodes(Scene *scene, else { ShaderNode *node = NULL; - if (b_node->ptr.data == output_node.ptr.data) { + if (b_node.ptr.data == output_node.ptr.data) { node = graph->output(); } else { - BL::ShaderNode b_shader_node(*b_node); + BL::ShaderNode b_shader_node(b_node); node = add_node( scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree, b_shader_node); } if (node) { /* map node sockets for linking */ - for (b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { - ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input); + for (BL::NodeSocket &b_input : b_node.inputs) { + ShaderInput *input = node_find_input_by_name(node, b_node, b_input); if (!input) { /* XXX should not happen, report error? */ continue; } - input_map[b_input->ptr.data] = input; + input_map[b_input.ptr.data] = input; - set_default_value(input, *b_input, b_data, b_ntree); + set_default_value(input, b_input, b_data, b_ntree); } - for (b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { - ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output); + for (BL::NodeSocket &b_output : b_node.outputs) { + ShaderOutput *output = node_find_output_by_name(node, b_node, b_output); if (!output) { /* XXX should not happen, report error? */ continue; } - output_map[b_output->ptr.data] = output; + output_map[b_output.ptr.data] = output; } } } } /* connect nodes */ - BL::NodeTree::links_iterator b_link; - - for (b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { + for (BL::NodeLink &b_link : b_ntree.links) { /* Ignore invalid links to avoid unwanted cycles created in graph. * Also ignore links with unavailable sockets. */ - if (!(b_link->is_valid() && b_link->from_socket().enabled() && - b_link->to_socket().enabled())) { + if (!(b_link.is_valid() && b_link.from_socket().enabled() && b_link.to_socket().enabled())) { continue; } /* get blender link data */ - BL::NodeSocket b_from_sock = b_link->from_socket(); - BL::NodeSocket b_to_sock = b_link->to_socket(); + BL::NodeSocket b_from_sock = b_link.from_socket(); + BL::NodeSocket b_to_sock = b_link.to_socket(); ShaderOutput *output = 0; ShaderInput *input = 0; @@ -1298,13 +1287,12 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) TaskPool pool; set<Shader *> updated_shaders; - BL::Depsgraph::ids_iterator b_id; - for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) { - if (!b_id->is_a(&RNA_Material)) { + for (BL::ID &b_id : b_depsgraph.ids) { + if (!b_id.is_a(&RNA_Material)) { continue; } - BL::Material b_mat(*b_id); + BL::Material b_mat(b_id); Shader *shader; /* test if we need to sync */ @@ -1497,7 +1485,6 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, shader->set_graph(graph); shader->tag_update(scene); - background->tag_update(scene); } PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); @@ -1517,8 +1504,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, viewport_parameters.custom_viewport_parameters()); background->set_use_ao(background->get_use_ao() && view_layer.use_background_ao); - if (background->is_modified()) - background->tag_update(scene); + background->tag_update(scene); } /* Sync Lights */ @@ -1527,13 +1513,12 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all) { shader_map.set_default(scene->default_light); - BL::Depsgraph::ids_iterator b_id; - for (b_depsgraph.ids.begin(b_id); b_id != b_depsgraph.ids.end(); ++b_id) { - if (!b_id->is_a(&RNA_Light)) { + for (BL::ID &b_id : b_depsgraph.ids) { + if (!b_id.is_a(&RNA_Light)) { continue; } - BL::Light b_light(*b_id); + BL::Light b_light(b_id); Shader *shader; /* test if we need to sync */ diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index e27daa2488d..aea601480bf 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -24,6 +24,7 @@ #include "render/mesh.h" #include "render/nodes.h" #include "render/object.h" +#include "render/procedural.h" #include "render/scene.h" #include "render/shader.h" @@ -131,9 +132,8 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d } /* Iterate over all IDs in this depsgraph. */ - BL::Depsgraph::updates_iterator b_update; - for (b_depsgraph.updates.begin(b_update); b_update != b_depsgraph.updates.end(); ++b_update) { - BL::ID b_id(b_update->id()); + for (BL::DepsgraphUpdate &b_update : b_depsgraph.updates) { + BL::ID b_id(b_update.id()); /* Material */ if (b_id.is_a(&RNA_Material)) { @@ -151,17 +151,17 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d const bool is_geometry = object_is_geometry(b_ob); const bool is_light = !is_geometry && object_is_light(b_ob); - if (b_ob.is_instancer() && b_update->is_updated_shading()) { + if (b_ob.is_instancer() && b_update.is_updated_shading()) { /* Needed for e.g. object color updates on instancer. */ object_map.set_recalc(b_ob); } if (is_geometry || is_light) { - const bool updated_geometry = b_update->is_updated_geometry(); + const bool updated_geometry = b_update.is_updated_geometry(); /* Geometry (mesh, hair, volume). */ if (is_geometry) { - if (b_update->is_updated_transform() || b_update->is_updated_shading()) { + if (b_update.is_updated_transform() || b_update.is_updated_shading()) { object_map.set_recalc(b_ob); } @@ -181,7 +181,7 @@ void BlenderSync::sync_recalc(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d } /* Light */ else if (is_light) { - if (b_update->is_updated_transform() || b_update->is_updated_shading()) { + if (b_update.is_updated_transform() || b_update.is_updated_shading()) { object_map.set_recalc(b_ob); light_map.set_recalc(b_ob); } @@ -302,11 +302,6 @@ void BlenderSync::sync_integrator() integrator->set_sample_clamp_direct(get_float(cscene, "sample_clamp_direct")); integrator->set_sample_clamp_indirect(get_float(cscene, "sample_clamp_indirect")); if (!preview) { - if (integrator->get_motion_blur() != r.use_motion_blur()) { - scene->object_manager->tag_update(scene); - scene->camera->tag_modified(); - } - integrator->set_motion_blur(r.use_motion_blur()); } @@ -375,8 +370,8 @@ void BlenderSync::sync_integrator() integrator->set_ao_bounces(0); } - if (integrator->is_modified()) - integrator->tag_update(scene); + /* UPDATE_NONE as we don't want to tag the integrator as modified, just tag dependent things */ + integrator->tag_update(scene, Integrator::UPDATE_NONE); } /* Film */ @@ -471,16 +466,15 @@ void BlenderSync::sync_images() return; } /* Free buffers used by images which are not needed for render. */ - BL::BlendData::images_iterator b_image; - for (b_data.images.begin(b_image); b_image != b_data.images.end(); ++b_image) { + for (BL::Image &b_image : b_data.images) { /* TODO(sergey): Consider making it an utility function to check * whether image is considered builtin. */ - const bool is_builtin = b_image->packed_file() || - b_image->source() == BL::Image::source_GENERATED || - b_image->source() == BL::Image::source_MOVIE || b_engine.is_preview(); + const bool is_builtin = b_image.packed_file() || + b_image.source() == BL::Image::source_GENERATED || + b_image.source() == BL::Image::source_MOVIE || b_engine.is_preview(); if (is_builtin == false) { - b_image->buffers_free(); + b_image.buffers_free(); } /* TODO(sergey): Free builtin images not used by any shader. */ } @@ -581,10 +575,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, vector<Pass> passes; /* loop over passes */ - BL::RenderLayer::passes_iterator b_pass_iter; - - for (b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) { - BL::RenderPass b_pass(*b_pass_iter); + for (BL::RenderPass &b_pass : b_rlay.passes) { PassType pass_type = get_pass_type(b_pass); if (pass_type == PASS_MOTION && scene->integrator->get_motion_blur()) @@ -729,7 +720,7 @@ vector<Pass> BlenderSync::sync_render_passes(BL::RenderLayer &b_rlay, scene->film->set_pass_alpha_threshold(b_view_layer.pass_alpha_threshold()); scene->film->tag_passes_update(scene, passes); - scene->integrator->tag_update(scene); + scene->integrator->tag_update(scene, Integrator::UPDATE_ALL); return passes; } @@ -752,9 +743,8 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph) /* TODO(sergey): We can actually remove the whole dependency graph, * but that will need some API support first. */ - BL::Depsgraph::objects_iterator b_ob; - for (b_depsgraph.objects.begin(b_ob); b_ob != b_depsgraph.objects.end(); ++b_ob) { - b_ob->cache_release(); + for (BL::Object &b_ob : b_depsgraph.objects) { + b_ob.cache_release(); } } @@ -952,7 +942,7 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine &b_engine, else if (shadingsystem == 1) params.shadingsystem = SHADINGSYSTEM_OSL; - /* color managagement */ + /* Color management. */ params.display_buffer_linear = b_engine.support_display_space_shader(b_scene); if (b_engine.is_preview()) { diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index ccf059d7704..1c43522a57e 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -134,6 +134,7 @@ class BlenderSync { void sync_view(); /* Shader */ + array<Node *> find_used_shaders(BL::Object &b_ob); void sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, bool update_all); void sync_shaders(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d); void sync_nodes(Shader *shader, BL::ShaderNodeTree &b_ntree); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 5185ebae789..43dbb4105df 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -538,11 +538,9 @@ static inline bool object_use_deform_motion(BL::Object &b_parent, BL::Object &b_ static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object &b_ob) { - BL::Object::modifiers_iterator b_mod; - - for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { - if (b_mod->is_a(&RNA_FluidModifier)) { - BL::FluidModifier b_mmd(*b_mod); + for (BL::Modifier &b_mod : b_ob.modifiers) { + if (b_mod.is_a(&RNA_FluidModifier)) { + BL::FluidModifier b_mmd(b_mod); if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN && b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_LIQUID) { @@ -556,11 +554,9 @@ static inline BL::FluidDomainSettings object_fluid_liquid_domain_find(BL::Object static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob) { - BL::Object::modifiers_iterator b_mod; - - for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { - if (b_mod->is_a(&RNA_FluidModifier)) { - BL::FluidModifier b_mmd(*b_mod); + for (BL::Modifier &b_mod : b_ob.modifiers) { + if (b_mod.is_a(&RNA_FluidModifier)) { + BL::FluidModifier b_mmd(b_mod); if (b_mmd.fluid_type() == BL::FluidModifier::fluid_type_DOMAIN && b_mmd.domain_settings().domain_type() == BL::FluidDomainSettings::domain_type_GAS) { diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 094d4bbc08c..410f7a72cf5 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -222,9 +222,7 @@ class BlenderVolumeLoader : public VDBImageLoader { b_volume.grids.load(b_data.ptr.data); #ifdef WITH_OPENVDB - BL::Volume::grids_iterator b_grid_iter; - for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { - BL::VolumeGrid b_volume_grid(*b_grid_iter); + for (BL::VolumeGrid &b_volume_grid : b_volume.grids) { if (b_volume_grid.name() == grid_name) { const bool unload = !b_volume_grid.is_loaded(); @@ -260,9 +258,7 @@ static void sync_volume_object(BL::BlendData &b_data, volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT)); /* Find grid with matching name. */ - BL::Volume::grids_iterator b_grid_iter; - for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) { - BL::VolumeGrid b_grid = *b_grid_iter; + for (BL::VolumeGrid &b_grid : b_volume.grids) { ustring name = ustring(b_grid.name()); AttributeStandard std = ATTR_STD_NONE; diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 1727082b7ec..296f9130f43 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -703,7 +703,7 @@ BVHNode *BVHBuild::build_node(const BVHRange &range, unalignedSplitSAH = params.sah_node_cost * unaligned_split.bounds.half_area() + params.sah_primitive_cost * unaligned_split.nodeSAH; /* TOOD(sergey): Check we can create leaf already. */ - /* Check whether unaligned split is better than the regulat one. */ + /* Check whether unaligned split is better than the regular one. */ if (unalignedSplitSAH < splitSAH) { do_unalinged_split = true; } @@ -842,7 +842,7 @@ BVHNode *BVHBuild::create_leaf_node(const BVHRange &range, const vector<BVHRefer vector<BVHReference, LeafReferenceStackAllocator> object_references; uint visibility[PRIMITIVE_NUM_TOTAL] = {0}; - /* NOTE: Keep initializtion in sync with actual number of primitives. */ + /* NOTE: Keep initialization in sync with actual number of primitives. */ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = { BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty}; int ob_num = 0; diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index b29f392a754..04ff598621a 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -383,7 +383,7 @@ if(WITH_CYCLES_OPENSUBDIV) optimized ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU.lib debug ${OPENSUBDIV_ROOT_DIR}/lib/osdCPU_d.lib debug ${OPENSUBDIV_ROOT_DIR}/lib/osdGPU_d.lib - ) + ) endif() endif() endif() diff --git a/intern/cycles/device/cuda/device_cuda_impl.cpp b/intern/cycles/device/cuda/device_cuda_impl.cpp index cff30eb9b48..44a51835f4c 100644 --- a/intern/cycles/device/cuda/device_cuda_impl.cpp +++ b/intern/cycles/device/cuda/device_cuda_impl.cpp @@ -184,7 +184,7 @@ CUDADevice::CUDADevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool functions.loaded = false; - /* Intialize CUDA. */ + /* Initialize CUDA. */ CUresult result = cuInit(0); if (result != CUDA_SUCCESS) { set_error(string_printf("Failed to initialize CUDA runtime (%s)", cuewErrorString(result))); diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 00b2aa864aa..1f63a152458 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -259,6 +259,8 @@ class device_memory { device_ptr original_device_ptr; size_t original_device_size; Device *original_device; + bool need_realloc_; + bool modified; }; /* Device Only Memory @@ -329,6 +331,8 @@ template<typename T> class device_vector : public device_memory { { data_type = device_type_traits<T>::data_type; data_elements = device_type_traits<T>::num_elements; + modified = true; + need_realloc_ = true; assert(data_elements > 0); } @@ -347,6 +351,7 @@ template<typename T> class device_vector : public device_memory { device_free(); host_free(); host_pointer = host_alloc(sizeof(T) * new_size); + modified = true; assert(device_pointer == 0); } @@ -400,6 +405,19 @@ template<typename T> class device_vector : public device_memory { assert(device_pointer == 0); } + void give_data(array<T> &to) + { + device_free(); + + to.set_data((T *)host_pointer, data_size); + data_size = 0; + data_width = 0; + data_height = 0; + data_depth = 0; + host_pointer = 0; + assert(device_pointer == 0); + } + /* Free device and host memory. */ void free() { @@ -411,10 +429,40 @@ template<typename T> class device_vector : public device_memory { data_height = 0; data_depth = 0; host_pointer = 0; + modified = true; + need_realloc_ = true; assert(device_pointer == 0); } - size_t size() + void free_if_need_realloc(bool force_free) + { + if (need_realloc_ || force_free) { + free(); + } + } + + bool is_modified() const + { + return modified; + } + + bool need_realloc() + { + return need_realloc_; + } + + void tag_modified() + { + modified = true; + } + + void tag_realloc() + { + need_realloc_ = true; + tag_modified(); + } + + size_t size() const { return data_size; } @@ -432,7 +480,24 @@ template<typename T> class device_vector : public device_memory { void copy_to_device() { - device_copy_to(); + if (data_size != 0) { + device_copy_to(); + } + } + + void copy_to_device_if_modified() + { + if (!modified) { + return; + } + + copy_to_device(); + } + + void clear_modified() + { + modified = false; + need_realloc_ = false; } void copy_from_device() diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index 44959577fb5..b272e59f99d 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -296,7 +296,7 @@ class MultiDevice : public Device { i++; } - /* Change geomtry BVH pointers back to the multi BVH */ + /* Change geometry BVH pointers back to the multi BVH. */ for (size_t k = 0; k < bvh->geometry.size(); ++k) { bvh->geometry[k]->bvh = geom_bvhs[k]; } diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h index e74c4508ab6..b3a0f6daa57 100644 --- a/intern/cycles/device/device_network.h +++ b/intern/cycles/device/device_network.h @@ -80,7 +80,7 @@ class network_device_memory : public device_memory { vector<char> local_data; }; -/* Common netowrk error function / object for both DeviceNetwork and DeviceServer*/ +/* Common network error function / object for both DeviceNetwork and DeviceServer. */ class NetworkError { public: NetworkError() diff --git a/intern/cycles/device/opencl/device_opencl.h b/intern/cycles/device/opencl/device_opencl.h index 4fd3c27f17e..2d6c6d04214 100644 --- a/intern/cycles/device/opencl/device_opencl.h +++ b/intern/cycles/device/opencl/device_opencl.h @@ -34,7 +34,7 @@ CCL_NAMESPACE_BEGIN /* Disable workarounds, seems to be working fine on latest drivers. */ # define CYCLES_DISABLE_DRIVER_WORKAROUNDS -/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workaounds for testing */ +/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workarounds for testing. */ # ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS /* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */ # undef clEnqueueNDRangeKernel @@ -287,7 +287,7 @@ class OpenCLDevice : public Device { /* Try to load the program from device cache or disk */ bool load(); - /* Compile the kernel (first separate, failback to local) */ + /* Compile the kernel (first separate, fail-back to local). */ void compile(); /* Create the OpenCL kernels after loading or compiling */ void create_kernels(); @@ -628,7 +628,7 @@ class OpenCLDevice : public Device { void release_mem_object_safe(cl_mem mem); void release_program_safe(cl_program program); - /* ** Those guys are for workign around some compiler-specific bugs ** */ + /* ** Those guys are for working around some compiler-specific bugs ** */ cl_program load_cached_kernel(ustring key, thread_scoped_lock &cache_locker); diff --git a/intern/cycles/device/opencl/device_opencl_impl.cpp b/intern/cycles/device/opencl/device_opencl_impl.cpp index ec699462bfe..aee3b0fb64f 100644 --- a/intern/cycles/device/opencl/device_opencl_impl.cpp +++ b/intern/cycles/device/opencl/device_opencl_impl.cpp @@ -2151,7 +2151,7 @@ void OpenCLDevice::release_program_safe(cl_program program) } } -/* ** Those guys are for workign around some compiler-specific bugs ** */ +/* ** Those guys are for working around some compiler-specific bugs ** */ cl_program OpenCLDevice::load_cached_kernel(ustring key, thread_scoped_lock &cache_locker) { diff --git a/intern/cycles/kernel/bvh/bvh_types.h b/intern/cycles/kernel/bvh/bvh_types.h index b173568266b..9f0879a2069 100644 --- a/intern/cycles/kernel/bvh/bvh_types.h +++ b/intern/cycles/kernel/bvh/bvh_types.h @@ -42,7 +42,7 @@ CCL_NAMESPACE_BEGIN #define BVH_FEATURE(f) (((BVH_FUNCTION_FEATURES) & (f)) != 0) -/* Debugging heleprs */ +/* Debugging helpers. */ #ifdef __KERNEL_DEBUG__ # define BVH_DEBUG_INIT() \ do { \ diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index d9e81535b62..32639ba24ec 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -125,7 +125,7 @@ ccl_device_inline void microfacet_beckmann_sample_slopes(KernelGlobals *kg, } *slope_y = fast_ierff(2.0f * randv - 1.0f); #else - /* Use precomputed table on CPU, it gives better perfomance. */ + /* Use precomputed table on CPU, it gives better performance. */ int beckmann_table_offset = kernel_data.tables.beckmann_offset; *slope_x = lookup_table_read_2D( diff --git a/intern/cycles/kernel/filter/filter_transform_gpu.h b/intern/cycles/kernel/filter/filter_transform_gpu.h index adc85881fe5..ec258a5212a 100644 --- a/intern/cycles/kernel/filter/filter_transform_gpu.h +++ b/intern/cycles/kernel/filter/filter_transform_gpu.h @@ -78,7 +78,7 @@ ccl_device void kernel_filter_construct_transform(const ccl_global float *ccl_re /* === Generate the feature transformation. === * This transformation maps the num_features-dimensional feature space to a reduced feature * (r-feature) space which generally has fewer dimensions. - * This mainly helps to prevent overfitting. */ + * This mainly helps to prevent over-fitting. */ float feature_matrix[DENOISE_FEATURES * DENOISE_FEATURES]; math_matrix_zero(feature_matrix, num_features); FOR_PIXEL_WINDOW @@ -91,7 +91,7 @@ ccl_device void kernel_filter_construct_transform(const ccl_global float *ccl_re math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, transform_stride); *rank = 0; - /* Prevent overfitting when a small window is used. */ + /* Prevent over-fitting when a small window is used. */ int max_rank = min(num_features, num_pixels / 3); if (pca_threshold < 0.0f) { float threshold_energy = 0.0f; diff --git a/intern/cycles/kernel/filter/filter_transform_sse.h b/intern/cycles/kernel/filter/filter_transform_sse.h index 5a124b5d73b..0304d990f9f 100644 --- a/intern/cycles/kernel/filter/filter_transform_sse.h +++ b/intern/cycles/kernel/filter/filter_transform_sse.h @@ -93,7 +93,7 @@ ccl_device void kernel_filter_construct_transform(const float *ccl_restrict buff math_matrix_jacobi_eigendecomposition(feature_matrix, transform, num_features, 1); *rank = 0; - /* Prevent overfitting when a small window is used. */ + /* Prevent over-fitting when a small window is used. */ int max_rank = min(num_features, num_pixels / 3); if (pca_threshold < 0.0f) { float threshold_energy = 0.0f; diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 1907f5d3935..fe73335a335 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -435,7 +435,7 @@ ccl_device_inline float bvh_instance_push( return t; } -/* Transorm ray to exit static object in BVH */ +/* Transform ray to exit static object in BVH. */ ccl_device_inline float bvh_instance_pop( KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, float t) @@ -497,7 +497,7 @@ ccl_device_inline float bvh_instance_motion_push(KernelGlobals *kg, return t; } -/* Transorm ray to exit motion blurred object in BVH */ +/* Transform ray to exit motion blurred object in BVH. */ ccl_device_inline float bvh_instance_motion_pop(KernelGlobals *kg, int object, diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index e876e5d8ca6..ddcf94be1de 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -251,7 +251,7 @@ ccl_device void kernel_bake_evaluate( path_rng_2D(kg, rng_hash, sample, num_samples, PRNG_FILTER_U, &filter_x, &filter_y); } - /* Barycentric UV with subpixel offset. */ + /* Barycentric UV with sub-pixel offset. */ float u = primitive[2]; float v = primitive[3]; diff --git a/intern/cycles/kernel/kernel_film.h b/intern/cycles/kernel/kernel_film.h index 17b69b6198b..a6fd4f1dc7e 100644 --- a/intern/cycles/kernel/kernel_film.h +++ b/intern/cycles/kernel/kernel_film.h @@ -63,12 +63,12 @@ ccl_device float4 film_map(KernelGlobals *kg, float4 rgba_in, float scale) { float4 result; - /* conversion to srgb */ + /* Conversion to SRGB. */ result.x = color_linear_to_srgb(rgba_in.x * scale); result.y = color_linear_to_srgb(rgba_in.y * scale); result.z = color_linear_to_srgb(rgba_in.z * scale); - /* clamp since alpha might be > 1.0 due to russian roulette */ + /* Clamp since alpha might be > 1.0 due to Russian roulette. */ result.w = saturate(rgba_in.w * scale); return result; diff --git a/intern/cycles/kernel/kernel_jitter.h b/intern/cycles/kernel/kernel_jitter.h index b9c48b86a5d..f4e60a807f7 100644 --- a/intern/cycles/kernel/kernel_jitter.h +++ b/intern/cycles/kernel/kernel_jitter.h @@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN /* "Correlated Multi-Jittered Sampling" * Andrew Kensler, Pixar Technical Memo 13-01, 2013 */ -/* todo: find good value, suggested 64 gives pattern on cornell box ceiling */ +/* TODO: find good value, suggested 64 gives pattern on cornell box ceiling. */ #define CMJ_RANDOM_OFFSET_LIMIT 4096 ccl_device_inline bool cmj_is_pow2(int i) @@ -179,7 +179,7 @@ ccl_device void cmj_sample_2D(int s, int N, int p, float *fx, float *fy) smodm = cmj_fast_mod_pow2(s, m); } else { - /* Doing s*inmv gives precision issues here. */ + /* Doing `s * inmv` gives precision issues here. */ sdivm = s / m; smodm = s - sdivm * m; } diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index b9569f531e6..9ce7a147369 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -155,7 +155,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, else # endif /* __VOLUME_DECOUPLED__ */ { - /* GPU: no decoupled ray marching, scatter probalistically */ + /* GPU: no decoupled ray marching, scatter probabilistically. */ int num_samples = kernel_data.integrator.volume_samples; float num_samples_inv = 1.0f / num_samples; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index a9b17854f25..49e5e25c2e0 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -304,7 +304,7 @@ ccl_device_inline bool sample_is_even(int pattern, int sample) #elif defined(__KERNEL_OPENCL__) return popcount(sample & 0xaaaaaaaa) & 1; #else - /* TODO(Stefan): popcnt intrinsic for Windows with fallback for older CPUs. */ + /* TODO(Stefan): pop-count intrinsic for Windows with fallback for older CPUs. */ int i = sample & 0xaaaaaaaa; i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f0e65542693..82cc11922e0 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1641,7 +1641,7 @@ enum RayState { RAY_UPDATE_BUFFER, /* Denotes ray needs to skip most surface shader work. */ RAY_HAS_ONLY_VOLUME, - /* Donotes ray has hit background */ + /* Denotes ray has hit background */ RAY_HIT_BACKGROUND, /* Denotes ray has to be regenerated */ RAY_TO_REGENERATE, @@ -1699,7 +1699,7 @@ typedef struct WorkTile { ccl_global float *buffer; } WorkTile; -/* Precoumputed sample table sizes for PMJ02 sampler. */ +/* Pre-computed sample table sizes for PMJ02 sampler. */ #define NUM_PMJ_SAMPLES 64 * 64 #define NUM_PMJ_PATTERNS 48 diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h index d87e5f193ad..bb6b8a40e8e 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h +++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h @@ -18,7 +18,7 @@ /* Data type to replace `double` used in the NanoVDB headers. Cycles don't need doubles, and is * safer and more portable to never use double datatype on GPU. * Use a special structure, so that the following is true: - * - No unnoticed implicit cast or mathermatical operations used on scalar 64bit type + * - No unnoticed implicit cast or mathematical operations used on scalar 64bit type * (which rules out trick like using `uint64_t` as a drop-in replacement for double). * - Padding rules are matching exactly `double` * (which rules out array of `uint8_t`). */ diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index caca3c28c8d..f1789f0d7eb 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -43,7 +43,7 @@ class ColorSpaceProcessor; * * Data needed by OSL render services, that is global to a rendering session. * This includes all OSL shaders, name to attribute mapping and texture handles. - * */ + */ struct OSLGlobals { OSLGlobals() diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index 2a4a1dfe325..2b7c21d0bc4 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -1033,7 +1033,7 @@ bool OSLRenderServices::get_background_attribute( return set_attribute_int(f, type, derivatives, val); } else if (name == u_ndc) { - /* NDC coordinates with special exception for otho */ + /* NDC coordinates with special exception for orthographic projection. */ OSLThreadData *tdata = kg->osl_tdata; OSL::ShaderGlobals *globals = &tdata->globals; float3 ndc[3]; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 3d0813c15e3..8606c459375 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -129,7 +129,7 @@ static void shaderdata_to_shaderglobals( /* clear trace data */ tdata->tracedata.init = false; - /* used by renderservices */ + /* Used by render-services. */ sd->osl_globals = kg; sd->osl_path_state = state; } diff --git a/intern/cycles/kernel/shaders/node_image_texture.osl b/intern/cycles/kernel/shaders/node_image_texture.osl index 22d34a1082c..9e2ef84c872 100644 --- a/intern/cycles/kernel/shaders/node_image_texture.osl +++ b/intern/cycles/kernel/shaders/node_image_texture.osl @@ -42,7 +42,7 @@ point map_to_sphere(vector dir) float v, u; if (len > 0.0) { if (dir[0] == 0.0 && dir[1] == 0.0) { - u = 0.0; /* Othwise domain error. */ + u = 0.0; /* Otherwise domain error. */ } else { u = (1.0 - atan2(dir[0], dir[1]) / M_PI) / 2.0; diff --git a/intern/cycles/kernel/split/kernel_branched.h b/intern/cycles/kernel/split/kernel_branched.h index bfcd21baac4..45f5037d321 100644 --- a/intern/cycles/kernel/split/kernel_branched.h +++ b/intern/cycles/kernel/split/kernel_branched.h @@ -41,7 +41,7 @@ ccl_device_inline void kernel_split_branched_path_indirect_loop_init(KernelGloba # undef BRANCHED_STORE - /* set loop counters to intial position */ + /* Set loop counters to initial position. */ branched_state->next_closure = 0; branched_state->next_sample = 0; } diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h index b24699ec39c..1775e870f07 100644 --- a/intern/cycles/kernel/split/kernel_do_volume.h +++ b/intern/cycles/kernel/split/kernel_do_volume.h @@ -35,7 +35,7 @@ ccl_device_noinline bool kernel_split_branched_path_volume_indirect_light_iter(K PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; ShaderData *emission_sd = AS_SHADER_DATA(&kernel_split_state.sd_DL_shadow[ray_index]); - /* GPU: no decoupled ray marching, scatter probalistically */ + /* GPU: no decoupled ray marching, scatter probabilistically. */ int num_samples = kernel_data.integrator.volume_samples; float num_samples_inv = 1.0f / num_samples; diff --git a/intern/cycles/kernel/split/kernel_enqueue_inactive.h b/intern/cycles/kernel/split/kernel_enqueue_inactive.h index 31d2daef616..745313f89f1 100644 --- a/intern/cycles/kernel/split/kernel_enqueue_inactive.h +++ b/intern/cycles/kernel/split/kernel_enqueue_inactive.h @@ -20,7 +20,7 @@ ccl_device void kernel_enqueue_inactive(KernelGlobals *kg, ccl_local_param unsigned int *local_queue_atomics) { #ifdef __BRANCHED_PATH__ - /* Enqeueue RAY_INACTIVE rays into QUEUE_INACTIVE_RAYS queue. */ + /* Enqueue RAY_INACTIVE rays into QUEUE_INACTIVE_RAYS queue. */ if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { *local_queue_atomics = 0; } diff --git a/intern/cycles/kernel/split/kernel_shader_setup.h b/intern/cycles/kernel/split/kernel_shader_setup.h index 900cbcb869c..551836d1653 100644 --- a/intern/cycles/kernel/split/kernel_shader_setup.h +++ b/intern/cycles/kernel/split/kernel_shader_setup.h @@ -25,7 +25,7 @@ CCL_NAMESPACE_BEGIN ccl_device void kernel_shader_setup(KernelGlobals *kg, ccl_local_param unsigned int *local_queue_atomics) { - /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */ + /* Enqueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */ if (ccl_local_id(0) == 0 && ccl_local_id(1) == 0) { *local_queue_atomics = 0; } diff --git a/intern/cycles/kernel/svm/svm_hsv.h b/intern/cycles/kernel/svm/svm_hsv.h index 1f7bd421869..c299cf58c7f 100644 --- a/intern/cycles/kernel/svm/svm_hsv.h +++ b/intern/cycles/kernel/svm/svm_hsv.h @@ -37,7 +37,7 @@ ccl_device void svm_node_hsv( color = rgb_to_hsv(color); - /* remember: fmod doesn't work for negative numbers here */ + /* Remember: `fmodf` doesn't work for negative numbers here. */ color.x = fmodf(color.x + hue + 0.5f, 1.0f); color.y = saturate(color.y * sat); color.z *= val; @@ -48,7 +48,7 @@ ccl_device void svm_node_hsv( color.y = fac * color.y + (1.0f - fac) * in_color.y; color.z = fac * color.z + (1.0f - fac) * in_color.z; - /* Clamp color to prevent negative values caused by oversaturation. */ + /* Clamp color to prevent negative values caused by over saturation. */ color.x = max(color.x, 0.0f); color.y = max(color.y, 0.0f); color.z = max(color.z, 0.0f); diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h index f57c85fc23e..742addab611 100644 --- a/intern/cycles/kernel/svm/svm_image.h +++ b/intern/cycles/kernel/svm/svm_image.h @@ -38,7 +38,7 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, return r; } -/* Remap coordnate from 0..1 box to -1..-1 */ +/* Remap coordinate from 0..1 box to -1..-1 */ ccl_device_inline float3 texco_remap_square(float3 co) { return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f; diff --git a/intern/cycles/kernel/svm/svm_noise.h b/intern/cycles/kernel/svm/svm_noise.h index 7db8ffcc6e1..7ad61f23cc1 100644 --- a/intern/cycles/kernel/svm/svm_noise.h +++ b/intern/cycles/kernel/svm/svm_noise.h @@ -615,8 +615,8 @@ ccl_device_noinline float perlin_3d(float x, float y, float z) * * Point Offset from v0 * v0 (0, 0, 0, 0) - * v1 (0, 0, 1, 0) The full avx type is computed by inserting the following - * v2 (0, 1, 0, 0) sse types into both the low and high parts of the avx. + * v1 (0, 0, 1, 0) The full AVX type is computed by inserting the following + * v2 (0, 1, 0, 0) sse types into both the low and high parts of the AVX. * v3 (0, 1, 1, 0) * v4 (1, 0, 0, 0) * v5 (1, 0, 1, 0) (0, 1, 0, 1) = shuffle<0, 2, 0, 2>(shuffle<2, 2, 2, 2>(V, V + 1)) diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index c228df14985..4a00afc1d7f 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -205,8 +205,8 @@ typedef enum NodeHairInfo { NODE_INFO_CURVE_IS_STRAND, NODE_INFO_CURVE_INTERCEPT, NODE_INFO_CURVE_THICKNESS, - /*fade for minimum hair width transpency*/ - /*NODE_INFO_CURVE_FADE,*/ + /* Fade for minimum hair width transiency. */ + // NODE_INFO_CURVE_FADE, NODE_INFO_CURVE_TANGENT_NORMAL, NODE_INFO_CURVE_RANDOM, } NodeHairInfo; diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index 9663e25cd93..389f913b145 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC_SYS ) set(SRC + alembic.cpp attribute.cpp background.cpp bake.cpp @@ -48,6 +49,7 @@ set(SRC mesh_displace.cpp mesh_subdivision.cpp nodes.cpp + procedural.cpp object.cpp osl.cpp particles.cpp @@ -64,6 +66,7 @@ set(SRC ) set(SRC_HEADERS + alembic.h attribute.h bake.h background.h @@ -90,6 +93,7 @@ set(SRC_HEADERS object.h osl.h particles.h + procedural.h curves.h scene.h session.h @@ -144,6 +148,16 @@ if(WITH_OPENVDB) ) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) + list(APPEND INC_SYS + ${ALEMBIC_INCLUDE_DIRS} + ) + list(APPEND LIB + ${ALEMBIC_LIBRARIES} + ) +endif() + if(WITH_NANOVDB) list(APPEND INC_SYS ${NANOVDB_INCLUDE_DIRS} diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp new file mode 100644 index 00000000000..5942e512e60 --- /dev/null +++ b/intern/cycles/render/alembic.cpp @@ -0,0 +1,1881 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "render/alembic.h" + +#include "render/camera.h" +#include "render/curves.h" +#include "render/mesh.h" +#include "render/object.h" +#include "render/scene.h" +#include "render/shader.h" + +#include "util/util_foreach.h" +#include "util/util_progress.h" +#include "util/util_transform.h" +#include "util/util_vector.h" + +#ifdef WITH_ALEMBIC + +using namespace Alembic::AbcGeom; + +CCL_NAMESPACE_BEGIN + +/* TODO(@kevindietrich): motion blur support */ + +void CachedData::clear() +{ + attributes.clear(); + curve_first_key.clear(); + curve_keys.clear(); + curve_radius.clear(); + curve_shader.clear(); + num_ngons.clear(); + shader.clear(); + subd_creases_edge.clear(); + subd_creases_weight.clear(); + subd_face_corners.clear(); + subd_num_corners.clear(); + subd_ptex_offset.clear(); + subd_smooth.clear(); + subd_start_corner.clear(); + transforms.clear(); + triangles.clear(); + triangles_loops.clear(); + vertices.clear(); + + for (CachedAttribute &attr : attributes) { + attr.data.clear(); + } + + attributes.clear(); +} + +CachedData::CachedAttribute &CachedData::add_attribute(const ustring &name, + const TimeSampling &time_sampling) +{ + for (auto &attr : attributes) { + if (attr.name == name) { + return attr; + } + } + + CachedAttribute &attr = attributes.emplace_back(); + attr.name = name; + attr.data.set_time_sampling(time_sampling); + return attr; +} + +bool CachedData::is_constant() const +{ +# define CHECK_IF_CONSTANT(data) \ + if (!data.is_constant()) { \ + return false; \ + } + + CHECK_IF_CONSTANT(curve_first_key) + CHECK_IF_CONSTANT(curve_keys) + CHECK_IF_CONSTANT(curve_radius) + CHECK_IF_CONSTANT(curve_shader) + CHECK_IF_CONSTANT(num_ngons) + CHECK_IF_CONSTANT(shader) + CHECK_IF_CONSTANT(subd_creases_edge) + CHECK_IF_CONSTANT(subd_creases_weight) + CHECK_IF_CONSTANT(subd_face_corners) + CHECK_IF_CONSTANT(subd_num_corners) + CHECK_IF_CONSTANT(subd_ptex_offset) + CHECK_IF_CONSTANT(subd_smooth) + CHECK_IF_CONSTANT(subd_start_corner) + CHECK_IF_CONSTANT(transforms) + CHECK_IF_CONSTANT(triangles) + CHECK_IF_CONSTANT(triangles_loops) + CHECK_IF_CONSTANT(vertices) + + for (const CachedAttribute &attr : attributes) { + if (!attr.data.is_constant()) { + return false; + } + } + + return true; + +# undef CHECK_IF_CONSTANT +} + +void CachedData::invalidate_last_loaded_time(bool attributes_only) +{ + if (attributes_only) { + for (CachedAttribute &attr : attributes) { + attr.data.invalidate_last_loaded_time(); + } + + return; + } + + curve_first_key.invalidate_last_loaded_time(); + curve_keys.invalidate_last_loaded_time(); + curve_radius.invalidate_last_loaded_time(); + curve_shader.invalidate_last_loaded_time(); + num_ngons.invalidate_last_loaded_time(); + shader.invalidate_last_loaded_time(); + subd_creases_edge.invalidate_last_loaded_time(); + subd_creases_weight.invalidate_last_loaded_time(); + subd_face_corners.invalidate_last_loaded_time(); + subd_num_corners.invalidate_last_loaded_time(); + subd_ptex_offset.invalidate_last_loaded_time(); + subd_smooth.invalidate_last_loaded_time(); + subd_start_corner.invalidate_last_loaded_time(); + transforms.invalidate_last_loaded_time(); + triangles.invalidate_last_loaded_time(); + triangles_loops.invalidate_last_loaded_time(); + vertices.invalidate_last_loaded_time(); +} + +void CachedData::set_time_sampling(TimeSampling time_sampling) +{ + curve_first_key.set_time_sampling(time_sampling); + curve_keys.set_time_sampling(time_sampling); + curve_radius.set_time_sampling(time_sampling); + curve_shader.set_time_sampling(time_sampling); + num_ngons.set_time_sampling(time_sampling); + shader.set_time_sampling(time_sampling); + subd_creases_edge.set_time_sampling(time_sampling); + subd_creases_weight.set_time_sampling(time_sampling); + subd_face_corners.set_time_sampling(time_sampling); + subd_num_corners.set_time_sampling(time_sampling); + subd_ptex_offset.set_time_sampling(time_sampling); + subd_smooth.set_time_sampling(time_sampling); + subd_start_corner.set_time_sampling(time_sampling); + transforms.set_time_sampling(time_sampling); + triangles.set_time_sampling(time_sampling); + triangles_loops.set_time_sampling(time_sampling); + vertices.set_time_sampling(time_sampling); + + for (CachedAttribute &attr : attributes) { + attr.data.set_time_sampling(time_sampling); + } +} + +/* get the sample times to load data for the given the start and end frame of the procedural */ +static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc, + const TimeSampling &time_sampling, + size_t num_samples) +{ + set<chrono_t> result; + + if (num_samples < 2) { + result.insert(0.0); + return result; + } + + double start_frame = (double)(proc->get_start_frame() / proc->get_frame_rate()); + double end_frame = (double)((proc->get_end_frame() + 1) / proc->get_frame_rate()); + + size_t start_index = time_sampling.getFloorIndex(start_frame, num_samples).first; + size_t end_index = time_sampling.getCeilIndex(end_frame, num_samples).first; + + for (size_t i = start_index; i < end_index; ++i) { + result.insert(time_sampling.getSampleTime(i)); + } + + return result; +} + +static float3 make_float3_from_yup(const V3f &v) +{ + return make_float3(v.x, -v.z, v.y); +} + +static M44d convert_yup_zup(const M44d &mtx, float scale_mult) +{ + V3d scale, shear, rotation, translation; + extractSHRT(mtx, + scale, + shear, + rotation, + translation, + true, + IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY); + + M44d rot_mat, scale_mat, trans_mat; + rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y)); + scale_mat.setScale(V3d(scale.x, scale.z, scale.y)); + trans_mat.setTranslation(V3d(translation.x, -translation.z, translation.y)); + + M44d temp_mat = scale_mat * rot_mat * trans_mat; + + scale_mat.setScale(static_cast<double>(scale_mult)); + + return temp_mat * scale_mat; +} + +static void transform_decompose( + const M44d &mat, V3d &scale, V3d &shear, Quatd &rotation, V3d &translation) +{ + M44d mat_remainder(mat); + + /* extract scale and shear */ + Imath::extractAndRemoveScalingAndShear(mat_remainder, scale, shear); + + /* extract translation */ + translation.x = mat_remainder[3][0]; + translation.y = mat_remainder[3][1]; + translation.z = mat_remainder[3][2]; + + /* extract rotation */ + rotation = extractQuat(mat_remainder); +} + +static M44d transform_compose(const V3d &scale, + const V3d &shear, + const Quatd &rotation, + const V3d &translation) +{ + M44d scale_mat, shear_mat, rot_mat, trans_mat; + + scale_mat.setScale(scale); + shear_mat.setShear(shear); + rot_mat = rotation.toMatrix44(); + trans_mat.setTranslation(translation); + + return scale_mat * shear_mat * rot_mat * trans_mat; +} + +/* get the matrix for the specified time, or return the identity matrix if there is no exact match + */ +static M44d get_matrix_for_time(const MatrixSampleMap &samples, chrono_t time) +{ + MatrixSampleMap::const_iterator iter = samples.find(time); + if (iter != samples.end()) { + return iter->second; + } + + return M44d(); +} + +/* get the matrix for the specified time, or interpolate between samples if there is no exact match + */ +static M44d get_interpolated_matrix_for_time(const MatrixSampleMap &samples, chrono_t time) +{ + if (samples.empty()) { + return M44d(); + } + + /* see if exact match */ + MatrixSampleMap::const_iterator iter = samples.find(time); + if (iter != samples.end()) { + return iter->second; + } + + if (samples.size() == 1) { + return samples.begin()->second; + } + + if (time <= samples.begin()->first) { + return samples.begin()->second; + } + + if (time >= samples.rbegin()->first) { + return samples.rbegin()->second; + } + + /* find previous and next time sample to interpolate */ + chrono_t prev_time = samples.begin()->first; + chrono_t next_time = samples.rbegin()->first; + + for (MatrixSampleMap::const_iterator I = samples.begin(); I != samples.end(); ++I) { + chrono_t current_time = (*I).first; + + if (current_time > prev_time && current_time <= time) { + prev_time = current_time; + } + + if (current_time > next_time && current_time >= time) { + next_time = current_time; + } + } + + const M44d prev_mat = get_matrix_for_time(samples, prev_time); + const M44d next_mat = get_matrix_for_time(samples, next_time); + + V3d prev_scale, next_scale; + V3d prev_shear, next_shear; + V3d prev_translation, next_translation; + Quatd prev_rotation, next_rotation; + + transform_decompose(prev_mat, prev_scale, prev_shear, prev_rotation, prev_translation); + transform_decompose(next_mat, next_scale, next_shear, next_rotation, next_translation); + + chrono_t t = (time - prev_time) / (next_time - prev_time); + + /* ensure rotation around the shortest angle */ + if ((prev_rotation ^ next_rotation) < 0) { + next_rotation = -next_rotation; + } + + return transform_compose(Imath::lerp(prev_scale, next_scale, t), + Imath::lerp(prev_shear, next_shear, t), + Imath::slerp(prev_rotation, next_rotation, t), + Imath::lerp(prev_translation, next_translation, t)); +} + +static void concatenate_xform_samples(const MatrixSampleMap &parent_samples, + const MatrixSampleMap &local_samples, + MatrixSampleMap &output_samples) +{ + set<chrono_t> union_of_samples; + + for (const std::pair<chrono_t, M44d> pair : parent_samples) { + union_of_samples.insert(pair.first); + } + + for (const std::pair<chrono_t, M44d> pair : local_samples) { + union_of_samples.insert(pair.first); + } + + foreach (chrono_t time, union_of_samples) { + M44d parent_matrix = get_interpolated_matrix_for_time(parent_samples, time); + M44d local_matrix = get_interpolated_matrix_for_time(local_samples, time); + + output_samples[time] = local_matrix * parent_matrix; + } +} + +static Transform make_transform(const M44d &a, float scale) +{ + M44d m = convert_yup_zup(a, scale); + Transform trans; + for (int j = 0; j < 3; j++) { + for (int i = 0; i < 4; i++) { + trans[j][i] = static_cast<float>(m[i][j]); + } + } + return trans; +} + +static void add_uvs(AlembicProcedural *proc, + const IV2fGeomParam &uvs, + CachedData &cached_data, + Progress &progress) +{ + if (uvs.getScope() != kFacevaryingScope) { + return; + } + + const TimeSamplingPtr time_sampling_ptr = uvs.getTimeSampling(); + + TimeSampling time_sampling; + if (time_sampling_ptr) { + time_sampling = *time_sampling_ptr; + } + + std::string name = Alembic::Abc::GetSourceName(uvs.getMetaData()); + + /* According to the convention, primary UVs should have had their name + * set using Alembic::Abc::SetSourceName, but you can't expect everyone + * to follow it! :) */ + if (name.empty()) { + name = uvs.getName(); + } + + CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(name), time_sampling); + attr.std = ATTR_STD_UV; + + ccl::set<chrono_t> times = get_relevant_sample_times(proc, time_sampling, uvs.getNumSamples()); + + foreach (chrono_t time, times) { + if (progress.get_cancel()) { + return; + } + + const ISampleSelector iss = ISampleSelector(time); + const IV2fGeomParam::Sample sample = uvs.getExpandedValue(iss); + + const IV2fGeomParam::Sample uvsample = uvs.getIndexedValue(iss); + + if (!uvsample.valid()) { + continue; + } + + const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check(time); + + if (!triangles || !triangles_loops) { + continue; + } + + array<char> data; + data.resize(triangles->size() * 3 * sizeof(float2)); + + float2 *data_float2 = reinterpret_cast<float2 *>(data.data()); + + const unsigned int *indices = uvsample.getIndices()->get(); + const V2f *values = uvsample.getVals()->get(); + + for (const int3 &loop : *triangles_loops) { + unsigned int v0 = indices[loop.x]; + unsigned int v1 = indices[loop.y]; + unsigned int v2 = indices[loop.z]; + + data_float2[0] = make_float2(values[v0][0], values[v0][1]); + data_float2[1] = make_float2(values[v1][0], values[v1][1]); + data_float2[2] = make_float2(values[v2][0], values[v2][1]); + data_float2 += 3; + } + + attr.data.add_data(data, time); + } +} + +static void add_normals(const Int32ArraySamplePtr face_indices, + const IN3fGeomParam &normals, + double time, + CachedData &cached_data) +{ + switch (normals.getScope()) { + case kFacevaryingScope: { + const ISampleSelector iss = ISampleSelector(time); + const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss); + + if (!sample.valid()) { + return; + } + + CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()), + *normals.getTimeSampling()); + attr.std = ATTR_STD_VERTEX_NORMAL; + + const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + + if (!vertices) { + return; + } + + array<char> data; + data.resize(vertices->size() * sizeof(float3)); + + float3 *data_float3 = reinterpret_cast<float3 *>(data.data()); + + const int *face_indices_array = face_indices->get(); + const N3fArraySamplePtr values = sample.getVals(); + + for (size_t i = 0; i < face_indices->size(); ++i) { + int point_index = face_indices_array[i]; + data_float3[point_index] = make_float3_from_yup(values->get()[i]); + } + + attr.data.add_data(data, time); + break; + } + case kVaryingScope: + case kVertexScope: { + const ISampleSelector iss = ISampleSelector(time); + const IN3fGeomParam::Sample sample = normals.getExpandedValue(iss); + + if (!sample.valid()) { + return; + } + + CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(normals.getName()), + *normals.getTimeSampling()); + attr.std = ATTR_STD_VERTEX_NORMAL; + + const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + + if (!vertices) { + return; + } + + array<char> data; + data.resize(vertices->size() * sizeof(float3)); + + float3 *data_float3 = reinterpret_cast<float3 *>(data.data()); + + const Imath::V3f *values = sample.getVals()->get(); + + for (size_t i = 0; i < vertices->size(); ++i) { + data_float3[i] = make_float3_from_yup(values[i]); + } + + attr.data.add_data(data, time); + + break; + } + default: { + break; + } + } +} + +static void add_positions(const P3fArraySamplePtr positions, double time, CachedData &cached_data) +{ + if (!positions) { + return; + } + + array<float3> vertices; + vertices.reserve(positions->size()); + + for (size_t i = 0; i < positions->size(); i++) { + V3f f = positions->get()[i]; + vertices.push_back_reserved(make_float3_from_yup(f)); + } + + cached_data.vertices.add_data(vertices, time); +} + +static void add_triangles(const Int32ArraySamplePtr face_counts, + const Int32ArraySamplePtr face_indices, + double time, + CachedData &cached_data, + const array<int> &polygon_to_shader) +{ + if (!face_counts || !face_indices) { + return; + } + + const size_t num_faces = face_counts->size(); + const int *face_counts_array = face_counts->get(); + const int *face_indices_array = face_indices->get(); + + size_t num_triangles = 0; + for (size_t i = 0; i < face_counts->size(); i++) { + num_triangles += face_counts_array[i] - 2; + } + + array<int> shader; + array<int3> triangles; + array<int3> triangles_loops; + shader.reserve(num_triangles); + triangles.reserve(num_triangles); + triangles_loops.reserve(num_triangles); + int index_offset = 0; + + for (size_t i = 0; i < num_faces; i++) { + int current_shader = 0; + + if (!polygon_to_shader.empty()) { + current_shader = polygon_to_shader[i]; + } + + for (int j = 0; j < face_counts_array[i] - 2; j++) { + int v0 = face_indices_array[index_offset]; + int v1 = face_indices_array[index_offset + j + 1]; + int v2 = face_indices_array[index_offset + j + 2]; + + shader.push_back_reserved(current_shader); + + /* Alembic orders the loops following the RenderMan convention, so need to go in reverse. */ + triangles.push_back_reserved(make_int3(v2, v1, v0)); + triangles_loops.push_back_reserved( + make_int3(index_offset + j + 2, index_offset + j + 1, index_offset)); + } + + index_offset += face_counts_array[i]; + } + + cached_data.triangles.add_data(triangles, time); + cached_data.triangles_loops.add_data(triangles_loops, time); + cached_data.shader.add_data(shader, time); +} + +NODE_DEFINE(AlembicObject) +{ + NodeType *type = NodeType::add("alembic_object", create); + + SOCKET_STRING(path, "Alembic Path", ustring()); + SOCKET_NODE_ARRAY(used_shaders, "Used Shaders", &Shader::node_type); + + SOCKET_INT(subd_max_level, "Max Subdivision Level", 1); + SOCKET_FLOAT(subd_dicing_rate, "Subdivision Dicing Rate", 1.0f); + + SOCKET_FLOAT(radius_scale, "Radius Scale", 1.0f); + + return type; +} + +AlembicObject::AlembicObject() : Node(node_type) +{ +} + +AlembicObject::~AlembicObject() +{ +} + +void AlembicObject::set_object(Object *object_) +{ + object = object_; +} + +Object *AlembicObject::get_object() +{ + return object; +} + +bool AlembicObject::has_data_loaded() const +{ + return data_loaded; +} + +void AlembicObject::update_shader_attributes(const ICompoundProperty &arb_geom_params, + Progress &progress) +{ + AttributeRequestSet requested_attributes = get_requested_attributes(); + + foreach (const AttributeRequest &attr, requested_attributes.requests) { + if (progress.get_cancel()) { + return; + } + + bool attr_exists = false; + foreach (CachedData::CachedAttribute &cached_attr, cached_data.attributes) { + if (cached_attr.name == attr.name) { + attr_exists = true; + break; + } + } + + if (attr_exists) { + continue; + } + + read_attribute(arb_geom_params, attr.name, progress); + } + + cached_data.invalidate_last_loaded_time(true); + need_shader_update = false; +} + +template<typename SchemaType> +void AlembicObject::read_face_sets(SchemaType &schema, + array<int> &polygon_to_shader, + ISampleSelector sample_sel) +{ + std::vector<std::string> face_sets; + schema.getFaceSetNames(face_sets); + + if (face_sets.empty()) { + return; + } + + const Int32ArraySamplePtr face_counts = schema.getFaceCountsProperty().getValue(); + + polygon_to_shader.resize(face_counts->size()); + + foreach (const std::string &face_set_name, face_sets) { + int shader_index = 0; + + foreach (Node *node, get_used_shaders()) { + if (node->name == face_set_name) { + break; + } + + ++shader_index; + } + + if (shader_index >= get_used_shaders().size()) { + /* use the first shader instead if none was found */ + shader_index = 0; + } + + const IFaceSet face_set = schema.getFaceSet(face_set_name); + + if (!face_set.valid()) { + continue; + } + + const IFaceSetSchema face_schem = face_set.getSchema(); + const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel); + const Int32ArraySamplePtr group_faces = face_sample.getFaces(); + const size_t num_group_faces = group_faces->size(); + + for (size_t l = 0; l < num_group_faces; l++) { + size_t pos = (*group_faces)[l]; + + if (pos >= polygon_to_shader.size()) { + continue; + } + + polygon_to_shader[pos] = shader_index; + } + } +} + +void AlembicObject::load_all_data(AlembicProcedural *proc, + IPolyMeshSchema &schema, + float scale, + Progress &progress) +{ + cached_data.clear(); + + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); + cached_data.set_time_sampling(*time_sampling); + + const IN3fGeomParam &normals = schema.getNormalsParam(); + + ccl::set<chrono_t> times = get_relevant_sample_times( + proc, *time_sampling, schema.getNumSamples()); + + /* read topology */ + foreach (chrono_t time, times) { + if (progress.get_cancel()) { + return; + } + + const ISampleSelector iss = ISampleSelector(time); + const IPolyMeshSchema::Sample sample = schema.getValue(iss); + + add_positions(sample.getPositions(), time, cached_data); + + /* Only copy triangles for other frames if the topology is changing over time as well. + * + * TODO(@kevindietrich): even for dynamic simulations, this is a waste of memory and + * processing time if only the positions are changing in a subsequence of frames but we + * cannot optimize in this current system if the attributes are changing over time as well, + * as we need valid data for each time point. This can be solved by using reference counting + * on the ccl::array and simply share the array across frames. */ + if (schema.getTopologyVariance() != kHomogenousTopology || cached_data.triangles.size() == 0) { + /* start by reading the face sets (per face shader), as we directly split polygons to + * triangles + */ + array<int> polygon_to_shader; + read_face_sets(schema, polygon_to_shader, iss); + + add_triangles( + sample.getFaceCounts(), sample.getFaceIndices(), time, cached_data, polygon_to_shader); + } + + if (normals.valid()) { + add_normals(sample.getFaceIndices(), normals, time, cached_data); + } + } + + if (progress.get_cancel()) { + return; + } + + update_shader_attributes(schema.getArbGeomParams(), progress); + + if (progress.get_cancel()) { + return; + } + + const IV2fGeomParam &uvs = schema.getUVsParam(); + + if (uvs.valid()) { + add_uvs(proc, uvs, cached_data, progress); + } + + if (progress.get_cancel()) { + return; + } + + setup_transform_cache(scale); + + data_loaded = true; +} + +void AlembicObject::load_all_data(AlembicProcedural *proc, + ISubDSchema &schema, + float scale, + Progress &progress) +{ + cached_data.clear(); + + AttributeRequestSet requested_attributes = get_requested_attributes(); + + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); + cached_data.set_time_sampling(*time_sampling); + + ccl::set<chrono_t> times = get_relevant_sample_times( + proc, *time_sampling, schema.getNumSamples()); + + /* read topology */ + foreach (chrono_t time, times) { + if (progress.get_cancel()) { + return; + } + + const ISampleSelector iss = ISampleSelector(time); + const ISubDSchema::Sample sample = schema.getValue(iss); + + add_positions(sample.getPositions(), time, cached_data); + + const Int32ArraySamplePtr face_counts = sample.getFaceCounts(); + const Int32ArraySamplePtr face_indices = sample.getFaceIndices(); + + /* start by reading the face sets (per face shader) */ + array<int> polygon_to_shader; + read_face_sets(schema, polygon_to_shader, iss); + + /* read faces */ + array<int> subd_start_corner; + array<int> shader; + array<int> subd_num_corners; + array<bool> subd_smooth; + array<int> subd_ptex_offset; + array<int> subd_face_corners; + + const size_t num_faces = face_counts->size(); + const int *face_counts_array = face_counts->get(); + const int *face_indices_array = face_indices->get(); + + int num_ngons = 0; + int num_corners = 0; + for (size_t i = 0; i < face_counts->size(); i++) { + num_ngons += (face_counts_array[i] == 4 ? 0 : 1); + num_corners += face_counts_array[i]; + } + + subd_start_corner.reserve(num_faces); + subd_num_corners.reserve(num_faces); + subd_smooth.reserve(num_faces); + subd_ptex_offset.reserve(num_faces); + shader.reserve(num_faces); + subd_face_corners.reserve(num_corners); + + int start_corner = 0; + int current_shader = 0; + int ptex_offset = 0; + + for (size_t i = 0; i < face_counts->size(); i++) { + num_corners = face_counts_array[i]; + + if (!polygon_to_shader.empty()) { + current_shader = polygon_to_shader[i]; + } + + subd_start_corner.push_back_reserved(start_corner); + subd_num_corners.push_back_reserved(num_corners); + + for (int j = 0; j < num_corners; ++j) { + subd_face_corners.push_back_reserved(face_indices_array[start_corner + j]); + } + + shader.push_back_reserved(current_shader); + subd_smooth.push_back_reserved(1); + subd_ptex_offset.push_back_reserved(ptex_offset); + + ptex_offset += (num_corners == 4 ? 1 : num_corners); + + start_corner += num_corners; + } + + cached_data.shader.add_data(shader, time); + cached_data.subd_start_corner.add_data(subd_start_corner, time); + cached_data.subd_num_corners.add_data(subd_num_corners, time); + cached_data.subd_smooth.add_data(subd_smooth, time); + cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time); + cached_data.subd_face_corners.add_data(subd_face_corners, time); + cached_data.num_ngons.add_data(num_ngons, time); + + /* read creases */ + Int32ArraySamplePtr creases_length = sample.getCreaseLengths(); + Int32ArraySamplePtr creases_indices = sample.getCreaseIndices(); + FloatArraySamplePtr creases_sharpnesses = sample.getCreaseSharpnesses(); + + if (creases_length && creases_indices && creases_sharpnesses) { + array<int> creases_edge; + array<float> creases_weight; + + creases_edge.reserve(creases_sharpnesses->size() * 2); + creases_weight.reserve(creases_sharpnesses->size()); + + int length_offset = 0; + int weight_offset = 0; + for (size_t c = 0; c < creases_length->size(); ++c) { + const int crease_length = creases_length->get()[c]; + + for (size_t j = 0; j < crease_length - 1; ++j) { + creases_edge.push_back_reserved(creases_indices->get()[length_offset + j]); + creases_edge.push_back_reserved(creases_indices->get()[length_offset + j + 1]); + creases_weight.push_back_reserved(creases_sharpnesses->get()[weight_offset++]); + } + + length_offset += crease_length; + } + + cached_data.subd_creases_edge.add_data(creases_edge, time); + cached_data.subd_creases_weight.add_data(creases_weight, time); + } + } + + /* TODO(@kevindietrich) : attributes, need test files */ + + if (progress.get_cancel()) { + return; + } + + setup_transform_cache(scale); + + data_loaded = true; +} + +void AlembicObject::load_all_data(AlembicProcedural *proc, + const ICurvesSchema &schema, + float scale, + Progress &progress, + float default_radius) +{ + cached_data.clear(); + + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); + cached_data.set_time_sampling(*time_sampling); + + ccl::set<chrono_t> times = get_relevant_sample_times( + proc, *time_sampling, schema.getNumSamples()); + + foreach (chrono_t time, times) { + if (progress.get_cancel()) { + return; + } + + const ISampleSelector iss = ISampleSelector(time); + const ICurvesSchema::Sample sample = schema.getValue(iss); + + const Int32ArraySamplePtr curves_num_vertices = sample.getCurvesNumVertices(); + const P3fArraySamplePtr position = sample.getPositions(); + + const IFloatGeomParam widths_param = schema.getWidthsParam(); + FloatArraySamplePtr radiuses; + + if (widths_param.valid()) { + IFloatGeomParam::Sample wsample = widths_param.getExpandedValue(iss); + radiuses = wsample.getVals(); + } + + const bool do_radius = (radiuses != nullptr) && (radiuses->size() > 1); + float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] : default_radius; + + array<float3> curve_keys; + array<float> curve_radius; + array<int> curve_first_key; + array<int> curve_shader; + + curve_keys.reserve(position->size()); + curve_radius.reserve(position->size()); + curve_first_key.reserve(curves_num_vertices->size()); + curve_shader.reserve(curves_num_vertices->size()); + + int offset = 0; + for (size_t i = 0; i < curves_num_vertices->size(); i++) { + const int num_vertices = curves_num_vertices->get()[i]; + + for (int j = 0; j < num_vertices; j++) { + const V3f &f = position->get()[offset + j]; + curve_keys.push_back_reserved(make_float3_from_yup(f)); + + if (do_radius) { + radius = (*radiuses)[offset + j]; + } + + curve_radius.push_back_reserved(radius * radius_scale); + } + + curve_first_key.push_back_reserved(offset); + curve_shader.push_back_reserved(0); + + offset += num_vertices; + } + + cached_data.curve_keys.add_data(curve_keys, time); + cached_data.curve_radius.add_data(curve_radius, time); + cached_data.curve_first_key.add_data(curve_first_key, time); + cached_data.curve_shader.add_data(curve_shader, time); + } + + // TODO(@kevindietrich): attributes, need example files + + setup_transform_cache(scale); + + data_loaded = true; +} + +void AlembicObject::setup_transform_cache(float scale) +{ + cached_data.transforms.clear(); + cached_data.transforms.invalidate_last_loaded_time(); + + if (xform_samples.size() == 0) { + Transform tfm = transform_scale(make_float3(scale)); + cached_data.transforms.add_data(tfm, 0.0); + } + else { + /* It is possible for a leaf node of the hierarchy to have multiple samples for its transforms + * if a sibling has animated transforms. So check if we indeed have animated transformations. + */ + M44d first_matrix = xform_samples.begin()->first; + bool has_animation = false; + for (const std::pair<chrono_t, M44d> pair : xform_samples) { + if (pair.second != first_matrix) { + has_animation = true; + break; + } + } + + if (!has_animation) { + Transform tfm = make_transform(first_matrix, scale); + cached_data.transforms.add_data(tfm, 0.0); + } + else { + for (const std::pair<chrono_t, M44d> pair : xform_samples) { + Transform tfm = make_transform(pair.second, scale); + cached_data.transforms.add_data(tfm, pair.first); + } + } + } +} + +AttributeRequestSet AlembicObject::get_requested_attributes() +{ + AttributeRequestSet requested_attributes; + + Geometry *geometry = object->get_geometry(); + assert(geometry); + + foreach (Node *node, geometry->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + + foreach (const AttributeRequest &attr, shader->attributes.requests) { + if (attr.name != "") { + requested_attributes.add(attr.name); + } + } + } + + return requested_attributes; +} + +void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, + const ustring &attr_name, + Progress &progress) +{ + const PropertyHeader *prop = arb_geom_params.getPropertyHeader(attr_name.c_str()); + + if (prop == nullptr) { + return; + } + + if (IV2fProperty::matches(prop->getMetaData()) && Alembic::AbcGeom::isUV(*prop)) { + const IV2fGeomParam ¶m = IV2fGeomParam(arb_geom_params, prop->getName()); + + CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name, + *param.getTimeSampling()); + + for (size_t i = 0; i < param.getNumSamples(); ++i) { + if (progress.get_cancel()) { + return; + } + + ISampleSelector iss = ISampleSelector(index_t(i)); + + IV2fGeomParam::Sample sample; + param.getIndexed(sample, iss); + + const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i)); + + if (param.getScope() == kFacevaryingScope) { + V2fArraySamplePtr values = sample.getVals(); + UInt32ArraySamplePtr indices = sample.getIndices(); + + attribute.std = ATTR_STD_NONE; + attribute.element = ATTR_ELEMENT_CORNER; + attribute.type_desc = TypeFloat2; + + const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check( + time); + + if (!triangles || !triangles_loops) { + return; + } + + array<char> data; + data.resize(triangles->size() * 3 * sizeof(float2)); + + float2 *data_float2 = reinterpret_cast<float2 *>(data.data()); + + for (const int3 &loop : *triangles_loops) { + unsigned int v0 = (*indices)[loop.x]; + unsigned int v1 = (*indices)[loop.y]; + unsigned int v2 = (*indices)[loop.z]; + + data_float2[0] = make_float2((*values)[v0][0], (*values)[v0][1]); + data_float2[1] = make_float2((*values)[v1][0], (*values)[v1][1]); + data_float2[2] = make_float2((*values)[v2][0], (*values)[v2][1]); + data_float2 += 3; + } + + attribute.data.set_time_sampling(*param.getTimeSampling()); + attribute.data.add_data(data, time); + } + } + } + else if (IC3fProperty::matches(prop->getMetaData())) { + const IC3fGeomParam ¶m = IC3fGeomParam(arb_geom_params, prop->getName()); + + CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name, + *param.getTimeSampling()); + + for (size_t i = 0; i < param.getNumSamples(); ++i) { + if (progress.get_cancel()) { + return; + } + + ISampleSelector iss = ISampleSelector(index_t(i)); + + IC3fGeomParam::Sample sample; + param.getIndexed(sample, iss); + + const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i)); + + C3fArraySamplePtr values = sample.getVals(); + + attribute.std = ATTR_STD_NONE; + + if (param.getScope() == kVaryingScope) { + attribute.element = ATTR_ELEMENT_CORNER_BYTE; + attribute.type_desc = TypeRGBA; + + const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + + if (!triangles) { + return; + } + + array<char> data; + data.resize(triangles->size() * 3 * sizeof(uchar4)); + + uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data()); + + int offset = 0; + for (const int3 &tri : *triangles) { + Imath::C3f v = (*values)[tri.x]; + data_uchar4[offset + 0] = color_float_to_byte(make_float3(v.x, v.y, v.z)); + + v = (*values)[tri.y]; + data_uchar4[offset + 1] = color_float_to_byte(make_float3(v.x, v.y, v.z)); + + v = (*values)[tri.z]; + data_uchar4[offset + 2] = color_float_to_byte(make_float3(v.x, v.y, v.z)); + + offset += 3; + } + + attribute.data.set_time_sampling(*param.getTimeSampling()); + attribute.data.add_data(data, time); + } + } + } + else if (IC4fProperty::matches(prop->getMetaData())) { + const IC4fGeomParam ¶m = IC4fGeomParam(arb_geom_params, prop->getName()); + + CachedData::CachedAttribute &attribute = cached_data.add_attribute(attr_name, + *param.getTimeSampling()); + + for (size_t i = 0; i < param.getNumSamples(); ++i) { + if (progress.get_cancel()) { + return; + } + + ISampleSelector iss = ISampleSelector(index_t(i)); + + IC4fGeomParam::Sample sample; + param.getIndexed(sample, iss); + + const chrono_t time = param.getTimeSampling()->getSampleTime(index_t(i)); + + C4fArraySamplePtr values = sample.getVals(); + + attribute.std = ATTR_STD_NONE; + + if (param.getScope() == kVaryingScope) { + attribute.element = ATTR_ELEMENT_CORNER_BYTE; + attribute.type_desc = TypeRGBA; + + const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + + if (!triangles) { + return; + } + + array<char> data; + data.resize(triangles->size() * 3 * sizeof(uchar4)); + + uchar4 *data_uchar4 = reinterpret_cast<uchar4 *>(data.data()); + + int offset = 0; + for (const int3 &tri : *triangles) { + Imath::C4f v = (*values)[tri.x]; + data_uchar4[offset + 0] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a)); + + v = (*values)[tri.y]; + data_uchar4[offset + 1] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a)); + + v = (*values)[tri.z]; + data_uchar4[offset + 2] = color_float4_to_uchar4(make_float4(v.r, v.g, v.b, v.a)); + + offset += 3; + } + + attribute.data.set_time_sampling(*param.getTimeSampling()); + attribute.data.add_data(data, time); + } + } + } +} + +/* Update existing attributes and remove any attribute not in the cached_data, those attributes + * were added by Cycles (e.g. face normals) */ +static void update_attributes(AttributeSet &attributes, CachedData &cached_data, double frame_time) +{ + set<Attribute *> cached_attributes; + + for (CachedData::CachedAttribute &attribute : cached_data.attributes) { + const array<char> *attr_data = attribute.data.data_for_time(frame_time); + + Attribute *attr = nullptr; + if (attribute.std != ATTR_STD_NONE) { + attr = attributes.add(attribute.std, attribute.name); + } + else { + attr = attributes.add(attribute.name, attribute.type_desc, attribute.element); + } + assert(attr); + + cached_attributes.insert(attr); + + if (!attr_data) { + /* no new data */ + continue; + } + + /* weak way of detecting if the topology has changed + * todo: reuse code from device_update patch */ + if (attr->buffer.size() != attr_data->size()) { + attr->buffer.resize(attr_data->size()); + } + + memcpy(attr->data(), attr_data->data(), attr_data->size()); + } + + /* remove any attributes not in cached_attributes */ + list<Attribute>::iterator it; + for (it = attributes.attributes.begin(); it != attributes.attributes.end();) { + if (cached_attributes.find(&(*it)) == cached_attributes.end()) { + attributes.attributes.erase(it++); + continue; + } + + it++; + } +} + +NODE_DEFINE(AlembicProcedural) +{ + NodeType *type = NodeType::add("alembic", create); + + SOCKET_STRING(filepath, "Filename", ustring()); + SOCKET_FLOAT(frame, "Frame", 1.0f); + SOCKET_FLOAT(start_frame, "Start Frame", 1.0f); + SOCKET_FLOAT(end_frame, "End Frame", 1.0f); + SOCKET_FLOAT(frame_rate, "Frame Rate", 24.0f); + SOCKET_FLOAT(frame_offset, "Frame Offset", 0.0f); + SOCKET_FLOAT(default_radius, "Default Radius", 0.01f); + SOCKET_FLOAT(scale, "Scale", 1.0f); + + SOCKET_NODE_ARRAY(objects, "Objects", &AlembicObject::node_type); + + return type; +} + +AlembicProcedural::AlembicProcedural() : Procedural(node_type) +{ + objects_loaded = false; + scene_ = nullptr; +} + +AlembicProcedural::~AlembicProcedural() +{ + ccl::set<Geometry *> geometries_set; + ccl::set<Object *> objects_set; + ccl::set<AlembicObject *> abc_objects_set; + + foreach (Node *node, objects) { + AlembicObject *abc_object = static_cast<AlembicObject *>(node); + + if (abc_object->get_object()) { + objects_set.insert(abc_object->get_object()); + + if (abc_object->get_object()->get_geometry()) { + geometries_set.insert(abc_object->get_object()->get_geometry()); + } + } + + delete_node(abc_object); + } + + /* We may delete a Procedural before rendering started, so scene_ can be null. */ + if (!scene_) { + assert(geometries_set.empty()); + assert(objects_set.empty()); + return; + } + + scene_->delete_nodes(geometries_set, this); + scene_->delete_nodes(objects_set, this); +} + +void AlembicProcedural::generate(Scene *scene, Progress &progress) +{ + assert(scene_ == nullptr || scene_ == scene); + scene_ = scene; + + bool need_shader_updates = false; + + /* Check for changes in shaders (newly requested attributes). */ + foreach (Node *object_node, objects) { + AlembicObject *object = static_cast<AlembicObject *>(object_node); + + foreach (Node *shader_node, object->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(shader_node); + + if (shader->need_update_geometry()) { + object->need_shader_update = true; + need_shader_updates = true; + } + } + } + + if (!is_modified() && !need_shader_updates) { + return; + } + + if (!archive.valid()) { + Alembic::AbcCoreFactory::IFactory factory; + factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy); + archive = factory.getArchive(filepath.c_str()); + + if (!archive.valid()) { + /* avoid potential infinite update loops in viewport synchronization */ + filepath.clear(); + clear_modified(); + return; + } + } + + if (!objects_loaded || objects_is_modified()) { + load_objects(progress); + objects_loaded = true; + } + + const chrono_t frame_time = (chrono_t)((frame - frame_offset) / frame_rate); + + foreach (Node *node, objects) { + AlembicObject *object = static_cast<AlembicObject *>(node); + + if (progress.get_cancel()) { + return; + } + + /* skip constant objects */ + if (object->has_data_loaded() && object->is_constant() && !object->is_modified() && + !object->need_shader_update && !scale_is_modified()) { + continue; + } + + if (IPolyMesh::matches(object->iobject.getHeader())) { + read_mesh(scene, object, frame_time, progress); + } + else if (ICurves::matches(object->iobject.getHeader())) { + read_curves(scene, object, frame_time, progress); + } + else if (ISubD::matches(object->iobject.getHeader())) { + read_subd(scene, object, frame_time, progress); + } + + object->clear_modified(); + } + + clear_modified(); +} + +void AlembicProcedural::add_object(AlembicObject *object) +{ + objects.push_back_slow(object); + tag_objects_modified(); +} + +void AlembicProcedural::tag_update(Scene *scene) +{ + scene->procedural_manager->tag_update(); +} + +AlembicObject *AlembicProcedural::get_or_create_object(const ustring &path) +{ + foreach (Node *node, objects) { + AlembicObject *object = static_cast<AlembicObject *>(node); + + if (object->get_path() == path) { + return object; + } + } + + AlembicObject *object = create_node<AlembicObject>(); + object->set_path(path); + + add_object(object); + + return object; +} + +void AlembicProcedural::load_objects(Progress &progress) +{ + unordered_map<string, AlembicObject *> object_map; + + foreach (Node *node, objects) { + AlembicObject *object = static_cast<AlembicObject *>(node); + + /* only consider newly added objects */ + if (object->get_object() == nullptr) { + object_map.insert({object->get_path().c_str(), object}); + } + } + + IObject root = archive.getTop(); + + for (size_t i = 0; i < root.getNumChildren(); ++i) { + walk_hierarchy(root, root.getChildHeader(i), nullptr, object_map, progress); + } +} + +void AlembicProcedural::read_mesh(Scene *scene, + AlembicObject *abc_object, + Abc::chrono_t frame_time, + Progress &progress) +{ + IPolyMesh polymesh(abc_object->iobject, Alembic::Abc::kWrapExisting); + + Mesh *mesh = nullptr; + + /* create a mesh node in the scene if not already done */ + if (!abc_object->get_object()) { + mesh = scene->create_node<Mesh>(); + mesh->set_owner(this); + mesh->name = abc_object->iobject.getName(); + + array<Node *> used_shaders = abc_object->get_used_shaders(); + mesh->set_used_shaders(used_shaders); + + /* create object*/ + Object *object = scene->create_node<Object>(); + object->set_owner(this); + object->set_geometry(mesh); + object->set_tfm(abc_object->xform); + object->name = abc_object->iobject.getName(); + + abc_object->set_object(object); + } + else { + mesh = static_cast<Mesh *>(abc_object->get_object()->get_geometry()); + } + + CachedData &cached_data = abc_object->get_cached_data(); + IPolyMeshSchema schema = polymesh.getSchema(); + + if (!abc_object->has_data_loaded()) { + abc_object->load_all_data(this, schema, scale, progress); + } + else { + if (abc_object->need_shader_update) { + abc_object->update_shader_attributes(schema.getArbGeomParams(), progress); + } + + if (scale_is_modified()) { + abc_object->setup_transform_cache(scale); + } + } + + /* update sockets */ + + Object *object = abc_object->get_object(); + cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket()); + + cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); + + cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket()); + + array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time); + if (triangle_data) { + array<int> triangles; + array<bool> smooth; + + triangles.reserve(triangle_data->size() * 3); + smooth.reserve(triangle_data->size()); + + for (size_t i = 0; i < triangle_data->size(); ++i) { + int3 tri = (*triangle_data)[i]; + triangles.push_back_reserved(tri.x); + triangles.push_back_reserved(tri.y); + triangles.push_back_reserved(tri.z); + smooth.push_back_reserved(1); + } + + mesh->set_triangles(triangles); + mesh->set_smooth(smooth); + } + + /* update attributes */ + + update_attributes(mesh->attributes, cached_data, frame_time); + + /* we don't yet support arbitrary attributes, for now add vertex + * coordinates as generated coordinates if requested */ + if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); + memcpy( + attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size()); + } + + if (mesh->is_modified()) { + bool need_rebuild = mesh->triangles_is_modified(); + mesh->tag_update(scene, need_rebuild); + } +} + +void AlembicProcedural::read_subd(Scene *scene, + AlembicObject *abc_object, + Abc::chrono_t frame_time, + Progress &progress) +{ + ISubD subd_mesh(abc_object->iobject, Alembic::Abc::kWrapExisting); + ISubDSchema schema = subd_mesh.getSchema(); + + Mesh *mesh = nullptr; + + /* create a mesh node in the scene if not already done */ + if (!abc_object->get_object()) { + mesh = scene->create_node<Mesh>(); + mesh->set_owner(this); + mesh->name = abc_object->iobject.getName(); + + array<Node *> used_shaders = abc_object->get_used_shaders(); + mesh->set_used_shaders(used_shaders); + + /* Alembic is OpenSubDiv compliant, there is no option to set another subdivision type. */ + mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_CATMULL_CLARK); + + /* create object*/ + Object *object = scene->create_node<Object>(); + object->set_owner(this); + object->set_geometry(mesh); + object->set_tfm(abc_object->xform); + object->name = abc_object->iobject.getName(); + + abc_object->set_object(object); + } + else { + mesh = static_cast<Mesh *>(abc_object->get_object()->get_geometry()); + } + + if (!abc_object->has_data_loaded()) { + abc_object->load_all_data(this, schema, scale, progress); + } + else { + if (abc_object->need_shader_update) { + abc_object->update_shader_attributes(schema.getArbGeomParams(), progress); + } + + if (scale_is_modified()) { + abc_object->setup_transform_cache(scale); + } + } + + mesh->set_subd_max_level(abc_object->get_subd_max_level()); + mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate()); + + CachedData &cached_data = abc_object->get_cached_data(); + + if (abc_object->subd_max_level_is_modified() || abc_object->subd_dicing_rate_is_modified()) { + /* need to reset the current data is something changed */ + cached_data.invalidate_last_loaded_time(); + } + + /* Cycles overwrites the original triangles when computing displacement, so we always have to + * repass the data if something is animated (vertices most likely) to avoid buffer overflows. */ + if (!cached_data.is_constant()) { + cached_data.invalidate_last_loaded_time(); + + /* remove previous triangles, if any */ + array<int> triangles; + mesh->set_triangles(triangles); + } + + mesh->clear_non_sockets(); + + /* Update sockets. */ + + Object *object = abc_object->get_object(); + cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket()); + + cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); + + /* cached_data.shader is also used for subd_shader */ + cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_subd_shader_socket()); + + cached_data.subd_start_corner.copy_to_socket( + frame_time, mesh, mesh->get_subd_start_corner_socket()); + + cached_data.subd_num_corners.copy_to_socket( + frame_time, mesh, mesh->get_subd_num_corners_socket()); + + cached_data.subd_smooth.copy_to_socket(frame_time, mesh, mesh->get_subd_smooth_socket()); + + cached_data.subd_ptex_offset.copy_to_socket( + frame_time, mesh, mesh->get_subd_ptex_offset_socket()); + + cached_data.subd_face_corners.copy_to_socket( + frame_time, mesh, mesh->get_subd_face_corners_socket()); + + cached_data.num_ngons.copy_to_socket(frame_time, mesh, mesh->get_num_ngons_socket()); + + cached_data.subd_creases_edge.copy_to_socket( + frame_time, mesh, mesh->get_subd_creases_edge_socket()); + + cached_data.subd_creases_weight.copy_to_socket( + frame_time, mesh, mesh->get_subd_creases_weight_socket()); + + mesh->set_num_subd_faces(mesh->get_subd_shader().size()); + + /* Update attributes. */ + + update_attributes(mesh->subd_attributes, cached_data, frame_time); + + /* we don't yet support arbitrary attributes, for now add vertex + * coordinates as generated coordinates if requested */ + if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED); + memcpy( + attr->data_float3(), mesh->get_verts().data(), sizeof(float3) * mesh->get_verts().size()); + } + + if (mesh->is_modified()) { + bool need_rebuild = (mesh->triangles_is_modified()) || + (mesh->subd_num_corners_is_modified()) || + (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) || + (mesh->subd_ptex_offset_is_modified()) || + (mesh->subd_start_corner_is_modified()) || + (mesh->subd_face_corners_is_modified()); + + mesh->tag_update(scene, need_rebuild); + } +} + +void AlembicProcedural::read_curves(Scene *scene, + AlembicObject *abc_object, + Abc::chrono_t frame_time, + Progress &progress) +{ + ICurves curves(abc_object->iobject, Alembic::Abc::kWrapExisting); + Hair *hair; + + /* create a hair node in the scene if not already done */ + if (!abc_object->get_object()) { + hair = scene->create_node<Hair>(); + hair->set_owner(this); + hair->name = abc_object->iobject.getName(); + + array<Node *> used_shaders = abc_object->get_used_shaders(); + hair->set_used_shaders(used_shaders); + + /* create object*/ + Object *object = scene->create_node<Object>(); + object->set_owner(this); + object->set_geometry(hair); + object->set_tfm(abc_object->xform); + object->name = abc_object->iobject.getName(); + + abc_object->set_object(object); + } + else { + hair = static_cast<Hair *>(abc_object->get_object()->get_geometry()); + } + + ICurvesSchema schema = curves.getSchema(); + + if (!abc_object->has_data_loaded() || default_radius_is_modified() || + abc_object->radius_scale_is_modified()) { + abc_object->load_all_data(this, schema, scale, progress, default_radius); + } + else { + if (scale_is_modified()) { + abc_object->setup_transform_cache(scale); + } + } + + CachedData &cached_data = abc_object->get_cached_data(); + + /* update sockets */ + + Object *object = abc_object->get_object(); + cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket()); + + cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket()); + + cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket()); + + cached_data.curve_shader.copy_to_socket(frame_time, hair, hair->get_curve_shader_socket()); + + cached_data.curve_first_key.copy_to_socket(frame_time, hair, hair->get_curve_first_key_socket()); + + /* update attributes */ + + update_attributes(hair->attributes, cached_data, frame_time); + + /* we don't yet support arbitrary attributes, for now add first keys as generated coordinates if + * requested */ + if (hair->need_attribute(scene, ATTR_STD_GENERATED)) { + Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED); + float3 *generated = attr_generated->data_float3(); + + for (size_t i = 0; i < hair->num_curves(); i++) { + generated[i] = hair->get_curve_keys()[hair->get_curve(i).first_key]; + } + } + + const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified()); + hair->tag_update(scene, rebuild); +} + +void AlembicProcedural::walk_hierarchy( + IObject parent, + const ObjectHeader &header, + MatrixSampleMap *xform_samples, + const unordered_map<std::string, AlembicObject *> &object_map, + Progress &progress) +{ + if (progress.get_cancel()) { + return; + } + + IObject next_object; + + MatrixSampleMap concatenated_xform_samples; + + if (IXform::matches(header)) { + IXform xform(parent, header.getName()); + + IXformSchema &xs = xform.getSchema(); + + if (xs.getNumOps() > 0) { + TimeSamplingPtr ts = xs.getTimeSampling(); + MatrixSampleMap local_xform_samples; + + MatrixSampleMap *temp_xform_samples = nullptr; + if (xform_samples == nullptr) { + /* If there is no parent transforms, fill the map directly. */ + temp_xform_samples = &concatenated_xform_samples; + } + else { + /* use a temporary map */ + temp_xform_samples = &local_xform_samples; + } + + for (size_t i = 0; i < xs.getNumSamples(); ++i) { + chrono_t sample_time = ts->getSampleTime(index_t(i)); + XformSample sample = xs.getValue(ISampleSelector(sample_time)); + temp_xform_samples->insert({sample_time, sample.getMatrix()}); + } + + if (xform_samples != nullptr) { + concatenate_xform_samples(*xform_samples, local_xform_samples, concatenated_xform_samples); + } + + xform_samples = &concatenated_xform_samples; + } + + next_object = xform; + } + else if (ISubD::matches(header)) { + ISubD subd(parent, header.getName()); + + unordered_map<std::string, AlembicObject *>::const_iterator iter; + iter = object_map.find(subd.getFullName()); + + if (iter != object_map.end()) { + AlembicObject *abc_object = iter->second; + abc_object->iobject = subd; + + if (xform_samples) { + abc_object->xform_samples = *xform_samples; + } + } + + next_object = subd; + } + else if (IPolyMesh::matches(header)) { + IPolyMesh mesh(parent, header.getName()); + + unordered_map<std::string, AlembicObject *>::const_iterator iter; + iter = object_map.find(mesh.getFullName()); + + if (iter != object_map.end()) { + AlembicObject *abc_object = iter->second; + abc_object->iobject = mesh; + + if (xform_samples) { + abc_object->xform_samples = *xform_samples; + } + } + + next_object = mesh; + } + else if (ICurves::matches(header)) { + ICurves curves(parent, header.getName()); + + unordered_map<std::string, AlembicObject *>::const_iterator iter; + iter = object_map.find(curves.getFullName()); + + if (iter != object_map.end()) { + AlembicObject *abc_object = iter->second; + abc_object->iobject = curves; + + if (xform_samples) { + abc_object->xform_samples = *xform_samples; + } + } + + next_object = curves; + } + else if (IFaceSet::matches(header)) { + // ignore the face set, it will be read along with the data + } + else { + // unsupported type for now (Points, NuPatch) + next_object = parent.getChild(header.getName()); + } + + if (next_object.valid()) { + for (size_t i = 0; i < next_object.getNumChildren(); ++i) { + walk_hierarchy( + next_object, next_object.getChildHeader(i), xform_samples, object_map, progress); + } + } +} + +CCL_NAMESPACE_END + +#endif diff --git a/intern/cycles/render/alembic.h b/intern/cycles/render/alembic.h new file mode 100644 index 00000000000..6b0d32fb3ab --- /dev/null +++ b/intern/cycles/render/alembic.h @@ -0,0 +1,404 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graph/node.h" +#include "render/attribute.h" +#include "render/procedural.h" +#include "util/util_set.h" +#include "util/util_transform.h" +#include "util/util_vector.h" + +#ifdef WITH_ALEMBIC + +# include <Alembic/AbcCoreFactory/All.h> +# include <Alembic/AbcGeom/All.h> + +CCL_NAMESPACE_BEGIN + +class AlembicProcedural; +class Geometry; +class Object; +class Progress; +class Shader; + +using MatrixSampleMap = std::map<Alembic::Abc::chrono_t, Alembic::Abc::M44d>; + +/* Helpers to detect if some type is a ccl::array. */ +template<typename> struct is_array : public std::false_type { +}; + +template<typename T> struct is_array<array<T>> : public std::true_type { +}; + +/* Store the data set for an animation at every time points, or at the beginning of the animation + * for constant data. + * + * The data is supposed to be stored in chronological order, and is looked up using the current + * animation time in seconds using the TimeSampling from the Alembic property. */ +template<typename T> class DataStore { + struct DataTimePair { + double time = 0; + T data{}; + }; + + vector<DataTimePair> data{}; + Alembic::AbcCoreAbstract::TimeSampling time_sampling{}; + + double last_loaded_time = std::numeric_limits<double>::max(); + + public: + void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling_) + { + time_sampling = time_sampling_; + } + + Alembic::AbcCoreAbstract::TimeSampling get_time_sampling() const + { + return time_sampling; + } + + /* Get the data for the specified time. + * Return nullptr if there is no data or if the data for this time was already loaded. */ + T *data_for_time(double time) + { + if (size() == 0) { + return nullptr; + } + + std::pair<size_t, Alembic::Abc::chrono_t> index_pair; + index_pair = time_sampling.getNearIndex(time, data.size()); + DataTimePair &data_pair = data[index_pair.first]; + + if (last_loaded_time == data_pair.time) { + return nullptr; + } + + last_loaded_time = data_pair.time; + + return &data_pair.data; + } + + /* get the data for the specified time, but do not check if the data was already loaded for this + * time return nullptr if there is no data */ + T *data_for_time_no_check(double time) + { + if (size() == 0) { + return nullptr; + } + + std::pair<size_t, Alembic::Abc::chrono_t> index_pair; + index_pair = time_sampling.getNearIndex(time, data.size()); + DataTimePair &data_pair = data[index_pair.first]; + return &data_pair.data; + } + + void add_data(T &data_, double time) + { + if constexpr (is_array<T>::value) { + data.emplace_back(); + data.back().data.steal_data(data_); + data.back().time = time; + return; + } + + data.push_back({time, data_}); + } + + bool is_constant() const + { + return data.size() <= 1; + } + + size_t size() const + { + return data.size(); + } + + void clear() + { + invalidate_last_loaded_time(); + data.clear(); + } + + void invalidate_last_loaded_time() + { + last_loaded_time = std::numeric_limits<double>::max(); + } + + /* Copy the data for the specified time to the node's socket. If there is no + * data for this time or it was already loaded, do nothing. */ + void copy_to_socket(double time, Node *node, const SocketType *socket) + { + T *data_ = data_for_time(time); + + if (data_ == nullptr) { + return; + } + + /* TODO(kevindietrich): arrays are emptied when passed to the sockets, so for now we copy the + * arrays to avoid reloading the data */ + T value = *data_; + node->set(*socket, value); + } +}; + +/* Actual cache for the stored data. + * This caches the topological, transformation, and attribute data for a Mesh node or a Hair node + * inside of DataStores. + */ +struct CachedData { + DataStore<Transform> transforms{}; + + /* mesh data */ + DataStore<array<float3>> vertices; + DataStore<array<int3>> triangles{}; + /* triangle "loops" are the polygons' vertices indices used for indexing face varying attributes + * (like UVs) */ + DataStore<array<int3>> triangles_loops{}; + DataStore<array<int>> shader{}; + + /* subd data */ + DataStore<array<int>> subd_start_corner; + DataStore<array<int>> subd_num_corners; + DataStore<array<bool>> subd_smooth; + DataStore<array<int>> subd_ptex_offset; + DataStore<array<int>> subd_face_corners; + DataStore<int> num_ngons; + DataStore<array<int>> subd_creases_edge; + DataStore<array<float>> subd_creases_weight; + + /* hair data */ + DataStore<array<float3>> curve_keys; + DataStore<array<float>> curve_radius; + DataStore<array<int>> curve_first_key; + DataStore<array<int>> curve_shader; + + struct CachedAttribute { + AttributeStandard std; + AttributeElement element; + TypeDesc type_desc; + ustring name; + DataStore<array<char>> data{}; + }; + + vector<CachedAttribute> attributes{}; + + void clear(); + + CachedAttribute &add_attribute(const ustring &name, + const Alembic::Abc::TimeSampling &time_sampling); + + bool is_constant() const; + + void invalidate_last_loaded_time(bool attributes_only = false); + + void set_time_sampling(Alembic::AbcCoreAbstract::TimeSampling time_sampling); +}; + +/* Representation of an Alembic object for the AlembicProcedural. + * + * The AlembicObject holds the path to the Alembic IObject inside of the archive that is desired + * for rendering, as well as the list of shaders that it is using. + * + * The names of the shaders should correspond to the names of the FaceSets inside of the Alembic + * archive for per-triangle shader association. If there is no FaceSets, or the names do not + * match, the first shader is used for rendering for all triangles. + */ +class AlembicObject : public Node { + public: + NODE_DECLARE + + /* Path to the IObject inside of the archive. */ + NODE_SOCKET_API(ustring, path) + + /* Shaders used for rendering. */ + NODE_SOCKET_API_ARRAY(array<Node *>, used_shaders) + + /* Maximum number of subdivisions for ISubD objects. */ + NODE_SOCKET_API(int, subd_max_level) + + /* Finest level of detail (in pixels) for the subdivision. */ + NODE_SOCKET_API(float, subd_dicing_rate) + + /* Scale the radius of points and curves. */ + NODE_SOCKET_API(float, radius_scale) + + AlembicObject(); + ~AlembicObject(); + + private: + friend class AlembicProcedural; + + void set_object(Object *object); + Object *get_object(); + + void load_all_data(AlembicProcedural *proc, + Alembic::AbcGeom::IPolyMeshSchema &schema, + float scale, + Progress &progress); + void load_all_data(AlembicProcedural *proc, + Alembic::AbcGeom::ISubDSchema &schema, + float scale, + Progress &progress); + void load_all_data(AlembicProcedural *proc, + const Alembic::AbcGeom::ICurvesSchema &schema, + float scale, + Progress &progress, + float default_radius); + + bool has_data_loaded() const; + + bool need_shader_update = true; + + MatrixSampleMap xform_samples; + Alembic::AbcGeom::IObject iobject; + Transform xform; + + CachedData &get_cached_data() + { + return cached_data; + } + + bool is_constant() const + { + return cached_data.is_constant(); + } + + Object *object = nullptr; + + bool data_loaded = false; + + CachedData cached_data; + + void update_shader_attributes(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params, + Progress &progress); + + void read_attribute(const Alembic::AbcGeom::ICompoundProperty &arb_geom_params, + const ustring &attr_name, + Progress &progress); + + template<typename SchemaType> + void read_face_sets(SchemaType &schema, + array<int> &polygon_to_shader, + Alembic::AbcGeom::ISampleSelector sample_sel); + + void setup_transform_cache(float scale); + + AttributeRequestSet get_requested_attributes(); +}; + +/* Procedural to render objects from a single Alembic archive. + * + * Every object desired to be rendered should be passed as an AlembicObject through the objects + * socket. + * + * This procedural will load the data set for the entire animation in memory on the first frame, + * and directly set the data for the new frames on the created Nodes if needed. This allows for + * faster updates between frames as it avoids reseeking the data on disk. + */ +class AlembicProcedural : public Procedural { + Alembic::AbcGeom::IArchive archive; + bool objects_loaded; + Scene *scene_; + + public: + NODE_DECLARE + + /* The file path to the Alembic archive */ + NODE_SOCKET_API(ustring, filepath) + + /* The current frame to render. */ + NODE_SOCKET_API(float, frame) + + /* The first frame to load data for. */ + NODE_SOCKET_API(float, start_frame) + + /* The last frame to load data for. */ + NODE_SOCKET_API(float, end_frame) + + /* Subtracted to the current frame. */ + NODE_SOCKET_API(float, frame_offset) + + /* The frame rate used for rendering in units of frames per second. */ + NODE_SOCKET_API(float, frame_rate) + + /* List of AlembicObjects to render. */ + NODE_SOCKET_API_ARRAY(array<Node *>, objects) + + /* Set the default radius to use for curves when the Alembic Curves Schemas do not have radius + * information. */ + NODE_SOCKET_API(float, default_radius) + + /* Multiplier to account for differences in default units for measuring objects in various + * software. */ + NODE_SOCKET_API(float, scale) + + AlembicProcedural(); + ~AlembicProcedural(); + + /* Populates the Cycles scene with Nodes for every contained AlembicObject on the first + * invocation, and updates the data on subsequent invocations if the frame changed. */ + void generate(Scene *scene, Progress &progress); + + /* Add an object to our list of objects, and tag the socket as modified. */ + void add_object(AlembicObject *object); + + /* Tag for an update only if something was modified. */ + void tag_update(Scene *scene); + + /* Returns a pointer to an existing or a newly created AlembicObject for the given path. */ + AlembicObject *get_or_create_object(const ustring &path); + + private: + /* Load the data for all the objects whose data has not yet been loaded. */ + void load_objects(Progress &progress); + + /* Traverse the Alembic hierarchy to lookup the IObjects for the AlembicObjects that were + * specified in our objects socket, and accumulate all of the transformations samples along the + * way for each IObject. */ + void walk_hierarchy(Alembic::AbcGeom::IObject parent, + const Alembic::AbcGeom::ObjectHeader &ohead, + MatrixSampleMap *xform_samples, + const unordered_map<string, AlembicObject *> &object_map, + Progress &progress); + + /* Read the data for an IPolyMesh at the specified frame_time. Creates corresponding Geometry and + * Object Nodes in the Cycles scene if none exist yet. */ + void read_mesh(Scene *scene, + AlembicObject *abc_object, + Alembic::AbcGeom::Abc::chrono_t frame_time, + Progress &progress); + + /* Read the data for an ICurves at the specified frame_time. Creates corresponding Geometry and + * Object Nodes in the Cycles scene if none exist yet. */ + void read_curves(Scene *scene, + AlembicObject *abc_object, + Alembic::AbcGeom::Abc::chrono_t frame_time, + Progress &progress); + + /* Read the data for an ISubD at the specified frame_time. Creates corresponding Geometry and + * Object Nodes in the Cycles scene if none exist yet. */ + void read_subd(Scene *scene, + AlembicObject *abc_object, + Alembic::AbcGeom::Abc::chrono_t frame_time, + Progress &progress); +}; + +CCL_NAMESPACE_END + +#endif diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index b478aae9ae2..ce4ae6e4295 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -28,7 +28,7 @@ CCL_NAMESPACE_BEGIN Attribute::Attribute( ustring name, TypeDesc type, AttributeElement element, Geometry *geom, AttributePrimitive prim) - : name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0) + : name(name), std(ATTR_STD_NONE), type(type), element(element), flags(0), modified(true) { /* string and matrix not supported! */ assert(type == TypeDesc::TypeFloat || type == TypeDesc::TypeColor || @@ -82,6 +82,8 @@ void Attribute::add(const float &f) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; } void Attribute::add(const uchar4 &f) @@ -93,6 +95,8 @@ void Attribute::add(const uchar4 &f) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; } void Attribute::add(const float2 &f) @@ -104,6 +108,8 @@ void Attribute::add(const float2 &f) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; } void Attribute::add(const float3 &f) @@ -115,6 +121,8 @@ void Attribute::add(const float3 &f) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; } void Attribute::add(const Transform &f) @@ -126,6 +134,8 @@ void Attribute::add(const Transform &f) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; } void Attribute::add(const char *data) @@ -134,6 +144,26 @@ void Attribute::add(const char *data) for (size_t i = 0; i < size; i++) buffer.push_back(data[i]); + + modified = true; +} + +void Attribute::set_data_from(Attribute &&other) +{ + assert(other.std == std); + assert(other.type == type); + assert(other.element == element); + + this->flags = other.flags; + + if (this->buffer.size() != other.buffer.size()) { + this->buffer = std::move(other.buffer); + modified = true; + } + else if (memcmp(this->data(), other.data(), other.buffer.size()) != 0) { + this->buffer = std::move(other.buffer); + modified = true; + } } size_t Attribute::data_sizeof() const @@ -627,6 +657,42 @@ void AttributeSet::clear(bool preserve_voxel_data) } } +void AttributeSet::update(AttributeSet &&new_attributes) +{ + /* add or update old_attributes based on the new_attributes */ + foreach (Attribute &attr, new_attributes.attributes) { + Attribute *nattr = add(attr.name, attr.type, attr.element); + nattr->std = attr.std; + nattr->set_data_from(std::move(attr)); + } + + /* remove any attributes not on new_attributes */ + list<Attribute>::iterator it; + for (it = attributes.begin(); it != attributes.end();) { + if (it->std != ATTR_STD_NONE) { + if (new_attributes.find(it->std) == nullptr) { + attributes.erase(it++); + continue; + } + } + else if (it->name != "") { + if (new_attributes.find(it->name) == nullptr) { + attributes.erase(it++); + continue; + } + } + + it++; + } +} + +void AttributeSet::clear_modified() +{ + foreach (Attribute &attr, attributes) { + attr.modified = false; + } +} + /* AttributeRequest */ AttributeRequest::AttributeRequest(ustring name_) diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h index 9990a1325a7..f9997d3c422 100644 --- a/intern/cycles/render/attribute.h +++ b/intern/cycles/render/attribute.h @@ -54,6 +54,8 @@ class Attribute { AttributeElement element; uint flags; /* enum AttributeFlag */ + bool modified; + Attribute(ustring name, TypeDesc type, AttributeElement element, @@ -159,6 +161,8 @@ class Attribute { void add(const Transform &tfm); void add(const char *data); + void set_data_from(Attribute &&other); + static bool same_storage(TypeDesc a, TypeDesc b); static const char *standard_name(AttributeStandard std); static AttributeStandard name_standard(const char *name); @@ -194,6 +198,12 @@ class AttributeSet { void resize(bool reserve_only = false); void clear(bool preserve_voxel_data = false); + + /* Update the attributes in this AttributeSet with the ones from the new set, + * and remove any attribute not found on the new set from this. */ + void update(AttributeSet &&new_attributes); + + void clear_modified(); }; /* AttributeRequest diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp index 7bdcb1578c3..1303f894912 100644 --- a/intern/cycles/render/background.cpp +++ b/intern/cycles/render/background.cpp @@ -130,8 +130,9 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/) void Background::tag_update(Scene *scene) { - scene->integrator->tag_update(scene); - tag_modified(); + if (ao_factor_is_modified() || use_ao_is_modified()) { + scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED); + } } Shader *Background::get_shader(const Scene *scene) diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 439ebdedb8e..317a3937cab 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -78,7 +78,7 @@ BakeManager::BakeManager() type = SHADER_EVAL_BAKE; pass_filter = 0; - need_update = true; + need_update_ = true; } BakeManager::~BakeManager() @@ -114,9 +114,9 @@ void BakeManager::set(Scene *scene, /* create device and update scene */ scene->film->tag_modified(); - scene->integrator->tag_update(scene); + scene->integrator->tag_update(scene, Integrator::UPDATE_ALL); - need_update = true; + need_update_ = true; } void BakeManager::device_update(Device * /*device*/, @@ -124,7 +124,7 @@ void BakeManager::device_update(Device * /*device*/, Scene *scene, Progress & /* progress */) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -152,11 +152,21 @@ void BakeManager::device_update(Device * /*device*/, object_index++; } - need_update = false; + need_update_ = false; } void BakeManager::device_free(Device * /*device*/, DeviceScene * /*dscene*/) { } +void BakeManager::tag_update() +{ + need_update_ = true; +} + +bool BakeManager::need_update() const +{ + return need_update_; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h index 93e664c2ab1..655b9b1cf7e 100644 --- a/intern/cycles/render/bake.h +++ b/intern/cycles/render/bake.h @@ -36,9 +36,12 @@ class BakeManager { void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); void device_free(Device *device, DeviceScene *dscene); - bool need_update; + void tag_update(); + + bool need_update() const; private: + bool need_update_; ShaderEvalType type; int pass_filter; std::string object_name; diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp index 045931ffdac..0948b20628f 100644 --- a/intern/cycles/render/buffers.cpp +++ b/intern/cycles/render/buffers.cpp @@ -448,7 +448,7 @@ bool RenderBuffers::get_pass_rect( pixels[1] = f.y * scale_exposure; pixels[2] = f.z * scale_exposure; - /* clamp since alpha might be > 1.0 due to russian roulette */ + /* Clamp since alpha might be > 1.0 due to Russian roulette. */ pixels[3] = saturate(f.w * scale); } } diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 3beb3d1d4d3..30bf6c4241a 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -252,11 +252,11 @@ void Camera::update(Scene *scene) Transform fulltoborder = transform_from_viewplane(viewport_camera_border); Transform bordertofull = transform_inverse(fulltoborder); - /* ndc to raster */ + /* NDC to raster. */ Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull; Transform full_ndctoraster = transform_scale(full_width, full_height, 1.0f) * bordertofull; - /* raster to screen */ + /* Raster to screen. */ Transform screentondc = fulltoborder * transform_from_viewplane(viewplane); Transform screentoraster = ndctoraster * screentondc; @@ -264,7 +264,7 @@ void Camera::update(Scene *scene) Transform full_screentoraster = full_ndctoraster * screentondc; Transform full_rastertoscreen = transform_inverse(full_screentoraster); - /* screen to camera */ + /* Screen to camera. */ ProjectionTransform cameratoscreen; if (camera_type == CAMERA_PERSPECTIVE) cameratoscreen = projection_perspective(fov, nearclip, farclip); diff --git a/intern/cycles/render/colorspace.cpp b/intern/cycles/render/colorspace.cpp index 57979d5f225..4c9e86ea278 100644 --- a/intern/cycles/render/colorspace.cpp +++ b/intern/cycles/render/colorspace.cpp @@ -386,7 +386,7 @@ void ColorSpaceManager::free_memory() #endif } -/* Template instanstations so we don't have to inline functions. */ +/* Template instantiations so we don't have to inline functions. */ template void ColorSpaceManager::to_scene_linear(ustring, uchar *, size_t, bool); template void ColorSpaceManager::to_scene_linear(ustring, ushort *, size_t, bool); template void ColorSpaceManager::to_scene_linear(ustring, half *, size_t, bool); diff --git a/intern/cycles/render/denoising.cpp b/intern/cycles/render/denoising.cpp index 76408ca4849..ddbe7484800 100644 --- a/intern/cycles/render/denoising.cpp +++ b/intern/cycles/render/denoising.cpp @@ -847,7 +847,7 @@ bool DenoiseImage::save_output(const string &out_filepath, string &error) out.reset(); - /* Copy temporary file to outputput filepath. */ + /* Copy temporary file to output filepath. */ string rename_error; if (ok && !OIIO::Filesystem::rename(tmp_filepath, out_filepath, rename_error)) { error = "Failed to move denoised image to " + out_filepath + ": " + rename_error; diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index 5c3778f6ae5..9b7657802d6 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -688,16 +688,16 @@ void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *sce void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes) { if (Pass::contains(scene->passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) { - scene->geometry_manager->tag_update(scene); + scene->geometry_manager->tag_update(scene, GeometryManager::UV_PASS_NEEDED); foreach (Shader *shader, scene->shaders) - shader->need_update_geometry = true; + shader->need_update_uvs = true; } else if (Pass::contains(scene->passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) { - scene->geometry_manager->tag_update(scene); + scene->geometry_manager->tag_update(scene, GeometryManager::MOTION_PASS_NEEDED); } else if (Pass::contains(scene->passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) { - scene->integrator->tag_update(scene); + scene->integrator->tag_update(scene, Integrator::AO_PASS_MODIFIED); } if (update_passes) { diff --git a/intern/cycles/render/geometry.cpp b/intern/cycles/render/geometry.cpp index 6fc217f2d76..f79b1689c14 100644 --- a/intern/cycles/render/geometry.cpp +++ b/intern/cycles/render/geometry.cpp @@ -240,7 +240,6 @@ void Geometry::compute_bvh( } } - clear_modified(); need_update_rebuild = false; } @@ -262,22 +261,21 @@ bool Geometry::has_voxel_attributes() const void Geometry::tag_update(Scene *scene, bool rebuild) { - tag_modified(); - if (rebuild) { need_update_rebuild = true; - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::MESH_NEED_REBUILD); } else { foreach (Node *node, used_shaders) { Shader *shader = static_cast<Shader *>(node); - if (shader->has_surface_emission) - scene->light_manager->need_update = true; + if (shader->has_surface_emission) { + scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED); + break; + } } } - scene->geometry_manager->need_update = true; - scene->object_manager->need_update = true; + scene->geometry_manager->tag_update(scene, GeometryManager::GEOMETRY_MODIFIED); } void Geometry::tag_bvh_update(bool rebuild) @@ -293,7 +291,7 @@ void Geometry::tag_bvh_update(bool rebuild) GeometryManager::GeometryManager() { - need_update = true; + update_flags = UPDATE_ALL; need_flags_update = true; } @@ -494,6 +492,10 @@ void GeometryManager::update_svm_attributes(Device *, if (attr_map_size == 0) return; + if (!dscene->attributes_map.need_realloc()) { + return; + } + /* create attribute map */ uint4 *attr_map = dscene->attributes_map.alloc(attr_map_size); memset(attr_map, 0, dscene->attributes_map.size() * sizeof(uint)); @@ -602,8 +604,10 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, offset = attr_uchar4_offset; assert(attr_uchar4.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_uchar4[offset + k] = data[k]; + if (mattr->modified) { + for (size_t k = 0; k < size; k++) { + attr_uchar4[offset + k] = data[k]; + } } attr_uchar4_offset += size; } @@ -612,8 +616,10 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, offset = attr_float_offset; assert(attr_float.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float[offset + k] = data[k]; + if (mattr->modified) { + for (size_t k = 0; k < size; k++) { + attr_float[offset + k] = data[k]; + } } attr_float_offset += size; } @@ -622,8 +628,10 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, offset = attr_float2_offset; assert(attr_float2.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float2[offset + k] = data[k]; + if (mattr->modified) { + for (size_t k = 0; k < size; k++) { + attr_float2[offset + k] = data[k]; + } } attr_float2_offset += size; } @@ -632,8 +640,10 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, offset = attr_float3_offset; assert(attr_float3.size() >= offset + size * 3); - for (size_t k = 0; k < size * 3; k++) { - attr_float3[offset + k] = (&tfm->x)[k]; + if (mattr->modified) { + for (size_t k = 0; k < size * 3; k++) { + attr_float3[offset + k] = (&tfm->x)[k]; + } } attr_float3_offset += size * 3; } @@ -642,8 +652,10 @@ void GeometryManager::update_attribute_element_offset(Geometry *geom, offset = attr_float3_offset; assert(attr_float3.size() >= offset + size); - for (size_t k = 0; k < size; k++) { - attr_float3[offset + k] = data[k]; + if (mattr->modified) { + for (size_t k = 0; k < size; k++) { + attr_float3[offset + k] = data[k]; + } } attr_float3_offset += size; } @@ -808,6 +820,11 @@ void GeometryManager::device_update_attributes(Device *device, dscene->attributes_float3.alloc(attr_float3_size); dscene->attributes_uchar4.alloc(attr_uchar4_size); + const bool copy_all_data = dscene->attributes_float.need_realloc() || + dscene->attributes_float2.need_realloc() || + dscene->attributes_float3.need_realloc() || + dscene->attributes_uchar4.need_realloc(); + size_t attr_float_offset = 0; size_t attr_float2_offset = 0; size_t attr_float3_offset = 0; @@ -822,6 +839,12 @@ void GeometryManager::device_update_attributes(Device *device, * they actually refer to the same mesh attributes, optimize */ foreach (AttributeRequest &req, attributes.requests) { Attribute *attr = geom->attributes.find(req); + + if (attr) { + /* force a copy if we need to reallocate all the data */ + attr->modified |= copy_all_data; + } + update_attribute_element_offset(geom, dscene->attributes_float, attr_float_offset, @@ -840,6 +863,11 @@ void GeometryManager::device_update_attributes(Device *device, Mesh *mesh = static_cast<Mesh *>(geom); Attribute *subd_attr = mesh->subd_attributes.find(req); + if (subd_attr) { + /* force a copy if we need to reallocate all the data */ + subd_attr->modified |= copy_all_data; + } + update_attribute_element_offset(mesh, dscene->attributes_float, attr_float_offset, @@ -903,18 +931,10 @@ void GeometryManager::device_update_attributes(Device *device, /* copy to device */ progress.set_status("Updating Mesh", "Copying Attributes to device"); - if (dscene->attributes_float.size()) { - dscene->attributes_float.copy_to_device(); - } - if (dscene->attributes_float2.size()) { - dscene->attributes_float2.copy_to_device(); - } - if (dscene->attributes_float3.size()) { - dscene->attributes_float3.copy_to_device(); - } - if (dscene->attributes_uchar4.size()) { - dscene->attributes_uchar4.copy_to_device(); - } + dscene->attributes_float.copy_to_device(); + dscene->attributes_float2.copy_to_device(); + dscene->attributes_float3.copy_to_device(); + dscene->attributes_uchar4.copy_to_device(); if (progress.get_cancel()) return; @@ -1066,17 +1086,34 @@ void GeometryManager::device_update_mesh( uint *tri_patch = dscene->tri_patch.alloc(tri_size); float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); + const bool copy_all_data = dscene->tri_shader.need_realloc() || + dscene->tri_vindex.need_realloc() || + dscene->tri_vnormal.need_realloc() || + dscene->tri_patch.need_realloc() || + dscene->tri_patch_uv.need_realloc(); + foreach (Geometry *geom, scene->geometry) { if (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME) { Mesh *mesh = static_cast<Mesh *>(geom); - mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); - mesh->pack_normals(&vnormal[mesh->vert_offset]); - mesh->pack_verts(tri_prim_index, - &tri_vindex[mesh->prim_offset], - &tri_patch[mesh->prim_offset], - &tri_patch_uv[mesh->vert_offset], - mesh->vert_offset, - mesh->prim_offset); + + if (mesh->shader_is_modified() || mesh->smooth_is_modified() || + mesh->triangles_is_modified() || copy_all_data) { + mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); + } + + if (mesh->verts_is_modified() || copy_all_data) { + mesh->pack_normals(&vnormal[mesh->vert_offset]); + } + + if (mesh->triangles_is_modified() || mesh->vert_patch_uv_is_modified() || copy_all_data) { + mesh->pack_verts(tri_prim_index, + &tri_vindex[mesh->prim_offset], + &tri_patch[mesh->prim_offset], + &tri_patch_uv[mesh->vert_offset], + mesh->vert_offset, + mesh->prim_offset); + } + if (progress.get_cancel()) return; } @@ -1085,11 +1122,11 @@ void GeometryManager::device_update_mesh( /* vertex coordinates */ progress.set_status("Updating Mesh", "Copying Mesh to device"); - dscene->tri_shader.copy_to_device(); - dscene->tri_vnormal.copy_to_device(); - dscene->tri_vindex.copy_to_device(); - dscene->tri_patch.copy_to_device(); - dscene->tri_patch_uv.copy_to_device(); + dscene->tri_shader.copy_to_device_if_modified(); + dscene->tri_vnormal.copy_to_device_if_modified(); + dscene->tri_vindex.copy_to_device_if_modified(); + dscene->tri_patch.copy_to_device_if_modified(); + dscene->tri_patch_uv.copy_to_device_if_modified(); } if (curve_size != 0) { @@ -1098,9 +1135,21 @@ void GeometryManager::device_update_mesh( float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); float4 *curves = dscene->curves.alloc(curve_size); + const bool copy_all_data = dscene->curve_keys.need_realloc() || dscene->curves.need_realloc(); + foreach (Geometry *geom, scene->geometry) { if (geom->is_hair()) { Hair *hair = static_cast<Hair *>(geom); + + bool curve_keys_co_modified = hair->curve_radius_is_modified() || + hair->curve_keys_is_modified(); + bool curve_data_modified = hair->curve_shader_is_modified() || + hair->curve_first_key_is_modified(); + + if (!curve_keys_co_modified && !curve_data_modified && !copy_all_data) { + continue; + } + hair->pack_curves(scene, &curve_keys[hair->curvekey_offset], &curves[hair->prim_offset], @@ -1110,11 +1159,11 @@ void GeometryManager::device_update_mesh( } } - dscene->curve_keys.copy_to_device(); - dscene->curves.copy_to_device(); + dscene->curve_keys.copy_to_device_if_modified(); + dscene->curves.copy_to_device_if_modified(); } - if (patch_size != 0) { + if (patch_size != 0 && dscene->patches.need_realloc()) { progress.set_status("Updating Mesh", "Copying Patches to device"); uint *patch_data = dscene->patches.alloc(patch_size); @@ -1180,16 +1229,25 @@ void GeometryManager::device_update_bvh(Device *device, VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout."; - delete scene->bvh; - BVH *bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device); - device->build_bvh(bvh, progress, false); + const bool can_refit = scene->bvh != nullptr && + (bparams.bvh_layout == BVHLayout::BVH_LAYOUT_OPTIX); + const bool pack_all = scene->bvh == nullptr; + + BVH *bvh = scene->bvh; + if (!scene->bvh) { + bvh = scene->bvh = BVH::create(bparams, scene->geometry, scene->objects, device); + } + + device->build_bvh(bvh, progress, can_refit); if (progress.get_cancel()) { return; } + const bool has_bvh2_layout = (bparams.bvh_layout == BVH_LAYOUT_BVH2); + PackedBVH pack; - if (bparams.bvh_layout == BVH_LAYOUT_BVH2) { + if (has_bvh2_layout) { pack = std::move(static_cast<BVH2 *>(bvh)->pack); } else { @@ -1210,12 +1268,22 @@ void GeometryManager::device_update_bvh(Device *device, } pack.root_index = -1; - pack.prim_tri_index.reserve(num_prims); - pack.prim_tri_verts.reserve(num_tri_verts); - pack.prim_type.reserve(num_prims); - pack.prim_index.reserve(num_prims); - pack.prim_object.reserve(num_prims); - pack.prim_visibility.reserve(num_prims); + + if (!pack_all) { + /* if we do not need to recreate the BVH, then only the vertices are updated, so we can + * safely retake the memory */ + dscene->prim_tri_verts.give_data(pack.prim_tri_verts); + } + else { + /* It is not strictly necessary to skip those resizes we if do not have to repack, as the OS + * will not allocate pages if we do not touch them, however it does help catching bugs. */ + pack.prim_tri_index.resize(num_prims); + pack.prim_tri_verts.resize(num_tri_verts); + pack.prim_type.resize(num_prims); + pack.prim_index.resize(num_prims); + pack.prim_object.resize(num_prims); + pack.prim_visibility.resize(num_prims); + } // Merge visibility flags of all objects and find object index for non-instanced geometry unordered_map<const Geometry *, pair<int, uint>> geometry_to_object_info; @@ -1229,17 +1297,27 @@ void GeometryManager::device_update_bvh(Device *device, } } + TaskPool pool; // Iterate over scene mesh list instead of objects, since 'optix_prim_offset' was calculated // based on that list, which may be ordered differently from the object list. foreach (Geometry *geom, scene->geometry) { + if (!pack_all && !geom->is_modified()) { + continue; + } + const pair<int, uint> &info = geometry_to_object_info[geom]; - geom->pack_primitives(pack, info.first, info.second); + pool.push(function_bind( + &Geometry::pack_primitives, geom, &pack, info.first, info.second, pack_all)); } + pool.wait_work(); } /* copy to device */ progress.set_status("Updating Scene BVH", "Copying BVH to device"); + /* When using BVH2, we always have to copy/update the data as its layout is dependent on the + * BVH's leaf nodes which may be different when the objects or vertices move. */ + if (pack.nodes.size()) { dscene->bvh_nodes.steal_data(pack.nodes); dscene->bvh_nodes.copy_to_device(); @@ -1252,7 +1330,7 @@ void GeometryManager::device_update_bvh(Device *device, dscene->object_node.steal_data(pack.object_node); dscene->object_node.copy_to_device(); } - if (pack.prim_tri_index.size()) { + if (pack.prim_tri_index.size() && (dscene->prim_tri_index.need_realloc() || has_bvh2_layout)) { dscene->prim_tri_index.steal_data(pack.prim_tri_index); dscene->prim_tri_index.copy_to_device(); } @@ -1260,23 +1338,23 @@ void GeometryManager::device_update_bvh(Device *device, dscene->prim_tri_verts.steal_data(pack.prim_tri_verts); dscene->prim_tri_verts.copy_to_device(); } - if (pack.prim_type.size()) { + if (pack.prim_type.size() && (dscene->prim_type.need_realloc() || has_bvh2_layout)) { dscene->prim_type.steal_data(pack.prim_type); dscene->prim_type.copy_to_device(); } - if (pack.prim_visibility.size()) { + if (pack.prim_visibility.size() && (dscene->prim_visibility.need_realloc() || has_bvh2_layout)) { dscene->prim_visibility.steal_data(pack.prim_visibility); dscene->prim_visibility.copy_to_device(); } - if (pack.prim_index.size()) { + if (pack.prim_index.size() && (dscene->prim_index.need_realloc() || has_bvh2_layout)) { dscene->prim_index.steal_data(pack.prim_index); dscene->prim_index.copy_to_device(); } - if (pack.prim_object.size()) { + if (pack.prim_object.size() && (dscene->prim_object.need_realloc() || has_bvh2_layout)) { dscene->prim_object.steal_data(pack.prim_object); dscene->prim_object.copy_to_device(); } - if (pack.prim_time.size()) { + if (pack.prim_time.size() && (dscene->prim_time.need_realloc() || has_bvh2_layout)) { dscene->prim_time.steal_data(pack.prim_time); dscene->prim_time.copy_to_device(); } @@ -1289,12 +1367,65 @@ void GeometryManager::device_update_bvh(Device *device, dscene->data.bvh.scene = NULL; } +/* Set of flags used to help determining what data has been modified or needs reallocation, so we + * can decide which device data to free or update. */ +enum { + DEVICE_CURVE_DATA_MODIFIED = (1 << 0), + DEVICE_MESH_DATA_MODIFIED = (1 << 1), + + ATTR_FLOAT_MODIFIED = (1 << 2), + ATTR_FLOAT2_MODIFIED = (1 << 3), + ATTR_FLOAT3_MODIFIED = (1 << 4), + ATTR_UCHAR4_MODIFIED = (1 << 5), + + CURVE_DATA_NEED_REALLOC = (1 << 6), + MESH_DATA_NEED_REALLOC = (1 << 7), + + ATTR_FLOAT_NEEDS_REALLOC = (1 << 8), + ATTR_FLOAT2_NEEDS_REALLOC = (1 << 9), + ATTR_FLOAT3_NEEDS_REALLOC = (1 << 10), + ATTR_UCHAR4_NEEDS_REALLOC = (1 << 11), + + ATTRS_NEED_REALLOC = (ATTR_FLOAT_NEEDS_REALLOC | ATTR_FLOAT2_NEEDS_REALLOC | + ATTR_FLOAT3_NEEDS_REALLOC | ATTR_UCHAR4_NEEDS_REALLOC), + DEVICE_MESH_DATA_NEEDS_REALLOC = (MESH_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC), + DEVICE_CURVE_DATA_NEEDS_REALLOC = (CURVE_DATA_NEED_REALLOC | ATTRS_NEED_REALLOC), +}; + +static void update_device_flags_attribute(uint32_t &device_update_flags, + const AttributeSet &attributes) +{ + foreach (const Attribute &attr, attributes.attributes) { + if (!attr.modified) { + continue; + } + + if (attr.element == ATTR_ELEMENT_CORNER) { + device_update_flags |= ATTR_UCHAR4_MODIFIED; + } + else if (attr.type == TypeDesc::TypeFloat) { + device_update_flags |= ATTR_FLOAT_MODIFIED; + } + else if (attr.type == TypeFloat2) { + device_update_flags |= ATTR_FLOAT2_MODIFIED; + } + else if (attr.type == TypeDesc::TypeMatrix) { + device_update_flags |= ATTR_FLOAT3_MODIFIED; + } + else if (attr.element != ATTR_ELEMENT_VOXEL) { + device_update_flags |= ATTR_FLOAT3_MODIFIED; + } + } +} + void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Progress &progress) { - if (!need_update && !need_flags_update) { + if (!need_update() && !need_flags_update) { return; } + uint32_t device_update_flags = 0; + scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { scene->update_stats->geometry.times.add_entry({"device_update_preprocess", time}); @@ -1314,9 +1445,54 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro if (shader->has_volume) { geom->has_volume = true; } + if (shader->has_surface_bssrdf) { geom->has_surface_bssrdf = true; } + + if (shader->need_update_uvs) { + device_update_flags |= ATTR_FLOAT2_NEEDS_REALLOC; + + /* Attributes might need to be tessellated if added. */ + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->need_tesselation()) { + mesh->tag_modified(); + } + } + } + + if (shader->need_update_attribute) { + device_update_flags |= ATTRS_NEED_REALLOC; + + /* Attributes might need to be tessellated if added. */ + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + if (mesh->need_tesselation()) { + mesh->tag_modified(); + } + } + } + + if (shader->need_update_displacement) { + /* tag displacement related sockets as modified */ + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + mesh->tag_verts_modified(); + mesh->tag_subd_dicing_rate_modified(); + mesh->tag_subd_max_level_modified(); + mesh->tag_subd_objecttoworld_modified(); + + device_update_flags |= ATTRS_NEED_REALLOC; + } + } + } + + /* only check for modified attributes if we do not need to reallocate them already */ + if ((device_update_flags & ATTRS_NEED_REALLOC) == 0) { + update_device_flags_attribute(device_update_flags, geom->attributes); + /* don't check for subd_attributes, as if they were modified, we would need to reallocate + * anyway */ } /* Re-create volume mesh if we will rebuild or refit the BVH. Note we @@ -1332,13 +1508,119 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro Volume *volume = static_cast<Volume *>(geom); create_volume_mesh(volume, progress); + + /* always reallocate when we have a volume, as we need to rebuild the BVH */ + device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC; } if (geom->is_hair()) { /* Set curve shape, still a global scene setting for now. */ Hair *hair = static_cast<Hair *>(geom); hair->curve_shape = scene->params.hair_shape; + + if (hair->need_update_rebuild) { + device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC; + } + else if (hair->is_modified()) { + device_update_flags |= DEVICE_CURVE_DATA_MODIFIED; + } } + + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + + if (mesh->need_update_rebuild) { + device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC; + } + else if (mesh->is_modified()) { + device_update_flags |= DEVICE_MESH_DATA_MODIFIED; + } + } + } + + if (update_flags & (MESH_ADDED | MESH_REMOVED)) { + device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC; + } + + if (update_flags & (HAIR_ADDED | HAIR_REMOVED)) { + device_update_flags |= DEVICE_CURVE_DATA_NEEDS_REALLOC; + } + + /* tag the device arrays for reallocation or modification */ + DeviceScene *dscene = &scene->dscene; + + if (device_update_flags & (DEVICE_MESH_DATA_NEEDS_REALLOC | DEVICE_CURVE_DATA_NEEDS_REALLOC)) { + delete scene->bvh; + scene->bvh = nullptr; + + dscene->bvh_nodes.tag_realloc(); + dscene->bvh_leaf_nodes.tag_realloc(); + dscene->object_node.tag_realloc(); + dscene->prim_tri_verts.tag_realloc(); + dscene->prim_tri_index.tag_realloc(); + dscene->prim_type.tag_realloc(); + dscene->prim_visibility.tag_realloc(); + dscene->prim_index.tag_realloc(); + dscene->prim_object.tag_realloc(); + dscene->prim_time.tag_realloc(); + + if (device_update_flags & DEVICE_MESH_DATA_NEEDS_REALLOC) { + dscene->tri_vnormal.tag_realloc(); + dscene->tri_vindex.tag_realloc(); + dscene->tri_patch.tag_realloc(); + dscene->tri_vnormal.tag_realloc(); + dscene->tri_patch_uv.tag_realloc(); + dscene->patches.tag_realloc(); + } + + if (device_update_flags & DEVICE_CURVE_DATA_NEEDS_REALLOC) { + dscene->curves.tag_realloc(); + dscene->curve_keys.tag_realloc(); + } + } + + if (device_update_flags & ATTR_FLOAT_NEEDS_REALLOC) { + dscene->attributes_map.tag_realloc(); + dscene->attributes_float.tag_realloc(); + } + else if (device_update_flags & ATTR_FLOAT_MODIFIED) { + dscene->attributes_float.tag_modified(); + } + + if (device_update_flags & ATTR_FLOAT2_NEEDS_REALLOC) { + dscene->attributes_map.tag_realloc(); + dscene->attributes_float2.tag_realloc(); + } + else if (device_update_flags & ATTR_FLOAT2_MODIFIED) { + dscene->attributes_float2.tag_modified(); + } + + if (device_update_flags & ATTR_FLOAT3_NEEDS_REALLOC) { + dscene->attributes_map.tag_realloc(); + dscene->attributes_float3.tag_realloc(); + } + else if (device_update_flags & ATTR_FLOAT3_MODIFIED) { + dscene->attributes_float3.tag_modified(); + } + + if (device_update_flags & ATTR_UCHAR4_NEEDS_REALLOC) { + dscene->attributes_map.tag_realloc(); + dscene->attributes_uchar4.tag_realloc(); + } + else if (device_update_flags & ATTR_UCHAR4_MODIFIED) { + dscene->attributes_uchar4.tag_modified(); + } + + if (device_update_flags & DEVICE_MESH_DATA_MODIFIED) { + /* if anything else than vertices or shaders are modified, we would need to reallocate, so + * these are the only arrays that can be updated */ + dscene->tri_vnormal.tag_modified(); + dscene->tri_shader.tag_modified(); + } + + if (device_update_flags & DEVICE_CURVE_DATA_MODIFIED) { + dscene->curve_keys.tag_modified(); + dscene->curves.tag_modified(); } need_flags_update = false; @@ -1423,7 +1705,7 @@ void GeometryManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; VLOG(1) << "Total " << scene->geometry.size() << " meshes."; @@ -1439,12 +1721,6 @@ void GeometryManager::device_update(Device *device, }); foreach (Geometry *geom, scene->geometry) { - foreach (Node *node, geom->get_used_shaders()) { - Shader *shader = static_cast<Shader *>(node); - if (shader->need_update_geometry) - geom->tag_modified(); - } - if (geom->is_modified() && (geom->geometry_type == Geometry::MESH || geom->geometry_type == Geometry::VOLUME)) { Mesh *mesh = static_cast<Mesh *>(geom); @@ -1541,7 +1817,7 @@ void GeometryManager::device_update(Device *device, } /* Device update. */ - device_free(device, dscene); + device_free(device, dscene, false); const BVHLayout bvh_layout = BVHParams::best_bvh_layout(scene->params.bvh_layout, device->get_bvh_layout_mask()); @@ -1614,7 +1890,7 @@ void GeometryManager::device_update(Device *device, {"device_update (displacement: attributes)", time}); } }); - device_free(device, dscene); + device_free(device, dscene, false); device_update_attributes(device, dscene, scene, progress); if (progress.get_cancel()) { @@ -1622,6 +1898,9 @@ void GeometryManager::device_update(Device *device, } } + /* update the bvh even when there is no geometry so the kernel bvh data is still valid, + * especially when removing all of the objects during interactive renders */ + bool need_update_scene_bvh = (scene->bvh == nullptr); { scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { @@ -1633,6 +1912,7 @@ void GeometryManager::device_update(Device *device, size_t i = 0; foreach (Geometry *geom, scene->geometry) { if (geom->is_modified()) { + need_update_scene_bvh = true; pool.push(function_bind( &Geometry::compute_bvh, geom, device, dscene, &scene->params, &progress, i, num_bvh)); if (geom->need_build_bvh(bvh_layout)) { @@ -1647,7 +1927,9 @@ void GeometryManager::device_update(Device *device, } foreach (Shader *shader, scene->shaders) { - shader->need_update_geometry = false; + shader->need_update_uvs = false; + shader->need_update_attribute = false; + shader->need_update_displacement = false; } Scene::MotionType need_motion = scene->need_motion(); @@ -1670,7 +1952,7 @@ void GeometryManager::device_update(Device *device, return; } - { + if (need_update_scene_bvh) { scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { scene->update_stats->geometry.times.add_entry({"device_update (build scene BVH)", time}); @@ -1695,8 +1977,6 @@ void GeometryManager::device_update(Device *device, } } - need_update = false; - if (true_displacement_used) { /* Re-tag flags for update, so they're re-evaluated * for meshes with correct bounding boxes. @@ -1706,33 +1986,71 @@ void GeometryManager::device_update(Device *device, */ scene->object_manager->need_flags_update = old_need_object_flags_update; } + + /* unset flags */ + + foreach (Geometry *geom, scene->geometry) { + geom->clear_modified(); + geom->attributes.clear_modified(); + + if (geom->is_mesh()) { + Mesh *mesh = static_cast<Mesh *>(geom); + mesh->subd_attributes.clear_modified(); + } + } + + update_flags = UPDATE_NONE; + + dscene->bvh_nodes.clear_modified(); + dscene->bvh_leaf_nodes.clear_modified(); + dscene->object_node.clear_modified(); + dscene->prim_tri_verts.clear_modified(); + dscene->prim_tri_index.clear_modified(); + dscene->prim_type.clear_modified(); + dscene->prim_visibility.clear_modified(); + dscene->prim_index.clear_modified(); + dscene->prim_object.clear_modified(); + dscene->prim_time.clear_modified(); + dscene->tri_shader.clear_modified(); + dscene->tri_vindex.clear_modified(); + dscene->tri_patch.clear_modified(); + dscene->tri_vnormal.clear_modified(); + dscene->tri_patch_uv.clear_modified(); + dscene->curves.clear_modified(); + dscene->curve_keys.clear_modified(); + dscene->patches.clear_modified(); + dscene->attributes_map.clear_modified(); + dscene->attributes_float.clear_modified(); + dscene->attributes_float2.clear_modified(); + dscene->attributes_float3.clear_modified(); + dscene->attributes_uchar4.clear_modified(); } -void GeometryManager::device_free(Device *device, DeviceScene *dscene) +void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool force_free) { - dscene->bvh_nodes.free(); - dscene->bvh_leaf_nodes.free(); - dscene->object_node.free(); - dscene->prim_tri_verts.free(); - dscene->prim_tri_index.free(); - dscene->prim_type.free(); - dscene->prim_visibility.free(); - dscene->prim_index.free(); - dscene->prim_object.free(); - dscene->prim_time.free(); - dscene->tri_shader.free(); - dscene->tri_vnormal.free(); - dscene->tri_vindex.free(); - dscene->tri_patch.free(); - dscene->tri_patch_uv.free(); - dscene->curves.free(); - dscene->curve_keys.free(); - dscene->patches.free(); - dscene->attributes_map.free(); - dscene->attributes_float.free(); - dscene->attributes_float2.free(); - dscene->attributes_float3.free(); - dscene->attributes_uchar4.free(); + dscene->bvh_nodes.free_if_need_realloc(force_free); + dscene->bvh_leaf_nodes.free_if_need_realloc(force_free); + dscene->object_node.free_if_need_realloc(force_free); + dscene->prim_tri_verts.free_if_need_realloc(force_free); + dscene->prim_tri_index.free_if_need_realloc(force_free); + dscene->prim_type.free_if_need_realloc(force_free); + dscene->prim_visibility.free_if_need_realloc(force_free); + dscene->prim_index.free_if_need_realloc(force_free); + dscene->prim_object.free_if_need_realloc(force_free); + dscene->prim_time.free_if_need_realloc(force_free); + dscene->tri_shader.free_if_need_realloc(force_free); + dscene->tri_vnormal.free_if_need_realloc(force_free); + dscene->tri_vindex.free_if_need_realloc(force_free); + dscene->tri_patch.free_if_need_realloc(force_free); + dscene->tri_patch_uv.free_if_need_realloc(force_free); + dscene->curves.free_if_need_realloc(force_free); + dscene->curve_keys.free_if_need_realloc(force_free); + dscene->patches.free_if_need_realloc(force_free); + dscene->attributes_map.free_if_need_realloc(force_free); + dscene->attributes_float.free_if_need_realloc(force_free); + dscene->attributes_float2.free_if_need_realloc(force_free); + dscene->attributes_float3.free_if_need_realloc(force_free); + dscene->attributes_uchar4.free_if_need_realloc(force_free); /* Signal for shaders like displacement not to do ray tracing. */ dscene->data.bvh.bvh_layout = BVH_LAYOUT_NONE; @@ -1750,10 +2068,19 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene) #endif } -void GeometryManager::tag_update(Scene *scene) +void GeometryManager::tag_update(Scene *scene, uint32_t flag) +{ + update_flags |= flag; + + /* do not tag the object manager for an update if it is the one who tagged us */ + if ((flag & OBJECT_MANAGER) == 0) { + scene->object_manager->tag_update(scene, ObjectManager::GEOMETRY_MANAGER); + } +} + +bool GeometryManager::need_update() const { - need_update = true; - scene->object_manager->need_update = true; + return update_flags != UPDATE_NONE; } void GeometryManager::collect_statistics(const Scene *scene, RenderStats *stats) diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h index b124e950ad2..88388f31a9b 100644 --- a/intern/cycles/render/geometry.h +++ b/intern/cycles/render/geometry.h @@ -125,7 +125,7 @@ class Geometry : public Node { int n, int total); - virtual void pack_primitives(PackedBVH &pack, int object, uint visibility) = 0; + virtual void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) = 0; /* Check whether the geometry should have own BVH built separately. Briefly, * own BVH is needed for geometry, if: @@ -155,6 +155,11 @@ class Geometry : public Node { return geometry_type == HAIR; } + bool is_volume() const + { + return geometry_type == VOLUME; + } + /* Updates */ void tag_update(Scene *scene, bool rebuild); @@ -164,9 +169,32 @@ class Geometry : public Node { /* Geometry Manager */ class GeometryManager { + uint32_t update_flags; + public: + enum : uint32_t { + UV_PASS_NEEDED = (1 << 0), + MOTION_PASS_NEEDED = (1 << 1), + GEOMETRY_MODIFIED = (1 << 2), + OBJECT_MANAGER = (1 << 3), + MESH_ADDED = (1 << 4), + MESH_REMOVED = (1 << 5), + HAIR_ADDED = (1 << 6), + HAIR_REMOVED = (1 << 7), + + SHADER_ATTRIBUTE_MODIFIED = (1 << 8), + SHADER_DISPLACEMENT_MODIFIED = (1 << 9), + + GEOMETRY_ADDED = MESH_ADDED | HAIR_ADDED, + GEOMETRY_REMOVED = MESH_REMOVED | HAIR_REMOVED, + + /* tag everything in the manager for an update */ + UPDATE_ALL = ~0u, + + UPDATE_NONE = 0u, + }; + /* Update Flags */ - bool need_update; bool need_flags_update; /* Constructor/Destructor */ @@ -176,10 +204,12 @@ class GeometryManager { /* Device Updates */ void device_update_preprocess(Device *device, Scene *scene, Progress &progress); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, bool force_free); /* Updates */ - void tag_update(Scene *scene); + void tag_update(Scene *scene, uint32_t flag); + + bool need_update() const; /* Statistics */ void collect_statistics(const Scene *scene, RenderStats *stats); diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index 4adfebf80ae..5e068e74ce0 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -276,7 +276,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to) emission->set_color(make_float3(1.0f, 1.0f, 1.0f)); emission->set_strength(1.0f); convert = add(emission); - /* Connect float inputs to Strength to save an additional Falue->Color conversion. */ + /* Connect float inputs to Strength to save an additional Value->Color conversion. */ if (from->type() == SocketType::FLOAT) { convert_in = convert->input("Strength"); } diff --git a/intern/cycles/render/hair.cpp b/intern/cycles/render/hair.cpp index 896e798b6f9..e94cad6b32e 100644 --- a/intern/cycles/render/hair.cpp +++ b/intern/cycles/render/hair.cpp @@ -494,33 +494,38 @@ void Hair::pack_curves(Scene *scene, } } -void Hair::pack_primitives(PackedBVH &pack, int object, uint visibility) +void Hair::pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) { if (curve_first_key.empty()) return; - const size_t num_prims = num_segments(); - pack.prim_tri_index.reserve(pack.prim_tri_index.size() + num_prims); - pack.prim_type.reserve(pack.prim_type.size() + num_prims); - pack.prim_visibility.reserve(pack.prim_visibility.size() + num_prims); - pack.prim_index.reserve(pack.prim_index.size() + num_prims); - pack.prim_object.reserve(pack.prim_object.size() + num_prims); - // 'pack.prim_time' is unused by Embree and OptiX + /* If the BVH does not have to be recreated, we can bail out. */ + if (!pack_all) { + return; + } + + unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset]; + int *prim_type = &pack->prim_type[optix_prim_offset]; + unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset]; + int *prim_index = &pack->prim_index[optix_prim_offset]; + int *prim_object = &pack->prim_object[optix_prim_offset]; + // 'pack->prim_time' is unused by Embree and OptiX uint type = has_motion_blur() ? ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : PRIMITIVE_MOTION_CURVE_THICK) : ((curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK); + size_t index = 0; for (size_t j = 0; j < num_curves(); ++j) { Curve curve = get_curve(j); - for (size_t k = 0; k < curve.num_segments(); ++k) { - pack.prim_tri_index.push_back_reserved(-1); - pack.prim_type.push_back_reserved(PRIMITIVE_PACK_SEGMENT(type, k)); - pack.prim_visibility.push_back_reserved(visibility); + for (size_t k = 0; k < curve.num_segments(); ++k, ++index) { + prim_tri_index[index] = -1; + prim_type[index] = PRIMITIVE_PACK_SEGMENT(type, k); + prim_visibility[index] = visibility; // Each curve segment points back to its curve index - pack.prim_index.push_back_reserved(j + prim_offset); - pack.prim_object.push_back_reserved(object); + prim_index[index] = j + prim_offset; + prim_object[index] = object; } } } diff --git a/intern/cycles/render/hair.h b/intern/cycles/render/hair.h index c7be08d679c..4b949f984e5 100644 --- a/intern/cycles/render/hair.h +++ b/intern/cycles/render/hair.h @@ -146,7 +146,7 @@ class Hair : public Geometry { /* BVH */ void pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset); - void pack_primitives(PackedBVH &pack, int object, uint visibility) override; + void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 30858c4f68b..29a95beaf7e 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -298,7 +298,7 @@ bool ImageLoader::is_vdb_loader() const ImageManager::ImageManager(const DeviceInfo &info) { - need_update = true; + need_update_ = true; osl_texture_system = NULL; animation_frame = 0; @@ -419,7 +419,7 @@ int ImageManager::add_image_slot(ImageLoader *loader, thread_scoped_lock device_lock(images_mutex); - /* Fnd existing image. */ + /* Find existing image. */ for (slot = 0; slot < images.size(); slot++) { img = images[slot]; if (img && ImageLoader::equals(img->loader, loader) && img->params == params) { @@ -451,7 +451,7 @@ int ImageManager::add_image_slot(ImageLoader *loader, images[slot] = img; - need_update = true; + need_update_ = true; return slot; } @@ -478,7 +478,7 @@ void ImageManager::remove_image_user(int slot) * the reasons for this is that on shader changes we add and remove nodes * that use them, but we do not want to reload the image all the time. */ if (image->users == 0) - need_update = true; + need_update_ = true; } static bool image_associate_alpha(ImageManager::Image *img) @@ -810,7 +810,7 @@ void ImageManager::device_free_image(Device *, int slot) void ImageManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) { + if (!need_update()) { return; } @@ -834,7 +834,7 @@ void ImageManager::device_update(Device *device, Scene *scene, Progress &progres pool.wait_work(); - need_update = false; + need_update_ = false; } void ImageManager::device_update_slot(Device *device, Scene *scene, int slot, Progress *progress) @@ -854,7 +854,7 @@ void ImageManager::device_load_builtin(Device *device, Scene *scene, Progress &p { /* Load only builtin images, Blender needs this to load evaluated * scene data from depsgraph before it is freed. */ - if (!need_update) { + if (!need_update()) { return; } @@ -896,4 +896,14 @@ void ImageManager::collect_statistics(RenderStats *stats) } } +void ImageManager::tag_update() +{ + need_update_ = true; +} + +bool ImageManager::need_update() const +{ + return need_update_; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h index 6ac1db9ed63..c802521db56 100644 --- a/intern/cycles/render/image.h +++ b/intern/cycles/render/image.h @@ -189,7 +189,9 @@ class ImageManager { void collect_statistics(RenderStats *stats); - bool need_update; + void tag_update(); + + bool need_update() const; struct Image { ImageParams params; @@ -209,6 +211,7 @@ class ImageManager { }; private: + bool need_update_; bool has_half_images; thread_mutex device_mutex; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index e5b9e6bfabf..d93856ceb61 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -17,9 +17,11 @@ #include "render/integrator.h" #include "device/device.h" #include "render/background.h" +#include "render/camera.h" #include "render/film.h" #include "render/jitter.h" #include "render/light.h" +#include "render/object.h" #include "render/scene.h" #include "render/shader.h" #include "render/sobol.h" @@ -113,6 +115,18 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene } }); + const bool need_update_lut = ao_samples_is_modified() || diffuse_samples_is_modified() || + glossy_samples_is_modified() || max_bounce_is_modified() || + max_transmission_bounce_is_modified() || + mesh_light_samples_is_modified() || method_is_modified() || + sampling_pattern_is_modified() || + subsurface_samples_is_modified() || + transmission_samples_is_modified() || volume_samples_is_modified(); + + if (need_update_lut) { + dscene->sample_pattern_lut.tag_realloc(); + } + device_free(device, dscene); KernelIntegrator *kintegrator = &dscene->data.integrator; @@ -242,45 +256,69 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene int dimensions = PRNG_BASE_NUM + max_samples * PRNG_BOUNCE_NUM; dimensions = min(dimensions, SOBOL_MAX_DIMENSIONS); - if (sampling_pattern == SAMPLING_PATTERN_SOBOL) { - uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions); + if (need_update_lut) { + if (sampling_pattern == SAMPLING_PATTERN_SOBOL) { + uint *directions = dscene->sample_pattern_lut.alloc(SOBOL_BITS * dimensions); - sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions); + sobol_generate_direction_vectors((uint(*)[SOBOL_BITS])directions, dimensions); - dscene->sample_pattern_lut.copy_to_device(); - } - else { - constexpr int sequence_size = NUM_PMJ_SAMPLES; - constexpr int num_sequences = NUM_PMJ_PATTERNS; - float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size * num_sequences * - 2); - TaskPool pool; - for (int j = 0; j < num_sequences; ++j) { - float2 *sequence = directions + j * sequence_size; - pool.push( - function_bind(&progressive_multi_jitter_02_generate_2D, sequence, sequence_size, j)); + dscene->sample_pattern_lut.copy_to_device(); + } + else { + constexpr int sequence_size = NUM_PMJ_SAMPLES; + constexpr int num_sequences = NUM_PMJ_PATTERNS; + float2 *directions = (float2 *)dscene->sample_pattern_lut.alloc(sequence_size * + num_sequences * 2); + TaskPool pool; + for (int j = 0; j < num_sequences; ++j) { + float2 *sequence = directions + j * sequence_size; + pool.push( + function_bind(&progressive_multi_jitter_02_generate_2D, sequence, sequence_size, j)); + } + pool.wait_work(); + dscene->sample_pattern_lut.copy_to_device(); } - pool.wait_work(); - dscene->sample_pattern_lut.copy_to_device(); } + dscene->sample_pattern_lut.clear_modified(); clear_modified(); } -void Integrator::device_free(Device *, DeviceScene *dscene) +void Integrator::device_free(Device *, DeviceScene *dscene, bool force_free) { - dscene->sample_pattern_lut.free(); + dscene->sample_pattern_lut.free_if_need_realloc(force_free); } -void Integrator::tag_update(Scene *scene) +void Integrator::tag_update(Scene *scene, uint32_t flag) { - foreach (Shader *shader, scene->shaders) { - if (shader->has_integrator_dependency) { - scene->shader_manager->need_update = true; - break; + if (flag & UPDATE_ALL) { + tag_modified(); + } + + if (flag & (AO_PASS_MODIFIED | BACKGROUND_AO_MODIFIED)) { + /* tag only the ao_bounces socket as modified so we avoid updating sample_pattern_lut + * unnecessarily */ + tag_ao_bounces_modified(); + } + + if ((flag & LIGHT_SAMPLES_MODIFIED) && (method == BRANCHED_PATH)) { + /* the number of light samples may affect the size of the sample_pattern_lut */ + tag_sampling_pattern_modified(); + } + + if (filter_glossy_is_modified()) { + foreach (Shader *shader, scene->shaders) { + if (shader->has_integrator_dependency) { + scene->shader_manager->tag_update(scene, ShaderManager::INTEGRATOR_MODIFIED); + break; + } } } - tag_modified(); + + if (motion_blur_is_modified()) { + scene->object_manager->tag_update(scene, ObjectManager::MOTION_BLUR_MODIFIED); + scene->camera->tag_modified(); + } } CCL_NAMESPACE_END diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 9fe46ad591c..4eeeda92d41 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -89,13 +89,24 @@ class Integrator : public Node { NODE_SOCKET_API(SamplingPattern, sampling_pattern) + enum : uint32_t { + AO_PASS_MODIFIED = (1 << 0), + BACKGROUND_AO_MODIFIED = (1 << 1), + LIGHT_SAMPLES_MODIFIED = (1 << 2), + + /* tag everything in the manager for an update */ + UPDATE_ALL = ~0u, + + UPDATE_NONE = 0u, + }; + Integrator(); ~Integrator(); void device_update(Device *device, DeviceScene *dscene, Scene *scene); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, bool force_free = false); - void tag_update(Scene *scene); + void tag_update(Scene *scene, uint32_t flag); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index 2bde3242b26..1e54a237816 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -162,7 +162,13 @@ Light::Light() : Node(node_type) void Light::tag_update(Scene *scene) { - scene->light_manager->need_update = is_modified(); + if (is_modified()) { + scene->light_manager->tag_update(scene, LightManager::LIGHT_MODIFIED); + + if (samples_is_modified()) { + scene->integrator->tag_update(scene, Integrator::LIGHT_SAMPLES_MODIFIED); + } + } } bool Light::has_contribution(Scene *scene) @@ -183,7 +189,7 @@ bool Light::has_contribution(Scene *scene) LightManager::LightManager() { - need_update = true; + update_flags = UPDATE_ALL; need_update_background = true; use_light_visibility = false; last_background_enabled = false; @@ -962,7 +968,7 @@ void LightManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -973,7 +979,7 @@ void LightManager::device_update(Device *device, VLOG(1) << "Total " << scene->lights.size() << " lights."; - /* Detect which lights are enabled, also determins if we need to update the background. */ + /* Detect which lights are enabled, also determines if we need to update the background. */ test_enabled_lights(scene); device_free(device, dscene, need_update_background); @@ -1000,7 +1006,7 @@ void LightManager::device_update(Device *device, scene->film->set_use_light_visibility(use_light_visibility); - need_update = false; + update_flags = UPDATE_NONE; need_update_background = false; } @@ -1015,9 +1021,14 @@ void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_ba dscene->ies_lights.free(); } -void LightManager::tag_update(Scene * /*scene*/) +void LightManager::tag_update(Scene * /*scene*/, uint32_t flag) +{ + update_flags |= flag; +} + +bool LightManager::need_update() const { - need_update = true; + return update_flags != UPDATE_NONE; } int LightManager::add_ies_from_file(const string &filename) @@ -1063,7 +1074,7 @@ int LightManager::add_ies(const string &content) ies_slots[slot]->users = 1; ies_slots[slot]->hash = hash; - need_update = true; + update_flags = UPDATE_ALL; need_update_background = true; return slot; @@ -1082,8 +1093,10 @@ void LightManager::remove_ies(int slot) ies_slots[slot]->users--; /* If the slot has no more users, update the device to remove it. */ - need_update |= (ies_slots[slot]->users == 0); - need_update_background |= need_update; + if (ies_slots[slot]->users == 0) { + update_flags |= UPDATE_ALL; + need_update_background = true; + } } void LightManager::device_update_ies(DeviceScene *dscene) diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h index e590e13b489..39014b5d667 100644 --- a/intern/cycles/render/light.h +++ b/intern/cycles/render/light.h @@ -91,8 +91,23 @@ class Light : public Node { class LightManager { public: + enum : uint32_t { + MESH_NEED_REBUILD = (1 << 0), + EMISSIVE_MESH_MODIFIED = (1 << 1), + LIGHT_MODIFIED = (1 << 2), + LIGHT_ADDED = (1 << 3), + LIGHT_REMOVED = (1 << 4), + OBJECT_MANAGER = (1 << 5), + SHADER_COMPILED = (1 << 6), + SHADER_MODIFIED = (1 << 7), + + /* tag everything in the manager for an update */ + UPDATE_ALL = ~0u, + + UPDATE_NONE = 0u, + }; + bool use_light_visibility; - bool need_update; /* Need to update background (including multiple importance map) */ bool need_update_background; @@ -108,7 +123,9 @@ class LightManager { void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); void device_free(Device *device, DeviceScene *dscene, const bool free_background = true); - void tag_update(Scene *scene); + void tag_update(Scene *scene, uint32_t flag); + + bool need_update() const; /* Check whether there is a background light. */ bool has_background_light(Scene *scene); @@ -145,6 +162,8 @@ class LightManager { bool last_background_enabled; int last_background_resolution; + + uint32_t update_flags; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/merge.cpp b/intern/cycles/render/merge.cpp index 3ea3952b96c..8a58c827e82 100644 --- a/intern/cycles/render/merge.cpp +++ b/intern/cycles/render/merge.cpp @@ -151,7 +151,7 @@ static bool parse_channels(const ImageSpec &in_spec, string layername, passname, channelname; if (parse_channel_name( pass.channel_name, layername, passname, channelname, multiview_channels)) { - /* Channer part of a render layer. */ + /* Channel part of a render layer. */ pass.op = parse_channel_operation(passname); } else { @@ -163,7 +163,7 @@ static bool parse_channels(const ImageSpec &in_spec, file_layers[layername].passes.push_back(pass); } - /* Loop over all detected RenderLayers, check whether they contain a full set of input channels. + /* Loop over all detected render-layers, check whether they contain a full set of input channels. * Any channels that won't be processed internally are also passed through. */ for (auto &i : file_layers) { const string &name = i.first; @@ -457,7 +457,7 @@ static bool save_output(const string &filepath, out.reset(); - /* Copy temporary file to outputput filepath. */ + /* Copy temporary file to output filepath. */ string rename_error; if (ok && !OIIO::Filesystem::rename(tmp_filepath, filepath, rename_error)) { error = "Failed to move merged image to " + filepath + ": " + rename_error; diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index a0afdd3b841..5f62da8f18b 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -805,34 +805,42 @@ void Mesh::pack_patches(uint *patch_data, uint vert_offset, uint face_offset, ui } } -void Mesh::pack_primitives(PackedBVH &pack, int object, uint visibility) +void Mesh::pack_primitives(ccl::PackedBVH *pack, int object, uint visibility, bool pack_all) { if (triangles.empty()) return; const size_t num_prims = num_triangles(); - pack.prim_tri_index.reserve(pack.prim_tri_index.size() + num_prims); - pack.prim_tri_verts.reserve(pack.prim_tri_verts.size() + num_prims * 3); - pack.prim_type.reserve(pack.prim_type.size() + num_prims); - pack.prim_visibility.reserve(pack.prim_visibility.size() + num_prims); - pack.prim_index.reserve(pack.prim_index.size() + num_prims); - pack.prim_object.reserve(pack.prim_object.size() + num_prims); - // 'pack.prim_time' is unused by Embree and OptiX + + /* Use prim_offset for indexing as it is computed per geometry type, and prim_tri_verts does not + * contain data for Hair geometries. */ + float4 *prim_tri_verts = &pack->prim_tri_verts[prim_offset * 3]; + // 'pack->prim_time' is unused by Embree and OptiX uint type = has_motion_blur() ? PRIMITIVE_MOTION_TRIANGLE : PRIMITIVE_TRIANGLE; - for (size_t k = 0; k < num_prims; ++k) { - pack.prim_tri_index.push_back_reserved(pack.prim_tri_verts.size()); + if (pack_all) { + /* Use optix_prim_offset for indexing as those arrays also contain data for Hair geometries. */ + unsigned int *prim_tri_index = &pack->prim_tri_index[optix_prim_offset]; + int *prim_type = &pack->prim_type[optix_prim_offset]; + unsigned int *prim_visibility = &pack->prim_visibility[optix_prim_offset]; + int *prim_index = &pack->prim_index[optix_prim_offset]; + int *prim_object = &pack->prim_object[optix_prim_offset]; + + for (size_t k = 0; k < num_prims; ++k) { + prim_tri_index[k] = (prim_offset + k) * 3; + prim_type[k] = type; + prim_index[k] = prim_offset + k; + prim_object[k] = object; + prim_visibility[k] = visibility; + } + } + for (size_t k = 0; k < num_prims; ++k) { const Mesh::Triangle t = get_triangle(k); - pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[0]])); - pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[1]])); - pack.prim_tri_verts.push_back_reserved(float3_to_float4(verts[t.v[2]])); - - pack.prim_type.push_back_reserved(type); - pack.prim_visibility.push_back_reserved(visibility); - pack.prim_index.push_back_reserved(k + prim_offset); - pack.prim_object.push_back_reserved(object); + prim_tri_verts[k * 3] = float3_to_float4(verts[t.v[0]]); + prim_tri_verts[k * 3 + 1] = float3_to_float4(verts[t.v[1]]); + prim_tri_verts[k * 3 + 2] = float3_to_float4(verts[t.v[2]]); } } diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index b0a16fdfd8f..2b0ff92ab62 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -232,7 +232,7 @@ class Mesh : public Geometry { size_t tri_offset); void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset); - void pack_primitives(PackedBVH &pack, int object, uint visibility) override; + void pack_primitives(PackedBVH *pack, int object, uint visibility, bool pack_all) override; void tessellate(DiagSplit *split); diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 4d51b4fccaf..d4603143ef4 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -1612,7 +1612,7 @@ class OSLNode : public ShaderNode { SHADER_NODE_NO_CLONE_CLASS(OSLNode) - /* ideally we could beter detect this, but we can't query this now */ + /* Ideally we could better detect this, but we can't query this now. */ bool has_spatial_varying() { return true; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 406982e3ef9..e837be9e6fb 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -153,6 +153,10 @@ void Object::update_motion() void Object::compute_bounds(bool motion_blur) { + if (!is_modified() && !geometry->is_modified()) { + return; + } + BoundBox mbounds = geometry->bounds; if (motion_blur && use_motion()) { @@ -205,20 +209,39 @@ void Object::apply_transform(bool apply_to_motion) void Object::tag_update(Scene *scene) { + uint32_t flag = ObjectManager::UPDATE_NONE; + + if (is_modified()) { + flag |= ObjectManager::OBJECT_MODIFIED; + + if (use_holdout_is_modified()) { + flag |= ObjectManager::HOLDOUT_MODIFIED; + } + } + if (geometry) { - if (geometry->transform_applied) - geometry->tag_modified(); + if (tfm_is_modified()) { + /* tag the geometry as modified so the BVH is updated, but do not tag everything as modified + */ + if (geometry->is_mesh() || geometry->is_volume()) { + Mesh *mesh = static_cast<Mesh *>(geometry); + mesh->tag_verts_modified(); + } + else if (geometry->is_hair()) { + Hair *hair = static_cast<Hair *>(geometry); + hair->tag_curve_keys_modified(); + } + } foreach (Node *node, geometry->get_used_shaders()) { Shader *shader = static_cast<Shader *>(node); if (shader->get_use_mis() && shader->has_surface_emission) - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::EMISSIVE_MESH_MODIFIED); } } scene->camera->need_flags_update = true; - scene->geometry_manager->need_update = true; - scene->object_manager->need_update = true; + scene->object_manager->tag_update(scene, flag); } bool Object::use_motion() const @@ -361,7 +384,7 @@ int Object::get_device_index() const ObjectManager::ObjectManager() { - need_update = true; + update_flags = UPDATE_ALL; need_flags_update = true; } @@ -382,7 +405,9 @@ static float object_volume_density(const Transform &tfm, Geometry *geom) return 1.0f; } -void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, Object *ob) +void ObjectManager::device_update_object_transform(UpdateObjectTransformState *state, + Object *ob, + bool update_all) { KernelObject &kobject = state->objects[ob->index]; Transform *object_motion_pass = state->object_motion_pass; @@ -456,8 +481,11 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.motion_offset = state->motion_offset[ob->index]; /* Decompose transforms for interpolation. */ - DecomposedTransform *decomp = state->object_motion + kobject.motion_offset; - transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size()); + if (ob->tfm_is_modified() || update_all) { + DecomposedTransform *decomp = state->object_motion + kobject.motion_offset; + transform_motion_decompose(decomp, ob->motion.data(), ob->motion.size()); + } + flag |= SD_OBJECT_MOTION; state->have_motion = true; } @@ -480,10 +508,14 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s 0; kobject.patch_map_offset = 0; kobject.attribute_map_offset = 0; - uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0); - uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0); - kobject.cryptomatte_object = util_hash_to_float(hash_name); - kobject.cryptomatte_asset = util_hash_to_float(hash_asset); + + if (ob->asset_name_is_modified() || update_all) { + uint32_t hash_name = util_murmur_hash3(ob->name.c_str(), ob->name.length(), 0); + uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0); + kobject.cryptomatte_object = util_hash_to_float(hash_name); + kobject.cryptomatte_asset = util_hash_to_float(hash_asset); + } + kobject.shadow_terminator_offset = 1.0f / (1.0f - 0.5f * ob->shadow_terminator_offset); /* Object flag. */ @@ -544,6 +576,9 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, numparticles += psys->particles.size(); } + /* as all the arrays are the same size, checking only dscene.objects is sufficient */ + const bool update_all = dscene->objects.need_realloc(); + /* Parallel object update, with grain size to avoid too much threading overhead * for individual objects. */ static const int OBJECTS_PER_TASK = 32; @@ -551,7 +586,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, [&](const blocked_range<size_t> &r) { for (size_t i = r.begin(); i != r.end(); i++) { Object *ob = state.scene->objects[i]; - device_update_object_transform(&state, ob); + device_update_object_transform(&state, ob, update_all); } }); @@ -559,7 +594,7 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, return; } - dscene->objects.copy_to_device(); + dscene->objects.copy_to_device_if_modified(); if (state.need_motion == Scene::MOTION_PASS) { dscene->object_motion_pass.copy_to_device(); } @@ -569,6 +604,10 @@ void ObjectManager::device_update_transforms(DeviceScene *dscene, Scene *scene, dscene->data.bvh.have_motion = state.have_motion; dscene->data.bvh.have_curves = state.have_curves; + + dscene->objects.clear_modified(); + dscene->object_motion_pass.clear_modified(); + dscene->object_motion.clear_modified(); } void ObjectManager::device_update(Device *device, @@ -576,12 +615,28 @@ void ObjectManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; + if (update_flags & (OBJECT_ADDED | OBJECT_REMOVED)) { + dscene->objects.tag_realloc(); + dscene->object_motion_pass.tag_realloc(); + dscene->object_motion.tag_realloc(); + dscene->object_flag.tag_realloc(); + dscene->object_volume_step.tag_realloc(); + } + + if (update_flags & HOLDOUT_MODIFIED) { + dscene->object_flag.tag_modified(); + } + + if (update_flags & PARTICLE_MODIFIED) { + dscene->objects.tag_modified(); + } + VLOG(1) << "Total " << scene->objects.size() << " objects."; - device_free(device, dscene); + device_free(device, dscene, false); if (scene->objects.size() == 0) return; @@ -597,6 +652,16 @@ void ObjectManager::device_update(Device *device, int index = 0; foreach (Object *object, scene->objects) { object->index = index++; + + /* this is a bit too broad, however a bigger refactor might be needed to properly separate + * update each type of data (transform, flags, etc.) */ + if (object->is_modified()) { + dscene->objects.tag_modified(); + dscene->object_motion_pass.tag_modified(); + dscene->object_motion.tag_modified(); + dscene->object_flag.tag_modified(); + dscene->object_volume_step.tag_modified(); + } } } @@ -638,7 +703,7 @@ void ObjectManager::device_update(Device *device, void ObjectManager::device_update_flags( Device *, DeviceScene *dscene, Scene *scene, Progress & /*progress*/, bool bounds_valid) { - if (!need_update && !need_flags_update) + if (!need_update() && !need_flags_update) return; scoped_callback_timer timer([scene](double time) { @@ -647,7 +712,7 @@ void ObjectManager::device_update_flags( } }); - need_update = false; + update_flags = UPDATE_NONE; need_flags_update = false; if (scene->objects.size() == 0) @@ -717,6 +782,9 @@ void ObjectManager::device_update_flags( /* Copy object flag. */ dscene->object_flag.copy_to_device(); dscene->object_volume_step.copy_to_device(); + + dscene->object_flag.clear_modified(); + dscene->object_volume_step.clear_modified(); } void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Scene *scene) @@ -764,13 +832,13 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc } } -void ObjectManager::device_free(Device *, DeviceScene *dscene) +void ObjectManager::device_free(Device *, DeviceScene *dscene, bool force_free) { - dscene->objects.free(); - dscene->object_motion_pass.free(); - dscene->object_motion.free(); - dscene->object_flag.free(); - dscene->object_volume_step.free(); + dscene->objects.free_if_need_realloc(force_free); + dscene->object_motion_pass.free_if_need_realloc(force_free); + dscene->object_motion.free_if_need_realloc(force_free); + dscene->object_flag.free_if_need_realloc(force_free); + dscene->object_volume_step.free_if_need_realloc(force_free); } void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress) @@ -841,11 +909,29 @@ void ObjectManager::apply_static_transforms(DeviceScene *dscene, Scene *scene, P } } -void ObjectManager::tag_update(Scene *scene) +void ObjectManager::tag_update(Scene *scene, uint32_t flag) +{ + update_flags |= flag; + + /* avoid infinite loops if the geometry manager tagged us for an update */ + if ((flag & GEOMETRY_MANAGER) == 0) { + uint32_t geometry_flag = GeometryManager::OBJECT_MANAGER; + + /* Also notify in case added or removed objects were instances, as no Geometry might have been + * added or removed, but the BVH still needs to updated. */ + if ((flag & (OBJECT_ADDED | OBJECT_REMOVED)) != 0) { + geometry_flag |= (GeometryManager::GEOMETRY_ADDED | GeometryManager::GEOMETRY_REMOVED); + } + + scene->geometry_manager->tag_update(scene, geometry_flag); + } + + scene->light_manager->tag_update(scene, LightManager::OBJECT_MANAGER); +} + +bool ObjectManager::need_update() const { - need_update = true; - scene->geometry_manager->need_update = true; - scene->light_manager->need_update = true; + return update_flags != UPDATE_NONE; } string ObjectManager::get_cryptomatte_objects(Scene *scene) diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 76c9c30abb0..cf1b9ca510a 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -122,8 +122,24 @@ class Object : public Node { /* Object Manager */ class ObjectManager { + uint32_t update_flags; + public: - bool need_update; + enum : uint32_t { + PARTICLE_MODIFIED = (1 << 0), + GEOMETRY_MANAGER = (1 << 1), + MOTION_BLUR_MODIFIED = (1 << 2), + OBJECT_ADDED = (1 << 3), + OBJECT_REMOVED = (1 << 4), + OBJECT_MODIFIED = (1 << 5), + HOLDOUT_MODIFIED = (1 << 6), + + /* tag everything in the manager for an update */ + UPDATE_ALL = ~0u, + + UPDATE_NONE = 0u, + }; + bool need_flags_update; ObjectManager(); @@ -139,9 +155,11 @@ class ObjectManager { bool bounds_valid = true); void device_update_mesh_offsets(Device *device, DeviceScene *dscene, Scene *scene); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, bool force_free); - void tag_update(Scene *scene); + void tag_update(Scene *scene, uint32_t flag); + + bool need_update() const; void apply_static_transforms(DeviceScene *dscene, Scene *scene, Progress &progress); @@ -149,7 +167,9 @@ class ObjectManager { string get_cryptomatte_assets(Scene *scene); protected: - void device_update_object_transform(UpdateObjectTransformState *state, Object *ob); + void device_update_object_transform(UpdateObjectTransformState *state, + Object *ob, + bool update_all); void device_update_object_transform_task(UpdateObjectTransformState *state); bool device_update_object_transform_pop_work(UpdateObjectTransformState *state, int *start_index, diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 35b62746f1b..53c67049571 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -96,7 +96,7 @@ void OSLShaderManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -132,7 +132,7 @@ void OSLShaderManager::device_update(Device *device, compiler.compile(og, shader); if (shader->get_use_mis() && shader->has_surface_emission) - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::SHADER_COMPILED); } /* setup shader engine */ @@ -147,7 +147,7 @@ void OSLShaderManager::device_update(Device *device, foreach (Shader *shader, scene->shaders) shader->clear_modified(); - need_update = false; + update_flags = UPDATE_NONE; /* add special builtin texture types */ services->textures.insert(ustring("@ao"), new OSLTextureHandle(OSLTextureHandle::AO)); @@ -380,7 +380,7 @@ const char *OSLShaderManager::shader_load_filepath(string filepath) return hash; } - /* autocompile .OSL to .OSO if needed */ + /* Auto-compile .OSL to .OSO if needed. */ if (oso_modified_time == 0 || (oso_modified_time < modified_time)) { OSLShaderManager::osl_compile(filepath, osopath); modified_time = path_modified_time(osopath); @@ -562,7 +562,7 @@ OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph, } } - /* set bytcode hash or filepath */ + /* Set byte-code hash or file-path. */ if (!bytecode_hash.empty()) { node->bytecode_hash = bytecode_hash; } diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index faad731d413..0e168050281 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -46,14 +46,14 @@ ParticleSystem::~ParticleSystem() void ParticleSystem::tag_update(Scene *scene) { - scene->particle_system_manager->need_update = true; + scene->particle_system_manager->tag_update(scene); } /* Particle System Manager */ ParticleSystemManager::ParticleSystemManager() { - need_update = true; + need_update_ = true; } ParticleSystemManager::~ParticleSystemManager() @@ -109,7 +109,7 @@ void ParticleSystemManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -128,7 +128,7 @@ void ParticleSystemManager::device_update(Device *device, if (progress.get_cancel()) return; - need_update = false; + need_update_ = false; } void ParticleSystemManager::device_free(Device *, DeviceScene *dscene) @@ -138,7 +138,12 @@ void ParticleSystemManager::device_free(Device *, DeviceScene *dscene) void ParticleSystemManager::tag_update(Scene * /*scene*/) { - need_update = true; + need_update_ = true; +} + +bool ParticleSystemManager::need_update() const +{ + return need_update_; } CCL_NAMESPACE_END diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h index 0b0408184fe..8b59756f148 100644 --- a/intern/cycles/render/particles.h +++ b/intern/cycles/render/particles.h @@ -57,9 +57,9 @@ class ParticleSystem : public Node { /* ParticleSystem Manager */ class ParticleSystemManager { - public: - bool need_update; + bool need_update_; + public: ParticleSystemManager(); ~ParticleSystemManager(); @@ -71,6 +71,8 @@ class ParticleSystemManager { void device_free(Device *device, DeviceScene *dscene); void tag_update(Scene *scene); + + bool need_update() const; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/procedural.cpp b/intern/cycles/render/procedural.cpp new file mode 100644 index 00000000000..1307a35dcf2 --- /dev/null +++ b/intern/cycles/render/procedural.cpp @@ -0,0 +1,89 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "procedural.h" + +#include "render/scene.h" +#include "render/stats.h" + +#include "util/util_foreach.h" +#include "util/util_progress.h" + +CCL_NAMESPACE_BEGIN + +NODE_ABSTRACT_DEFINE(Procedural) +{ + NodeType *type = NodeType::add("procedural_base", NULL); + return type; +} + +Procedural::Procedural(const NodeType *type) : Node(type) +{ +} + +Procedural::~Procedural() +{ +} + +ProceduralManager::ProceduralManager() +{ + need_update_ = true; +} + +ProceduralManager::~ProceduralManager() +{ +} + +void ProceduralManager::update(Scene *scene, Progress &progress) +{ + if (!need_update()) { + return; + } + + progress.set_status("Updating Procedurals"); + + scoped_callback_timer timer([scene](double time) { + if (scene->update_stats) { + scene->update_stats->procedurals.times.add_entry({"update", time}); + } + }); + + foreach (Procedural *procedural, scene->procedurals) { + if (progress.get_cancel()) { + return; + } + + procedural->generate(scene, progress); + } + + if (progress.get_cancel()) { + return; + } + + need_update_ = false; +} + +void ProceduralManager::tag_update() +{ + need_update_ = true; +} + +bool ProceduralManager::need_update() const +{ + return need_update_; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/procedural.h b/intern/cycles/render/procedural.h new file mode 100644 index 00000000000..985b8d69979 --- /dev/null +++ b/intern/cycles/render/procedural.h @@ -0,0 +1,73 @@ +/* + * Copyright 2011-2018 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "graph/node.h" + +CCL_NAMESPACE_BEGIN + +class Progress; +class Scene; + +/* A Procedural is a Node which can create other Nodes before rendering starts. + * + * The Procedural is supposed to be the owner of any nodes that it creates. It can also create + * Nodes directly in the Scene (through Scene.create_node), it should still be set as the owner of + * those Nodes. + */ +class Procedural : public Node, public NodeOwner { + public: + NODE_ABSTRACT_DECLARE + + explicit Procedural(const NodeType *type); + virtual ~Procedural(); + + /* Called each time the ProceduralManager is tagged for an update, this function is the entry + * point for the data generated by this Procedural. */ + virtual void generate(Scene *scene, Progress &progress) = 0; + + /* Create a node and set this Procedural as the owner. */ + template<typename T> T *create_node() + { + T *node = new T(); + node->set_owner(this); + return node; + } + + /* Delete a Node created and owned by this Procedural. */ + template<typename T> void delete_node(T *node) + { + assert(node->get_owner() == this); + delete node; + } +}; + +class ProceduralManager { + bool need_update_; + + public: + ProceduralManager(); + ~ProceduralManager(); + + void update(Scene *scene, Progress &progress); + + void tag_update(); + + bool need_update() const; +}; + +CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index b7720b7aa99..6bb25677965 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -18,6 +18,7 @@ #include "bvh/bvh.h" #include "device/device.h" +#include "render/alembic.h" #include "render/background.h" #include "render/bake.h" #include "render/camera.h" @@ -29,6 +30,7 @@ #include "render/object.h" #include "render/osl.h" #include "render/particles.h" +#include "render/procedural.h" #include "render/scene.h" #include "render/session.h" #include "render/shader.h" @@ -114,6 +116,7 @@ Scene::Scene(const SceneParams ¶ms_, Device *device) image_manager = new ImageManager(device->info); particle_system_manager = new ParticleSystemManager(); bake_manager = new BakeManager(); + procedural_manager = new ProceduralManager(); kernels_loaded = false; /* TODO(sergey): Check if it's indeed optimal value for the split kernel. */ @@ -142,6 +145,9 @@ void Scene::free_memory(bool final) foreach (Shader *s, shaders) delete s; + /* delete procedurals before other types as they may hold pointers to those types */ + foreach (Procedural *p, procedurals) + delete p; foreach (Geometry *g, geometry) delete g; foreach (Object *o, objects) @@ -156,15 +162,16 @@ void Scene::free_memory(bool final) objects.clear(); lights.clear(); particle_systems.clear(); + procedurals.clear(); if (device) { camera->device_free(device, &dscene, this); film->device_free(device, &dscene, this); background->device_free(device, &dscene); - integrator->device_free(device, &dscene); + integrator->device_free(device, &dscene, true); - object_manager->device_free(device, &dscene); - geometry_manager->device_free(device, &dscene); + object_manager->device_free(device, &dscene, true); + geometry_manager->device_free(device, &dscene, true); shader_manager->device_free(device, &dscene, this); light_manager->device_free(device, &dscene); @@ -195,6 +202,7 @@ void Scene::free_memory(bool final) delete image_manager; delete bake_manager; delete update_stats; + delete procedural_manager; } } @@ -236,6 +244,11 @@ void Scene::device_update(Device *device_, Progress &progress) if (progress.get_cancel() || device->have_error()) return; + procedural_manager->update(this, progress); + + if (progress.get_cancel()) + return; + progress.set_status("Updating Background"); background->device_update(device, &dscene, this); @@ -386,11 +399,12 @@ bool Scene::need_update() bool Scene::need_data_update() { - return (background->is_modified() || image_manager->need_update || object_manager->need_update || - geometry_manager->need_update || light_manager->need_update || - lookup_tables->need_update || integrator->is_modified() || shader_manager->need_update || - particle_system_manager->need_update || bake_manager->need_update || - film->is_modified()); + return (background->is_modified() || image_manager->need_update() || + object_manager->need_update() || geometry_manager->need_update() || + light_manager->need_update() || lookup_tables->need_update() || + integrator->is_modified() || shader_manager->need_update() || + particle_system_manager->need_update() || bake_manager->need_update() || + film->is_modified() || procedural_manager->need_update()); } bool Scene::need_reset() @@ -407,12 +421,15 @@ void Scene::reset() camera->tag_modified(); dicing_camera->tag_modified(); film->tag_modified(); + background->tag_modified(); + background->tag_update(this); - integrator->tag_update(this); - object_manager->tag_update(this); - geometry_manager->tag_update(this); - light_manager->tag_update(this); + integrator->tag_update(this, Integrator::UPDATE_ALL); + object_manager->tag_update(this, ObjectManager::UPDATE_ALL); + geometry_manager->tag_update(this, GeometryManager::UPDATE_ALL); + light_manager->tag_update(this, LightManager::UPDATE_ALL); particle_system_manager->tag_update(this); + procedural_manager->tag_update(); } void Scene::device_free() @@ -596,7 +613,7 @@ template<> Light *Scene::create_node<Light>() Light *node = new Light(); node->set_owner(this); lights.push_back(node); - light_manager->tag_update(this); + light_manager->tag_update(this, LightManager::LIGHT_ADDED); return node; } @@ -605,7 +622,7 @@ template<> Mesh *Scene::create_node<Mesh>() Mesh *node = new Mesh(); node->set_owner(this); geometry.push_back(node); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::MESH_ADDED); return node; } @@ -614,7 +631,7 @@ template<> Hair *Scene::create_node<Hair>() Hair *node = new Hair(); node->set_owner(this); geometry.push_back(node); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::HAIR_ADDED); return node; } @@ -623,7 +640,7 @@ template<> Volume *Scene::create_node<Volume>() Volume *node = new Volume(); node->set_owner(this); geometry.push_back(node); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::MESH_ADDED); return node; } @@ -632,7 +649,7 @@ template<> Object *Scene::create_node<Object>() Object *node = new Object(); node->set_owner(this); objects.push_back(node); - object_manager->tag_update(this); + object_manager->tag_update(this, ObjectManager::OBJECT_ADDED); return node; } @@ -650,10 +667,23 @@ template<> Shader *Scene::create_node<Shader>() Shader *node = new Shader(); node->set_owner(this); shaders.push_back(node); - shader_manager->need_update = true; + shader_manager->tag_update(this, ShaderManager::SHADER_ADDED); return node; } +template<> AlembicProcedural *Scene::create_node<AlembicProcedural>() +{ +#ifdef WITH_ALEMBIC + AlembicProcedural *node = new AlembicProcedural(); + node->set_owner(this); + procedurals.push_back(node); + procedural_manager->tag_update(); + return node; +#else + return nullptr; +#endif +} + template<typename T> void delete_node_from_array(vector<T> &nodes, T node) { for (size_t i = 0; i < nodes.size(); ++i) { @@ -664,43 +694,52 @@ template<typename T> void delete_node_from_array(vector<T> &nodes, T node) } nodes.resize(nodes.size() - 1); + delete node; } template<> void Scene::delete_node_impl(Light *node) { delete_node_from_array(lights, node); - light_manager->tag_update(this); + light_manager->tag_update(this, LightManager::LIGHT_REMOVED); } template<> void Scene::delete_node_impl(Mesh *node) { delete_node_from_array(geometry, static_cast<Geometry *>(node)); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED); } template<> void Scene::delete_node_impl(Hair *node) { delete_node_from_array(geometry, static_cast<Geometry *>(node)); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::HAIR_REMOVED); } template<> void Scene::delete_node_impl(Volume *node) { delete_node_from_array(geometry, static_cast<Geometry *>(node)); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::MESH_REMOVED); } template<> void Scene::delete_node_impl(Geometry *node) { + uint flag; + if (node->is_hair()) { + flag = GeometryManager::HAIR_REMOVED; + } + else { + flag = GeometryManager::MESH_REMOVED; + } + delete_node_from_array(geometry, node); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, flag); } template<> void Scene::delete_node_impl(Object *node) { delete_node_from_array(objects, node); - object_manager->tag_update(this); + object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED); } template<> void Scene::delete_node_impl(ParticleSystem *node) @@ -714,6 +753,21 @@ template<> void Scene::delete_node_impl(Shader * /*node*/) /* don't delete unused shaders, not supported */ } +template<> void Scene::delete_node_impl(Procedural *node) +{ + delete_node_from_array(procedurals, node); + procedural_manager->tag_update(); +} + +template<> void Scene::delete_node_impl(AlembicProcedural *node) +{ +#ifdef WITH_ALEMBIC + delete_node_impl(static_cast<Procedural *>(node)); +#else + (void)node; +#endif +} + template<typename T> static void remove_nodes_in_set(const set<T *> &nodes_set, vector<T *> &nodes_array, @@ -742,19 +796,19 @@ static void remove_nodes_in_set(const set<T *> &nodes_set, template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner) { remove_nodes_in_set(nodes, lights, owner); - light_manager->tag_update(this); + light_manager->tag_update(this, LightManager::LIGHT_REMOVED); } template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner) { remove_nodes_in_set(nodes, geometry, owner); - geometry_manager->tag_update(this); + geometry_manager->tag_update(this, GeometryManager::GEOMETRY_REMOVED); } template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner) { remove_nodes_in_set(nodes, objects, owner); - object_manager->tag_update(this); + object_manager->tag_update(this, ObjectManager::OBJECT_REMOVED); } template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner) @@ -768,4 +822,10 @@ template<> void Scene::delete_nodes(const set<Shader *> & /*nodes*/, const NodeO /* don't delete unused shaders, not supported */ } +template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner) +{ + remove_nodes_in_set(nodes, procedurals, owner); + procedural_manager->tag_update(); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index 27e9a131bbd..61c753e411c 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -36,6 +36,7 @@ CCL_NAMESPACE_BEGIN +class AlembicProcedural; class AttributeRequestSet; class Background; class BVH; @@ -53,6 +54,8 @@ class Object; class ObjectManager; class ParticleSystemManager; class ParticleSystem; +class Procedural; +class ProceduralManager; class CurveSystemManager; class Shader; class ShaderManager; @@ -236,6 +239,7 @@ class Scene : public NodeOwner { vector<Light *> lights; vector<ParticleSystem *> particle_systems; vector<Pass> passes; + vector<Procedural *> procedurals; /* data managers */ ImageManager *image_manager; @@ -245,6 +249,7 @@ class Scene : public NodeOwner { ObjectManager *object_manager; ParticleSystemManager *particle_system_manager; BakeManager *bake_manager; + ProceduralManager *procedural_manager; /* default shaders */ Shader *default_surface; @@ -353,7 +358,7 @@ class Scene : public NodeOwner { DeviceRequestedFeatures get_requested_device_features(); - /* Maximumnumber of closure during session lifetime. */ + /* Maximum number of closure during session lifetime. */ int max_closure_global; /* Get maximum number of closures to be used in kernel. */ @@ -379,6 +384,8 @@ template<> ParticleSystem *Scene::create_node<ParticleSystem>(); template<> Shader *Scene::create_node<Shader>(); +template<> AlembicProcedural *Scene::create_node<AlembicProcedural>(); + template<> void Scene::delete_node_impl(Light *node); template<> void Scene::delete_node_impl(Mesh *node); @@ -395,6 +402,10 @@ template<> void Scene::delete_node_impl(ParticleSystem *node); template<> void Scene::delete_node_impl(Shader *node); +template<> void Scene::delete_node_impl(Procedural *node); + +template<> void Scene::delete_node_impl(AlembicProcedural *node); + template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner); template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner); @@ -405,6 +416,8 @@ template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const No template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner *owner); +template<> void Scene::delete_nodes(const set<Procedural *> &nodes, const NodeOwner *owner); + CCL_NAMESPACE_END #endif /* __SCENE_H__ */ diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7a30ecb24f7..3c601e18126 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -1040,13 +1040,7 @@ bool Session::update_scene() BakeManager *bake_manager = scene->bake_manager; if (integrator->get_sampling_pattern() != SAMPLING_PATTERN_SOBOL || bake_manager->get_baking()) { - int aa_samples = tile_manager.num_samples; - - integrator->set_aa_samples(aa_samples); - - if (integrator->is_modified()) { - integrator->tag_update(scene); - } + integrator->set_aa_samples(tile_manager.num_samples); } bool kernel_switch_needed = false; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index 7e06b427e4d..332599be708 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -16,6 +16,7 @@ #include "device/device.h" +#include "render/alembic.h" #include "render/background.h" #include "render/camera.h" #include "render/colorspace.h" @@ -218,7 +219,9 @@ Shader::Shader() : Node(node_type) id = -1; used = false; - need_update_geometry = true; + need_update_uvs = true; + need_update_attribute = true; + need_update_displacement = true; } Shader::~Shader() @@ -291,7 +294,7 @@ void Shader::set_graph(ShaderGraph *graph_) const char *new_hash = (graph_) ? graph_->displacement_hash.c_str() : ""; if (strcmp(old_hash, new_hash) != 0) { - need_update_geometry = true; + need_update_displacement = true; } } @@ -308,13 +311,14 @@ void Shader::tag_update(Scene *scene) { /* update tag */ tag_modified(); - scene->shader_manager->need_update = true; + + scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED); /* if the shader previously was emissive, update light distribution, * if the new shader is emissive, a light manager update tag will be * done in the shader manager device update. */ if (use_mis && has_surface_emission) - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED); /* Special handle of background MIS light for now: for some reason it * has use_mis set to false. We are quite close to release now, so @@ -323,7 +327,7 @@ void Shader::tag_update(Scene *scene) if (this == scene->background->get_shader(scene)) { scene->light_manager->need_update_background = true; if (scene->light_manager->has_background_light(scene)) { - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::SHADER_MODIFIED); } } @@ -352,17 +356,18 @@ void Shader::tag_update(Scene *scene) attributes.add(ATTR_STD_POSITION_UNDISPLACED); } if (displacement_method_is_modified()) { - need_update_geometry = true; - scene->geometry_manager->need_update = true; + need_update_displacement = true; + scene->geometry_manager->tag_update(scene, GeometryManager::SHADER_DISPLACEMENT_MODIFIED); scene->object_manager->need_flags_update = true; } } /* compare if the attributes changed, mesh manager will check - * need_update_geometry, update the relevant meshes and clear it. */ + * need_update_attribute, update the relevant meshes and clear it. */ if (attributes.modified(prev_attributes)) { - need_update_geometry = true; - scene->geometry_manager->need_update = true; + need_update_attribute = true; + scene->geometry_manager->tag_update(scene, GeometryManager::SHADER_ATTRIBUTE_MODIFIED); + scene->procedural_manager->tag_update(); } if (has_volume != prev_has_volume || volume_step_rate != prev_volume_step_rate) { @@ -378,15 +383,20 @@ void Shader::tag_used(Scene *scene) * recompiled because it was skipped for compilation before */ if (!used) { tag_modified(); - scene->shader_manager->need_update = true; + scene->shader_manager->tag_update(scene, ShaderManager::SHADER_MODIFIED); } } +bool Shader::need_update_geometry() const +{ + return need_update_uvs || need_update_attribute || need_update_displacement; +} + /* Shader Manager */ ShaderManager::ShaderManager() { - need_update = true; + update_flags = UPDATE_ALL; beckmann_table_offset = TABLE_OFFSET_INVALID; xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f); @@ -484,7 +494,7 @@ int ShaderManager::get_shader_id(Shader *shader, bool smooth) void ShaderManager::update_shaders_used(Scene *scene) { - if (!need_update) { + if (!need_update()) { return; } @@ -504,6 +514,21 @@ void ShaderManager::update_shaders_used(Scene *scene) if (scene->background->get_shader()) scene->background->get_shader()->used = true; +#ifdef WITH_ALEMBIC + foreach (Procedural *procedural, scene->procedurals) { + AlembicProcedural *abc_proc = static_cast<AlembicProcedural *>(procedural); + + foreach (Node *abc_node, abc_proc->get_objects()) { + AlembicObject *abc_object = static_cast<AlembicObject *>(abc_node); + + foreach (Node *node, abc_object->get_used_shaders()) { + Shader *shader = static_cast<Shader *>(node); + shader->used = true; + } + } + } +#endif + foreach (Geometry *geom, scene->geometry) foreach (Node *node, geom->get_used_shaders()) { Shader *shader = static_cast<Shader *>(node); @@ -793,4 +818,15 @@ string ShaderManager::get_cryptomatte_materials(Scene *scene) return manifest; } +void ShaderManager::tag_update(Scene * /*scene*/, uint32_t /*flag*/) +{ + /* update everything for now */ + update_flags = ShaderManager::UPDATE_ALL; +} + +bool ShaderManager::need_update() const +{ + return update_flags != UPDATE_NONE; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index de19048d8e1..4375ef9e978 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -100,7 +100,9 @@ class Shader : public Node { float prev_volume_step_rate; /* synchronization */ - bool need_update_geometry; + bool need_update_uvs; + bool need_update_attribute; + bool need_update_displacement; /* If the shader has only volume components, the surface is assumed to * be transparent. @@ -152,6 +154,8 @@ class Shader : public Node { void set_graph(ShaderGraph *graph); void tag_update(Scene *scene); void tag_used(Scene *scene); + + bool need_update_geometry() const; }; /* Shader Manager virtual base class @@ -161,7 +165,16 @@ class Shader : public Node { class ShaderManager { public: - bool need_update; + enum : uint32_t { + SHADER_ADDED = (1 << 0), + SHADER_MODIFIED = (1 << 2), + INTEGRATOR_MODIFIED = (1 << 3), + + /* tag everything in the manager for an update */ + UPDATE_ALL = ~0u, + + UPDATE_NONE = 0u, + }; static ShaderManager *create(int shadingsystem); virtual ~ShaderManager(); @@ -204,9 +217,15 @@ class ShaderManager { string get_cryptomatte_materials(Scene *scene); + void tag_update(Scene *scene, uint32_t flag); + + bool need_update() const; + protected: ShaderManager(); + uint32_t update_flags; + typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap; AttributeIDMap unique_attribute_id; diff --git a/intern/cycles/render/stats.cpp b/intern/cycles/render/stats.cpp index 1a840a906a5..2c6273842e2 100644 --- a/intern/cycles/render/stats.cpp +++ b/intern/cycles/render/stats.cpp @@ -375,6 +375,7 @@ string SceneUpdateStats::full_report() result += "Particles:\n" + particles.full_report(1); result += "SVM:\n" + svm.full_report(1); result += "Tables:\n" + tables.full_report(1); + result += "Procedurals:\n" + procedurals.full_report(1); return result; } @@ -394,6 +395,7 @@ void SceneUpdateStats::clear() scene.times.clear(); svm.times.clear(); tables.times.clear(); + procedurals.times.clear(); } CCL_NAMESPACE_END diff --git a/intern/cycles/render/stats.h b/intern/cycles/render/stats.h index a6be27db4c2..93d029bba61 100644 --- a/intern/cycles/render/stats.h +++ b/intern/cycles/render/stats.h @@ -219,6 +219,7 @@ class SceneUpdateStats { UpdateTimeStats scene; UpdateTimeStats svm; UpdateTimeStats tables; + UpdateTimeStats procedurals; string full_report(); diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 6f5a03124f2..fce604234f1 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -74,7 +74,7 @@ void SVMShaderManager::device_update(Device *device, Scene *scene, Progress &progress) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -125,7 +125,7 @@ void SVMShaderManager::device_update(Device *device, shader->clear_modified(); if (shader->get_use_mis() && shader->has_surface_emission) { - scene->light_manager->need_update = true; + scene->light_manager->tag_update(scene, LightManager::SHADER_COMPILED); } /* Update the global jump table. @@ -159,7 +159,7 @@ void SVMShaderManager::device_update(Device *device, device_update_common(device, dscene, scene, progress); - need_update = false; + update_flags = UPDATE_NONE; VLOG(1) << "Shader manager updated " << num_shaders << " shaders in " << time_dt() - start_time << " seconds."; diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp index b581537c852..a0813400b1c 100644 --- a/intern/cycles/render/tables.cpp +++ b/intern/cycles/render/tables.cpp @@ -28,7 +28,7 @@ CCL_NAMESPACE_BEGIN LookupTables::LookupTables() { - need_update = true; + need_update_ = true; } LookupTables::~LookupTables() @@ -38,7 +38,7 @@ LookupTables::~LookupTables() void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene) { - if (!need_update) + if (!need_update()) return; scoped_callback_timer timer([scene](double time) { @@ -52,7 +52,7 @@ void LookupTables::device_update(Device *, DeviceScene *dscene, Scene *scene) if (lookup_tables.size() > 0) dscene->lookup_table.copy_to_device(); - need_update = false; + need_update_ = false; } void LookupTables::device_free(Device *, DeviceScene *dscene) @@ -60,6 +60,11 @@ void LookupTables::device_free(Device *, DeviceScene *dscene) dscene->lookup_table.free(); } +bool LookupTables::need_update() const +{ + return need_update_; +} + static size_t round_up_to_multiple(size_t size, size_t chunk) { return ((size + chunk - 1) / chunk) * chunk; @@ -69,7 +74,7 @@ size_t LookupTables::add_table(DeviceScene *dscene, vector<float> &data) { assert(data.size() > 0); - need_update = true; + need_update_ = true; Table new_table; new_table.offset = 0; @@ -107,7 +112,7 @@ void LookupTables::remove_table(size_t *offset) return; } - need_update = true; + need_update_ = true; list<Table>::iterator table; diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h index e912d9c01f4..de538e2af78 100644 --- a/intern/cycles/render/tables.h +++ b/intern/cycles/render/tables.h @@ -30,13 +30,14 @@ enum { TABLE_CHUNK_SIZE = 256 }; enum { TABLE_OFFSET_INVALID = -1 }; class LookupTables { + bool need_update_; + public: struct Table { size_t offset; size_t size; }; - bool need_update; list<Table> lookup_tables; LookupTables(); @@ -45,6 +46,8 @@ class LookupTables { void device_update(Device *device, DeviceScene *dscene, Scene *scene); void device_free(Device *device, DeviceScene *dscene); + bool need_update() const; + size_t add_table(DeviceScene *dscene, vector<float> &data); void remove_table(size_t *offset); }; diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp index 928f5bf2ed7..4d648eb1f77 100644 --- a/intern/cycles/subd/subd_split.cpp +++ b/intern/cycles/subd/subd_split.cpp @@ -549,7 +549,7 @@ void DiagSplit::split_ngon(const Mesh::SubdFace &face, Patch *patches, size_t pa subpatch.edge_v1.indices_decrease_along_edge = true; subpatch.edge_u0.indices_decrease_along_edge = u0_reversed; - /* Perfrom split. */ + /* Perform split. */ { subpatch.edge_u0.T = T(subpatch.patch, subpatch.c00, subpatch.c10); subpatch.edge_u1.T = T(subpatch.patch, subpatch.c01, subpatch.c11); @@ -646,7 +646,7 @@ void DiagSplit::post_split() /* Set start and end indices for edges generated from a split. */ foreach (Edge &edge, edges) { if (edge.start_vert_index < 0) { - /* Fixup offsets. */ + /* Fix up offsets. */ if (edge.top_indices_decrease) { edge.top_offset = edge.top->T - edge.top_offset; } diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h index 773f4ddf120..7416b2fbbf8 100644 --- a/intern/cycles/subd/subd_split.h +++ b/intern/cycles/subd/subd_split.h @@ -40,7 +40,7 @@ class DiagSplit { SubdParams params; vector<Subpatch> subpatches; - /* deque is used so that element pointers remain vaild when size is changed. */ + /* `deque` is used so that element pointers remain valid when size is changed. */ deque<Edge> edges; float3 to_world(Patch *patch, float2 uv); diff --git a/intern/cycles/util/util_array.h b/intern/cycles/util/util_array.h index ea481787018..73f7d6cf7f8 100644 --- a/intern/cycles/util/util_array.h +++ b/intern/cycles/util/util_array.h @@ -131,6 +131,14 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra } } + void set_data(T *ptr_, size_t datasize) + { + clear(); + data_ = ptr_; + datasize_ = datasize; + capacity_ = datasize; + } + T *steal_pointer() { T *ptr = data_; diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 8caabf6eac3..ad04340231e 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -349,7 +349,7 @@ ccl_device_inline float fractf(float x) return x - floorf(x); } -/* Adapted from godotengine math_funcs.h. */ +/* Adapted from godot-engine math_funcs.h. */ ccl_device_inline float wrapf(float value, float max, float min) { float range = max - min; @@ -385,7 +385,7 @@ ccl_device_inline float nonzerof(float f, float eps) return f; } -/* Signum function testing for zero. Matches GLSL and OSL functions. */ +/* `signum` function testing for zero. Matches GLSL and OSL functions. */ ccl_device_inline float compatible_signf(float f) { if (f == 0.0f) { @@ -754,7 +754,7 @@ ccl_device_inline float2 map_to_sphere(const float3 co) float u, v; if (l > 0.0f) { if (UNLIKELY(co.x == 0.0f && co.y == 0.0f)) { - u = 0.0f; /* othwise domain error */ + u = 0.0f; /* Otherwise domain error. */ } else { u = (1.0f - atan2f(co.x, co.y) / M_PI_F) / 2.0f; diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index 07b0878e3d5..107b36ce6cd 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -84,7 +84,7 @@ ccl_device_inline int fast_rint(float x) { /* used by sin/cos/tan range reduction. */ #ifdef __KERNEL_SSE4__ - /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */ + /* Single `roundps` instruction on SSE4.1+ (for gcc/clang at least). */ return float_to_int(rintf(x)); #else /* emulate rounding by adding/subtracting 0.5. */ @@ -613,7 +613,7 @@ ccl_device_inline float fast_erfcf(float x) ccl_device_inline float fast_ierff(float x) { - /* From: Approximating the erfinv function by Mike Giles. */ + /* From: Approximating the `erfinv` function by Mike Giles. */ /* To avoid trouble at the limit, clamp input to 1-eps. */ float a = fabsf(x); if (a > 0.99999994f) { diff --git a/intern/cycles/util/util_math_matrix.h b/intern/cycles/util/util_math_matrix.h index 1dc661a7aa7..123736f75a6 100644 --- a/intern/cycles/util/util_math_matrix.h +++ b/intern/cycles/util/util_math_matrix.h @@ -161,7 +161,7 @@ ccl_device_inline void math_trimatrix_add_gramian(ccl_global float *A, } } -/* Transpose matrix A inplace. */ +/* Transpose matrix A in place. */ ccl_device_inline void math_matrix_transpose(ccl_global float *A, int n, int stride) { for (int i = 0; i < n; i++) { diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h index 4622945f9d2..3102a0f4bad 100644 --- a/intern/cycles/util/util_md5.h +++ b/intern/cycles/util/util_md5.h @@ -49,7 +49,7 @@ class MD5Hash { void process(const uint8_t *data); void finish(uint8_t digest[16]); - uint32_t count[2]; /* message length in bits, lsw first */ + uint32_t count[2]; /* message length in bits, LSW first. */ uint32_t abcd[4]; /* digest buffer */ uint8_t buf[64]; /* accumulate block */ }; diff --git a/intern/cycles/util/util_stack_allocator.h b/intern/cycles/util/util_stack_allocator.h index 36db655e5eb..ef31c0fe5e2 100644 --- a/intern/cycles/util/util_stack_allocator.h +++ b/intern/cycles/util/util_stack_allocator.h @@ -126,7 +126,7 @@ template<int SIZE, typename T> class ccl_try_align(16) StackAllocator return size_t(-1); } - /* Rebind to other ype of allocator. */ + /* Rebind to other type of allocator. */ template<class U> struct rebind { typedef StackAllocator<SIZE, U> other; diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h index f51aa7111e8..6b6f493bd94 100644 --- a/intern/cycles/util/util_string.h +++ b/intern/cycles/util/util_string.h @@ -66,9 +66,9 @@ string string_from_wstring(const wstring &path); string string_to_ansi(const string &str); #endif -/* Make a string from a size in bytes in human readable form */ +/* Make a string from a size in bytes in human readable form. */ string string_human_readable_size(size_t size); -/* Make a string from a unitless quantity in human readable form */ +/* Make a string from a unit-less quantity in human readable form. */ string string_human_readable_number(size_t num); CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_tbb.h b/intern/cycles/util/util_tbb.h index 168bd5db961..73e0f92d19c 100644 --- a/intern/cycles/util/util_tbb.h +++ b/intern/cycles/util/util_tbb.h @@ -21,11 +21,14 @@ * WIN32_LEAN_AND_MEAN and similar are defined beforehand. */ #include "util_windows.h" -#define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 -#include <tbb/tbb.h> +#include <tbb/enumerable_thread_specific.h> +#include <tbb/parallel_for.h> +#include <tbb/task_arena.h> +#include <tbb/task_group.h> #if TBB_INTERFACE_VERSION_MAJOR >= 10 # define WITH_TBB_GLOBAL_CONTROL +# include <tbb/global_control.h> #endif CCL_NAMESPACE_BEGIN diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index d6eb5f9db1d..727fd4b9601 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -49,16 +49,6 @@ #include <libswscale/swscale.h> -/* Stupid way to distinguish FFmpeg from Libav: - * - FFmpeg's MICRO version starts from 100 and goes up, while - * - Libav's micro is always below 100. - */ -#if LIBAVCODEC_VERSION_MICRO >= 100 -# define AV_USING_FFMPEG -#else -# define AV_USING_LIBAV -#endif - #if (LIBAVFORMAT_VERSION_MAJOR > 52) || \ ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 105)) # define FFMPEG_HAVE_AVIO 1 @@ -528,22 +518,6 @@ bool av_check_encoded_with_ffmpeg(AVFormatContext *ctx) return false; } -/* Libav doesn't have av_guess_frame_rate(). - * It was introduced in FFmpeg's lavf 55.1.100. */ -#ifdef AV_USING_LIBAV -AVRational av_guess_frame_rate(AVFormatContext *ctx, AVStream *stream, AVFrame *frame) -{ - (void)ctx; - (void)frame; -# if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 23, 1) - /* For until r_frame_rate was deprecated (in Libav) use it. */ - return stream->r_frame_rate; -# else - return stream->avg_frame_rate; -# endif -} -#endif - #if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0) # define AV_OPT_SEARCH_FAKE_OBJ 0 #endif diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 2bc73f7eb22..d79111b742f 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -25,6 +25,8 @@ #include "GHOST_Types.h" +#include <stdbool.h> + #ifdef __cplusplus extern "C" { #endif @@ -160,6 +162,7 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. * \param systemhandle: The handle to the system. + * \param parentWindow: Handle of parent (or owner) window, or NULL * \param title: The name of the window. * (displayed in the title bar of the window if the OS supports it). * \param left: The coordinate of the left edge of the window. @@ -167,31 +170,23 @@ extern void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle, * \param width: The width the window. * \param height: The height the window. * \param state: The state of the window when opened. + * \param is_dialog: Stay on top of parent window, no icon in taskbar, can't be minimized. * \param type: The type of drawing context installed in this window. * \param glSettings: Misc OpenGL options. * \return A handle to the new window ( == NULL if creation failed). */ extern GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle parent_windowhandle, const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + bool is_dialog, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings); -extern GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle parent_windowhandle, - const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - GHOST_GLSettings glSettings); - /** * Create a new offscreen context. * Never explicitly delete the context, use disposeContext() instead. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 8bce064ce63..bd7ba6657f0 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -580,7 +580,7 @@ typedef struct { GHOST_TUns32 xPixels; /** Number of lines. */ GHOST_TUns32 yPixels; - /** Numberof bits per pixel. */ + /** Number of bits per pixel. */ GHOST_TUns32 bpp; /** Refresh rate (in Hertz). */ GHOST_TUns32 frequency; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index e4bb908fec8..af65e1cd4d2 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -153,34 +153,19 @@ GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle, } GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle, + GHOST_WindowHandle parent_windowhandle, const char *title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, + bool is_dialog, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings) { GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; - return (GHOST_WindowHandle)system->createWindow( - title, left, top, width, height, state, type, glSettings, false, false); -} - -GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle parent_windowhandle, - const char *title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - GHOST_GLSettings glSettings) -{ - GHOST_ISystem *system = (GHOST_ISystem *)systemhandle; - return (GHOST_WindowHandle)system->createWindow(title, left, top, @@ -190,7 +175,7 @@ GHOST_WindowHandle GHOST_CreateDialogWindow(GHOST_SystemHandle systemhandle, type, glSettings, false, - true, + is_dialog, (GHOST_IWindow *)parent_windowhandle); } diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h index d07913b28c4..810b78a7d39 100644 --- a/intern/ghost/intern/GHOST_Context.h +++ b/intern/ghost/intern/GHOST_Context.h @@ -127,8 +127,8 @@ class GHOST_Context : public GHOST_IContext { } /** - * Gets the OpenGL framebuffer associated with the OpenGL context - * \return The ID of an OpenGL framebuffer object. + * Gets the OpenGL frame-buffer associated with the OpenGL context + * \return The ID of an OpenGL frame-buffer object. */ virtual unsigned int getDefaultFramebuffer() { diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h index d499ec987b0..8e4376236fa 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.h +++ b/intern/ghost/intern/GHOST_ContextCGL.h @@ -115,10 +115,10 @@ class GHOST_ContextCGL : public GHOST_Context { /** The OpenGL drawing context */ NSOpenGLContext *m_openGLContext; - /** The virtualized default framebuffer */ + /** The virtualized default frame-buffer. */ unsigned int m_defaultFramebuffer; - /** The virtualized default framebuffer's texture */ + /** The virtualized default frame-buffer's texture. */ MTLTexture *m_defaultFramebufferMetalTexture; bool m_coreProfile; diff --git a/intern/ghost/intern/GHOST_ContextD3D.h b/intern/ghost/intern/GHOST_ContextD3D.h index 18b4a5d1286..8b9537ca439 100644 --- a/intern/ghost/intern/GHOST_ContextD3D.h +++ b/intern/ghost/intern/GHOST_ContextD3D.h @@ -97,8 +97,8 @@ class GHOST_ContextD3D : public GHOST_Context { } /** - * Gets the OpenGL framebuffer associated with the OpenGL context - * \return The ID of an OpenGL framebuffer object. + * Gets the OpenGL frame-buffer associated with the OpenGL context + * \return The ID of an OpenGL frame-buffer object. */ unsigned int getDefaultFramebuffer() { diff --git a/intern/ghost/intern/GHOST_Debug.h b/intern/ghost/intern/GHOST_Debug.h index 424f95aa573..13858410c5a 100644 --- a/intern/ghost/intern/GHOST_Debug.h +++ b/intern/ghost/intern/GHOST_Debug.h @@ -26,7 +26,7 @@ #ifdef _MSC_VER # ifdef DEBUG -/* Suppress stl-MSVC debug info warning. */ +/* Suppress STL-MSVC debug info warning. */ # pragma warning(disable : 4786) # endif #endif diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp index 816d9c254ee..82ed9de230d 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.cpp +++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp @@ -203,7 +203,7 @@ void *GHOST_DropTargetX11::getURIListGhostData(unsigned char *dropBuffer, int dr GHOST_TStringArray *strArray = NULL; int totPaths = 0, curLength = 0; - /* count total number of file pathes in buffer */ + /* Count total number of file paths in buffer. */ for (int i = 0; i <= dropBufferSize; i++) { if (dropBuffer[i] == 0 || dropBuffer[i] == '\n' || dropBuffer[i] == '\r') { if (curLength) { diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h index 69f6fec7ac1..f538dbbb617 100644 --- a/intern/ghost/intern/GHOST_DropTargetX11.h +++ b/intern/ghost/intern/GHOST_DropTargetX11.h @@ -103,22 +103,22 @@ class GHOST_DropTargetX11 { /* Data type of the dragged object */ GHOST_TDragnDropTypes m_draggedObjectType; - /* is dnd stuff initialzied */ + /* Is drag-and-drop stuff initialized. */ static bool m_xdndInitialized; - /* class holding internal stiff of xdnd library */ + /* Class holding internal stiff of `xdnd` library. */ static DndClass m_dndClass; - /* list of supported types to eb draggeg into */ + /* List of supported types to be dragged into. */ static Atom *m_dndTypes; - /* list of supported dran'n'drop actions */ + /* List of supported drag-and-drop actions. */ static Atom *m_dndActions; - /* List of supported MIME types to be dragged into */ + /* List of supported MIME types to be dragged into. */ static const char *m_dndMimeTypes[]; - /* counter of references to global XDND structures */ + /* Counter of references to global #XDND structures. */ static int m_refCounter; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index 63ecfd96cb8..cbef0f0edc4 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -303,10 +303,10 @@ class GHOST_ImeWin32 { */ void EndIME(HWND window_handle); - /* Updatg resultInfo and compInfo */ + /** Update #resultInfo and #compInfo */ void UpdateInfo(HWND window_handle); - /* disable ime when start up */ + /** Disable IME when start up. */ void CheckFirst(HWND window_handle); ImeComposition resultInfo, compInfo; diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index 193633b5c3e..47e71b0d733 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -40,7 +40,7 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32() const GHOST_TUns8 *GHOST_SystemPathsWin32::getSystemDir(int, const char *versionstr) const { - /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/ + /* 1 utf-16 might translate into 3 utf-8. 2 utf-16 translates into 4 utf-8. */ static char knownpath[MAX_PATH * 3 + 128] = {0}; PWSTR knownpath_16 = NULL; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 718ace9db4a..b71b6b9e170 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -963,7 +963,7 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, processCursorEvent(window); } else { - /* Tablet should be hadling inbetween mouse moves, only move to event position. */ + /* Tablet should be handling in between mouse moves, only move to event position. */ DWORD msgPos = ::GetMessagePos(); int msgPosX = GET_X_LPARAM(msgPos); int msgPosY = GET_Y_LPARAM(msgPos); diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 8e7b966aadf..9152aa22495 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -23,7 +23,7 @@ * \ingroup GHOST */ -#include <X11/XKBlib.h> /* Allow detectable auto-repeate. */ +#include <X11/XKBlib.h> /* Allow detectable auto-repeat. */ #include <X11/Xatom.h> #include <X11/Xutil.h> #include <X11/keysym.h> @@ -185,10 +185,10 @@ GHOST_SystemX11::GHOST_SystemX11() : GHOST_System(), m_xkb_descr(NULL), m_start_ GHOST_ASSERT(false, "Could not instantiate timer!"); } - /* Taking care not to overflow the tv.tv_sec * 1000 */ + /* Taking care not to overflow the `tv.tv_sec * 1000`. */ m_start_time = GHOST_TUns64(tv.tv_sec) * 1000 + tv.tv_usec / 1000; - /* Use detectable auto-repeate, mac and windows also do this. */ + /* Use detectable auto-repeat, mac and windows also do this. */ int use_xkb; int xkb_opcode, xkb_event, xkb_error; int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion; @@ -528,7 +528,7 @@ bool GHOST_SystemX11::openX11_IM() if (!m_display) return false; - /* set locale modifiers such as "@im=ibus" specified by XMODIFIERS */ + /* set locale modifiers such as `@im=ibus` specified by XMODIFIERS. */ XSetLocaleModifiers(""); m_xim = XOpenIM(m_display, NULL, (char *)GHOST_X11_RES_NAME, (char *)GHOST_X11_RES_CLASS); @@ -1146,7 +1146,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) */ if ((xke->keycode >= 10 && xke->keycode < 20) && ((key_sym = XLookupKeysym(xke, ShiftMask)) >= XK_0) && (key_sym <= XK_9)) { - /* pass (keep shift'ed key_sym) */ + /* Pass (keep shifted `key_sym`). */ } else { /* regular case */ @@ -1161,12 +1161,12 @@ void GHOST_SystemX11::processEvent(XEvent *xe) #endif #if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING) - /* getting unicode on key-up events gives XLookupNone status */ + /* Setting unicode on key-up events gives #XLookupNone status. */ XIC xic = window->getX11_XIC(); if (xic && xke->type == KeyPress) { Status status; - /* use utf8 because its not locale depentant, from xorg docs */ + /* Use utf8 because its not locale repentant, from XORG docs. */ if (!(len = Xutf8LookupString( xic, xke, utf8_buf, sizeof(utf8_array) - 5, &key_sym, &status))) { utf8_buf[0] = '\0'; @@ -1269,8 +1269,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) gbmask = GHOST_kButtonMaskRight; /* It seems events 6 and 7 are for horizontal scrolling. * you can re-order button mapping like this... (swaps 6,7 with 8,9) - * xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7" - */ + * `xmodmap -e "pointer = 1 2 3 4 5 8 9 6 7"` */ else if (xbe.button == 6) gbmask = GHOST_kButtonMaskButton6; else if (xbe.button == 7) @@ -1289,8 +1288,7 @@ void GHOST_SystemX11::processEvent(XEvent *xe) /* change of size, border, layer etc. */ case ConfigureNotify: { - /* XConfigureEvent & xce = xe->xconfigure; */ - + // XConfigureEvent & xce = xe->xconfigure; g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window); break; } @@ -1934,8 +1932,8 @@ static GHOST_TKey ghost_key_from_keycode(const XkbDescPtr xkb_descr, const KeyCo #define XCLIB_XCOUT_SENTCONVSEL 1 /* sent a request */ #define XCLIB_XCOUT_INCR 2 /* in an incr loop */ #define XCLIB_XCOUT_FALLBACK 3 /* STRING failed, need fallback to UTF8 */ -#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compouned */ -#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compouned failed, move to text. */ +#define XCLIB_XCOUT_FALLBACK_UTF8 4 /* UTF8 failed, move to compound. */ +#define XCLIB_XCOUT_FALLBACK_COMP 5 /* compound failed, move to text. */ #define XCLIB_XCOUT_FALLBACK_TEXT 6 /* Retrieves the contents of a selections. */ @@ -2198,30 +2196,30 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const restore_events.push_back(evt); } - /* fallback is needed. set XA_STRING to target and restart the loop. */ + /* Fallback is needed. Set #XA_STRING to target and restart the loop. */ if (context == XCLIB_XCOUT_FALLBACK) { context = XCLIB_XCOUT_NONE; target = m_atom.STRING; continue; } else if (context == XCLIB_XCOUT_FALLBACK_UTF8) { - /* utf8 fail, move to compouned text. */ + /* utf8 fail, move to compound text. */ context = XCLIB_XCOUT_NONE; target = m_atom.COMPOUND_TEXT; continue; } else if (context == XCLIB_XCOUT_FALLBACK_COMP) { - /* compouned text fail, move to text. */ + /* Compound text fail, move to text. */ context = XCLIB_XCOUT_NONE; target = m_atom.TEXT; continue; } else if (context == XCLIB_XCOUT_FALLBACK_TEXT) { - /* text fail, nothing else to try, break. */ + /* Text fail, nothing else to try, break. */ context = XCLIB_XCOUT_NONE; } - /* only continue if xcout() is doing something */ + /* Only continue if #xcout() is doing something. */ if (context == XCLIB_XCOUT_NONE) break; } @@ -2232,9 +2230,7 @@ GHOST_TUns8 *GHOST_SystemX11::getClipboard(bool selection) const } if (sel_len) { - /* only print the buffer out, and free it, if it's not - * empty - */ + /* Only print the buffer out, and free it, if it's not empty. */ unsigned char *tmp_data = (unsigned char *)malloc(sel_len + 1); memcpy((char *)tmp_data, (char *)sel_buf, sel_len); tmp_data[sel_len] = '\0'; @@ -2288,28 +2284,28 @@ void GHOST_SystemX11::putClipboard(GHOST_TInt8 *buffer, bool selection) const * \{ */ class DialogData { public: - /* Width of the dialog */ + /* Width of the dialog. */ uint width; - /* Heigth of the dialog */ + /* Height of the dialog. */ uint height; - /* Default padding (x direction) between controls and edge of dialog */ + /* Default padding (x direction) between controls and edge of dialog. */ uint padding_x; - /* Default padding (y direction) between controls and edge of dialog */ + /* Default padding (y direction) between controls and edge of dialog. */ uint padding_y; - /* Width of a single button */ + /* Width of a single button. */ uint button_width; - /* Height of a single button */ + /* Height of a single button. */ uint button_height; - /* Inset of a button to its text */ + /* Inset of a button to its text. */ uint button_inset_x; - /* Size of the border of the button */ + /* Size of the border of the button. */ uint button_border_size; /* Height of a line of text */ uint line_height; - /* offset of the text inside the button */ + /* Offset of the text inside the button. */ uint button_text_offset_y; - /* Construct a new DialogData with the default settings */ + /* Construct a new #DialogData with the default settings. */ DialogData() : width(640), height(175), diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index bcebda66ae3..a7e325bc9e1 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -24,7 +24,7 @@ #pragma once -#include <X11/XKBlib.h> /* Allow detectable auto-repeate. */ +#include <X11/XKBlib.h> /* Allow detectable auto-repeat. */ #include <X11/Xlib.h> #include "../GHOST_Types.h" diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index d897fafc003..1f2fed5b823 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -392,7 +392,7 @@ class GHOST_Window : public GHOST_IWindow { /** Stores whether this is a full screen window. */ bool m_fullScreen; - /** Whether to attempt to initialize a context with a stereo framebuffer. */ + /** Whether to attempt to initialize a context with a stereo frame-buffer. */ bool m_wantStereoVisual; /** Full-screen width */ diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 255d487649b..18aa19c0863 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -88,103 +88,55 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, m_fpGetPointerInfoHistory(NULL), m_fpGetPointerPenInfoHistory(NULL), m_fpGetPointerTouchInfoHistory(NULL), - m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL), + m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : HWND_DESKTOP), m_debug_context(is_debug) { - // Create window - if (state != GHOST_kWindowStateFullScreen) { - RECT rect; - MONITORINFO monitor; - GHOST_TUns32 tw, th; - -#ifndef _MSC_VER - int cxsizeframe = GetSystemMetrics(SM_CXSIZEFRAME); - int cysizeframe = GetSystemMetrics(SM_CYSIZEFRAME); -#else - // MSVC 2012+ returns bogus values from GetSystemMetrics, bug in Windows - // http://connect.microsoft.com/VisualStudio/feedback/details/753224/regression-getsystemmetrics-delivers-different-values - RECT cxrect = {0, 0, 0, 0}; - AdjustWindowRectEx( - &cxrect, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_THICKFRAME | WS_DLGFRAME, FALSE, 0); - - int cxsizeframe = abs(cxrect.bottom); - int cysizeframe = abs(cxrect.left); -#endif - - width += cxsizeframe * 2; - height += cysizeframe * 2 + GetSystemMetrics(SM_CYCAPTION); + wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); + RECT win_rect = {left, top, left + width, top + height}; + RECT parent_rect = {0, 0, 0, 0}; + if (parentwindow) { + GetWindowRect(m_parentWindowHwnd, &parent_rect); + } - rect.left = left; - rect.right = left + width; - rect.top = top; - rect.bottom = top + height; + DWORD style = parentwindow ? + WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX : + WS_OVERLAPPEDWINDOW; - monitor.cbSize = sizeof(monitor); - monitor.dwFlags = 0; + if (state == GHOST_kWindowStateFullScreen) { + style |= WS_MAXIMIZE; + } - // take taskbar into account - GetMonitorInfo(MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST), &monitor); + /* Forces owned windows onto taskbar and allows minimization. */ + DWORD extended_style = parentwindow ? WS_EX_APPWINDOW : 0; - th = monitor.rcWork.bottom - monitor.rcWork.top; - tw = monitor.rcWork.right - monitor.rcWork.left; + /* Monitor details. */ + MONITORINFOEX monitor; + monitor.cbSize = sizeof(MONITORINFOEX); + monitor.dwFlags = 0; + GetMonitorInfo( + MonitorFromRect(parentwindow ? &parent_rect : &win_rect, MONITOR_DEFAULTTONEAREST), + &monitor); - if (tw < width) { - width = tw; - left = monitor.rcWork.left; - } - else if (monitor.rcWork.right < left + (int)width) - left = monitor.rcWork.right - width; - else if (left < monitor.rcWork.left) - left = monitor.rcWork.left; - - if (th < height) { - height = th; - top = monitor.rcWork.top; - } - else if (monitor.rcWork.bottom < top + (int)height) - top = monitor.rcWork.bottom - height; - else if (top < monitor.rcWork.top) - top = monitor.rcWork.top; - - int wintype = WS_OVERLAPPEDWINDOW; - if ((m_parentWindowHwnd != 0) && !dialog) { - wintype = WS_CHILD; - GetWindowRect(m_parentWindowHwnd, &rect); - left = 0; - top = 0; - width = rect.right - rect.left; - height = rect.bottom - rect.top; - } + /* Adjust our requested size to allow for caption and borders and constrain to monitor. */ + AdjustWindowRectEx(&win_rect, WS_CAPTION, FALSE, 0); + width = min(monitor.rcWork.right - monitor.rcWork.left, win_rect.right - win_rect.left); + left = min(max(monitor.rcWork.left, win_rect.left), monitor.rcWork.right - width); + height = min(monitor.rcWork.bottom - monitor.rcWork.top, win_rect.bottom - win_rect.top); + top = min(max(monitor.rcWork.top, win_rect.top), monitor.rcWork.bottom - height); - wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); - m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name - title_16, // pointer to window name - wintype, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height - dialog ? 0 : m_parentWindowHwnd, // handle to parent or owner window - 0, // handle to menu or child-window identifier - ::GetModuleHandle(0), // handle to application instance - 0); // pointer to window-creation data - free(title_16); - } - else { - wchar_t *title_16 = alloc_utf16_from_8((char *)title, 0); - m_hWnd = ::CreateWindowW(s_windowClassName, // pointer to registered class name + m_hWnd = ::CreateWindowExW(extended_style, // window extended style + s_windowClassName, // pointer to registered class name title_16, // pointer to window name - WS_MAXIMIZE, // window style + style, // window style left, // horizontal position of window top, // vertical position of window width, // window width height, // window height - HWND_DESKTOP, // handle to parent or owner window + m_parentWindowHwnd, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance 0); // pointer to window-creation data - free(title_16); - } + free(title_16); m_user32 = ::LoadLibrary("user32.dll"); @@ -268,14 +220,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system, } } - if (dialog && parentwindow) { - ::SetWindowLongPtr( - m_hWnd, GWL_STYLE, WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION | WS_MAXIMIZEBOX | WS_SIZEBOX); - ::SetWindowLongPtr(m_hWnd, GWLP_HWNDPARENT, (LONG_PTR)m_parentWindowHwnd); - ::SetWindowPos( - m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - } - else if (parentwindow) { + if (parentwindow && !dialog) { RAWINPUTDEVICE device = {0}; device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ @@ -1423,7 +1368,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap GHOST_TUns32 fullBitRow, fullMaskRow; int x, y, cols; - cols = sizeX / 8; /* Num of whole bytes per row (width of bm/mask) */ + cols = sizeX / 8; /* Number of whole bytes per row (width of bm/mask). */ if (sizeX % 8) cols++; @@ -1462,7 +1407,7 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCustomCursorShape(GHOST_TUns8 *bitmap GHOST_TSuccess GHOST_WindowWin32::setProgressBar(float progress) { - /*SetProgressValue sets state to TBPF_NORMAL automaticly*/ + /* #SetProgressValue sets state to #TBPF_NORMAL automatically. */ if (m_Bar && S_OK == m_Bar->SetProgressValue(m_hWnd, 10000 * progress, 10000)) return GHOST_kSuccess; diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a7e7cdc6602..661d80c02aa 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -573,7 +573,7 @@ class GHOST_WindowWin32 : public GHOST_Window { /** Pointer to system. */ GHOST_SystemWin32 *m_system; - /** Pointer to COM IDropTarget implementor. */ + /** Pointer to COM #IDropTarget implementer. */ GHOST_DropTargetWin32 *m_dropTarget; /** Window handle. */ HWND m_hWnd; @@ -582,14 +582,16 @@ class GHOST_WindowWin32 : public GHOST_Window { /** Flag for if window has captured the mouse. */ bool m_hasMouseCaptured; - /** Flag if an operator grabs the mouse with WM_cursor_grab_enable/ungrab(). - * Multiple grabs must be released with a single ungrab. */ + /** + * Flag if an operator grabs the mouse with #WM_cursor_grab_enable, #WM_cursor_grab_disable + * Multiple grabs must be released with a single un-grab. + */ bool m_hasGrabMouse; /** Count of number of pressed buttons. */ int m_nPressedButtons; /** HCURSOR structure of the custom cursor. */ HCURSOR m_customCursor; - /** Request GL context aith alpha channel. */ + /** Request GL context with alpha channel. */ bool m_wantAlphaBackground; /** ITaskbarList3 structure for progress bar. */ diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 9a38631adb9..fc006c62803 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -293,55 +293,18 @@ GHOST_WindowX11::GHOST_WindowX11(GHOST_SystemX11 *system, m_display, RootWindow(m_display, m_visualInfo->screen), m_visualInfo->visual, AllocNone); /* create the window! */ - if ((parentWindow == 0) || is_dialog) { - m_window = XCreateWindow(m_display, - RootWindow(m_display, m_visualInfo->screen), - left, - top, - width, - height, - 0, /* no border. */ - m_visualInfo->depth, - InputOutput, - m_visualInfo->visual, - xattributes_valuemask, - &xattributes); - } - else { - Window root_return; - int x_return, y_return; - unsigned int w_return, h_return, border_w_return, depth_return; - - XGetGeometry(m_display, - parentWindow->m_window, - &root_return, - &x_return, - &y_return, - &w_return, - &h_return, - &border_w_return, - &depth_return); - - left = 0; - top = 0; - width = w_return; - height = h_return; - - m_window = XCreateWindow(m_display, - parentWindow->m_window, /* reparent against embedder */ - left, - top, - width, - height, - 0, /* no border. */ - m_visualInfo->depth, - InputOutput, - m_visualInfo->visual, - xattributes_valuemask, - &xattributes); - - XSelectInput(m_display, parentWindow->m_window, SubstructureNotifyMask); - } + m_window = XCreateWindow(m_display, + RootWindow(m_display, m_visualInfo->screen), + left, + top, + width, + height, + 0, /* no border. */ + m_visualInfo->depth, + InputOutput, + m_visualInfo->visual, + xattributes_valuemask, + &xattributes); #ifdef WITH_XDND /* initialize drop target for newly created window */ @@ -1169,7 +1132,7 @@ GHOST_TSuccess GHOST_WindowX11::setOrder(GHOST_TWindowOrder order) XGetWindowAttributes(m_display, m_window, &attr); - /* iconized windows give bad match error */ + /* Minimized windows give bad match error. */ if (attr.map_state == IsViewable) XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); XFlush(m_display); diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp index 39b7f0776e1..30a2a238ccd 100644 --- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp +++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp @@ -125,7 +125,7 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { oxr_binding.wgl.hGLRC = ctx_wgl.m_hGLRC; #endif - /* Generate a framebuffer to use for blitting into the texture. */ + /* Generate a frame-buffer to use for blitting into the texture. */ glGenFramebuffers(1, &m_fbo); } diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 73b73a8f046..a1fd7fc2781 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -338,7 +338,7 @@ void GHOST_XrSession::endFrameDrawing(std::vector<XrCompositionLayerBaseHeader * void GHOST_XrSession::draw(void *draw_customdata) { std::vector<XrCompositionLayerProjectionView> - projection_layer_views; /* Keep alive until xrEndFrame() call! */ + projection_layer_views; /* Keep alive until #xrEndFrame() call! */ XrCompositionLayerProjection proj_layer; std::vector<XrCompositionLayerBaseHeader *> layers; @@ -354,7 +354,7 @@ void GHOST_XrSession::draw(void *draw_customdata) static void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose &r_ghost_pose) { - /* Set and convert to Blender coodinate space. */ + /* Set and convert to Blender coordinate space. */ r_ghost_pose.position[0] = oxr_pose.position.x; r_ghost_pose.position[1] = oxr_pose.position.y; r_ghost_pose.position[2] = oxr_pose.position.z; @@ -366,7 +366,7 @@ static void copy_openxr_pose_to_ghost_pose(const XrPosef &oxr_pose, GHOST_XrPose static void ghost_xr_draw_view_info_from_view(const XrView &view, GHOST_XrDrawViewInfo &r_info) { - /* Set and convert to Blender coodinate space. */ + /* Set and convert to Blender coordinate space. */ copy_openxr_pose_to_ghost_pose(view.pose, r_info.eye_pose); r_info.fov.angle_left = view.fov.angleLeft; diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt index 27a764cd050..37bb00332dd 100644 --- a/intern/ghost/test/CMakeLists.txt +++ b/intern/ghost/test/CMakeLists.txt @@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.5) project(GhostMultiTest) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../../..//build_files/cmake/Modules") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../../../build_files/cmake/Modules") set(WITH_GUARDEDALLOC ON) diff --git a/intern/ghost/test/gears/GHOST_C-Test.c b/intern/ghost/test/gears/GHOST_C-Test.c index 3419f70dfcf..4283f990cfb 100644 --- a/intern/ghost/test/gears/GHOST_C-Test.c +++ b/intern/ghost/test/gears/GHOST_C-Test.c @@ -440,12 +440,14 @@ int main(int argc, char **argv) if (shSystem) { /* Create the main window */ sMainWindow = GHOST_CreateWindow(shSystem, + NULL, title1, 10, 64, 320, 200, GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glSettings); if (!sMainWindow) { @@ -455,12 +457,14 @@ int main(int argc, char **argv) /* Create a secondary window */ sSecondaryWindow = GHOST_CreateWindow(shSystem, + NULL, title2, 340, 64, 320, 200, GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glSettings); if (!sSecondaryWindow) { diff --git a/intern/ghost/test/multitest/MultiTest.c b/intern/ghost/test/multitest/MultiTest.c index b6b83f2a47d..8c8858fc6d8 100644 --- a/intern/ghost/test/multitest/MultiTest.c +++ b/intern/ghost/test/multitest/MultiTest.c @@ -318,12 +318,14 @@ MainWindow *mainwindow_new(MultiTestApp *app) GHOST_GLSettings glSettings = {0}; win = GHOST_CreateWindow(sys, + NULL, "MultiTest:Main", 40, 40, 400, 400, GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glSettings); @@ -573,12 +575,14 @@ LoggerWindow *loggerwindow_new(MultiTestApp *app) GHOST_GetMainDisplayDimensions(sys, &screensize[0], &screensize[1]); win = GHOST_CreateWindow(sys, + NULL, "MultiTest:Logger", 40, screensize[1] - 432, 800, 300, GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glSettings); @@ -773,12 +777,14 @@ ExtraWindow *extrawindow_new(MultiTestApp *app) GHOST_WindowHandle win; win = GHOST_CreateWindow(sys, + NULL, "MultiTest:Extra", 500, 40, 400, 400, GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glSettings); diff --git a/intern/guardedalloc/CMakeLists.txt b/intern/guardedalloc/CMakeLists.txt index 0d46e81cd87..b47565b8ef9 100644 --- a/intern/guardedalloc/CMakeLists.txt +++ b/intern/guardedalloc/CMakeLists.txt @@ -49,12 +49,6 @@ set(LIB ) if(WIN32 AND NOT UNIX) - list(APPEND SRC - intern/mmap_win.c - - mmap_win.h - ) - list(APPEND INC_SYS ${PTHREADS_INC} ) diff --git a/intern/guardedalloc/MEM_guardedalloc.h b/intern/guardedalloc/MEM_guardedalloc.h index a0174e30aff..62f28c9e97e 100644 --- a/intern/guardedalloc/MEM_guardedalloc.h +++ b/intern/guardedalloc/MEM_guardedalloc.h @@ -122,7 +122,7 @@ extern void *(*MEM_calloc_arrayN)(size_t len, /** * Allocate a block of memory of size len, with tag name str. The * name must be a static, because only a pointer to it is stored ! - * */ + */ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT ATTR_ALLOC_SIZE(1) ATTR_NONNULL(2); @@ -130,7 +130,7 @@ extern void *(*MEM_mallocN)(size_t len, const char *str) /* ATTR_MALLOC */ ATTR_ * Allocate a block of memory of size (len * size), with tag name str, * aborting in case of integer overflow to prevent vulnerabilities. The * name must be a static, because only a pointer to it is stored ! - * */ + */ extern void *(*MEM_malloc_arrayN)(size_t len, size_t size, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT @@ -139,7 +139,7 @@ extern void *(*MEM_malloc_arrayN)(size_t len, /** * Allocate an aligned block of memory of size len, with tag name str. The * name must be a static, because only a pointer to it is stored ! - * */ + */ extern void *(*MEM_mallocN_aligned)(size_t len, size_t alignment, const char *str) /* ATTR_MALLOC */ ATTR_WARN_UNUSED_RESULT diff --git a/intern/guardedalloc/intern/mmap_win.c b/intern/guardedalloc/intern/mmap_win.c deleted file mode 100644 index a02a0f88fa9..00000000000 --- a/intern/guardedalloc/intern/mmap_win.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM - */ - -#ifdef WIN32 - -# include <errno.h> -# include <io.h> -# include <stdio.h> -# include <sys/types.h> -# include <windows.h> - -# include "mmap_win.h" - -# ifndef FILE_MAP_EXECUTE -// not defined in earlier versions of the Platform SDK (before February 2003) -# define FILE_MAP_EXECUTE 0x0020 -# endif - -/* copied from BLI_utildefines.h, ugh */ -# ifdef __GNUC__ -# define UNUSED(x) UNUSED_##x __attribute__((__unused__)) -# else -# define UNUSED(x) x -# endif - -/* --------------------------------------------------------------------- */ -/* local storage definitions */ -/* --------------------------------------------------------------------- */ -/* all memory mapped chunks are put in linked lists */ -typedef struct mmapLink { - struct mmapLink *next, *prev; -} mmapLink; - -typedef struct mmapListBase { - void *first, *last; -} mmapListBase; - -typedef struct MemMap { - struct MemMap *next, *prev; - void *mmap; - HANDLE fhandle; - HANDLE maphandle; -} MemMap; - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink); -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink); -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr); - -static int mmap_get_prot_flags(int flags); -static int mmap_get_access_flags(int flags); - -/* --------------------------------------------------------------------- */ -/* vars */ -/* --------------------------------------------------------------------- */ -volatile static struct mmapListBase _mmapbase; -volatile static struct mmapListBase *mmapbase = &_mmapbase; - -/* --------------------------------------------------------------------- */ -/* implementation */ -/* --------------------------------------------------------------------- */ - -/* mmap for windows */ -void *mmap(void *UNUSED(start), size_t len, int prot, int flags, int fd, off_t offset) -{ - HANDLE fhandle = INVALID_HANDLE_VALUE; - HANDLE maphandle; - int prot_flags = mmap_get_prot_flags(prot); - int access_flags = mmap_get_access_flags(prot); - MemMap *mm = NULL; - void *ptr = NULL; - - if (flags & MAP_FIXED) { - return MAP_FAILED; - } - -# if 0 - if (fd == -1) { - _set_errno(EBADF); - return MAP_FAILED; - } -# endif - - if (fd != -1) { - fhandle = (HANDLE)_get_osfhandle(fd); - } - if (fhandle == INVALID_HANDLE_VALUE) { - if (!(flags & MAP_ANONYMOUS)) { - errno = EBADF; - return MAP_FAILED; - } - } - else { - if (!DuplicateHandle(GetCurrentProcess(), - fhandle, - GetCurrentProcess(), - &fhandle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS)) { - return MAP_FAILED; - } - } - - /* Split 64 bit size into low and high bits. */ - DWORD len_bits_high = len >> 32; - DWORD len_bits_low = len & 0xFFFFFFFF; - - maphandle = CreateFileMapping(fhandle, NULL, prot_flags, len_bits_high, len_bits_low, NULL); - if (maphandle == 0) { - errno = EBADF; - return MAP_FAILED; - } - - ptr = MapViewOfFile(maphandle, access_flags, 0, offset, 0); - if (ptr == NULL) { - DWORD dwLastErr = GetLastError(); - if (dwLastErr == ERROR_MAPPED_ALIGNMENT) { - errno = EINVAL; - } - else { - errno = EACCES; - } - CloseHandle(maphandle); - return MAP_FAILED; - } - - mm = (MemMap *)malloc(sizeof(MemMap)); - if (!mm) { - errno = ENOMEM; - } - mm->fhandle = fhandle; - mm->maphandle = maphandle; - mm->mmap = ptr; - mmap_addtail(mmapbase, mm); - - return ptr; -} - -/* munmap for windows */ -intptr_t munmap(void *ptr, size_t UNUSED(size)) -{ - MemMap *mm = mmap_findlink(mmapbase, ptr); - if (!mm) { - errno = EINVAL; - return -1; - } - UnmapViewOfFile(mm->mmap); - CloseHandle(mm->maphandle); - CloseHandle(mm->fhandle); - mmap_remlink(mmapbase, mm); - free(mm); - return 0; -} - -/* --------------------------------------------------------------------- */ -/* local functions */ -/* --------------------------------------------------------------------- */ - -static void mmap_addtail(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - - link->next = 0; - link->prev = listbase->last; - - if (listbase->last) { - ((struct mmapLink *)listbase->last)->next = link; - } - if (listbase->first == NULL) { - listbase->first = link; - } - listbase->last = link; -} - -static void mmap_remlink(volatile mmapListBase *listbase, void *vlink) -{ - struct mmapLink *link = vlink; - - if (link == NULL) { - return; - } - if (listbase == NULL) { - return; - } - if (link->next) { - link->next->prev = link->prev; - } - if (link->prev) { - link->prev->next = link->next; - } - - if (listbase->last == link) { - listbase->last = link->prev; - } - if (listbase->first == link) { - listbase->first = link->next; - } -} - -static void *mmap_findlink(volatile mmapListBase *listbase, void *ptr) -{ - MemMap *mm; - - if (ptr == NULL) { - return NULL; - } - if (listbase == NULL) { - return NULL; - } - - mm = (MemMap *)listbase->first; - while (mm) { - if (mm->mmap == ptr) { - return mm; - } - mm = mm->next; - } - return NULL; -} - -static int mmap_get_prot_flags(int flags) -{ - int prot = PAGE_NOACCESS; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - } - else { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_READONLY; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - prot = (flags & PROT_EXEC) ? PAGE_EXECUTE_READ : PAGE_WRITECOPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - prot = PAGE_EXECUTE_READ; - } - return prot; -} - -static int mmap_get_access_flags(int flags) -{ - int access = 0; - - if ((flags & PROT_READ) == PROT_READ) { - if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_WRITE; - } - else { - access = (flags & PROT_EXEC) ? FILE_MAP_EXECUTE : FILE_MAP_READ; - } - } - else if ((flags & PROT_WRITE) == PROT_WRITE) { - access = FILE_MAP_COPY; - } - else if ((flags & PROT_EXEC) == PROT_EXEC) { - access = FILE_MAP_EXECUTE; - } - return access; -} - -#endif // WIN32 diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp index 7f77968a5d4..82aaaf7bb9a 100644 --- a/intern/iksolver/intern/IK_QJacobian.cpp +++ b/intern/iksolver/intern/IK_QJacobian.cpp @@ -203,7 +203,7 @@ void IK_QJacobian::InvertSDLS() // singular the least squares inverse tries to minimize |J(dtheta) - dX)| // and doesn't try to minimize dTheta. This results in eratic changes in // angle. The damped least squares minimizes |dtheta| to try and reduce this - // erratic behaviour. + // erratic behavior. // // The selectively damped least squares (SDLS) is used here instead of the // DLS. The SDLS damps individual singular values, instead of using a single @@ -325,7 +325,7 @@ void IK_QJacobian::InvertDLS() // inverse tries to minimize |J(dtheta) - dX)| and doesn't // try to minimize dTheta. This results in eratic changes in angle. // Damped least squares minimizes |dtheta| to try and reduce this - // erratic behaviour. + // erratic behavior. // We don't want to use the damped solution everywhere so we // only increase lamda from zero as we approach a singularity. diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h index 6312b4eb1a6..f5478bee6ab 100644 --- a/intern/libmv/libmv/numeric/numeric.h +++ b/intern/libmv/libmv/numeric/numeric.h @@ -463,7 +463,7 @@ inline bool isnan(double i) { #endif } -/// Ceil function that has the same behaviour for positive +/// Ceil function that has the same behavior for positive /// and negative values template <typename FloatType> FloatType ceil0(const FloatType& value) { diff --git a/intern/mikktspace/mikktspace.c b/intern/mikktspace/mikktspace.c index 17cd997f451..b0119f54019 100644 --- a/intern/mikktspace/mikktspace.c +++ b/intern/mikktspace/mikktspace.c @@ -138,7 +138,7 @@ MIKK_INLINE tbool VNotZero(const SVec3 v) // Shift operations in C are only defined for shift values which are // not negative and smaller than sizeof(value) * CHAR_BIT. -// The mask, used with bitwise-and (&), prevents undefined behaviour +// The mask, used with bitwise-and (&), prevents undefined behavior // when the shift count is 0 or >= the width of unsigned int. MIKK_INLINE unsigned int rotl(unsigned int value, unsigned int count) { @@ -1454,12 +1454,12 @@ static void BuildNeighborsFast(STriInfo pTriInfos[], pEdges[f * 3 + i].f = f; // record face number } - // sort over all edges by i0, this is the pricy one. + // sort over all edges by i0, this is the pricey one. QuickSortEdges(pEdges, 0, iNrTrianglesIn * 3 - 1, 0, uSeed); // sort channel 0 which is i0 // sub sort over i1, should be fast. // could replace this with a 64 bit int sort over (i0,i1) - // with i0 as msb in the quicksort call above. + // with i0 as msb in the quick-sort call above. iEntries = iNrTrianglesIn * 3; iCurStartIndex = 0; for (i = 1; i < iEntries; i++) { diff --git a/release/darwin/Blender.app/Contents/Info.plist b/release/darwin/Blender.app/Contents/Info.plist index 2408cf363b1..67b786bd933 100644 --- a/release/darwin/Blender.app/Contents/Info.plist +++ b/release/darwin/Blender.app/Contents/Info.plist @@ -11,8 +11,6 @@ <array> <string>blend</string> </array> - <key>CFBundleTypeIconFile</key> - <string>blender file icon.icns</string> <key>CFBundleTypeName</key> <string>Blender File</string> <key>CFBundleTypeOSTypes</key> @@ -23,6 +21,12 @@ <string>Editor</string> <key>LSIsAppleDefaultForType</key> <true/> + <key>LSItemContentTypes</key> + <array> + <string>org.blenderfoundation.blender.file</string> + </array> + <key>CFBundleTypeIconSystemGenerated</key> + <true/> </dict> </array> <key>CFBundleExecutable</key> @@ -49,5 +53,30 @@ <string>NSApplication</string> <key>NSHighResolutionCapable</key> <true/> + <key>UTExportedTypeDeclarations</key> + <array> + <dict> + <key>UTTypeConformsTo</key> + <array> + <string>public.data</string> + </array> + <key>UTTypeIdentifier</key> + <string>org.blenderfoundation.blender.file</string> + <key>UTTypeIcons</key> + <dict> + <key>UTTypeIconName</key> + <string>Blender File</string> + <key>UTTypeIconText</key> + <string>blend</string> + </dict> + <key>UTTypeTagSpecification</key> + <dict> + <key>public.filename-extension</key> + <array> + <string>blend</string> + </array> + </dict> + </dict> + </array> </dict> </plist> diff --git a/release/darwin/Blender.app/Contents/Resources/blender file icon.icns b/release/darwin/Blender.app/Contents/Resources/blender file icon.icns Binary files differdeleted file mode 100644 index 2bf78d3eb0d..00000000000 --- a/release/darwin/Blender.app/Contents/Resources/blender file icon.icns +++ /dev/null diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png Binary files differindex 858709833fb..babb3e30c6d 100644 --- a/release/datafiles/splash.png +++ b/release/datafiles/splash.png diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index b448a230da8..6383d7dfcca 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -105,7 +105,7 @@ const UserDef U_default = { .autoexec_paths = {NULL}, .user_menus = {NULL}, - .keyconfigstr = "blender", + .keyconfigstr = "Blender", .undosteps = 32, .undomemory = 0, .gp_manhattandist = 1, @@ -119,6 +119,7 @@ const UserDef U_default = { .gizmo_flag = USER_GIZMO_DRAW, .gizmo_size = 75, + .gizmo_size_navigate_v3d = 80, .edit_studio_light = 0, .lookdev_sphere_size = 150, .vbotimeout = 120, diff --git a/release/datafiles/userdef/userdef_default_theme.c b/release/datafiles/userdef/userdef_default_theme.c index 2754b7f06f8..0477b0c9f23 100644 --- a/release/datafiles/userdef/userdef_default_theme.c +++ b/release/datafiles/userdef/userdef_default_theme.c @@ -489,16 +489,17 @@ const bTheme U_theme_default = { .facedot_size = 4, .info_selected = RGBA(0x3b5689ff), .info_selected_text = RGBA(0xffffffff), - .info_error = RGBA(0xff613dff), + .info_error = RGBA(0xb34c34ff), .info_error_text = RGBA(0xffffffff), - .info_warning = RGBA(0xf5bc41ff), + .info_warning = RGBA(0xac8737ff), .info_warning_text = RGBA(0xffffffff), - .info_info = RGBA(0x1d4383ff), + .info_info = RGBA(0x1f3862ff), .info_info_text = RGBA(0xffffffff), - .info_debug = RGBA(0xd3d3d3ff), - .info_property = RGBA(0x3ace87ff), + .info_debug = RGBA(0x6b3293ff), + .info_debug_text = RGBA(0xffffffff), + .info_property = RGBA(0x329364ff), .info_property_text = RGBA(0xffffffff), - .info_operator = RGBA(0x3ace87ff), + .info_operator = RGBA(0x329364ff), .info_operator_text = RGBA(0xffffffff), }, .space_action = { diff --git a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py index ebc5370a7af..ef398d5e08f 100644 --- a/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py +++ b/release/scripts/modules/bl_keymap_utils/keymap_from_toolbar.py @@ -74,8 +74,6 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True): if tap_reset_tool not in items_all_id: use_tap_reset = False - from bl_operators.wm import use_toolbar_release_hack - # Pie-menu style release to activate. use_release_confirm = use_reset @@ -437,7 +435,7 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True): kmi = keymap.keymap_items.new( "wm.tool_set_by_id", - value='PRESS' if use_toolbar_release_hack else 'DOUBLE_CLICK', + value='DOUBLE_CLICK', **kmi_toolbar_args_available, ) kmi.properties.name = tap_reset_tool @@ -451,15 +449,6 @@ def generate(context, space_type, use_fallback_keys=True, use_reset=True): ) kmi.properties.skip_depressed = True - if use_toolbar_release_hack: - # ... or pass through to let the toolbar know we're released. - # Let the operator know we're released. - kmi = keymap.keymap_items.new( - "wm.tool_set_by_id", - type=kmi_toolbar_type, - value='RELEASE', - any=True, - ) wm.keyconfigs.update() return keymap diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index 3860445233d..fad52eae84a 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -201,12 +201,13 @@ _display_name_literals = { } -def display_name(name, *, has_ext=True): +def display_name(name, *, has_ext=True, title_case=True): """ Creates a display string from name to be used menus and the user interface. - Capitalize the first letter in all lowercase names, - mixed case names are kept as is. Intended for use with - filenames and module names. + Intended for use with filenames and module names. + + :arg has_ext: Remove file extension from name + :arg title_case: Convert lowercase names to title case """ if has_ext: @@ -220,7 +221,7 @@ def display_name(name, *, has_ext=True): # (when paths can't start with numbers for eg). name = name.replace("_", " ").lstrip(" ") - if name.islower(): + if title_case and name.islower(): name = name.lower().title() name = _clean_utf8(name) diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 897010e80cf..7f39cc5d422 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -606,7 +606,7 @@ def preset_find(name, preset_path, display_name=False, ext=".py"): if display_name: filename = "" for fn in _os.listdir(directory): - if fn.endswith(ext) and name == _bpy.path.display_name(fn): + if fn.endswith(ext) and name == _bpy.path.display_name(fn, title_case=False): filename = fn break else: @@ -624,7 +624,7 @@ def keyconfig_init(): active_config = _preferences.keymap.active_keyconfig # Load the default key configuration. - default_filepath = preset_find("blender", "keyconfig") + default_filepath = preset_find("Blender", "keyconfig") keyconfig_set(default_filepath) # Set the active key configuration if different diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index d863778a9c2..5d89763f34b 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -982,6 +982,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta): props_default=props_default, filter_ext=lambda ext: ext.lower() in ext_valid, add_operator=add_operator, + display_name=lambda name: bpy.path.display_name(name, title_case=False) ) @classmethod diff --git a/release/scripts/presets/cloth/cotton.py b/release/scripts/presets/cloth/Cotton.py index 9e766416a75..9e766416a75 100644 --- a/release/scripts/presets/cloth/cotton.py +++ b/release/scripts/presets/cloth/Cotton.py diff --git a/release/scripts/presets/cloth/denim.py b/release/scripts/presets/cloth/Denim.py index 7abf4469709..7abf4469709 100644 --- a/release/scripts/presets/cloth/denim.py +++ b/release/scripts/presets/cloth/Denim.py diff --git a/release/scripts/presets/cloth/leather.py b/release/scripts/presets/cloth/Leather.py index 8ba9ff7dabe..8ba9ff7dabe 100644 --- a/release/scripts/presets/cloth/leather.py +++ b/release/scripts/presets/cloth/Leather.py diff --git a/release/scripts/presets/cloth/rubber.py b/release/scripts/presets/cloth/Rubber.py index 0d791fab2a9..0d791fab2a9 100644 --- a/release/scripts/presets/cloth/rubber.py +++ b/release/scripts/presets/cloth/Rubber.py diff --git a/release/scripts/presets/cloth/silk.py b/release/scripts/presets/cloth/Silk.py index af867cf9c60..af867cf9c60 100644 --- a/release/scripts/presets/cloth/silk.py +++ b/release/scripts/presets/cloth/Silk.py diff --git a/release/scripts/presets/cycles/integrator/direct_light.py b/release/scripts/presets/cycles/integrator/Direct_Light.py index 701aa10d556..701aa10d556 100644 --- a/release/scripts/presets/cycles/integrator/direct_light.py +++ b/release/scripts/presets/cycles/integrator/Direct_Light.py diff --git a/release/scripts/presets/cycles/integrator/full_global_illumination.py b/release/scripts/presets/cycles/integrator/Full_Global_Illumination.py index a03c6c8bd64..a03c6c8bd64 100644 --- a/release/scripts/presets/cycles/integrator/full_global_illumination.py +++ b/release/scripts/presets/cycles/integrator/Full_Global_Illumination.py diff --git a/release/scripts/presets/cycles/integrator/limited_global_illumination.py b/release/scripts/presets/cycles/integrator/Limited_Global_Illumination.py index d37bf46c705..d37bf46c705 100644 --- a/release/scripts/presets/cycles/integrator/limited_global_illumination.py +++ b/release/scripts/presets/cycles/integrator/Limited_Global_Illumination.py diff --git a/release/scripts/presets/cycles/sampling/final.py b/release/scripts/presets/cycles/sampling/Final.py index f1222d927c1..f1222d927c1 100644 --- a/release/scripts/presets/cycles/sampling/final.py +++ b/release/scripts/presets/cycles/sampling/Final.py diff --git a/release/scripts/presets/cycles/sampling/preview.py b/release/scripts/presets/cycles/sampling/Preview.py index c16449e2c8f..c16449e2c8f 100644 --- a/release/scripts/presets/cycles/sampling/preview.py +++ b/release/scripts/presets/cycles/sampling/Preview.py diff --git a/release/scripts/presets/ffmpeg/h264_in_MP4.py b/release/scripts/presets/ffmpeg/H264_in_MP4.py index 0e9c32c4878..0e9c32c4878 100644 --- a/release/scripts/presets/ffmpeg/h264_in_MP4.py +++ b/release/scripts/presets/ffmpeg/H264_in_MP4.py diff --git a/release/scripts/presets/ffmpeg/h264_in_Matroska.py b/release/scripts/presets/ffmpeg/H264_in_Matroska.py index 1fe066dc4bf..1fe066dc4bf 100644 --- a/release/scripts/presets/ffmpeg/h264_in_Matroska.py +++ b/release/scripts/presets/ffmpeg/H264_in_Matroska.py diff --git a/release/scripts/presets/ffmpeg/h264_in_Matroska_for_scrubbing.py b/release/scripts/presets/ffmpeg/H264_in_Matroska_for_scrubbing.py index eb1889d272f..eb1889d272f 100644 --- a/release/scripts/presets/ffmpeg/h264_in_Matroska_for_scrubbing.py +++ b/release/scripts/presets/ffmpeg/H264_in_Matroska_for_scrubbing.py diff --git a/release/scripts/presets/ffmpeg/ogg_theora.py b/release/scripts/presets/ffmpeg/Ogg_Theora.py index b450b67fd98..b450b67fd98 100644 --- a/release/scripts/presets/ffmpeg/ogg_theora.py +++ b/release/scripts/presets/ffmpeg/Ogg_Theora.py diff --git a/release/scripts/presets/ffmpeg/xvid.py b/release/scripts/presets/ffmpeg/Xvid.py index dba0f71c279..dba0f71c279 100644 --- a/release/scripts/presets/ffmpeg/xvid.py +++ b/release/scripts/presets/ffmpeg/Xvid.py diff --git a/release/scripts/presets/fluid/honey.py b/release/scripts/presets/fluid/Honey.py index 0ed3658470a..0ed3658470a 100644 --- a/release/scripts/presets/fluid/honey.py +++ b/release/scripts/presets/fluid/Honey.py diff --git a/release/scripts/presets/fluid/oil.py b/release/scripts/presets/fluid/Oil.py index c33e5d4b6cf..c33e5d4b6cf 100644 --- a/release/scripts/presets/fluid/oil.py +++ b/release/scripts/presets/fluid/Oil.py diff --git a/release/scripts/presets/fluid/water.py b/release/scripts/presets/fluid/Water.py index f34ecc834ff..f34ecc834ff 100644 --- a/release/scripts/presets/fluid/water.py +++ b/release/scripts/presets/fluid/Water.py diff --git a/release/scripts/presets/gpencil_material/fill_only.py b/release/scripts/presets/gpencil_material/Fill_Only.py index aa4d58a8c10..aa4d58a8c10 100644 --- a/release/scripts/presets/gpencil_material/fill_only.py +++ b/release/scripts/presets/gpencil_material/Fill_Only.py diff --git a/release/scripts/presets/gpencil_material/stroke_only.py b/release/scripts/presets/gpencil_material/Stroke_Only.py index 4e02b108e01..4e02b108e01 100644 --- a/release/scripts/presets/gpencil_material/stroke_only.py +++ b/release/scripts/presets/gpencil_material/Stroke_Only.py diff --git a/release/scripts/presets/gpencil_material/stroke_and_fill.py b/release/scripts/presets/gpencil_material/Stroke_and_Fill.py index 3572036de5e..3572036de5e 100644 --- a/release/scripts/presets/gpencil_material/stroke_and_fill.py +++ b/release/scripts/presets/gpencil_material/Stroke_and_Fill.py diff --git a/release/scripts/presets/hair_dynamics/default.py b/release/scripts/presets/hair_dynamics/Default.py index 830d28a76f0..830d28a76f0 100644 --- a/release/scripts/presets/hair_dynamics/default.py +++ b/release/scripts/presets/hair_dynamics/Default.py diff --git a/release/scripts/presets/interface_theme/blender_dark.xml b/release/scripts/presets/interface_theme/Blender_Dark.xml index 8bbb747447b..8bbb747447b 100644 --- a/release/scripts/presets/interface_theme/blender_dark.xml +++ b/release/scripts/presets/interface_theme/Blender_Dark.xml diff --git a/release/scripts/presets/interface_theme/blender_light.xml b/release/scripts/presets/interface_theme/Blender_Light.xml index 91ccd574c31..77908bb6bbf 100644 --- a/release/scripts/presets/interface_theme/blender_light.xml +++ b/release/scripts/presets/interface_theme/Blender_Light.xml @@ -1053,19 +1053,19 @@ <info> <ThemeInfo info_selected="#6080ff" - info_selected_text="#ffffff" - info_error="#990000ff" - info_error_text="#ffffff" - info_warning="#b36a00ff" - info_warning_text="#ffffff" - info_info="#1d4383ff" - info_info_text="#ffffff" - info_debug="#d3d3d3ff" + info_selected_text="#000000" + info_error="#FF0038ff" + info_error_text="#000000" + info_warning="#FFE900ff" + info_warning_text="#000000" + info_info="#0068B3ff" + info_info_text="#000000" + info_debug="#B30095ff" info_debug_text="#000000" - info_property="#3ace87ff" - info_property_text="#ffffff" - info_operator="#3ace87ff" - info_operator_text="#ffffff" + info_property="#44B300ff" + info_property_text="#000000" + info_operator="#44B300ff" + info_operator_text="#000000" > <space> <ThemeSpaceGeneric diff --git a/release/scripts/presets/keyconfig/blender.py b/release/scripts/presets/keyconfig/Blender.py index eb66c961472..eb66c961472 100644 --- a/release/scripts/presets/keyconfig/blender.py +++ b/release/scripts/presets/keyconfig/Blender.py diff --git a/release/scripts/presets/keyconfig/blender_27x.py b/release/scripts/presets/keyconfig/Blender_27x.py index efb013b9216..2a7f0b07fa6 100644 --- a/release/scripts/presets/keyconfig/blender_27x.py +++ b/release/scripts/presets/keyconfig/Blender_27x.py @@ -1,3 +1,28 @@ +# +# Notes on this key-map: +# +# This uses Blender's key-map, running with `legacy=True`. +# +# The intention of this key-map is to match Blender 2.7x which had many more key-map items available. +# +# There are some differences with the original Blender 2.7x key-map. +# There is no intention to change these are they are not considered significant +# enough to make a 1:1 match with the previous Blender version. +# +# These include: +# +# 3D View +# ======= +# +# - Border Render (`Shift-B` -> `Ctrl-B`) +# Both `Shift-B` and `Ctrl-B` were used. +# +# Time Line/Animation Views +# ========================= +# +# - Start Frame/End Frame (`S/E` -> `Ctrl-Home/Ctrl-End`) +# + import os import bpy from bpy.props import ( diff --git a/release/scripts/presets/keyconfig/industry_compatible.py b/release/scripts/presets/keyconfig/Industry_Compatible.py index 09a43452e93..09a43452e93 100644 --- a/release/scripts/presets/keyconfig/industry_compatible.py +++ b/release/scripts/presets/keyconfig/Industry_Compatible.py diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 73f05fb3d80..fd9d699ed01 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -5131,6 +5131,8 @@ def km_transform_modal_map(_params): ("INSERTOFS_TOGGLE_DIR", {"type": 'T', "value": 'PRESS'}, None), ("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY'}, None), ("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True}, None), + ("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None), + ("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None), ]) return keymap diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index 4cffb6805a0..234781b7bc8 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -3962,6 +3962,8 @@ def km_transform_modal_map(_params): ("INSERTOFS_TOGGLE_DIR", {"type": 'T', "value": 'PRESS'}, None), ("AUTOCONSTRAIN", {"type": 'MIDDLEMOUSE', "value": 'ANY'}, None), ("AUTOCONSTRAINPLANE", {"type": 'MIDDLEMOUSE', "value": 'ANY', "shift": True}, None), + ("PRECISION", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None), + ("PRECISION", {"type": 'RIGHT_SHIFT', "value": 'ANY', "any": True}, None), ]) return keymap diff --git a/release/scripts/presets/render/4k_UHDTV_2160p.py b/release/scripts/presets/render/4K_UHDTV_2160p.py index 4517d2f435e..4517d2f435e 100644 --- a/release/scripts/presets/render/4k_UHDTV_2160p.py +++ b/release/scripts/presets/render/4K_UHDTV_2160p.py diff --git a/release/scripts/presets/tracking_settings/blurry_footage.py b/release/scripts/presets/tracking_settings/Blurry_Footage.py index 253a8f395ba..253a8f395ba 100644 --- a/release/scripts/presets/tracking_settings/blurry_footage.py +++ b/release/scripts/presets/tracking_settings/Blurry_Footage.py diff --git a/release/scripts/presets/tracking_settings/default.py b/release/scripts/presets/tracking_settings/Default.py index 3d2481ce7ad..3d2481ce7ad 100644 --- a/release/scripts/presets/tracking_settings/default.py +++ b/release/scripts/presets/tracking_settings/Default.py diff --git a/release/scripts/presets/tracking_settings/fast_motion.py b/release/scripts/presets/tracking_settings/Fast_Motion.py index 4294b7327d1..4294b7327d1 100644 --- a/release/scripts/presets/tracking_settings/fast_motion.py +++ b/release/scripts/presets/tracking_settings/Fast_Motion.py diff --git a/release/scripts/presets/tracking_settings/planar.py b/release/scripts/presets/tracking_settings/Planar.py index a099b3a800d..a099b3a800d 100644 --- a/release/scripts/presets/tracking_settings/planar.py +++ b/release/scripts/presets/tracking_settings/Planar.py diff --git a/release/scripts/presets/tracking_track_color/default.py b/release/scripts/presets/tracking_track_color/Default.py index 3213d6e0c83..3213d6e0c83 100644 --- a/release/scripts/presets/tracking_track_color/default.py +++ b/release/scripts/presets/tracking_track_color/Default.py diff --git a/release/scripts/presets/tracking_track_color/far_plane.py b/release/scripts/presets/tracking_track_color/Far_Plane.py index 579d5562642..579d5562642 100644 --- a/release/scripts/presets/tracking_track_color/far_plane.py +++ b/release/scripts/presets/tracking_track_color/Far_Plane.py diff --git a/release/scripts/presets/tracking_track_color/near_plane.py b/release/scripts/presets/tracking_track_color/Near_Plane.py index 790429ce7a1..790429ce7a1 100644 --- a/release/scripts/presets/tracking_track_color/near_plane.py +++ b/release/scripts/presets/tracking_track_color/Near_Plane.py diff --git a/release/scripts/presets/tracking_track_color/object.py b/release/scripts/presets/tracking_track_color/Object.py index 5cb663d3f97..5cb663d3f97 100644 --- a/release/scripts/presets/tracking_track_color/object.py +++ b/release/scripts/presets/tracking_track_color/Object.py diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index 793a8648ee4..5132b358f5e 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -77,7 +77,7 @@ class AddPresetBase: setattr(cls, attr, trans) return trans - name = name.lower().strip() + name = name.strip() name = bpy.path.display_name_to_filepath(name) trans = maketrans_init() # Strip surrounding "_" as they are displayed as spaces. @@ -249,7 +249,7 @@ class ExecutePreset(Operator): # change the menu title to the most recently chosen option preset_class = getattr(bpy.types, self.menu_idname) - preset_class.bl_label = bpy.path.display_name(basename(filepath)) + preset_class.bl_label = bpy.path.display_name(basename(filepath), title_case=False) ext = splitext(filepath)[1].lower() diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index ee46742fbd0..2ee20e08589 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -33,11 +33,6 @@ from bpy.props import ( ) from bpy.app.translations import pgettext_iface as iface_ -# FIXME, we need a way to detect key repeat events. -# unfortunately checking event previous values isn't reliable. -use_toolbar_release_hack = True - - rna_path_prop = StringProperty( name="Context Attributes", description="RNA context string", @@ -1698,18 +1693,6 @@ class WM_OT_tool_set_by_id(Operator): space_type: rna_space_type_prop - if use_toolbar_release_hack: - def invoke(self, context, event): - # Hack :S - if not self.properties.is_property_set("name"): - WM_OT_toolbar._key_held = False - return {'PASS_THROUGH'} - elif (WM_OT_toolbar._key_held == event.type) and (event.value != 'RELEASE'): - return {'PASS_THROUGH'} - WM_OT_toolbar._key_held = None - - return self.execute(context) - def execute(self, context): from bl_ui.space_toolsystem_common import ( activate_by_id, @@ -1801,13 +1784,6 @@ class WM_OT_toolbar(Operator): def poll(cls, context): return context.space_data is not None - if use_toolbar_release_hack: - _key_held = None - - def invoke(self, context, event): - WM_OT_toolbar._key_held = event.type - return self.execute(context) - @staticmethod def keymap_from_toolbar(context, space_type, use_fallback_keys=True, use_reset=True): from bl_ui.space_toolsystem_common import ToolSelectPanelHelper diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py index 351d4928ddf..9db6eedb04c 100644 --- a/release/scripts/startup/bl_ui/properties_data_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py @@ -23,6 +23,7 @@ from rna_prop_ui import PropertyPanel from bl_ui.properties_grease_pencil_common import ( GreasePencilLayerMasksPanel, + GreasePencilLayerTransformPanel, GreasePencilLayerAdjustmentsPanel, GreasePencilLayerRelationsPanel, GreasePencilLayerDisplayPanel, @@ -90,8 +91,10 @@ class GPENCIL_MT_layer_context_menu(Menu): layout = self.layout ob = context.object gpd = ob.data + gpl = gpd.layers.active - layout.operator("gpencil.layer_duplicate", icon='DUPLICATE') + layout.operator("gpencil.layer_duplicate", text="Duplicate", icon='DUPLICATE').mode='ALL' + layout.operator("gpencil.layer_duplicate", text="Duplicate Empty Keyframes").mode='EMPTY' layout.separator() @@ -103,6 +106,7 @@ class GPENCIL_MT_layer_context_menu(Menu): layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All") layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="Unlock All") layout.prop(gpd, "use_autolock_layers", text="Autolock Inactive Layers") + layout.prop(gpl, "lock_material") layout.separator() @@ -188,6 +192,12 @@ class DATA_PT_gpencil_layer_masks(LayerDataButtonsPanel, GreasePencilLayerMasksP bl_options = {'DEFAULT_CLOSED'} +class DATA_PT_gpencil_layer_transform(LayerDataButtonsPanel, GreasePencilLayerTransformPanel, Panel): + bl_label = "Transform" + bl_parent_id = 'DATA_PT_gpencil_layers' + bl_options = {'DEFAULT_CLOSED'} + + class DATA_PT_gpencil_layer_adjustments(LayerDataButtonsPanel, GreasePencilLayerAdjustmentsPanel, Panel): bl_label = "Adjustments" bl_parent_id = 'DATA_PT_gpencil_layers' @@ -424,6 +434,7 @@ classes = ( DATA_PT_gpencil_onion_skinning_custom_colors, DATA_PT_gpencil_onion_skinning_display, DATA_PT_gpencil_layer_masks, + DATA_PT_gpencil_layer_transform, DATA_PT_gpencil_layer_adjustments, DATA_PT_gpencil_layer_relations, DATA_PT_gpencil_layer_display, diff --git a/release/scripts/startup/bl_ui/properties_data_volume.py b/release/scripts/startup/bl_ui/properties_data_volume.py index d4f108dcf24..e7bf9adb876 100644 --- a/release/scripts/startup/bl_ui/properties_data_volume.py +++ b/release/scripts/startup/bl_ui/properties_data_volume.py @@ -63,7 +63,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel): layout.prop(volume, "filepath", text="") - if len(volume.filepath): + if volume.filepath: layout.use_property_split = True layout.use_property_decorate = False @@ -76,7 +76,7 @@ class DATA_PT_volume_file(DataButtonsPanel, Panel): col.prop(volume, "sequence_mode", text="Mode") error_msg = volume.grids.error_message - if len(error_msg): + if error_msg: layout.separator() col = layout.column(align=True) col.label(text="Failed to load volume:") diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 8b404c4a306..67905192fe8 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -727,12 +727,32 @@ class GreasePencilSimplifyPanel: col.prop(rd, "simplify_gpencil_antialiasing") +class GreasePencilLayerTransformPanel: + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + ob = context.object + gpd = ob.data + gpl = gpd.layers.active + layout.active = not gpl.lock + + row = layout.row(align=True) + row.prop(gpl, "location") + + row = layout.row(align=True) + row.prop(gpl, "rotation") + + row = layout.row(align=True) + row.prop(gpl, "scale") + + class GreasePencilLayerAdjustmentsPanel: def draw(self, context): layout = self.layout layout.use_property_split = True - scene = context.scene ob = context.object gpd = ob.data @@ -750,15 +770,6 @@ class GreasePencilLayerAdjustmentsPanel: col = layout.row(align=True) col.prop(gpl, "line_change", text="Stroke Thickness") - col = layout.row(align=True) - col.prop(gpl, "pass_index") - - col = layout.row(align=True) - col.prop_search(gpl, "viewlayer_render", scene, "view_layers", text="View Layer") - - col = layout.row(align=True) - col.prop(gpl, "lock_material") - class GPENCIL_UL_masks(UIList): def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): @@ -826,6 +837,7 @@ class GreasePencilLayerRelationsPanel: layout.use_property_split = True layout.use_property_decorate = False + scene = context.scene ob = context.object gpd = ob.data gpl = gpd.layers.active @@ -839,6 +851,14 @@ class GreasePencilLayerRelationsPanel: if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE': col.prop_search(gpl, "parent_bone", parent.data, "bones", text="Bone") + layout.separator() + + col = layout.row(align=True) + col.prop(gpl, "pass_index") + + col = layout.row(align=True) + col.prop_search(gpl, "viewlayer_render", scene, "view_layers", text="View Layer") + class GreasePencilLayerDisplayPanel: diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 5d241e8e216..54c6de30ef8 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -1218,11 +1218,11 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False) row = layout.row(align=True) row.prop(gp_settings, "fill_direction", text="", expand=True) row = layout.row(align=True) + row.prop(gp_settings, "fill_factor") + row = layout.row(align=True) row.prop(gp_settings, "fill_leak", text="Leak Size") row = layout.row(align=True) row.prop(brush, "size", text="Thickness") - row = layout.row(align=True) - row.prop(gp_settings, "fill_simplify_level", text="Simplify") else: # brush.gpencil_tool == 'DRAW/TINT': row = layout.row(align=True) diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index c8c49ee02b0..7e017b121b3 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -118,6 +118,9 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel): col.prop(field, "strength") + sub = col.column(heading="Affect") + sub.prop(field, "apply_to_location", text="Location") + col = flow.column() col.prop(field, "texture_nabla") col.prop(field, "use_object_coords") @@ -128,6 +131,10 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel): col.prop(field, "strength") col.prop(field, "flow") + sub = col.column(heading="Affect") + sub.prop(field, "apply_to_location", text="Location") + sub.prop(field, "apply_to_rotation", text="Rotation") + col = flow.column() col.prop(field, "source_object") col.prop(field, "use_smoke_density") diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 9d74a9c9fea..96920af1c7e 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -502,7 +502,9 @@ class CLIP_PT_tools_tracking(CLIP_PT_tracking_panel, Panel): col = layout.column(align=True) row = col.row(align=True) row.label(text="Merge:") - row.operator("clip.join_tracks", text="Join Tracks") + sub = row.column() + sub.operator("clip.join_tracks", text="Join Tracks") + sub.operator("clip.average_tracks", text="Average Tracks") class CLIP_PT_tools_plane_tracking(CLIP_PT_tracking_panel, Panel): @@ -1482,6 +1484,7 @@ class CLIP_MT_track(Menu): layout.separator() layout.operator("clip.join_tracks") + layout.operator("clip.average_tracks") layout.separator() @@ -1608,6 +1611,7 @@ class CLIP_MT_tracking_context_menu(Menu): layout.separator() layout.operator("clip.join_tracks") + layout.operator("clip.average_tracks") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 0c222e8c023..aa98e4292f4 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -27,6 +27,7 @@ from bpy.types import ( from bl_ui.properties_grease_pencil_common import ( GreasePencilLayerMasksPanel, + GreasePencilLayerTransformPanel, GreasePencilLayerAdjustmentsPanel, GreasePencilLayerRelationsPanel, GreasePencilLayerDisplayPanel, @@ -726,6 +727,12 @@ class DOPESHEET_PT_gpencil_layer_masks(LayersDopeSheetPanel, GreasePencilLayerMa bl_options = {'DEFAULT_CLOSED'} +class DOPESHEET_PT_gpencil_layer_transform(LayersDopeSheetPanel, GreasePencilLayerTransformPanel, Panel): + bl_label = "Transform" + bl_parent_id = 'DOPESHEET_PT_gpencil_mode' + bl_options = {'DEFAULT_CLOSED'} + + class DOPESHEET_PT_gpencil_layer_adjustments(LayersDopeSheetPanel, GreasePencilLayerAdjustmentsPanel, Panel): bl_label = "Adjustments" bl_parent_id = 'DOPESHEET_PT_gpencil_mode' @@ -762,6 +769,7 @@ classes = ( DOPESHEET_PT_filters, DOPESHEET_PT_gpencil_mode, DOPESHEET_PT_gpencil_layer_masks, + DOPESHEET_PT_gpencil_layer_transform, DOPESHEET_PT_gpencil_layer_adjustments, DOPESHEET_PT_gpencil_layer_relations, DOPESHEET_PT_gpencil_layer_display, diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 342b72acb8c..73cc674858c 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -235,6 +235,7 @@ class IMAGE_MT_image(Menu): layout.menu("IMAGE_MT_image_invert") layout.operator("image.resize", text="Resize") + layout.menu("IMAGE_MT_image_flip") if ima and not show_render: if ima.packed_file: @@ -250,6 +251,13 @@ class IMAGE_MT_image(Menu): layout.operator("palette.extract_from_image", text="Extract Palette") layout.operator("gpencil.image_to_grease_pencil", text="Generate Grease Pencil") +class IMAGE_MT_image_flip(Menu): + bl_label = "Flip" + + def draw(self, _context): + layout = self.layout + layout.operator("image.flip", text="Horizontally").use_flip_horizontal = True + layout.operator("image.flip", text="Vertically").use_flip_vertical = True class IMAGE_MT_image_invert(Menu): bl_label = "Invert" @@ -1584,6 +1592,7 @@ classes = ( IMAGE_MT_select, IMAGE_MT_select_linked, IMAGE_MT_image, + IMAGE_MT_image_flip, IMAGE_MT_image_invert, IMAGE_MT_uvs, IMAGE_MT_uvs_showhide, diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index e6af83b61f4..a9934850acd 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -678,16 +678,8 @@ class NODE_UL_interface_sockets(bpy.types.UIList): if self.layout_type in {'DEFAULT', 'COMPACT'}: row = layout.row(align=True) - # inputs get icon on the left - if not socket.is_output: - row.template_node_socket(color=color) - + row.template_node_socket(color=color) row.prop(socket, "name", text="", emboss=False, icon_value=icon) - - # outputs get icon on the right - if socket.is_output: - row.template_node_socket(color=color) - elif self.layout_type == 'GRID': layout.alignment = 'CENTER' layout.template_node_socket(color=color) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 4b30266a5fe..a0b5355e64d 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -691,6 +691,9 @@ class USERPREF_PT_viewport_display(ViewportPanel, CenterAlignMixIn, Panel): col.prop(view, "mini_axis_size", text="Size") col.prop(view, "mini_axis_brightness", text="Brightness") + if view.mini_axis_type == 'GIZMO': + col.prop(view, "gizmo_size_navigate_v3d", text="Size") + class USERPREF_PT_viewport_quality(ViewportPanel, CenterAlignMixIn, Panel): bl_label = "Quality" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b9a57674a6e..0fe16720d81 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -695,6 +695,10 @@ class VIEW3D_HT_header(Header): row.prop(tool_settings, "use_gpencil_vertex_select_mask_stroke", text="") row.prop(tool_settings, "use_gpencil_vertex_select_mask_segment", text="") + if gpd.is_stroke_paint_mode: + row = layout.row(align=True) + row.prop(gpd, "use_multiedit", text="", icon='GP_MULTIFRAME_EDITING') + if ( gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or @@ -2236,11 +2240,6 @@ class VIEW3D_MT_object_relations(Menu): layout.operator_menu_enum("object.make_local", "type", text="Make Local...") layout.menu("VIEW3D_MT_make_single_user") - layout.separator() - - layout.operator("object.data_transfer") - layout.operator("object.datalayout_transfer") - class VIEW3D_MT_object(Menu): bl_context = "objectmode" @@ -2274,7 +2273,7 @@ class VIEW3D_MT_object(Menu): layout.menu("VIEW3D_MT_object_relations") layout.menu("VIEW3D_MT_object_constraints") layout.menu("VIEW3D_MT_object_track") - layout.menu("VIEW3D_MT_make_links", text="Make Links") + layout.menu("VIEW3D_MT_make_links") layout.separator() @@ -2292,16 +2291,7 @@ class VIEW3D_MT_object(Menu): layout.separator() - ob = context.active_object - if ob and ob.type == 'GPENCIL' and context.gpencil_data: - layout.operator_menu_enum("gpencil.convert", "type", text="Convert To") - else: - layout.operator_menu_enum("object.convert", "target") - - # Potrace lib dependency - if bpy.app.build_options.potrace: - layout.separator() - layout.operator("gpencil.trace_image") + layout.menu("VIEW3D_MT_object_convert") layout.separator() @@ -2397,37 +2387,25 @@ class VIEW3D_MT_object_context_menu(Menu): ''' # If something is selected - if obj is not None and obj.type in {'MESH', 'CURVE', 'SURFACE'}: - layout.operator("object.shade_smooth", text="Shade Smooth") - layout.operator("object.shade_flat", text="Shade Flat") - - layout.separator() + # Individual object types. if obj is None: pass - elif obj.type == 'MESH': - layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type") - - layout.operator_context = 'INVOKE_DEFAULT' - # If more than one object is selected - if selected_objects_len > 1: - layout.operator("object.join") - - layout.separator() elif obj.type == 'CAMERA': layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("view3d.object_as_camera", text="Set Active Camera") + if obj.data.type == 'PERSP': - props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle") + props = layout.operator("wm.context_modal_mouse", text="Adjust Focal Length") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.lens" props.input_scale = 0.1 if obj.data.lens_unit == 'MILLIMETERS': - props.header_text = "Camera Lens Angle: %.1fmm" + props.header_text = "Camera Focal Length: %.1fmm" else: - props.header_text = "Camera Lens Angle: %.1f\u00B0" + props.header_text = "Camera Focal Length: %.1f\u00B0" else: props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale") @@ -2440,88 +2418,83 @@ class VIEW3D_MT_object_context_menu(Menu): if view and view.camera == obj and view.region_3d.view_perspective == 'CAMERA': props = layout.operator("ui.eyedropper_depth", text="DOF Distance (Pick)") else: - props = layout.operator("wm.context_modal_mouse", text="DOF Distance") + props = layout.operator("wm.context_modal_mouse", text="Adjust Focus Distance") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.dof.focus_distance" props.input_scale = 0.02 - props.header_text = "DOF Distance: %.3f" + props.header_text = "Focus Distance: %.3f" layout.separator() elif obj.type in {'CURVE', 'FONT'}: layout.operator_context = 'INVOKE_REGION_WIN' - props = layout.operator("wm.context_modal_mouse", text="Extrude Size") + props = layout.operator("wm.context_modal_mouse", text="Adjust Extrusion") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.extrude" props.input_scale = 0.01 - props.header_text = "Extrude Size: %.3f" + props.header_text = "Extrude: %.3f" - props = layout.operator("wm.context_modal_mouse", text="Width Size") + props = layout.operator("wm.context_modal_mouse", text="Adjust Offset") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.offset" props.input_scale = 0.01 - props.header_text = "Width Size: %.3f" - - layout.separator() - - layout.operator("object.convert", text="Convert to Mesh").target = 'MESH' - layout.operator("object.convert", text="Convert to Grease Pencil").target = 'GPENCIL' - layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type") - - layout.separator() - - elif obj.type == 'GPENCIL': - layout.operator("gpencil.convert", text="Convert to Path").type = 'PATH' - layout.operator("gpencil.convert", text="Convert to Bezier Curve").type = 'CURVE' - layout.operator("gpencil.convert", text="Convert to Polygon Curve").type = 'POLY' - - layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type") + props.header_text = "Offset: %.3f" layout.separator() elif obj.type == 'EMPTY': layout.operator_context = 'INVOKE_REGION_WIN' - props = layout.operator("wm.context_modal_mouse", text="Empty Draw Size") + props = layout.operator("wm.context_modal_mouse", text="Adjust Empty Display Size") props.data_path_iter = "selected_editable_objects" props.data_path_item = "empty_display_size" props.input_scale = 0.01 - props.header_text = "Empty Draw Size: %.3f" + props.header_text = "Empty Display Size: %.3f" layout.separator() + if obj.empty_display_type == 'IMAGE': + layout.operator("gpencil.trace_image") + + layout.separator() + elif obj.type == 'LIGHT': light = obj.data layout.operator_context = 'INVOKE_REGION_WIN' - props = layout.operator("wm.context_modal_mouse", text="Power") + props = layout.operator("wm.context_modal_mouse", text="Adjust Light Power") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.energy" props.input_scale = 1.0 props.header_text = "Light Power: %.3f" if light.type == 'AREA': - props = layout.operator("wm.context_modal_mouse", text="Size X") - props.data_path_iter = "selected_editable_objects" - props.data_path_item = "data.size" - props.header_text = "Light Size X: %.3f" - if light.shape in {'RECTANGLE', 'ELLIPSE'}: - props = layout.operator("wm.context_modal_mouse", text="Size Y") + props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light X Size") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.size" + props.header_text = "Light Size X: %.3f" + + props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Y Size") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.size_y" props.header_text = "Light Size Y: %.3f" + else: + props = layout.operator("wm.context_modal_mouse", text="Adjust Area Light Size") + props.data_path_iter = "selected_editable_objects" + props.data_path_item = "data.size" + props.header_text = "Light Size: %.3f" elif light.type in {'SPOT', 'POINT'}: - props = layout.operator("wm.context_modal_mouse", text="Radius") + props = layout.operator("wm.context_modal_mouse", text="Adjust Light Radius") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.shadow_soft_size" props.header_text = "Light Radius: %.3f" elif light.type == 'SUN': - props = layout.operator("wm.context_modal_mouse", text="Angle") + props = layout.operator("wm.context_modal_mouse", text="Adjust Sun Light Angle") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.angle" props.header_text = "Light Angle: %.3f" @@ -2529,13 +2502,13 @@ class VIEW3D_MT_object_context_menu(Menu): if light.type == 'SPOT': layout.separator() - props = layout.operator("wm.context_modal_mouse", text="Spot Size") + props = layout.operator("wm.context_modal_mouse", text="Adjust Spot Light Size") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.spot_size" props.input_scale = 0.01 props.header_text = "Spot Size: %.2f" - props = layout.operator("wm.context_modal_mouse", text="Spot Blend") + props = layout.operator("wm.context_modal_mouse", text="Adjust Spot Light Blend") props.data_path_iter = "selected_editable_objects" props.data_path_item = "data.spot_blend" props.input_scale = -0.01 @@ -2543,6 +2516,35 @@ class VIEW3D_MT_object_context_menu(Menu): layout.separator() + # Shared among some object types. + if obj is not None: + if obj.type in {'MESH', 'CURVE', 'SURFACE'}: + layout.operator("object.shade_smooth", text="Shade Smooth") + layout.operator("object.shade_flat", text="Shade Flat") + + layout.separator() + + if obj.type in {'MESH', 'CURVE', 'SURFACE', 'ARMATURE', 'GPENCIL'}: + if selected_objects_len > 1: + layout.operator("object.join") + + if obj.type in {'MESH', 'CURVE', 'SURFACE', 'POINTCLOUD', 'META', 'FONT'}: + layout.operator_menu_enum("object.convert", "target") + + if obj.type == 'GPENCIL': + layout.operator_menu_enum("gpencil.convert", "type", text="Convert To") + + if ( + obj.type in {'MESH', 'CURVE', 'SURFACE', 'GPENCIL', 'LATTICE', 'ARMATURE', 'META'} or + (obj.type == 'EMPTY' and obj.instance_collection is not None) + ): + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator_menu_enum("object.origin_set", text="Set Origin", property="type") + layout.operator_context = 'INVOKE_DEFAULT' + + layout.separator() + + # Shared among all object types layout.operator("view3d.copybuffer", text="Copy Objects", icon='COPYDOWN') layout.operator("view3d.pastebuffer", text="Paste Objects", icon='PASTEDOWN') @@ -2787,8 +2789,25 @@ class VIEW3D_MT_make_single_user(Menu): props.object = props.obdata = props.material = False +class VIEW3D_MT_object_convert(Menu): + bl_label = "Convert" + + def draw(self, context): + layout = self.layout + ob = context.active_object + + if ob and ob.type == 'GPENCIL' and context.gpencil_data: + layout.operator_enum("gpencil.convert", "type") + else: + layout.operator_enum("object.convert", "target") + + # Potrace lib dependency. + if bpy.app.build_options.potrace: + layout.operator("gpencil.trace_image", icon='OUTLINER_OB_GREASEPENCIL') + + class VIEW3D_MT_make_links(Menu): - bl_label = "Make Links" + bl_label = "Link/Transfer Data" def draw(self, _context): layout = self.layout @@ -2796,10 +2815,10 @@ class VIEW3D_MT_make_links(Menu): if len(bpy.data.scenes) > 10: layout.operator_context = 'INVOKE_REGION_WIN' - layout.operator("object.make_links_scene", text="Objects to Scene...", icon='OUTLINER_OB_EMPTY') + layout.operator("object.make_links_scene", text="Link Objects to Scene...", icon='OUTLINER_OB_EMPTY') else: layout.operator_context = 'EXEC_REGION_WIN' - layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene") + layout.operator_menu_enum("object.make_links_scene", "scene", text="Link Objects to Scene") layout.separator() @@ -2807,7 +2826,12 @@ class VIEW3D_MT_make_links(Menu): layout.operator_enum("object.make_links_data", "type") # inline - layout.operator("object.join_uvs") # stupid place to add this! + layout.operator("object.join_uvs", text="Copy UV Maps") + + layout.separator() + + layout.operator("object.data_transfer") + layout.operator("object.datalayout_transfer") class VIEW3D_MT_brush_paint_modes(Menu): @@ -7529,6 +7553,7 @@ classes = ( VIEW3D_MT_object_rigid_body, VIEW3D_MT_object_clear, VIEW3D_MT_object_context_menu, + VIEW3D_MT_object_convert, VIEW3D_MT_object_shading, VIEW3D_MT_object_apply, VIEW3D_MT_object_relations, diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 577f9678a62..f93a6f3346b 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -352,10 +352,13 @@ class VIEW3D_PT_tools_particlemode(Panel, View3DPaintPanel): layout.row().prop(brush, "puff_mode", expand=True) layout.prop(brush, "use_puff_volume") elif tool == 'COMB': - layout.prop(settings, "use_emitter_deflect", text="Deflect Emitter") - col = layout.column() - col.active = settings.use_emitter_deflect - col.prop(settings, "emitter_distance", text="Distance") + col = layout.column(align=False, heading="Deflect Emitter") + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(settings, "use_emitter_deflect", text="") + sub = sub.row(align=True) + sub.active = settings.use_emitter_deflect + sub.prop(settings, "emitter_distance", text="") # TODO, move to space_view3d.py @@ -1231,14 +1234,20 @@ class VIEW3D_PT_tools_particlemode_options(View3DPanel, Panel): col = layout.column(align=True) col.active = pe.is_editable - col.prop(ob.data, "use_mirror_x") - if pe.tool == 'ADD': - col.prop(ob.data, "use_mirror_topology") - col.separator() - col.prop(pe, "use_preserve_length", text="Preserve Strand Lengths") - col.prop(pe, "use_preserve_root", text="Preserve Root Positions") + if not pe.is_hair: col.prop(pe, "use_auto_velocity", text="Auto-Velocity") + col.separator() + + sub = col.column(align=True, heading="Mirror") + sub.prop(ob.data, "use_mirror_x") + if pe.tool == 'ADD': + sub.prop(ob.data, "use_mirror_topology") + col.separator() + + sub = col.column(align=True, heading="Preserve") + sub.prop(pe, "use_preserve_length", text="Strand Lengths") + sub.prop(pe, "use_preserve_root", text="Root Positions") class VIEW3D_PT_tools_particlemode_options_shapecut(View3DPanel, Panel): @@ -1282,10 +1291,13 @@ class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel): else: if pe.type == 'PARTICLES': col.prop(pe, "show_particles", text="Particles") - col.prop(pe, "use_fade_time") - sub = col.row(align=True) + col = layout.column(align=False, heading="Fade Time") + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(pe, "use_fade_time", text="") + sub = sub.row(align=True) sub.active = pe.use_fade_time - sub.prop(pe, "fade_frames", slider=True) + sub.prop(pe, "fade_frames", slider=True, text="") # ********** grease pencil object tool panels **************** @@ -1382,7 +1394,7 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel): bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings' bl_category = "Tool" bl_options = {'DEFAULT_CLOSED'} - bl_ui_units_x = 11 + bl_ui_units_x = 13 @classmethod def poll(cls, context): @@ -1435,7 +1447,12 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel): row.prop(gp_settings, "fill_layer_mode", text="Layers") col.separator() - col.prop(gp_settings, "fill_factor", text="Resolution") + row = col.row(align=True) + row.prop(gp_settings, "extend_stroke_factor") + row.prop(gp_settings, "show_fill_extend", text="", icon='GRID') + + col.separator() + col.prop(gp_settings, "fill_simplify_level", text="Simplify") if gp_settings.fill_draw_mode != 'STROKE': col = layout.column(align=False, heading="Ignore Transparent") col.use_property_decorate = False @@ -1446,6 +1463,10 @@ class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel): sub.active = gp_settings.show_fill sub.prop(gp_settings, "fill_threshold", text="") + col.separator() + row = col.row(align=True) + row.prop(gp_settings, "use_fill_limit") + class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel): bl_context = ".greasepencil_paint" diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 7abc62a69e3..9d7485a0837 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -487,8 +487,12 @@ geometry_node_categories = [ NodeItem("GeometryNodeAttributeCompare"), NodeItem("GeometryNodeAttributeFill"), NodeItem("GeometryNodeAttributeMix"), + NodeItem("GeometryNodeAttributeProximity"), NodeItem("GeometryNodeAttributeColorRamp"), NodeItem("GeometryNodeAttributeVectorMath"), + NodeItem("GeometryNodeAttributeSampleTexture"), + NodeItem("GeometryNodeAttributeCombineXYZ"), + NodeItem("GeometryNodeAttributeSeparateXYZ"), ]), GeometryNodeCategory("GEO_COLOR", "Color", items=[ NodeItem("ShaderNodeValToRGB"), @@ -501,9 +505,11 @@ geometry_node_categories = [ ]), GeometryNodeCategory("GEO_INPUT", "Input", items=[ NodeItem("GeometryNodeObjectInfo"), + NodeItem("GeometryNodeCollectionInfo"), NodeItem("FunctionNodeRandomFloat"), NodeItem("ShaderNodeValue"), NodeItem("FunctionNodeInputVector"), + NodeItem("GeometryNodeIsViewport"), ]), GeometryNodeCategory("GEO_MESH", "Mesh", items=[ NodeItem("GeometryNodeBoolean"), @@ -520,6 +526,10 @@ geometry_node_categories = [ NodeItem("GeometryNodeRotatePoints"), NodeItem("GeometryNodeAlignRotationToVector"), ]), + GeometryNodeCategory("GEO_VOLUME", "Volume", items=[ + NodeItem("GeometryNodePointsToVolume"), + NodeItem("GeometryNodeVolumeToMesh"), + ]), GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[ NodeItem("ShaderNodeMapRange"), NodeItem("ShaderNodeClamp"), diff --git a/release/windows/batch/blender_debug_gpu.cmd b/release/windows/batch/blender_debug_gpu.cmd index 46d126ab621..53d7863ec70 100644 --- a/release/windows/batch/blender_debug_gpu.cmd +++ b/release/windows/batch/blender_debug_gpu.cmd @@ -12,5 +12,5 @@ mkdir "%temp%\blender\debug_logs" > NUL 2>&1 echo. echo Starting blender and waiting for it to exit.... set PYTHONPATH= -"%~dp0\blender" --debug --debug-gpu --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0 +"%~dp0\blender" --debug --debug-gpu --debug-cycles --python-expr "import bpy; bpy.ops.wm.sysinfo(filepath=r'%temp%\blender\debug_logs\blender_system_info.txt')" > "%temp%\blender\debug_logs\blender_debug_output.txt" 2>&1 < %0 explorer "%temp%\blender\debug_logs"
\ No newline at end of file diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index efd30ba8509..f875a990d0a 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ID.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ID_enums.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_action_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_anim_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_armature_types.h diff --git a/source/blender/blendthumb/src/Dll.cpp b/source/blender/blendthumb/src/Dll.cpp index 8a8ae8c9996..6516540034e 100644 --- a/source/blender/blendthumb/src/Dll.cpp +++ b/source/blender/blendthumb/src/Dll.cpp @@ -160,7 +160,7 @@ struct REGISTRY_ENTRY { PCWSTR pszValueName; DWORD dwValueType; PCWSTR pszData; // These two fields could/should have been a union, but C++ - DWORD dwData; // only lets you initalize the first field in a union. + DWORD dwData; // only lets you initialize the first field in a union. }; // Creates a registry key (if needed) and sets the default value of the key diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 8d904bd6019..2fce4bfc5b8 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -212,8 +212,7 @@ struct NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, - const struct AnimationEvalContext *anim_eval_context, - const bool flush_to_original); + const struct AnimationEvalContext *anim_eval_context); bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context, struct PointerRNA *prop_ptr, struct PropertyRNA *prop, diff --git a/source/blender/blenkernel/BKE_attribute_access.hh b/source/blender/blenkernel/BKE_attribute_access.hh index abcf8ed1c54..55c8b36669d 100644 --- a/source/blender/blenkernel/BKE_attribute_access.hh +++ b/source/blender/blenkernel/BKE_attribute_access.hh @@ -24,6 +24,7 @@ #include "BKE_attribute.h" #include "BLI_color.hh" +#include "BLI_float2.hh" #include "BLI_float3.hh" namespace blender::bke { @@ -127,7 +128,7 @@ class WriteAttribute { void *array_buffer_ = nullptr; /* True, when the buffer points to a temporary array. */ bool array_is_temporary_ = false; - /* This helps to protect agains forgetting to apply changes done to the array. */ + /* This helps to protect against forgetting to apply changes done to the array. */ bool array_should_be_applied_ = false; public: @@ -301,11 +302,13 @@ template<typename T> class TypedWriteAttribute { using BooleanReadAttribute = TypedReadAttribute<bool>; using FloatReadAttribute = TypedReadAttribute<float>; +using Float2ReadAttribute = TypedReadAttribute<float2>; using Float3ReadAttribute = TypedReadAttribute<float3>; using Int32ReadAttribute = TypedReadAttribute<int>; using Color4fReadAttribute = TypedReadAttribute<Color4f>; using BooleanWriteAttribute = TypedWriteAttribute<bool>; using FloatWriteAttribute = TypedWriteAttribute<float>; +using Float2WriteAttribute = TypedWriteAttribute<float2>; using Float3WriteAttribute = TypedWriteAttribute<float3>; using Int32WriteAttribute = TypedWriteAttribute<int>; using Color4fWriteAttribute = TypedWriteAttribute<Color4f>; diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh new file mode 100644 index 00000000000..0294a8c09d5 --- /dev/null +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -0,0 +1,256 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_array.hh" +#include "BLI_color.hh" +#include "BLI_float2.hh" +#include "BLI_float3.hh" + +#include "DNA_customdata_types.h" + +namespace blender::attribute_math { + +/** + * Utility function that simplifies calling a templated function based on a custom data type. + */ +template<typename Func> +void convert_to_static_type(const CustomDataType data_type, const Func &func) +{ + switch (data_type) { + case CD_PROP_FLOAT: + func(float()); + break; + case CD_PROP_FLOAT2: + func(float2()); + break; + case CD_PROP_FLOAT3: + func(float3()); + break; + case CD_PROP_INT32: + func(int()); + break; + case CD_PROP_BOOL: + func(bool()); + break; + case CD_PROP_COLOR: + func(Color4f()); + break; + default: + BLI_assert(false); + break; + } +} + +/* -------------------------------------------------------------------- */ +/** \name Mix three values of the same type. + * + * This is typically used to interpolate values within a triangle. + * \{ */ + +template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2); + +template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2) +{ + return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f; +} + +template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2) +{ + return static_cast<int>(weights.x * v0 + weights.y * v1 + weights.z * v2); +} + +template<> +inline float mix3(const float3 &weights, const float &v0, const float &v1, const float &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline float2 mix3(const float3 &weights, const float2 &v0, const float2 &v1, const float2 &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline float3 mix3(const float3 &weights, const float3 &v0, const float3 &v1, const float3 &v2) +{ + return weights.x * v0 + weights.y * v1 + weights.z * v2; +} + +template<> +inline Color4f mix3(const float3 &weights, const Color4f &v0, const Color4f &v1, const Color4f &v2) +{ + Color4f result; + interp_v4_v4v4v4(result, v0, v1, v2, weights); + return result; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mix a dynamic amount of values with weights for many elements. + * + * This section provides an abstraction for "mixers". The abstraction encapsulates details about + * how different types should be mixed. Usually #DefaultMixer<T> should be used to get a mixer for + * a specific type. + * \{ */ + +template<typename T> class SimpleMixer { + private: + MutableSpan<T> buffer_; + T default_value_; + Array<float> total_weights_; + + public: + /** + * \param buffer: Span where the interpolated values should be stored. + * \param default_value: Output value for an element that has not been affected by a #mix_in. + */ + SimpleMixer(MutableSpan<T> buffer, T default_value = {}) + : buffer_(buffer), default_value_(default_value), total_weights_(buffer.size(), 0.0f) + { + BLI_STATIC_ASSERT(std::is_trivial_v<T>, ""); + memset(buffer_.data(), 0, sizeof(T) * buffer_.size()); + } + + /** + * Mix a #value into the element with the given #index. + */ + void mix_in(const int64_t index, const T &value, const float weight = 1.0f) + { + BLI_assert(weight >= 0.0f); + buffer_[index] += value * weight; + total_weights_[index] += weight; + } + + /** + * Has to be called before the buffer provided in the constructor is used. + */ + void finalize() + { + for (const int64_t i : buffer_.index_range()) { + const float weight = total_weights_[i]; + if (weight > 0.0f) { + buffer_[i] *= 1.0f / weight; + } + else { + buffer_[i] = default_value_; + } + } + } +}; + +/** This mixer accumulates values in a type that is different from the one that is mixed. Some + * types cannot encode the floating point weights in their values (e.g. int and bool). */ +template<typename T, typename AccumulationT, T (*ConvertToT)(const AccumulationT &value)> +class SimpleMixerWithAccumulationType { + private: + struct Item { + /* Store both values together, because they are accessed together. */ + AccumulationT value = {0}; + float weight = 0.0f; + }; + + MutableSpan<T> buffer_; + T default_value_; + Array<Item> accumulation_buffer_; + + public: + SimpleMixerWithAccumulationType(MutableSpan<T> buffer, T default_value = {}) + : buffer_(buffer), default_value_(default_value), accumulation_buffer_(buffer.size()) + { + } + + void mix_in(const int64_t index, const T &value, const float weight = 1.0f) + { + const AccumulationT converted_value = static_cast<AccumulationT>(value); + Item &item = accumulation_buffer_[index]; + item.value += converted_value * weight; + item.weight += weight; + } + + void finalize() + { + for (const int64_t i : buffer_.index_range()) { + const Item &item = accumulation_buffer_[i]; + if (item.weight > 0.0f) { + const float weight_inv = 1.0f / item.weight; + const T converted_value = ConvertToT(item.value * weight_inv); + buffer_[i] = converted_value; + } + else { + buffer_[i] = default_value_; + } + } + } +}; + +class Color4fMixer { + private: + MutableSpan<Color4f> buffer_; + Color4f default_color_; + Array<float> total_weights_; + + public: + Color4fMixer(MutableSpan<Color4f> buffer, Color4f default_color = {0, 0, 0, 1}); + void mix_in(const int64_t index, const Color4f &color, const float weight = 1.0f); + void finalize(); +}; + +template<typename T> struct DefaultMixerStruct { + /* Use void by default. This can be check for in `if constexpr` statements. */ + using type = void; +}; +template<> struct DefaultMixerStruct<float> { + using type = SimpleMixer<float>; +}; +template<> struct DefaultMixerStruct<float2> { + using type = SimpleMixer<float2>; +}; +template<> struct DefaultMixerStruct<float3> { + using type = SimpleMixer<float3>; +}; +template<> struct DefaultMixerStruct<Color4f> { + /* Use a special mixer for colors. Color4f can't be added/multiplied, because this is not + * something one should usually do with colors. */ + using type = Color4fMixer; +}; +template<> struct DefaultMixerStruct<int> { + static int double_to_int(const double &value) + { + return static_cast<int>(value); + } + /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It + * uses double instead of float so that it is accurate for all 32 bit integers. */ + using type = SimpleMixerWithAccumulationType<int, double, double_to_int>; +}; +template<> struct DefaultMixerStruct<bool> { + static bool float_to_bool(const float &value) + { + return value >= 0.5f; + } + /* Store interpolated booleans in a float temporary. + * Otherwise information provided by weights is easily rounded away. */ + using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>; +}; + +/* Utility to get a good default mixer for a given type. This is `void` when there is no default + * mixer for the given type. */ +template<typename T> using DefaultMixer = typename DefaultMixerStruct<T>::type; + +/** \} */ + +} // namespace blender::attribute_math diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h index e5ce91df3fb..1febe75b6f2 100644 --- a/source/blender/blenkernel/BKE_blender_undo.h +++ b/source/blender/blenkernel/BKE_blender_undo.h @@ -27,12 +27,14 @@ struct Main; struct MemFileUndoData; struct bContext; +enum eUndoStepDir; + #define BKE_UNDO_STR_MAX 64 struct MemFileUndoData *BKE_memfile_undo_encode(struct Main *bmain, struct MemFileUndoData *mfu_prev); bool BKE_memfile_undo_decode(struct MemFileUndoData *mfu, - const int undo_direction, + const enum eUndoStepDir undo_direction, const bool use_old_bmain_data, struct bContext *C); void BKE_memfile_undo_free(struct MemFileUndoData *mfu); diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 4ee96d1ab8d..c6fe02202a6 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,15 +31,15 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 292 +#define BLENDER_VERSION 293 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 14 +#define BLENDER_FILE_SUBVERSION 7 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h index 84a17136361..78908908343 100644 --- a/source/blender/blenkernel/BKE_bvhutils.h +++ b/source/blender/blenkernel/BKE_bvhutils.h @@ -38,6 +38,7 @@ struct BMEditMesh; struct MFace; struct MVert; struct Mesh; +struct PointCloud; struct BVHCache; @@ -249,6 +250,20 @@ float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray, const float v1[3], const float v2[3]); +typedef struct BVHTreeFromPointCloud { + struct BVHTree *tree; + + BVHTree_NearestPointCallback nearest_callback; + + const float (*coords)[3]; +} BVHTreeFromPointCloud; + +BVHTree *BKE_bvhtree_from_pointcloud_get(struct BVHTreeFromPointCloud *data, + const struct PointCloud *pointcloud, + const int tree_type); + +void free_bvhtree_from_pointcloud(struct BVHTreeFromPointCloud *data); + /** * BVHCache */ diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 3cba47afc46..231a4563630 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -121,7 +121,8 @@ void BKE_effector_relations_free(struct ListBase *lb); struct ListBase *BKE_effectors_create(struct Depsgraph *depsgraph, struct Object *ob_src, struct ParticleSystem *psys_src, - struct EffectorWeights *weights); + struct EffectorWeights *weights, + bool use_rotation); void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 31739465afd..5f1ddea0f13 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -37,6 +37,7 @@ struct Collection; struct Mesh; struct Object; struct PointCloud; +struct Volume; /* Each geometry component has a specific type. The type determines what kind of data the component * stores. Functions modifying a geometry will usually just modify a subset of the component types. @@ -45,6 +46,7 @@ enum class GeometryComponentType { Mesh = 0, PointCloud = 1, Instances = 2, + Volume = 3, }; enum class GeometryOwnershipType { @@ -66,6 +68,10 @@ template<> struct DefaultHash<GeometryComponentType> { }; } // namespace blender +namespace blender::bke { +class ComponentAttributeProviders; +} + class GeometryComponent; /** @@ -150,40 +156,35 @@ class GeometryComponent { bool attribute_exists(const blender::StringRef attribute_name) const; /* Returns true when the geometry component supports this attribute domain. */ - virtual bool attribute_domain_supported(const AttributeDomain domain) const; - /* Returns true when the given data type is supported in the given domain. */ - virtual bool attribute_domain_with_type_supported(const AttributeDomain domain, - const CustomDataType data_type) const; + bool attribute_domain_supported(const AttributeDomain domain) const; /* Can only be used with supported domain types. */ virtual int attribute_domain_size(const AttributeDomain domain) const; - /* Attributes with these names cannot be created or removed via this api. */ - virtual bool attribute_is_builtin(const blender::StringRef attribute_name) const; /* Get read-only access to the highest priority attribute with the given name. * Returns null if the attribute does not exist. */ - virtual blender::bke::ReadAttributePtr attribute_try_get_for_read( + blender::bke::ReadAttributePtr attribute_try_get_for_read( const blender::StringRef attribute_name) const; /* Get read and write access to the highest priority attribute with the given name. * Returns null if the attribute does not exist. */ - virtual blender::bke::WriteAttributePtr attribute_try_get_for_write( + blender::bke::WriteAttributePtr attribute_try_get_for_write( const blender::StringRef attribute_name); /* Get a read-only attribute for the domain based on the given attribute. This can be used to * interpolate from one domain to another. * Returns null if the interpolation is not implemented. */ virtual blender::bke::ReadAttributePtr attribute_try_adapt_domain( - blender::bke::ReadAttributePtr attribute, const AttributeDomain domain) const; + blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const; /* Returns true when the attribute has been deleted. */ - virtual bool attribute_try_delete(const blender::StringRef attribute_name); + bool attribute_try_delete(const blender::StringRef attribute_name); /* Returns true when the attribute has been created. */ - virtual bool attribute_try_create(const blender::StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type); + bool attribute_try_create(const blender::StringRef attribute_name, + const AttributeDomain domain, + const CustomDataType data_type); - virtual blender::Set<std::string> attribute_names() const; + blender::Set<std::string> attribute_names() const; virtual bool is_empty() const; /* Get a read-only attribute for the given domain and data type. @@ -255,6 +256,9 @@ class GeometryComponent { const AttributeDomain domain, const CustomDataType data_type, const void *default_value = nullptr); + + private: + virtual const blender::bke::ComponentAttributeProviders *get_attribute_providers() const; }; template<typename T> @@ -320,10 +324,13 @@ struct GeometrySet { bool has_mesh() const; bool has_pointcloud() const; bool has_instances() const; + bool has_volume() const; const Mesh *get_mesh_for_read() const; const PointCloud *get_pointcloud_for_read() const; + const Volume *get_volume_for_read() const; Mesh *get_mesh_for_write(); PointCloud *get_pointcloud_for_write(); + Volume *get_volume_for_write(); /* Utility methods for replacement. */ void replace_mesh(Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); @@ -354,30 +361,22 @@ class MeshComponent : public GeometryComponent { Mesh *release(); void copy_vertex_group_names_from_object(const struct Object &object); + const blender::Map<std::string, int> &vertex_group_names() const; + blender::Map<std::string, int> &vertex_group_names(); const Mesh *get_for_read() const; Mesh *get_for_write(); - bool attribute_domain_supported(const AttributeDomain domain) const final; - bool attribute_domain_with_type_supported(const AttributeDomain domain, - const CustomDataType data_type) const final; int attribute_domain_size(const AttributeDomain domain) const final; - bool attribute_is_builtin(const blender::StringRef attribute_name) const final; + blender::bke::ReadAttributePtr attribute_try_adapt_domain( + blender::bke::ReadAttributePtr attribute, const AttributeDomain new_domain) const final; - blender::bke::ReadAttributePtr attribute_try_get_for_read( - const blender::StringRef attribute_name) const final; - blender::bke::WriteAttributePtr attribute_try_get_for_write( - const blender::StringRef attribute_name) final; - - bool attribute_try_delete(const blender::StringRef attribute_name) final; - bool attribute_try_create(const blender::StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type) final; - - blender::Set<std::string> attribute_names() const final; bool is_empty() const final; static constexpr inline GeometryComponentType static_type = GeometryComponentType::Mesh; + + private: + const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final; }; /** A geometry component that stores a point cloud. */ @@ -400,26 +399,14 @@ class PointCloudComponent : public GeometryComponent { const PointCloud *get_for_read() const; PointCloud *get_for_write(); - bool attribute_domain_supported(const AttributeDomain domain) const final; - bool attribute_domain_with_type_supported(const AttributeDomain domain, - const CustomDataType data_type) const final; int attribute_domain_size(const AttributeDomain domain) const final; - bool attribute_is_builtin(const blender::StringRef attribute_name) const final; - - blender::bke::ReadAttributePtr attribute_try_get_for_read( - const blender::StringRef attribute_name) const final; - blender::bke::WriteAttributePtr attribute_try_get_for_write( - const blender::StringRef attribute_name) final; - bool attribute_try_delete(const blender::StringRef attribute_name) final; - bool attribute_try_create(const blender::StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type) final; - - blender::Set<std::string> attribute_names() const final; bool is_empty() const final; static constexpr inline GeometryComponentType static_type = GeometryComponentType::PointCloud; + + private: + const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final; }; /** A geometry component that stores instances. */ @@ -449,3 +436,25 @@ class InstancesComponent : public GeometryComponent { static constexpr inline GeometryComponentType static_type = GeometryComponentType::Instances; }; + +/** A geometry component that stores volume grids. */ +class VolumeComponent : public GeometryComponent { + private: + Volume *volume_ = nullptr; + GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned; + + public: + VolumeComponent(); + ~VolumeComponent(); + GeometryComponent *copy() const override; + + void clear(); + bool has_volume() const; + void replace(Volume *volume, GeometryOwnershipType ownership = GeometryOwnershipType::Owned); + Volume *release(); + + const Volume *get_for_read() const; + Volume *get_for_write(); + + static constexpr inline GeometryComponentType static_type = GeometryComponentType::Volume; +}; diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 5e16c9c979c..d6b6ffd425e 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -59,7 +59,7 @@ typedef struct Global { short moving; - /** To indicate render is busy, prevent renderwindow events etc. */ + /** To indicate render is busy, prevent render-window events etc. */ bool is_rendering; /** @@ -147,21 +147,18 @@ enum { G_DEBUG_DEPSGRAPH = (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_EVAL | G_DEBUG_DEPSGRAPH_TAG | G_DEBUG_DEPSGRAPH_TIME | G_DEBUG_DEPSGRAPH_UUID), G_DEBUG_SIMDATA = (1 << 15), /* sim debug data display */ - G_DEBUG_GPU_MEM = (1 << 16), /* gpu memory in status bar */ - G_DEBUG_GPU = (1 << 17), /* gpu debug */ - G_DEBUG_IO = (1 << 18), /* IO Debugging (for Collada, ...)*/ - G_DEBUG_GPU_SHADERS = (1 << 19), /* GLSL shaders */ - G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 20), /* force gpu workarounds bypassing detections. */ - G_DEBUG_XR = (1 << 21), /* XR/OpenXR messages */ - G_DEBUG_XR_TIME = (1 << 22), /* XR/OpenXR timing messages */ - - G_DEBUG_GHOST = (1 << 23), /* Debug GHOST module. */ + G_DEBUG_GPU = (1 << 16), /* gpu debug */ + G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_GPU_FORCE_WORKAROUNDS = (1 << 18), /* force gpu workarounds bypassing detections. */ + G_DEBUG_XR = (1 << 19), /* XR/OpenXR messages */ + G_DEBUG_XR_TIME = (1 << 20), /* XR/OpenXR timing messages */ + + G_DEBUG_GHOST = (1 << 21), /* Debug GHOST module. */ }; #define G_DEBUG_ALL \ (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \ - G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS | \ - G_DEBUG_GHOST) + G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_IO | G_DEBUG_GHOST) /** #Global.fileflags */ enum { diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index df5711f5120..a8caf317467 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -109,9 +109,14 @@ struct bGPDframe *BKE_gpencil_frame_addcopy(struct bGPDlayer *gpl, int cframe); struct bGPDlayer *BKE_gpencil_layer_addnew(struct bGPdata *gpd, const char *name, bool setactive); struct bGPdata *BKE_gpencil_data_addnew(struct Main *bmain, const char name[]); -struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src); -struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src); +struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src, + const bool dup_strokes); +struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src, + const bool dup_frames, + const bool dup_strokes); void BKE_gpencil_frame_copy_strokes(struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst); +void BKE_gpencil_frame_selected_hash(struct bGPdata *gpd, struct GHash *r_list); + struct bGPDcurve *BKE_gpencil_stroke_curve_duplicate(struct bGPDcurve *gpc_src); struct bGPDstroke *BKE_gpencil_stroke_duplicate(struct bGPDstroke *gps_src, const bool dup_points, @@ -280,12 +285,12 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig const struct bGPDframe *gpf_eval); void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval); -void BKE_gpencil_parent_matrix_get(const struct Depsgraph *depsgraph, - struct Object *obact, - struct bGPDlayer *gpl, - float diff_mat[4][4]); +void BKE_gpencil_layer_transform_matrix_get(const struct Depsgraph *depsgraph, + struct Object *obact, + struct bGPDlayer *gpl, + float diff_mat[4][4]); -void BKE_gpencil_update_layer_parent(const struct Depsgraph *depsgraph, struct Object *ob); +void BKE_gpencil_update_layer_transforms(const struct Depsgraph *depsgraph, struct Object *ob); int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char *name_prefix); diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 1c86df73d3c..89a794f2df3 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -149,6 +149,11 @@ void BKE_gpencil_stroke_join(struct bGPDstroke *gps_a, struct bGPDstroke *gps_b, const bool leave_gaps, const bool fit_thickness); +void BKE_gpencil_stroke_copy_to_keyframes(struct bGPdata *gpd, + struct bGPDlayer *gpl, + struct bGPDframe *gpf, + struct bGPDstroke *gps, + const bool tail); bool BKE_gpencil_convert_mesh(struct Main *bmain, struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index 61ccf3d60f6..c066c161f46 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -248,7 +248,7 @@ typedef struct GpencilModifierTypeInfo { #define GPENCIL_MODIFIER_TYPE_PANEL_PREFIX "MOD_PT_gpencil_" -/* Initialize modifier's global data (type info and some common global storages). */ +/* Initialize modifier's global data (type info and some common global storage). */ void BKE_gpencil_modifier_init(void); void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname); diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index 1298e3c2bbf..edfc96f3059 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -106,6 +106,8 @@ typedef void (*IDTypeBlendReadUndoPreserve)(struct BlendLibReader *reader, struct ID *id_new, struct ID *id_old); +typedef void (*IDTypeLibOverrideApplyPost)(struct ID *id_dst, struct ID *id_src); + typedef struct IDTypeInfo { /* ********** General IDType data. ********** */ @@ -207,6 +209,13 @@ typedef struct IDTypeInfo { * \note Called from #setup_app_data when undoing or redoing a memfile step. */ IDTypeBlendReadUndoPreserve blend_read_undo_preserve; + + /** + * Called after library override operations have been applied. + * + * \note Currently needed for some update operation on point caches. + */ + IDTypeLibOverrideApplyPost lib_override_apply_post; } IDTypeInfo; /* ********** Declaration of each IDTypeInfo. ********** */ diff --git a/source/blender/blenkernel/BKE_keyconfig.h b/source/blender/blenkernel/BKE_keyconfig.h index ab42d5742ea..1cacbf61976 100644 --- a/source/blender/blenkernel/BKE_keyconfig.h +++ b/source/blender/blenkernel/BKE_keyconfig.h @@ -43,10 +43,10 @@ typedef struct wmKeyConfigPrefType_Runtime { typedef struct wmKeyConfigPrefType_Runtime wmKeyConfigPrefType_Runtime; #endif -/* KeyConfig preferenes (UserDef). */ +/* KeyConfig preferences (UserDef). */ struct wmKeyConfigPref *BKE_keyconfig_pref_ensure(struct UserDef *userdef, const char *kc_idname); -/* KeyConfig preferenes (RNA). */ +/* KeyConfig preferences (RNA). */ struct wmKeyConfigPrefType_Runtime *BKE_keyconfig_pref_type_find(const char *idname, bool quiet); void BKE_keyconfig_pref_type_add(struct wmKeyConfigPrefType_Runtime *kpt_rt); void BKE_keyconfig_pref_type_remove(const struct wmKeyConfigPrefType_Runtime *kpt_rt); diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index cfd1db1317c..5a8d36b94ec 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -219,7 +219,7 @@ void id_fake_user_set(struct ID *id); void id_fake_user_clear(struct ID *id); void BKE_id_clear_newpoin(struct ID *id); -/** Flags to control make local code behaviour. */ +/** Flags to control make local code behavior. */ enum { /** Making that ID local is part of making local a whole library. */ LIB_ID_MAKELOCAL_FULL_LIBRARY = 1 << 0, diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index c9a9c26e222..5fd451dc986 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -65,15 +65,6 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain, struct ID *reference_id, const bool do_tagged_remap); bool BKE_lib_override_library_create_from_tag(struct Main *bmain); -void BKE_lib_override_library_dependencies_tag(struct Main *bmain, - struct ID *id_root, - const uint tag, - const bool do_create_main_relashionships); -void BKE_lib_override_library_override_group_tag(struct Main *bmain, - struct ID *id_root, - const uint tag, - const uint missing_tag, - const bool do_create_main_relashionships); bool BKE_lib_override_library_create(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h index b6abe0bf18c..bdda5bb0372 100644 --- a/source/blender/blenkernel/BKE_lib_query.h +++ b/source/blender/blenkernel/BKE_lib_query.h @@ -77,7 +77,7 @@ enum { IDWALK_CB_USER = (1 << 8), /** * This ID usage is not refcounted, but at least one user should be generated by it (to avoid - * e.g. loosing the used ID on save/reload). + * e.g. losing the used ID on save/reload). * Callback is responsible to deal accordingly with #ID.us if needed. */ IDWALK_CB_USER_ONE = (1 << 9), diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 8106607572b..b6116b32ca5 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -60,22 +60,52 @@ typedef struct BlendThumbnail { } BlendThumbnail; /* Structs caching relations between data-blocks in a given Main. */ +typedef struct MainIDRelationsEntryItem { + struct MainIDRelationsEntryItem *next; + + union { + /* For `from_ids` list, a user of the hashed ID. */ + struct ID *from; + /* For `to_ids` list, an ID used by the hashed ID. */ + struct ID **to; + } id_pointer; + /* Session uuid of the `id_pointer`. */ + uint session_uuid; + + int usage_flag; /* Using IDWALK_ enums, defined in BKE_lib_query.h */ +} MainIDRelationsEntryItem; + typedef struct MainIDRelationsEntry { - struct MainIDRelationsEntry *next; - /* WARNING! for user_to_used, - * that pointer is really an ID** one, but for used_to_user, it’s only an ID* one! */ - struct ID **id_pointer; - int usage_flag; /* Using IDWALK_ enums, in BKE_lib_query.h */ + /* Linked list of IDs using that ID. */ + struct MainIDRelationsEntryItem *from_ids; + /* Linked list of IDs used by that ID. */ + struct MainIDRelationsEntryItem *to_ids; + + /* Session uuid of the ID matching that entry. */ + uint session_uuid; + + /* Runtime tags, users should ensure those are reset after usage. */ + uint tags; } MainIDRelationsEntry; +/* MainIDRelationsEntry.tags */ +typedef enum MainIDRelationsEntryTags { + /* Generic tag marking the entry as to be processed. */ + MAINIDRELATIONS_ENTRY_TAGS_DOIT = 1 << 0, + /* Generic tag marking the entry as processed. */ + MAINIDRELATIONS_ENTRY_TAGS_PROCESSED = 1 << 1, +} MainIDRelationsEntryTags; + typedef struct MainIDRelations { - struct GHash *id_user_to_used; - struct GHash *id_used_to_user; + /* Mapping from an ID pointer to all of its parents (IDs using it) and children (IDs it uses). + * Values are `MainIDRelationsEntry` pointers. */ + struct GHash *relations_from_pointers; + /* Note: we could add more mappings when needed (e.g. from session uuid?). */ short flag; /* Private... */ - struct BLI_mempool *entry_pool; + struct BLI_mempool *entry_items_pool; } MainIDRelations; enum { @@ -172,7 +202,9 @@ void BKE_main_unlock(struct Main *bmain); void BKE_main_relations_create(struct Main *bmain, const short flag); void BKE_main_relations_free(struct Main *bmain); -void BKE_main_relations_ID_remove(struct Main *bmain, struct ID *id); +void BKE_main_relations_tag_set(struct Main *bmain, + const MainIDRelationsEntryTags tag, + const bool value); struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 29072742f81..8e2f6e6f10c 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -269,18 +269,18 @@ int BKE_mask_spline_differentiate_calc_total(const struct MaskSpline *spline, const unsigned int resol); float (*BKE_mask_spline_differentiate_with_resolution(struct MaskSpline *spline, - unsigned int *tot_diff_point, - const unsigned int resol))[2]; + const unsigned int resol, + unsigned int *r_tot_diff_point))[2]; void BKE_mask_spline_feather_collapse_inner_loops(struct MaskSpline *spline, float (*feather_points)[2], const unsigned int tot_feather_point); float (*BKE_mask_spline_differentiate( - struct MaskSpline *spline, int width, int height, unsigned int *tot_diff_point))[2]; + struct MaskSpline *spline, int width, int height, unsigned int *r_tot_diff_point))[2]; float (*BKE_mask_spline_feather_differentiated_points_with_resolution( struct MaskSpline *spline, - unsigned int *tot_feather_point, const unsigned int resol, - const bool do_feather_isect))[2]; + const bool do_feather_isect, + unsigned int *r_tot_feather_point))[2]; /* *** mask point functions which involve evaluation *** */ float (*BKE_mask_spline_feather_points(struct MaskSpline *spline, int *tot_feather_point))[2]; @@ -289,7 +289,7 @@ float *BKE_mask_point_segment_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, int width, int height, - unsigned int *tot_diff_point); + unsigned int *r_tot_diff_point); float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct MaskSplinePoint *point, diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 685a8ed98e2..32b74d161b2 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -399,7 +399,7 @@ typedef struct ModifierTypeInfo { /* Used to find a modifier's panel type. */ #define MODIFIER_TYPE_PANEL_PREFIX "MOD_PT_" -/* Initialize modifier's global data (type info and some common global storages). */ +/* Initialize modifier's global data (type info and some common global storage). */ void BKE_modifier_init(void); const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 79bc00766fd..7984bbc980a 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -419,7 +419,7 @@ struct GHashIterator *ntreeTypeGetIterator(void); GHashIterator *__node_tree_type_iter__ = ntreeTypeGetIterator(); \ for (; !BLI_ghashIterator_done(__node_tree_type_iter__); \ BLI_ghashIterator_step(__node_tree_type_iter__)) { \ - bNodeTreeType *ntype = BLI_ghashIterator_getValue(__node_tree_type_iter__); + bNodeTreeType *ntype = (bNodeTreeType *)BLI_ghashIterator_getValue(__node_tree_type_iter__); #define NODE_TREE_TYPES_END \ } \ @@ -453,7 +453,9 @@ void ntreeUpdateTree(struct Main *main, struct bNodeTree *ntree); void ntreeUpdateAllNew(struct Main *main); void ntreeUpdateAllUsers(struct Main *main, struct ID *id); -void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes); +void ntreeGetDependencyList(struct bNodeTree *ntree, + struct bNode ***r_deplist, + int *r_deplist_len); /* XXX old trees handle output flags automatically based on special output * node types and last active selection. @@ -463,8 +465,8 @@ void ntreeSetOutput(struct bNodeTree *ntree); void ntreeFreeCache(struct bNodeTree *ntree); -bool ntreeNodeExists(struct bNodeTree *ntree, struct bNode *testnode); -bool ntreeOutputExists(struct bNode *node, struct bNodeSocket *testsock); +bool ntreeNodeExists(const struct bNodeTree *ntree, const struct bNode *testnode); +bool ntreeOutputExists(const struct bNode *node, const struct bNodeSocket *testsock); void ntreeNodeFlagSet(const bNodeTree *ntree, const int flag, const bool enable); struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree); void ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree); @@ -501,7 +503,7 @@ struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree struct bNodeSocket *from_sock); void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock); -struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, int create); +struct StructRNA *ntreeInterfaceTypeGet(struct bNodeTree *ntree, bool create); void ntreeInterfaceTypeFree(struct bNodeTree *ntree); void ntreeInterfaceTypeUpdate(struct bNodeTree *ntree); @@ -523,7 +525,7 @@ struct GHashIterator *nodeTypeGetIterator(void); GHashIterator *__node_type_iter__ = nodeTypeGetIterator(); \ for (; !BLI_ghashIterator_done(__node_type_iter__); \ BLI_ghashIterator_step(__node_type_iter__)) { \ - bNodeType *ntype = BLI_ghashIterator_getValue(__node_type_iter__); + bNodeType *ntype = (bNodeType *)BLI_ghashIterator_getValue(__node_type_iter__); #define NODE_TYPES_END \ } \ @@ -545,7 +547,8 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype); GHashIterator *__node_socket_type_iter__ = nodeSocketTypeGetIterator(); \ for (; !BLI_ghashIterator_done(__node_socket_type_iter__); \ BLI_ghashIterator_step(__node_socket_type_iter__)) { \ - bNodeSocketType *stype = BLI_ghashIterator_getValue(__node_socket_type_iter__); + bNodeSocketType *stype = (bNodeSocketType *)BLI_ghashIterator_getValue( \ + __node_socket_type_iter__); #define NODE_SOCKET_TYPES_END \ } \ @@ -624,12 +627,12 @@ struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNodeSocket *tosock); void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link); void nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); -bool nodeLinkIsHidden(struct bNodeLink *link); +bool nodeLinkIsHidden(const struct bNodeLink *link); void nodeInternalRelink(struct bNodeTree *ntree, struct bNode *node); -void nodeToView(struct bNode *node, float x, float y, float *rx, float *ry); -void nodeFromView(struct bNode *node, float x, float y, float *rx, float *ry); -bool nodeAttachNodeCheck(struct bNode *node, struct bNode *parent); +void nodeToView(const struct bNode *node, float x, float y, float *rx, float *ry); +void nodeFromView(const struct bNode *node, float x, float y, float *rx, float *ry); +bool nodeAttachNodeCheck(const struct bNode *node, const struct bNode *parent); void nodeAttachNode(struct bNode *node, struct bNode *parent); void nodeDetachNode(struct bNode *node); @@ -661,9 +664,9 @@ void nodeChainIterBackwards(const bNodeTree *ntree, void nodeParentsIter(bNode *node, bool (*callback)(bNode *, void *), void *userdata); struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, - struct bNodeSocket *from, - struct bNodeSocket *to); -int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock); + const struct bNodeSocket *from, + const struct bNodeSocket *to); +int nodeCountSocketLinks(const struct bNodeTree *ntree, const struct bNodeSocket *sock); void nodeSetSelected(struct bNode *node, bool select); void nodeSetActive(struct bNodeTree *ntree, struct bNode *node); @@ -678,14 +681,14 @@ void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); bool nodeUpdateID(struct bNodeTree *ntree, struct ID *id); void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); -int nodeSocketIsHidden(struct bNodeSocket *sock); +int nodeSocketIsHidden(const struct bNodeSocket *sock); void ntreeTagUsedSockets(struct bNodeTree *ntree); void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available); -int nodeSocketLinkLimit(struct bNodeSocket *sock); +int nodeSocketLinkLimit(const struct bNodeSocket *sock); /* Node Clipboard */ -void BKE_node_clipboard_init(struct bNodeTree *ntree); +void BKE_node_clipboard_init(const struct bNodeTree *ntree); void BKE_node_clipboard_clear(void); void BKE_node_clipboard_free(void); bool BKE_node_clipboard_validate(void); @@ -706,8 +709,8 @@ extern const bNodeInstanceKey NODE_INSTANCE_KEY_BASE; extern const bNodeInstanceKey NODE_INSTANCE_KEY_NONE; bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, - struct bNodeTree *ntree, - struct bNode *node); + const struct bNodeTree *ntree, + const struct bNode *node); bNodeInstanceHash *BKE_node_instance_hash_new(const char *info); void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp); @@ -767,7 +770,7 @@ BLI_INLINE bool BKE_node_instance_hash_iterator_done(bNodeInstanceHashIterator * /* Node Previews */ -int BKE_node_preview_used(struct bNode *node); +bool BKE_node_preview_used(const struct bNode *node); bNodePreview *BKE_node_preview_verify( struct bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create); bNodePreview *BKE_node_preview_copy(struct bNodePreview *preview); @@ -1361,6 +1364,14 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_ALIGN_ROTATION_TO_VECTOR 1018 #define GEO_NODE_POINT_TRANSLATE 1019 #define GEO_NODE_POINT_SCALE 1020 +#define GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE 1021 +#define GEO_NODE_POINTS_TO_VOLUME 1022 +#define GEO_NODE_COLLECTION_INFO 1023 +#define GEO_NODE_IS_VIEWPORT 1024 +#define GEO_NODE_ATTRIBUTE_PROXIMITY 1025 +#define GEO_NODE_VOLUME_TO_MESH 1026 +#define GEO_NODE_ATTRIBUTE_COMBINE_XYZ 1027 +#define GEO_NODE_ATTRIBUTE_SEPARATE_XYZ 1028 /** \} */ diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 0a35658464a..4369f332c35 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -365,7 +365,7 @@ typedef struct SculptBoundaryEditInfo { /* How many steps were needed to reach this vertex from the boundary. */ int num_propagation_steps; - /* Stregth that is used to deform this vertex. */ + /* Strength that is used to deform this vertex. */ float strength_factor; } SculptBoundaryEditInfo; @@ -530,7 +530,7 @@ typedef struct SculptSession { float gesture_initial_normal[3]; bool gesture_initial_hit; - /* TODO(jbakker): Replace rv3d adn v3d with ViewContext */ + /* TODO(jbakker): Replace rv3d and v3d with ViewContext */ struct RegionView3D *rv3d; struct View3D *v3d; struct Scene *scene; diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 7b5df98d148..2fc0caf1a2c 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -67,6 +67,13 @@ struct wmWindowManager; #define BKE_ST_MAXNAME 64 +typedef struct wmSpaceTypeListenerParams { + struct wmWindow *window; + struct ScrArea *area; + struct wmNotifier *notifier; + const struct Scene *scene; +} wmSpaceTypeListenerParams; + typedef struct SpaceType { struct SpaceType *next, *prev; @@ -85,10 +92,7 @@ typedef struct SpaceType { /* exit is called when the area is hidden or removed */ void (*exit)(struct wmWindowManager *wm, struct ScrArea *area); /* Listeners can react to bContext changes */ - void (*listener)(struct wmWindow *win, - struct ScrArea *area, - struct wmNotifier *wmn, - struct Scene *scene); + void (*listener)(const wmSpaceTypeListenerParams *params); /* called when the mouse moves out of the area */ void (*deactivate)(struct ScrArea *area); @@ -134,6 +138,24 @@ typedef struct SpaceType { /* region types are also defined using spacetypes_init, via a callback */ +typedef struct wmRegionListenerParams { + struct wmWindow *window; + struct ScrArea *area; /* Can be NULL when the region is not part of an area. */ + struct ARegion *region; + struct wmNotifier *notifier; + const struct Scene *scene; +} wmRegionListenerParams; + +typedef struct wmRegionMessageSubscribeParams { + const struct bContext *context; + struct wmMsgBus *message_bus; + struct WorkSpace *workspace; + struct Scene *scene; + struct bScreen *screen; + struct ScrArea *area; + struct ARegion *region; +} wmRegionMessageSubscribeParams; + typedef struct ARegionType { struct ARegionType *next, *prev; @@ -158,19 +180,9 @@ typedef struct ARegionType { /* snap the size of the region (can be NULL for no snapping). */ int (*snap_size)(const struct ARegion *region, int size, int axis); /* contextual changes should be handled here */ - void (*listener)(struct wmWindow *win, - struct ScrArea *area, - struct ARegion *region, - struct wmNotifier *wmn, - const struct Scene *scene); + void (*listener)(const wmRegionListenerParams *params); /* Optional callback to generate subscriptions. */ - void (*message_subscribe)(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); + void (*message_subscribe)(const wmRegionMessageSubscribeParams *params); void (*free)(struct ARegion *); diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index 23bd62c70bc..e385f77565b 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -149,7 +149,7 @@ typedef struct ShaderFxTypeInfo { #define SHADERFX_TYPE_PANEL_PREFIX "FX_PT_" -/* Initialize global data (type info and some common global storages). */ +/* Initialize global data (type info and some common global storage). */ void BKE_shaderfx_init(void); void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname); diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index d1cffd26432..4f8b21141b6 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -49,7 +49,7 @@ typedef struct BodyPoint { /* allocates and initializes general main data */ extern struct SoftBody *sbNew(struct Scene *scene); -/* frees internal data and softbody itself */ +/* frees internal data and soft-body itself */ extern void sbFree(struct Object *ob); /* frees simulation data to reset simulation */ @@ -66,7 +66,7 @@ extern void sbObjectStep(struct Depsgraph *depsgraph, /* makes totally fresh start situation, resets time */ extern void sbObjectToSoftbody(struct Object *ob); -/* links the softbody module to a 'test for Interrupt' function */ +/* links the soft-body module to a 'test for Interrupt' function */ /* pass NULL to unlink again */ extern void sbSetInterruptCallBack(int (*f)(void)); diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index f0ca154c4b9..b7d4ab8d8ed 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -293,7 +293,7 @@ bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG *subdiv_ccg, const SubdivC * neighbor elements in total). * * - For the corner element a single neighboring element on every adjacent edge, single from - * every gird. + * every grid. * * - For the boundary element two neighbor elements on the boundary (from same grid) and one * element inside of every neighboring grid. */ diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 4dbc22ae18f..c2544c06514 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -89,6 +89,23 @@ struct MovieTrackingTrack *BKE_tracking_track_duplicate(struct MovieTrackingTrac void BKE_tracking_track_unique_name(struct ListBase *tracksbase, struct MovieTrackingTrack *track); void BKE_tracking_track_free(struct MovieTrackingTrack *track); +void BKE_tracking_track_first_last_frame_get(const struct MovieTrackingTrack *track, + int *r_first_frame, + int *r_last_frame); + +void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ struct MovieTrackingTrack **tracks, + const int num_tracks, + int *r_first_frame, + int *r_last_frame); + +int BKE_tracking_count_selected_tracks_in_list(const struct ListBase *tracks_list); +int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ struct MovieTracking *tracking); + +/* Get array of selected tracks from the current active object in the tracking structure. + * If nothing is selected then the result is nullptr and `r_num_tracks` is set to 0. */ +struct MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object( + struct MovieTracking *tracking, int *r_num_tracks); + void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag); void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag); @@ -96,10 +113,15 @@ bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, in bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action); + void BKE_tracking_tracks_join(struct MovieTracking *tracking, struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); +void BKE_tracking_tracks_average(struct MovieTrackingTrack *dst_track, + /*const*/ struct MovieTrackingTrack **src_tracks, + const int num_src_tracks); + struct MovieTrackingTrack *BKE_tracking_track_get_named(struct MovieTracking *tracking, struct MovieTrackingObject *object, const char *name); @@ -139,6 +161,17 @@ struct MovieTrackingMarker *BKE_tracking_marker_get_exact(struct MovieTrackingTr struct MovieTrackingMarker *BKE_tracking_marker_ensure(struct MovieTrackingTrack *track, int framenr); +/* Get marker position, possibly interpolating interpolating gap between keyframed/tracked markers. + * + * The result marker frame number is set to the requested frame number. Its flags are 0 if the + * marker is interpolated, and is set to original marker flag if there were no interpolation + * involved. + * + * Returns truth if the result is usable. */ +bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track, + const int framenr, + struct MovieTrackingMarker *r_marker); + void BKE_tracking_marker_pattern_minmax(const struct MovieTrackingMarker *marker, float min[2], float max[2]); diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h index 0603ef85cc1..620496864f5 100644 --- a/source/blender/blenkernel/BKE_undo_system.h +++ b/source/blender/blenkernel/BKE_undo_system.h @@ -96,6 +96,12 @@ typedef struct UndoStep { /* Over alloc 'type->struct_size'. */ } UndoStep; +typedef enum eUndoStepDir { + STEP_REDO = 1, + STEP_UNDO = -1, + STEP_INVALID = 0, +} eUndoStepDir; + typedef enum UndoPushReturn { UNDO_PUSH_RET_FAILURE = 0, UNDO_PUSH_RET_SUCCESS = (1 << 0), @@ -127,7 +133,7 @@ typedef struct UndoType { bool (*step_encode)(struct bContext *C, struct Main *bmain, UndoStep *us); void (*step_decode)( - struct bContext *C, struct Main *bmain, UndoStep *us, int dir, bool is_final); + struct bContext *C, struct Main *bmain, UndoStep *us, const eUndoStepDir dir, bool is_final); /** * \note When freeing all steps, @@ -203,23 +209,32 @@ UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack, UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut); UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name); +eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack, + const UndoStep *us_target, + const UndoStep *us_reference); + +bool BKE_undosys_step_load_data_ex(UndoStack *ustack, + struct bContext *C, + UndoStep *us_target, + UndoStep *us_reference, + const bool use_skip); +bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target); +void BKE_undosys_step_load_from_index(UndoStack *ustack, struct bContext *C, const int index); + bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip); -bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us); +bool BKE_undosys_step_undo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target); bool BKE_undosys_step_undo(UndoStack *ustack, struct bContext *C); bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack, struct bContext *C, UndoStep *us, bool use_skip); -bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us); +bool BKE_undosys_step_redo_with_data(UndoStack *ustack, struct bContext *C, UndoStep *us_target); bool BKE_undosys_step_redo(UndoStack *ustack, struct bContext *C); -bool BKE_undosys_step_load_data(UndoStack *ustack, struct bContext *C, UndoStep *us); - -void BKE_undosys_step_undo_from_index(UndoStack *ustack, struct bContext *C, int index); UndoStep *BKE_undosys_step_same_type_next(UndoStep *us); UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us); diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h index 12c37ec56e0..53626dbeb1b 100644 --- a/source/blender/blenkernel/BKE_volume.h +++ b/source/blender/blenkernel/BKE_volume.h @@ -170,7 +170,7 @@ openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *vo struct VolumeGrid *grid, const bool clear); -VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase::Ptr &grid); +VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid); template<typename OpType> auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op) diff --git a/intern/guardedalloc/mmap_win.h b/source/blender/blenkernel/BKE_volume_to_mesh.hh index c0cbaa0e512..1ec8a8e84cd 100644 --- a/intern/guardedalloc/mmap_win.h +++ b/source/blender/blenkernel/BKE_volume_to_mesh.hh @@ -12,39 +12,32 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2008 Blender Foundation. - * All rights reserved. - */ - -/** \file - * \ingroup MEM */ -#ifndef __MMAP_WIN_H__ -#define __MMAP_WIN_H__ - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 +#include "DNA_modifier_types.h" -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_TYPE 0xF -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x20 -#define MAP_ANON MAP_ANONYMOUS - -#define MAP_FAILED ((void *)-1) +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +#endif -/* needed for uintptr_t, exception, dont use BLI anywhere else in MEM_* */ -#include "../../source/blender/blenlib/BLI_sys_types.h" +struct Mesh; +struct VolumeGrid; -#include <sys/types.h> +namespace blender::bke { -void *mmap(void *start, size_t len, int prot, int flags, int fd, off_t offset); -intptr_t munmap(void *ptr, size_t size); +struct VolumeToMeshResolution { + VolumeToMeshResolutionMode mode; + union { + float voxel_size; + float voxel_amount; + } settings; +}; +#ifdef WITH_OPENVDB +struct Mesh *volume_to_mesh(const openvdb::GridBase &grid, + const VolumeToMeshResolution &resolution, + const float threshold, + const float adaptivity); #endif + +} // namespace blender::bke diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9aa2baef53c..6b6d2b45d02 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -78,9 +78,10 @@ set(SRC intern/armature.c intern/armature_deform.c intern/armature_update.c - intern/asset.c + intern/asset.cc intern/attribute.c intern/attribute_access.cc + intern/attribute_math.cc intern/autoexec.c intern/blender.c intern/blender_copybuffer.c @@ -197,7 +198,7 @@ set(SRC intern/multires_unsubdivide.c intern/multires_versioning.c intern/nla.c - intern/node.c + intern/node.cc intern/object.c intern/object_deform.c intern/object_dupli.c @@ -259,6 +260,7 @@ set(SRC intern/unit.c intern/volume.cc intern/volume_render.cc + intern/volume_to_mesh.cc intern/workspace.c intern/world.c intern/writeavi.c @@ -275,6 +277,7 @@ set(SRC BKE_asset.h BKE_attribute.h BKE_attribute_access.hh + BKE_attribute_math.hh BKE_autoexec.h BKE_blender.h BKE_blender_copybuffer.h @@ -412,6 +415,7 @@ set(SRC BKE_unit.h BKE_volume.h BKE_volume_render.h + BKE_volume_to_mesh.hh BKE_workspace.h BKE_world.h BKE_writeavi.h @@ -682,7 +686,7 @@ endif() if(WITH_OPENVDB) list(APPEND INC - ../../../intern/openvdb + ../../../intern/openvdb ) list(APPEND INC_SYS ${OPENVDB_INCLUDE_DIRS} @@ -696,10 +700,10 @@ endif() if(WITH_QUADRIFLOW) list(APPEND INC - ../../../intern/quadriflow + ../../../intern/quadriflow ) list(APPEND LIB - bf_intern_quadriflow + bf_intern_quadriflow ) add_definitions(-DWITH_QUADRIFLOW) endif() diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index ccb077d6b82..94680dc5c0c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -54,6 +54,7 @@ #include "BKE_constraint.h" #include "BKE_deform.h" #include "BKE_fcurve.h" +#include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" @@ -101,10 +102,7 @@ static CLG_LogRef LOG = {"bke.action"}; * * \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more). */ -static void action_copy_data(Main *UNUSED(bmain), - ID *id_dst, - const ID *id_src, - const int UNUSED(flag)) +static void action_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) { bAction *action_dst = (bAction *)id_dst; const bAction *action_src = (const bAction *)id_src; @@ -145,6 +143,13 @@ static void action_copy_data(Main *UNUSED(bmain), } } } + + if (flag & LIB_ID_COPY_NO_PREVIEW) { + action_dst->preview = NULL; + } + else { + BKE_previewimg_id_copy(&action_dst->id, &action_src->id); + } } /** Free (or release) any data used by this action (does not free the action itself). */ @@ -161,6 +166,8 @@ static void action_free_data(struct ID *id) /* Free pose-references (aka local markers). */ BLI_freelistN(&action->markers); + + BKE_previewimg_free(&action->preview); } static void action_foreach_id(ID *id, LibraryForeachIDData *data) @@ -192,6 +199,8 @@ static void action_blend_write(BlendWriter *writer, ID *id, const void *id_addre LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) { BLO_write_struct(writer, TimeMarker, marker); } + + BKE_previewimg_blend_write(writer, act->preview); } } @@ -218,6 +227,9 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id) BLO_read_data_address(reader, &agrp->channels.first); BLO_read_data_address(reader, &agrp->channels.last); } + + BLO_read_data_address(reader, &act->preview); + BKE_previewimg_blend_read(reader, act->preview); } static void blend_read_lib_constraint_channels(BlendLibReader *reader, ID *id, ListBase *chanbase) @@ -298,6 +310,8 @@ IDTypeInfo IDType_ID_AC = { .blend_read_expand = action_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* ***************** Library data level operations on action ************** */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 20956d6eb18..965dc4e0bec 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -362,6 +362,20 @@ void BKE_keyingsets_blend_read_expand(BlendExpander *expander, ListBase *list) /* ***************************************** */ /* Evaluation Data-Setting Backend */ +static bool is_fcurve_evaluatable(FCurve *fcu) +{ + if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { + return false; + } + if (fcu->grp != NULL && (fcu->grp->flag & AGRP_MUTED)) { + return false; + } + if (BKE_fcurve_is_empty(fcu)) { + return false; + } + return true; +} + bool BKE_animsys_store_rna_setting(PointerRNA *ptr, /* typically 'fcu->rna_path', 'fcu->array_index' */ const char *rna_path, @@ -594,18 +608,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, { /* Calculate then execute each curve. */ LISTBASE_FOREACH (FCurve *, fcu, list) { - /* Check if this F-Curve doesn't belong to a muted group. */ - if ((fcu->grp != NULL) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - /* Check if this curve should be skipped. */ - if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) { - continue; - } - /* Skip empty curves, as if muted. */ - if (BKE_fcurve_is_empty(fcu)) { + + if (!is_fcurve_evaluatable(fcu)) { continue; } + PathResolvedRNA anim_rna; if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context); @@ -979,6 +986,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, return nes; } +static NlaEvalStrip *nlastrips_ctime_get_strip_single( + ListBase *dst_list, + NlaStrip *single_strip, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) +{ + ListBase single_tracks_list; + single_tracks_list.first = single_tracks_list.last = single_strip; + + return nlastrips_ctime_get_strip( + dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original); +} + /* ---------------------- */ /* Initialize a valid mask, allocating memory if necessary. */ @@ -1152,11 +1172,7 @@ static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot) /* Free memory owned by this evaluation channel. */ static void nlaevalchan_free_data(NlaEvalChannel *nec) { - nlavalidmask_free(&nec->valid); - - if (nec->blend_snapshot != NULL) { - nlaevalchan_snapshot_free(nec->blend_snapshot); - } + nlavalidmask_free(&nec->domain); } /* Initialize a full NLA evaluation state structure. */ @@ -1353,7 +1369,7 @@ static NlaEvalChannel *nlaevalchan_verify_key(NlaEvalData *nlaeval, nec->mix_mode = nlaevalchan_detect_mix_mode(key, length); - nlavalidmask_init(&nec->valid, length); + nlavalidmask_init(&nec->domain, length); nec->base_snapshot.channel = nec; nec->base_snapshot.length = length; @@ -1578,7 +1594,7 @@ static bool nla_combine_get_inverted_strip_value(const int mix_mode, if (IS_EQF(base_value, 0.0f)) { base_value = 1.0f; } - /* Divison by zero. */ + /* Division by zero. */ if (IS_EQF(lower_value, 0.0f)) { /* Resolve 0/0 to 1. */ if (IS_EQF(blended_value, 0.0f)) { @@ -1641,149 +1657,6 @@ static bool nla_combine_quaternion_get_inverted_strip_values(const float lower_v return true; } -/* Data about the current blend mode. */ -typedef struct NlaBlendData { - NlaEvalSnapshot *snapshot; - int mode; - float influence; - - NlaEvalChannel *blend_queue; -} NlaBlendData; - -/* Queue the channel for deferred blending. */ -static NlaEvalChannelSnapshot *nlaevalchan_queue_blend(NlaBlendData *blend, NlaEvalChannel *nec) -{ - if (!nec->in_blend) { - if (nec->blend_snapshot == NULL) { - nec->blend_snapshot = nlaevalchan_snapshot_new(nec); - } - - nec->in_blend = true; - nlaevalchan_snapshot_copy(nec->blend_snapshot, &nec->base_snapshot); - - nec->next_blend = blend->blend_queue; - blend->blend_queue = nec; - } - - return nec->blend_snapshot; -} - -/* Accumulate (i.e. blend) the given value on to the channel it affects. */ -static bool nlaeval_blend_value(NlaBlendData *blend, - NlaEvalChannel *nec, - int array_index, - float value) -{ - if (nec == NULL) { - return false; - } - - if (!nlaevalchan_validate_index_ex(nec, array_index)) { - return false; - } - - if (nec->mix_mode == NEC_MIX_QUATERNION) { - /* For quaternion properties, always output all sub-channels. */ - BLI_bitmap_set_all(nec->valid.ptr, true, 4); - } - else { - BLI_BITMAP_ENABLE(nec->valid.ptr, array_index); - } - - NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec); - float *p_value = &nec_snapshot->values[array_index]; - - if (blend->mode == NLASTRIP_MODE_COMBINE) { - /* Quaternion blending is deferred until all sub-channel values are known. */ - if (nec->mix_mode == NEC_MIX_QUATERNION) { - NlaEvalChannelSnapshot *blend_snapshot = nlaevalchan_queue_blend(blend, nec); - - blend_snapshot->values[array_index] = value; - } - else { - float base_value = nec->base_snapshot.values[array_index]; - - *p_value = nla_combine_value(nec->mix_mode, base_value, *p_value, value, blend->influence); - } - } - else { - *p_value = nla_blend_value(blend->mode, *p_value, value, blend->influence); - } - - return true; -} - -/* Finish deferred quaternion blending. */ -static void nlaeval_blend_flush(NlaBlendData *blend) -{ - NlaEvalChannel *nec; - - while ((nec = blend->blend_queue)) { - blend->blend_queue = nec->next_blend; - nec->in_blend = false; - - NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec); - NlaEvalChannelSnapshot *blend_snapshot = nec->blend_snapshot; - - if (nec->mix_mode == NEC_MIX_QUATERNION) { - nla_combine_quaternion( - nec_snapshot->values, blend_snapshot->values, blend->influence, nec_snapshot->values); - } - else { - BLI_assert(!"mix quaternion"); - } - } -} - -/* Blend the specified snapshots into the target, and free the input snapshots. */ -static void nlaeval_snapshot_mix_and_free(NlaEvalData *nlaeval, - NlaEvalSnapshot *out, - NlaEvalSnapshot *in1, - NlaEvalSnapshot *in2, - float alpha) -{ - BLI_assert(in1->base == out && in2->base == out); - - nlaeval_snapshot_ensure_size(out, nlaeval->num_channels); - - for (int i = 0; i < nlaeval->num_channels; i++) { - NlaEvalChannelSnapshot *c_in1 = nlaeval_snapshot_get(in1, i); - NlaEvalChannelSnapshot *c_in2 = nlaeval_snapshot_get(in2, i); - - if (c_in1 || c_in2) { - NlaEvalChannelSnapshot *c_out = out->channels[i]; - - /* Steal the entry from one of the input snapshots. */ - if (c_out == NULL) { - if (c_in1 != NULL) { - c_out = c_in1; - in1->channels[i] = NULL; - } - else { - c_out = c_in2; - in2->channels[i] = NULL; - } - } - - if (c_in1 == NULL) { - c_in1 = nlaeval_snapshot_find_channel(in1->base, c_out->channel); - } - if (c_in2 == NULL) { - c_in2 = nlaeval_snapshot_find_channel(in2->base, c_out->channel); - } - - out->channels[i] = c_out; - - for (int j = 0; j < c_out->length; j++) { - c_out->values[j] = c_in1->values[j] * (1.0f - alpha) + c_in2->values[j] * alpha; - } - } - } - - nlaeval_snapshot_free_data(in1); - nlaeval_snapshot_free_data(in2); -} - /* ---------------------- */ /* F-Modifier stack joining/separation utilities - * should we generalize these for BLI_listbase.h interface? */ @@ -1845,6 +1718,50 @@ static void nlaeval_fmodifiers_split_stacks(ListBase *list1, ListBase *list2) /* ---------------------- */ +/** Fills \a r_snapshot with the \a action's evaluated fcurve values with modifiers applied. */ +static void nlasnapshot_from_action(PointerRNA *ptr, + NlaEvalData *channels, + ListBase *modifiers, + bAction *action, + const float evaltime, + NlaEvalSnapshot *r_snapshot) +{ + FCurve *fcu; + + action_idcode_patch_check(ptr->owner_id, action); + + /* Evaluate modifiers which modify time to evaluate the base curves at. */ + FModifiersStackStorage storage; + storage.modifier_count = BLI_listbase_count(modifiers); + storage.size_per_modifier = evaluate_fmodifiers_storage_size_per_modifier(modifiers); + storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier); + + const float modified_evaltime = evaluate_time_fmodifiers( + &storage, modifiers, NULL, 0.0f, evaltime); + + for (fcu = action->curves.first; fcu; fcu = fcu->next) { + if (!is_fcurve_evaluatable(fcu)) { + continue; + } + + NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path); + + /* Invalid path or property cannot be animated. */ + if (nec == NULL) { + continue; + } + + NlaEvalChannelSnapshot *necs = nlaeval_snapshot_ensure_channel(r_snapshot, nec); + if (!nlaevalchan_validate_index_ex(nec, fcu->array_index)) { + continue; + } + + float value = evaluate_fcurve(fcu, modified_evaltime); + evaluate_value_fmodifiers(&storage, modifiers, fcu, &value, evaltime); + necs->values[fcu->array_index] = value; + } +} + /* evaluate action-clip strip */ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, NlaEvalData *channels, @@ -1852,10 +1769,8 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, NlaEvalStrip *nes, NlaEvalSnapshot *snapshot) { - ListBase tmp_modifiers = {NULL, NULL}; + NlaStrip *strip = nes->strip; - FCurve *fcu; - float evaltime; /* sanity checks for action */ if (strip == NULL) { @@ -1867,62 +1782,20 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr, return; } - action_idcode_patch_check(ptr->owner_id, strip->act); + ListBase tmp_modifiers = {NULL, NULL}; /* join this strip's modifiers to the parent's modifiers (own modifiers first) */ nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers); - /* evaluate strip's modifiers which modify time to evaluate the base curves at */ - FModifiersStackStorage storage; - storage.modifier_count = BLI_listbase_count(&tmp_modifiers); - storage.size_per_modifier = evaluate_fmodifiers_storage_size_per_modifier(&tmp_modifiers); - storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier); - - evaltime = evaluate_time_fmodifiers(&storage, &tmp_modifiers, NULL, 0.0f, strip->strip_time); - - NlaBlendData blend = { - .snapshot = snapshot, - .mode = strip->blendmode, - .influence = strip->influence, - }; - - /* Evaluate all the F-Curves in the action, - * saving the relevant pointers to data that will need to be used. */ - for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) { - float value = 0.0f; - - /* check if this curve should be skipped */ - if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { - continue; - } - if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - if (BKE_fcurve_is_empty(fcu)) { - continue; - } - - /* evaluate the F-Curve's value for the time given in the strip - * NOTE: we use the modified time here, since strip's F-Curve Modifiers - * are applied on top of this. - */ - value = evaluate_fcurve(fcu, evaltime); + NlaEvalSnapshot strip_snapshot; + nlaeval_snapshot_init(&strip_snapshot, channels, NULL); - /* apply strip's F-Curve Modifiers on this value - * NOTE: we apply the strip's original evaluation time not the modified one - * (as per standard F-Curve eval) - */ - evaluate_value_fmodifiers(&storage, &tmp_modifiers, fcu, &value, strip->strip_time); + nlasnapshot_from_action( + ptr, channels, &tmp_modifiers, strip->act, strip->strip_time, &strip_snapshot); + nlasnapshot_blend( + channels, snapshot, &strip_snapshot, strip->blendmode, strip->influence, snapshot); - /* Get an NLA evaluation channel to work with, - * and accumulate the evaluated value with the value(s) - * stored in this channel if it has been used already. */ - NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path); - - nlaeval_blend_value(&blend, nec, fcu->array_index, value); - } - - nlaeval_blend_flush(&blend); + nlaeval_snapshot_free_data(&strip_snapshot); /* unlink this strip's modifiers from the parent's modifiers again */ nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers); @@ -1988,8 +1861,13 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr, nlastrip_evaluate( ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context, flush_to_original); - /* accumulate temp-buffer and full-buffer, using the 'real' strip */ - nlaeval_snapshot_mix_and_free(channels, snapshot, &snapshot1, &snapshot2, nes->strip_time); + /** Replace \a snapshot2 NULL channels with base or default values so all channels blend. */ + nlasnapshot_ensure_channels(channels, &snapshot2); + nlasnapshot_blend( + channels, &snapshot1, &snapshot2, NLASTRIP_MODE_REPLACE, nes->strip_time, snapshot); + + nlaeval_snapshot_free_data(&snapshot1); + nlaeval_snapshot_free_data(&snapshot2); /* unlink this strip's modifiers from the parent's modifiers again */ nlaeval_fmodifiers_split_stacks(&nes->strip->modifiers, modifiers); @@ -2099,12 +1977,21 @@ void nladata_flush_channels(PointerRNA *ptr, /* for each channel with accumulated values, write its value on the property it affects */ LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) { + /** + * The bitmask is set for all channels touched by NLA due to the domain() function. + * Channels touched by current set of evaluated strips will have a snapshot channel directly + * from the evaluation snapshot. + * + * This function falls back to the default value if the snapshot channel doesn't exist. + * Thus channels, touched by NLA but not by the current set of evaluated strips, will be + * reset to default. If channel not touched by NLA then it's value is unchanged. + */ NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(snapshot, nec); PathResolvedRNA rna = {nec->key.ptr, nec->key.prop, -1}; for (int i = 0; i < nec_snapshot->length; i++) { - if (BLI_BITMAP_TEST(nec->valid.ptr, i)) { + if (BLI_BITMAP_TEST(nec->domain.ptr, i)) { float value = nec_snapshot->values[i]; if (nec->is_array) { rna.prop_index = i; @@ -2131,13 +2018,7 @@ static void nla_eval_domain_action(PointerRNA *ptr, LISTBASE_FOREACH (FCurve *, fcu, &act->curves) { /* check if this curve should be skipped */ - if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) { - continue; - } - if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) { - continue; - } - if (BKE_fcurve_is_empty(fcu)) { + if (!is_fcurve_evaluatable(fcu)) { continue; } @@ -2146,14 +2027,14 @@ static void nla_eval_domain_action(PointerRNA *ptr, if (nec != NULL) { /* For quaternion properties, enable all sub-channels. */ if (nec->mix_mode == NEC_MIX_QUATERNION) { - BLI_bitmap_set_all(nec->valid.ptr, true, 4); + BLI_bitmap_set_all(nec->domain.ptr, true, 4); continue; } int idx = nlaevalchan_validate_index(nec, fcu->array_index); if (idx >= 0) { - BLI_BITMAP_ENABLE(nec->valid.ptr, idx); + BLI_BITMAP_ENABLE(nec->domain.ptr, idx); } } } @@ -2212,190 +2093,345 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels, /* ---------------------- */ +/** Tweaked strip is evaluated differently from other strips. Adjacent strips are ignored + * and includes a workaround for when user is not editing in place. */ +static void animsys_create_tweak_strip(const AnimData *adt, + const bool keyframing_to_strip, + NlaStrip *r_tweak_strip) + +{ + /* Copy active strip so we can modify how it evaluates without affecting user data. */ + memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip)); + r_tweak_strip->next = r_tweak_strip->prev = NULL; + + /* If tweaked strip is syncing action length, then evaluate using action length. */ + if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) { + BKE_nlastrip_recalculate_bounds_sync_action(r_tweak_strip); + } + + /* Strips with a user-defined time curve don't get properly remapped for editing + * at the moment, so mapping them just for display may be confusing. */ + const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) && + !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME); + + if (!is_inplace_tweak) { + /* Use Hold due to no proper remapping yet (the note above). */ + r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD; + + /* Disable range. */ + r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; + } + + /** Controls whether able to keyframe outside range of tweaked strip. */ + if (keyframing_to_strip) { + r_tweak_strip->extendmode = (is_inplace_tweak && + !(r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ? + NLASTRIP_EXTEND_NOTHING : + NLASTRIP_EXTEND_HOLD; + } +} + +/** Action track and strip are associated with the non-pushed action. */ +static void animsys_create_action_track_strip(const AnimData *adt, + const bool keyframing_to_strip, + NlaStrip *r_action_strip) +{ + memset(r_action_strip, 0, sizeof(NlaStrip)); + + bAction *action = adt->action; + + if ((adt->flag & ADT_NLA_EDIT_ON)) { + action = adt->tmpact; + } + + /* Set settings of dummy NLA strip from AnimData settings. */ + r_action_strip->act = action; + + /* Action range is calculated taking F-Modifiers into account + * (which making new strips doesn't do due to the troublesome nature of that). */ + calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1); + r_action_strip->start = r_action_strip->actstart; + r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ? + (r_action_strip->actstart + 1.0f) : + (r_action_strip->actend); + + r_action_strip->blendmode = adt->act_blendmode; + r_action_strip->extendmode = adt->act_extendmode; + r_action_strip->influence = adt->act_influence; + + /* NOTE: must set this, or else the default setting overrides, + * and this setting doesn't work. */ + r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; + + /* Unless extendmode is Nothing (might be useful for flattening NLA evaluation), disable range. + * Extendmode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold. + */ + if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { + r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; + } + + const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0; + const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0; + const bool actionstrip_evaluated = r_action_strip->act && !soloing && !tweaking; + if (!actionstrip_evaluated) { + r_action_strip->flag |= NLASTRIP_FLAG_MUTED; + } + + /** If we're keyframing, then we must allow keyframing outside fcurve bounds. */ + if (keyframing_to_strip) { + r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD; + } +} + +static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt) +{ + /* Skip disabled tracks unless it contains the tweaked strip. */ + const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) && + (nlt->index == adt->act_track->index); + if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) { + return false; + } + + /* Solo and muting are mutually exclusive. */ + if (adt->flag & ADT_NLA_SOLO_TRACK) { + /* Skip if there is a solo track, but this isn't it. */ + if ((nlt->flag & NLATRACK_SOLO) == 0) { + return false; + } + } + else { + /* Skip track if muted. */ + if (nlt->flag & NLATRACK_MUTED) { + return false; + } + } + + return true; +} + +/** Check for special case of non-pushed action being evaluated with no NLA influence (off and no + * strips evaluated) nor NLA interference (ensure NLA not soloing). */ +static bool is_action_track_evaluated_without_nla(const AnimData *adt, + const bool any_strip_evaluated) +{ + if (adt->action == NULL) { + return false; + } + + if (any_strip_evaluated) { + return false; + } + + /** NLA settings interference. */ + if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) != 0) { + return false; + } + + /** Allow action track to evaluate as if there isn't any NLA data. */ + return true; +} + /** - * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" + * XXX(Wayde Moss): #BKE_nlatrack_find_tweaked() exists within nla.c, but it doesn't appear to + * work as expected. From #animsys_evaluate_nla_for_flush(), it returns NULL in tweak mode. I'm not + * sure why. Preferably, it would be as simple as checking for `(adt->act_Track == nlt)` but that + * doesn't work either, neither does comparing indices. * + * This function is a temporary work around. The first disabled track is always the tweaked track. + */ +static NlaTrack *nlatrack_find_tweaked(const AnimData *adt) +{ + NlaTrack *nlt; + + if (adt == NULL) { + return NULL; + } + + /* Since the track itself gets disabled, we want the first disabled. */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { + if (nlt->flag & NLATRACK_DISABLED) { + return nlt; + } + } + + return NULL; +} + +/** + * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels" * \param[out] echannels: Evaluation channels with calculated values - * \param[out] r_context: If not NULL, - * data about the currently edited strip is stored here and excluded from value calculation. - * \return false if NLA evaluation isn't actually applicable. */ -static bool animsys_evaluate_nla(NlaEvalData *echannels, - PointerRNA *ptr, - AnimData *adt, - const AnimationEvalContext *anim_eval_context, - const bool flush_to_original, - NlaKeyframingContext *r_context) +static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels, + PointerRNA *ptr, + const AnimData *adt, + const AnimationEvalContext *anim_eval_context, + const bool flush_to_original) { NlaTrack *nlt; short track_index = 0; bool has_strips = false; - ListBase estrips = {NULL, NULL}; NlaEvalStrip *nes; - NlaStrip dummy_strip_buf; - /* dummy strip for active action */ - NlaStrip *dummy_strip = r_context ? &r_context->strip : &dummy_strip_buf; + NlaStrip tweak_strip; - memset(dummy_strip, 0, sizeof(*dummy_strip)); + NlaTrack *tweaked_track = nlatrack_find_tweaked(adt); - /* 1. get the stack of strips to evaluate at current time (influence calculated here) */ + /* Get the stack of strips to evaluate at current time (influence calculated here). */ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) { - /* stop here if tweaking is on and this strip is the tweaking track - * (it will be the first one that's 'disabled')... */ - if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) { - break; + + if (!is_nlatrack_evaluatable(adt, nlt)) { + continue; } - /* solo and muting are mutually exclusive... */ - if (adt->flag & ADT_NLA_SOLO_TRACK) { - /* skip if there is a solo track, but this isn't it */ - if ((nlt->flag & NLATRACK_SOLO) == 0) { - continue; - } - /* else - mute doesn't matter */ + if (nlt->strips.first) { + has_strips = true; + } + + /** Append strip to evaluate for this track. */ + if (nlt == tweaked_track) { + /** Tweaked strip is evaluated differently. */ + animsys_create_tweak_strip(adt, false, &tweak_strip); + nes = nlastrips_ctime_get_strip_single( + &estrips, &tweak_strip, anim_eval_context, flush_to_original); } else { - /* no solo tracks - skip track if muted */ - if (nlt->flag & NLATRACK_MUTED) { - continue; - } + nes = nlastrips_ctime_get_strip( + &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); + } + if (nes) { + nes->track = nlt; + } + } + + if (is_action_track_evaluated_without_nla(adt, has_strips)) { + BLI_freelistN(&estrips); + return false; + } + + NlaStrip action_strip = {0}; + animsys_create_action_track_strip(adt, false, &action_strip); + nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original); + + /* Per strip, evaluate and accumulate on top of existing channels. */ + for (nes = estrips.first; nes; nes = nes->next) { + nlastrip_evaluate(ptr, + echannels, + NULL, + nes, + &echannels->eval_snapshot, + anim_eval_context, + flush_to_original); + } + + /* Free temporary evaluation data that's not used elsewhere. */ + BLI_freelistN(&estrips); + return true; +} + +/** Lower blended values are calculated and accumulated into r_context->lower_eval_data. */ +static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr, + const AnimData *adt, + const AnimationEvalContext *anim_eval_context, + NlaKeyframingContext *r_context) +{ + if (!r_context) { + return; + } + + /* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe + * insertion. */ + if (adt->flag & ADT_NLA_SOLO_TRACK) { + if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) { + r_context->eval_strip = NULL; + return; + } + } + + NlaTrack *nlt; + short track_index = 0; + bool has_strips = false; + + ListBase lower_estrips = {NULL, NULL}; + NlaEvalStrip *nes; + + NlaTrack *tweaked_track = nlatrack_find_tweaked(adt); + + /* Get the lower stack of strips to evaluate at current time (influence calculated here). */ + for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) { + + if (!is_nlatrack_evaluatable(adt, nlt)) { + continue; + } + + /* Tweaked strip effect should not be stored in any snapshot. */ + if (nlt == tweaked_track) { + break; } - /* if this track has strips (but maybe they won't be suitable), set has_strips - * - used for mainly for still allowing normal action evaluation... - */ if (nlt->strips.first) { has_strips = true; } - /* otherwise, get strip to evaluate for this channel */ + /* Get strip to evaluate for this channel. */ nes = nlastrips_ctime_get_strip( - &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original); + &lower_estrips, &nlt->strips, track_index, anim_eval_context, false); if (nes) { nes->track = nlt; } } - /* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack - * - only do this if we're not exclusively evaluating the 'solo' NLA-track - * - however, if the 'solo' track houses the current 'tweaking' strip, - * then we should allow this to play, otherwise nothing happens + /** Note: Although we early out, we can still keyframe to the non-pushed action since the + * keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without + * remapping. */ - if ((adt->action) && ((adt->flag & ADT_NLA_SOLO_TRACK) == 0 || (adt->flag & ADT_NLA_EDIT_ON))) { - /* if there are strips, evaluate action as per NLA rules */ - if ((has_strips) || (adt->actstrip)) { - /* make dummy NLA strip, and add that to the stack */ - ListBase dummy_trackslist; - - dummy_trackslist.first = dummy_trackslist.last = dummy_strip; - - /* Strips with a user-defined time curve don't get properly remapped for editing - * at the moment, so mapping them just for display may be confusing. */ - bool is_inplace_tweak = (nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP) && - !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME); - - if (is_inplace_tweak) { - /* edit active action in-place according to its active strip, so copy the data */ - memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip)); - /* Prevents nla eval from considering active strip's adj strips. - * For user, this means entering tweak mode on a strip ignores evaluating adjacent strips - * in the same track. */ - dummy_strip->next = dummy_strip->prev = NULL; - - /* If tweaked strip is syncing action length, then evaluate using action length. */ - if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) { - BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip); - } - } - else { - /* set settings of dummy NLA strip from AnimData settings */ - dummy_strip->act = adt->action; - - /* action range is calculated taking F-Modifiers into account - * (which making new strips doesn't do due to the troublesome nature of that) */ - calc_action_range(dummy_strip->act, &dummy_strip->actstart, &dummy_strip->actend, 1); - dummy_strip->start = dummy_strip->actstart; - dummy_strip->end = (IS_EQF(dummy_strip->actstart, dummy_strip->actend)) ? - (dummy_strip->actstart + 1.0f) : - (dummy_strip->actend); - - /* Always use the blend mode of the strip in tweak mode, even if not in-place. */ - if (nlt && adt->actstrip) { - dummy_strip->blendmode = adt->actstrip->blendmode; - dummy_strip->extendmode = NLASTRIP_EXTEND_HOLD; - } - else { - dummy_strip->blendmode = adt->act_blendmode; - dummy_strip->extendmode = adt->act_extendmode; - } + if (is_action_track_evaluated_without_nla(adt, has_strips)) { + BLI_freelistN(&lower_estrips); + return; + } - /* Unless extend-mode is Nothing (might be useful for flattening NLA evaluation), - * disable range. */ - if (dummy_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { - dummy_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; - } + /* Write r_context->eval_strip. */ + if (adt->flag & ADT_NLA_EDIT_ON) { - dummy_strip->influence = adt->act_influence; + NlaStrip *tweak_strip = &r_context->strip; + animsys_create_tweak_strip(adt, true, tweak_strip); + r_context->eval_strip = nlastrips_ctime_get_strip_single( + NULL, tweak_strip, anim_eval_context, false); + } + else { - /* NOTE: must set this, or else the default setting overrides, - * and this setting doesn't work. */ - dummy_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; - } + NlaStrip *action_strip = &r_context->strip; + animsys_create_action_track_strip(adt, true, action_strip); + r_context->eval_strip = nlastrips_ctime_get_strip_single( + NULL, action_strip, anim_eval_context, false); + } - /* add this to our list of evaluation strips */ - if (r_context == NULL) { - nlastrips_ctime_get_strip( - &estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original); - } - /* If computing the context for keyframing, store data there instead of the list. */ - else { - /* The extend mode here effectively controls - * whether it is possible to key-frame beyond the ends.*/ - dummy_strip->extendmode = (is_inplace_tweak && - !(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ? - NLASTRIP_EXTEND_NOTHING : - NLASTRIP_EXTEND_HOLD; - - r_context->eval_strip = nes = nlastrips_ctime_get_strip( - NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original); - - /* These setting combinations require no data from strips below, so exit immediately. */ - if ((nes == NULL) || - (dummy_strip->blendmode == NLASTRIP_MODE_REPLACE && dummy_strip->influence == 1.0f)) { - BLI_freelistN(&estrips); - return true; - } - } - } - else { - /* special case - evaluate as if there isn't any NLA data */ - BLI_freelistN(&estrips); - return false; - } + /* If NULL, then keyframing will fail. No need to do any more processing. */ + if (!r_context->eval_strip) { + BLI_freelistN(&lower_estrips); + return; } - /* only continue if there are strips to evaluate */ - if (BLI_listbase_is_empty(&estrips)) { - return true; + /* If tweak strip is full REPLACE, then lower strips not needed. */ + if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE && + IS_EQF(r_context->strip.influence, 1.0f)) { + BLI_freelistN(&lower_estrips); + return; } - /* 2. for each strip, evaluate then accumulate on top of existing channels, - * but don't set values yet. */ - for (nes = estrips.first; nes; nes = nes->next) { + /* For each strip, evaluate then accumulate on top of existing channels. */ + for (nes = lower_estrips.first; nes; nes = nes->next) { nlastrip_evaluate(ptr, - echannels, + &r_context->lower_eval_data, NULL, nes, - &echannels->eval_snapshot, + &r_context->lower_eval_data.eval_snapshot, anim_eval_context, - flush_to_original); + false); } - /* 3. free temporary evaluation data that's not used elsewhere */ - BLI_freelistN(&estrips); - return true; + /* Free temporary evaluation data that's not used elsewhere. */ + BLI_freelistN(&lower_estrips); } /* NLA Evaluation function (mostly for use through do_animdata) @@ -2412,7 +2448,7 @@ static void animsys_calculate_nla(PointerRNA *ptr, nlaeval_init(&echannels); /* evaluate the NLA stack, obtaining a set of values to flush */ - if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) { + if (animsys_evaluate_nla_for_flush(&echannels, ptr, adt, anim_eval_context, flush_to_original)) { /* reset any channels touched by currently inactive actions to default value */ animsys_evaluate_nla_domain(ptr, &echannels, adt); @@ -2435,6 +2471,74 @@ static void animsys_calculate_nla(PointerRNA *ptr, /* ---------------------- */ +void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapshot) +{ + LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) { + nlaeval_snapshot_ensure_channel(snapshot, nec); + } +} + +/** Blends the \a lower_snapshot with the \a upper_snapshot into \a r_blended_snapshot according + * to the given \a upper_blendmode and \a upper_influence. */ +void nlasnapshot_blend(NlaEvalData *eval_data, + NlaEvalSnapshot *lower_snapshot, + NlaEvalSnapshot *upper_snapshot, + const short upper_blendmode, + const float upper_influence, + NlaEvalSnapshot *r_blended_snapshot) +{ + nlaeval_snapshot_ensure_size(r_blended_snapshot, eval_data->num_channels); + + const bool zero_upper_influence = IS_EQF(upper_influence, 0.0f); + + LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) { + const int length = nec->base_snapshot.length; + + NlaEvalChannelSnapshot *upper_necs = nlaeval_snapshot_get(upper_snapshot, nec->index); + NlaEvalChannelSnapshot *lower_necs = nlaeval_snapshot_get(lower_snapshot, nec->index); + if (upper_necs == NULL && lower_necs == NULL) { + continue; + } + + /** Blend with lower_snapshot's base or default. */ + if (lower_necs == NULL) { + lower_necs = nlaeval_snapshot_find_channel(lower_snapshot->base, nec); + } + + NlaEvalChannelSnapshot *result_necs = nlaeval_snapshot_ensure_channel(r_blended_snapshot, nec); + + if (upper_necs == NULL || zero_upper_influence) { + memcpy(result_necs->values, lower_necs->values, length * sizeof(float)); + continue; + } + + if (upper_blendmode == NLASTRIP_MODE_COMBINE) { + const int mix_mode = nec->mix_mode; + if (mix_mode == NEC_MIX_QUATERNION) { + nla_combine_quaternion( + lower_necs->values, upper_necs->values, upper_influence, result_necs->values); + } + else { + for (int j = 0; j < length; j++) { + result_necs->values[j] = nla_combine_value(mix_mode, + nec->base_snapshot.values[j], + lower_necs->values[j], + upper_necs->values[j], + upper_influence); + } + } + } + else { + for (int j = 0; j < length; j++) { + result_necs->values[j] = nla_blend_value( + upper_blendmode, lower_necs->values[j], upper_necs->values[j], upper_influence); + } + } + } +} + +/* ---------------------- */ + /** * Prepare data necessary to compute correct keyframe values for NLA strips * with non-Replace mode or influence different from 1. @@ -2448,8 +2552,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( struct ListBase *cache, struct PointerRNA *ptr, struct AnimData *adt, - const AnimationEvalContext *anim_eval_context, - const bool flush_to_original) + const AnimationEvalContext *anim_eval_context) { /* No remapping needed if NLA is off or no action. */ if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) || @@ -2472,8 +2575,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context( ctx->adt = adt; nlaeval_init(&ctx->lower_eval_data); - animsys_evaluate_nla( - &ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx); + animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx); BLI_assert(ELEM(ctx->strip.act, NULL, adt->action)); BLI_addtail(cache, ctx); diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 4c9fb4b191a..a59ead84aca 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -331,6 +331,8 @@ IDTypeInfo IDType_ID_AR = { .blend_read_expand = armature_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /** \} */ @@ -1889,9 +1891,8 @@ void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph, * bone loc/sca/rot is ignored, scene and frame are not used. */ BKE_pose_where_is_bone(depsgraph, NULL, ob, &work_pchan, 0.0f, false); - /* find the matrix, need to remove the bone transforms first so this is - * calculated as a matrix to set rather than a difference ontop of what's - * already there. */ + /* Find the matrix, need to remove the bone transforms first so this is calculated + * as a matrix to set rather than a difference on top of what's already there. */ unit_m4(outmat); BKE_pchan_apply_mat4(&work_pchan, outmat, false); @@ -1943,7 +1944,7 @@ void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3]) float quat[4]; /* NOTE: we now don't normalize the stored values anymore, - * since this was kindof evil in some cases but if this proves to be too problematic, + * since this was kind of evil in some cases but if this proves to be too problematic, * switch back to the old system of operating directly on the stored copy. */ normalize_qt_qt(quat, pchan->quat); quat_to_mat3(r_mat, quat); diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index 8c666597276..8f74b8ff054 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -428,8 +428,8 @@ static void splineik_evaluate_bone( if (fabsf(scaleFac) != 0.0f) { scale = 1.0f / fabsf(scaleFac); - /* we need to clamp this within sensible values */ - /* NOTE: these should be fine for now, but should get sanitised in future */ + /* We need to clamp this within sensible values. */ + /* NOTE: these should be fine for now, but should get sanitized in future. */ CLAMP(scale, 0.0001f, 100000.0f); } else { @@ -483,7 +483,7 @@ static void splineik_evaluate_bone( final_scale = 1.0f; } - /* apply the scaling (assuming normalised scale) */ + /* Apply the scaling (assuming normalized scale). */ mul_v3_fl(poseMat[0], final_scale); mul_v3_fl(poseMat[2], final_scale); break; diff --git a/source/blender/blenkernel/intern/asset.c b/source/blender/blenkernel/intern/asset.cc index 7ccb0aa2b57..89c3523285d 100644 --- a/source/blender/blenkernel/intern/asset.c +++ b/source/blender/blenkernel/intern/asset.cc @@ -20,6 +20,10 @@ #include <string.h> +#include "DNA_ID.h" +#include "DNA_asset_types.h" +#include "DNA_defaults.h" + #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_utils.h" @@ -29,17 +33,13 @@ #include "BKE_icons.h" #include "BKE_idprop.h" -#include "DNA_ID.h" -#include "DNA_asset_types.h" -#include "DNA_defaults.h" - #include "BLO_read_write.h" #include "MEM_guardedalloc.h" AssetMetaData *BKE_asset_metadata_create(void) { - AssetMetaData *asset_data = MEM_callocN(sizeof(*asset_data), __func__); + AssetMetaData *asset_data = (AssetMetaData *)MEM_callocN(sizeof(*asset_data), __func__); memcpy(asset_data, DNA_struct_default_get(AssetMetaData), sizeof(*asset_data)); return asset_data; } @@ -57,7 +57,7 @@ void BKE_asset_metadata_free(AssetMetaData **asset_data) static AssetTag *asset_metadata_tag_add(AssetMetaData *asset_data, const char *const name) { - AssetTag *tag = MEM_callocN(sizeof(*tag), __func__); + AssetTag *tag = (AssetTag *)MEM_callocN(sizeof(*tag), __func__); BLI_strncpy(tag->name, name, sizeof(tag->name)); BLI_addtail(&asset_data->tags, tag); @@ -81,12 +81,12 @@ AssetTag *BKE_asset_metadata_tag_add(AssetMetaData *asset_data, const char *name struct AssetTagEnsureResult BKE_asset_metadata_tag_ensure(AssetMetaData *asset_data, const char *name) { - struct AssetTagEnsureResult result = {.tag = NULL}; + struct AssetTagEnsureResult result = {nullptr}; if (!name[0]) { return result; } - AssetTag *tag = BLI_findstring(&asset_data->tags, name, offsetof(AssetTag, name)); + AssetTag *tag = (AssetTag *)BLI_findstring(&asset_data->tags, name, offsetof(AssetTag, name)); if (tag) { result.tag = tag; diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index e1e8d06b9ec..378fdfd27f2 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -17,6 +17,7 @@ #include <utility> #include "BKE_attribute_access.hh" +#include "BKE_attribute_math.hh" #include "BKE_customdata.h" #include "BKE_deform.h" #include "BKE_geometry_set.hh" @@ -323,29 +324,47 @@ template<typename T> class ArrayReadAttribute final : public ReadAttribute { } }; -template<typename StructT, typename ElemT, typename GetFuncT, typename SetFuncT> +template<typename T> class OwnedArrayReadAttribute final : public ReadAttribute { + private: + Array<T> data_; + + public: + OwnedArrayReadAttribute(AttributeDomain domain, Array<T> data) + : ReadAttribute(domain, CPPType::get<T>(), data.size()), data_(std::move(data)) + { + } + + void get_internal(const int64_t index, void *r_value) const override + { + new (r_value) T(data_[index]); + } + + void initialize_span() const override + { + /* The data will not be modified, so this const_cast is fine. */ + array_buffer_ = const_cast<T *>(data_.data()); + array_is_temporary_ = false; + } +}; + +template<typename StructT, + typename ElemT, + ElemT (*GetFunc)(const StructT &), + void (*SetFunc)(StructT &, const ElemT &)> class DerivedArrayWriteAttribute final : public WriteAttribute { private: MutableSpan<StructT> data_; - GetFuncT get_function_; - SetFuncT set_function_; public: - DerivedArrayWriteAttribute(AttributeDomain domain, - MutableSpan<StructT> data, - GetFuncT get_function, - SetFuncT set_function) - : WriteAttribute(domain, CPPType::get<ElemT>(), data.size()), - data_(data), - get_function_(std::move(get_function)), - set_function_(std::move(set_function)) + DerivedArrayWriteAttribute(AttributeDomain domain, MutableSpan<StructT> data) + : WriteAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data) { } void get_internal(const int64_t index, void *r_value) const override { const StructT &struct_value = data_[index]; - const ElemT value = get_function_(struct_value); + const ElemT value = GetFunc(struct_value); new (r_value) ElemT(value); } @@ -353,28 +372,25 @@ class DerivedArrayWriteAttribute final : public WriteAttribute { { StructT &struct_value = data_[index]; const ElemT &typed_value = *reinterpret_cast<const ElemT *>(value); - set_function_(struct_value, typed_value); + SetFunc(struct_value, typed_value); } }; -template<typename StructT, typename ElemT, typename GetFuncT> +template<typename StructT, typename ElemT, ElemT (*GetFunc)(const StructT &)> class DerivedArrayReadAttribute final : public ReadAttribute { private: Span<StructT> data_; - GetFuncT get_function_; public: - DerivedArrayReadAttribute(AttributeDomain domain, Span<StructT> data, GetFuncT get_function) - : ReadAttribute(domain, CPPType::get<ElemT>(), data.size()), - data_(data), - get_function_(std::move(get_function)) + DerivedArrayReadAttribute(AttributeDomain domain, Span<StructT> data) + : ReadAttribute(domain, CPPType::get<ElemT>(), data.size()), data_(data) { } void get_internal(const int64_t index, void *r_value) const override { const StructT &struct_value = data_[index]; - const ElemT value = get_function_(struct_value); + const ElemT value = GetFunc(struct_value); new (r_value) ElemT(value); } }; @@ -492,133 +508,835 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type) return static_cast<CustomDataType>(-1); } -} // namespace blender::bke +/** + * A #BuiltinAttributeProvider is responsible for exactly one attribute on a geometry component. + * The attribute is identified by its name and has a fixed domain and type. Builtin attributes do + * not follow the same loose rules as other attributes, because they are mapped to internal + * "legacy" data structures. For example, some builtin attributes cannot be deleted. */ +class BuiltinAttributeProvider { + public: + /* Some utility enums to avoid hard to read booleans in function calls. */ + enum CreatableEnum { + Creatable, + NonCreatable, + }; + enum WritableEnum { + Writable, + Readonly, + }; + enum DeletableEnum { + Deletable, + NonDeletable, + }; -/* -------------------------------------------------------------------- */ -/** \name Utilities for Accessing Attributes - * \{ */ + protected: + const std::string name_; + const AttributeDomain domain_; + const CustomDataType data_type_; + const CreatableEnum createable_; + const WritableEnum writable_; + const DeletableEnum deletable_; -static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom_data, - const int size, - const StringRef attribute_name, - const AttributeDomain domain) -{ - using namespace blender; - using namespace blender::bke; - for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) { - if (layer.name != nullptr && layer.name == attribute_name) { - switch (layer.type) { + public: + BuiltinAttributeProvider(std::string name, + const AttributeDomain domain, + const CustomDataType data_type, + const CreatableEnum createable, + const WritableEnum writable, + const DeletableEnum deletable) + : name_(std::move(name)), + domain_(domain), + data_type_(data_type), + createable_(createable), + writable_(writable), + deletable_(deletable) + { + } + + virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component) const = 0; + virtual WriteAttributePtr try_get_for_write(GeometryComponent &component) const = 0; + virtual bool try_delete(GeometryComponent &component) const = 0; + virtual bool try_create(GeometryComponent &UNUSED(component)) const = 0; + virtual bool exists(const GeometryComponent &component) const = 0; + + StringRefNull name() const + { + return name_; + } + + AttributeDomain domain() const + { + return domain_; + } + + CustomDataType data_type() const + { + return data_type_; + } +}; + +/** + * A #DynamicAttributesProvider manages a set of named attributes on a geometry component. Each + * attribute has a name, domain and type. + */ +class DynamicAttributesProvider { + public: + virtual ReadAttributePtr try_get_for_read(const GeometryComponent &component, + const StringRef attribute_name) const = 0; + virtual WriteAttributePtr try_get_for_write(GeometryComponent &component, + const StringRef attribute_name) const = 0; + virtual bool try_delete(GeometryComponent &component, const StringRef attribute_name) const = 0; + virtual bool try_create(GeometryComponent &UNUSED(component), + const StringRef UNUSED(attribute_name), + const AttributeDomain UNUSED(domain), + const CustomDataType UNUSED(data_type)) const + { + /* Some providers should not create new attributes. */ + return false; + }; + + virtual void list(const GeometryComponent &component, Set<std::string> &r_names) const = 0; + virtual void supported_domains(Vector<AttributeDomain> &r_domains) const = 0; +}; + +/** + * Utility to group together multiple functions that are used to access custom data on geometry + * components in a generic way. + */ +struct CustomDataAccessInfo { + using CustomDataGetter = CustomData *(*)(GeometryComponent &component); + using ConstCustomDataGetter = const CustomData *(*)(const GeometryComponent &component); + using UpdateCustomDataPointers = void (*)(GeometryComponent &component); + + CustomDataGetter get_custom_data; + ConstCustomDataGetter get_const_custom_data; + UpdateCustomDataPointers update_custom_data_pointers; +}; + +/** + * This provider is used to provide access to builtin attributes. It supports making internal types + * available as different types. For example, the vertex position attribute is stored as part of + * the #MVert struct, but is exposed as float3 attribute. + */ +class BuiltinCustomDataLayerProvider final : public BuiltinAttributeProvider { + using AsReadAttribute = ReadAttributePtr (*)(const void *data, const int domain_size); + using AsWriteAttribute = WriteAttributePtr (*)(void *data, const int domain_size); + const CustomDataType stored_type_; + const CustomDataAccessInfo custom_data_access_; + const AsReadAttribute as_read_attribute_; + const AsWriteAttribute as_write_attribute_; + + public: + BuiltinCustomDataLayerProvider(std::string attribute_name, + const AttributeDomain domain, + const CustomDataType attribute_type, + const CustomDataType stored_type, + const CreatableEnum creatable, + const WritableEnum writable, + const DeletableEnum deletable, + const CustomDataAccessInfo custom_data_access, + const AsReadAttribute as_read_attribute, + const AsWriteAttribute as_write_attribute) + : BuiltinAttributeProvider( + std::move(attribute_name), domain, attribute_type, creatable, writable, deletable), + stored_type_(stored_type), + custom_data_access_(custom_data_access), + as_read_attribute_(as_read_attribute), + as_write_attribute_(as_write_attribute) + { + } + + ReadAttributePtr try_get_for_read(const GeometryComponent &component) const final + { + const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); + if (custom_data == nullptr) { + return {}; + } + const int domain_size = component.attribute_domain_size(domain_); + const void *data = CustomData_get_layer(custom_data, stored_type_); + if (data == nullptr) { + return {}; + } + return as_read_attribute_(data, domain_size); + } + + WriteAttributePtr try_get_for_write(GeometryComponent &component) const final + { + if (writable_ != Writable) { + return {}; + } + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return {}; + } + const int domain_size = component.attribute_domain_size(domain_); + void *data = CustomData_get_layer(custom_data, stored_type_); + if (data == nullptr) { + return {}; + } + void *new_data = CustomData_duplicate_referenced_layer(custom_data, stored_type_, domain_size); + if (data != new_data) { + custom_data_access_.update_custom_data_pointers(component); + data = new_data; + } + return as_write_attribute_(data, domain_size); + } + + bool try_delete(GeometryComponent &component) const final + { + if (deletable_ != Deletable) { + return false; + } + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return {}; + } + + const int domain_size = component.attribute_domain_size(domain_); + const int layer_index = CustomData_get_layer_index(custom_data, stored_type_); + const bool delete_success = CustomData_free_layer( + custom_data, stored_type_, domain_size, layer_index); + if (delete_success) { + custom_data_access_.update_custom_data_pointers(component); + } + return delete_success; + } + + bool try_create(GeometryComponent &component) const final + { + if (createable_ != Creatable) { + return false; + } + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return false; + } + if (CustomData_get_layer(custom_data, stored_type_) != nullptr) { + /* Exists already. */ + return false; + } + const int domain_size = component.attribute_domain_size(domain_); + const void *data = CustomData_add_layer( + custom_data, stored_type_, CD_DEFAULT, nullptr, domain_size); + const bool success = data != nullptr; + if (success) { + custom_data_access_.update_custom_data_pointers(component); + } + return success; + } + + bool exists(const GeometryComponent &component) const final + { + const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); + if (custom_data == nullptr) { + return false; + } + const void *data = CustomData_get_layer(custom_data, stored_type_); + return data != nullptr; + } +}; + +/** + * This is the attribute provider for most user generated attributes. + */ +class CustomDataAttributeProvider final : public DynamicAttributesProvider { + private: + static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 | + CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 | + CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL; + const AttributeDomain domain_; + const CustomDataAccessInfo custom_data_access_; + + public: + CustomDataAttributeProvider(const AttributeDomain domain, + const CustomDataAccessInfo custom_data_access) + : domain_(domain), custom_data_access_(custom_data_access) + { + } + + ReadAttributePtr try_get_for_read(const GeometryComponent &component, + const StringRef attribute_name) const final + { + const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); + if (custom_data == nullptr) { + return {}; + } + const int domain_size = component.attribute_domain_size(domain_); + for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) { + if (layer.name != attribute_name) { + continue; + } + const CustomDataType data_type = (CustomDataType)layer.type; + switch (data_type) { case CD_PROP_FLOAT: - return std::make_unique<ArrayReadAttribute<float>>( - domain, Span(static_cast<float *>(layer.data), size)); + return this->layer_to_read_attribute<float>(layer, domain_size); case CD_PROP_FLOAT2: - return std::make_unique<ArrayReadAttribute<float2>>( - domain, Span(static_cast<float2 *>(layer.data), size)); + return this->layer_to_read_attribute<float2>(layer, domain_size); case CD_PROP_FLOAT3: - return std::make_unique<ArrayReadAttribute<float3>>( - domain, Span(static_cast<float3 *>(layer.data), size)); + return this->layer_to_read_attribute<float3>(layer, domain_size); case CD_PROP_INT32: - return std::make_unique<ArrayReadAttribute<int>>( - domain, Span(static_cast<int *>(layer.data), size)); + return this->layer_to_read_attribute<int>(layer, domain_size); case CD_PROP_COLOR: - return std::make_unique<ArrayReadAttribute<Color4f>>( - domain, Span(static_cast<Color4f *>(layer.data), size)); + return this->layer_to_read_attribute<Color4f>(layer, domain_size); case CD_PROP_BOOL: - return std::make_unique<ArrayReadAttribute<bool>>( - domain, Span(static_cast<bool *>(layer.data), size)); + return this->layer_to_read_attribute<bool>(layer, domain_size); + default: + break; } } + return {}; } - return {}; -} - -static WriteAttributePtr write_attribute_from_custom_data( - CustomData &custom_data, - const int size, - const StringRef attribute_name, - const AttributeDomain domain, - const std::function<void()> &update_customdata_pointers) -{ - using namespace blender; - using namespace blender::bke; - for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) { - if (layer.name != nullptr && layer.name == attribute_name) { - const void *data_before = layer.data; - /* The data layer might be shared with someone else. Since the caller wants to modify it, we - * copy it first. */ - CustomData_duplicate_referenced_layer_named(&custom_data, layer.type, layer.name, size); - if (data_before != layer.data) { - update_customdata_pointers(); + WriteAttributePtr try_get_for_write(GeometryComponent &component, + const StringRef attribute_name) const final + { + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return {}; + } + const int domain_size = component.attribute_domain_size(domain_); + for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) { + if (layer.name != attribute_name) { + continue; } - switch (layer.type) { + CustomData_duplicate_referenced_layer_named( + custom_data, layer.type, layer.name, domain_size); + const CustomDataType data_type = (CustomDataType)layer.type; + switch (data_type) { case CD_PROP_FLOAT: - return std::make_unique<ArrayWriteAttribute<float>>( - domain, MutableSpan(static_cast<float *>(layer.data), size)); + return this->layer_to_write_attribute<float>(layer, domain_size); case CD_PROP_FLOAT2: - return std::make_unique<ArrayWriteAttribute<float2>>( - domain, MutableSpan(static_cast<float2 *>(layer.data), size)); + return this->layer_to_write_attribute<float2>(layer, domain_size); case CD_PROP_FLOAT3: - return std::make_unique<ArrayWriteAttribute<float3>>( - domain, MutableSpan(static_cast<float3 *>(layer.data), size)); + return this->layer_to_write_attribute<float3>(layer, domain_size); case CD_PROP_INT32: - return std::make_unique<ArrayWriteAttribute<int>>( - domain, MutableSpan(static_cast<int *>(layer.data), size)); + return this->layer_to_write_attribute<int>(layer, domain_size); case CD_PROP_COLOR: - return std::make_unique<ArrayWriteAttribute<Color4f>>( - domain, MutableSpan(static_cast<Color4f *>(layer.data), size)); + return this->layer_to_write_attribute<Color4f>(layer, domain_size); case CD_PROP_BOOL: - return std::make_unique<ArrayWriteAttribute<bool>>( - domain, MutableSpan(static_cast<bool *>(layer.data), size)); + return this->layer_to_write_attribute<bool>(layer, domain_size); + default: + break; + } + } + return {}; + } + + bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final + { + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return false; + } + const int domain_size = component.attribute_domain_size(domain_); + for (const int i : IndexRange(custom_data->totlayer)) { + const CustomDataLayer &layer = custom_data->layers[i]; + if (this->type_is_supported((CustomDataType)layer.type) && layer.name == attribute_name) { + CustomData_free_layer(custom_data, layer.type, domain_size, i); + return true; } } + return false; } - return {}; + + bool try_create(GeometryComponent &component, + const StringRef attribute_name, + const AttributeDomain domain, + const CustomDataType data_type) const final + { + if (domain_ != domain) { + return false; + } + if (!this->type_is_supported(data_type)) { + return false; + } + CustomData *custom_data = custom_data_access_.get_custom_data(component); + if (custom_data == nullptr) { + return false; + } + for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) { + if (layer.name == attribute_name) { + return false; + } + } + const int domain_size = component.attribute_domain_size(domain_); + char attribute_name_c[MAX_NAME]; + attribute_name.copy(attribute_name_c); + CustomData_add_layer_named( + custom_data, data_type, CD_DEFAULT, nullptr, domain_size, attribute_name_c); + return true; + } + + void list(const GeometryComponent &component, Set<std::string> &r_names) const final + { + const CustomData *custom_data = custom_data_access_.get_const_custom_data(component); + if (custom_data == nullptr) { + return; + } + for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) { + if (this->type_is_supported((CustomDataType)layer.type)) { + r_names.add(layer.name); + } + } + } + + void supported_domains(Vector<AttributeDomain> &r_domains) const final + { + r_domains.append_non_duplicates(domain_); + } + + private: + template<typename T> + ReadAttributePtr layer_to_read_attribute(const CustomDataLayer &layer, + const int domain_size) const + { + return std::make_unique<ArrayReadAttribute<T>>( + domain_, Span(static_cast<const T *>(layer.data), domain_size)); + } + + template<typename T> + WriteAttributePtr layer_to_write_attribute(CustomDataLayer &layer, const int domain_size) const + { + return std::make_unique<ArrayWriteAttribute<T>>( + domain_, MutableSpan(static_cast<T *>(layer.data), domain_size)); + } + + bool type_is_supported(CustomDataType data_type) const + { + return ((1ULL << data_type) & supported_types_mask) != 0; + } +}; + +static Mesh *get_mesh_from_component_for_write(GeometryComponent &component) +{ + BLI_assert(component.type() == GeometryComponentType::Mesh); + MeshComponent &mesh_component = static_cast<MeshComponent &>(component); + return mesh_component.get_for_write(); } -/* Returns true when the layer was found and is deleted. */ -static bool delete_named_custom_data_layer(CustomData &custom_data, - const StringRef attribute_name, - const int size) +static const Mesh *get_mesh_from_component_for_read(const GeometryComponent &component) { - for (const int index : blender::IndexRange(custom_data.totlayer)) { - const CustomDataLayer &layer = custom_data.layers[index]; - if (layer.name == attribute_name) { - CustomData_free_layer(&custom_data, layer.type, size, index); + BLI_assert(component.type() == GeometryComponentType::Mesh); + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + return mesh_component.get_for_read(); +} + +/** + * This attribute provider makes uv maps available as float2 attributes. + */ +class MeshUVsAttributeProvider final : public DynamicAttributesProvider { + public: + ReadAttributePtr try_get_for_read(const GeometryComponent &component, + const StringRef attribute_name) const final + { + const Mesh *mesh = get_mesh_from_component_for_read(component); + if (mesh == nullptr) { + return {}; + } + for (const CustomDataLayer &layer : Span(mesh->ldata.layers, mesh->ldata.totlayer)) { + if (layer.type == CD_MLOOPUV) { + if (layer.name == attribute_name) { + return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, get_loop_uv>>( + ATTR_DOMAIN_CORNER, Span(static_cast<const MLoopUV *>(layer.data), mesh->totloop)); + } + } + } + return {}; + } + + WriteAttributePtr try_get_for_write(GeometryComponent &component, + const StringRef attribute_name) const final + { + Mesh *mesh = get_mesh_from_component_for_write(component); + if (mesh == nullptr) { + return {}; + } + for (CustomDataLayer &layer : MutableSpan(mesh->ldata.layers, mesh->ldata.totlayer)) { + if (layer.type == CD_MLOOPUV) { + if (layer.name == attribute_name) { + void *data_old = layer.data; + void *data_new = CustomData_duplicate_referenced_layer_named( + &mesh->ldata, CD_MLOOPUV, layer.name, mesh->totloop); + if (data_old != data_new) { + BKE_mesh_update_customdata_pointers(mesh, false); + } + return std::make_unique< + DerivedArrayWriteAttribute<MLoopUV, float2, get_loop_uv, set_loop_uv>>( + ATTR_DOMAIN_CORNER, MutableSpan(static_cast<MLoopUV *>(layer.data), mesh->totloop)); + } + } + } + return {}; + } + + bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final + { + Mesh *mesh = get_mesh_from_component_for_write(component); + if (mesh == nullptr) { + return false; + } + for (const int i : IndexRange(mesh->ldata.totlayer)) { + const CustomDataLayer &layer = mesh->ldata.layers[i]; + if (layer.type == CD_MLOOPUV && layer.name == attribute_name) { + CustomData_free_layer(&mesh->ldata, CD_MLOOPUV, mesh->totloop, i); + return true; + } + } + return false; + } + + void list(const GeometryComponent &component, Set<std::string> &r_names) const final + { + const Mesh *mesh = get_mesh_from_component_for_read(component); + if (mesh == nullptr) { + return; + } + for (const CustomDataLayer &layer : Span(mesh->ldata.layers, mesh->ldata.totlayer)) { + if (layer.type == CD_MLOOPUV) { + r_names.add(layer.name); + } + } + } + + void supported_domains(Vector<AttributeDomain> &r_domains) const final + { + r_domains.append_non_duplicates(ATTR_DOMAIN_CORNER); + } + + private: + static float2 get_loop_uv(const MLoopUV &uv) + { + return float2(uv.uv); + } + + static void set_loop_uv(MLoopUV &uv, const float2 &co) + { + copy_v2_v2(uv.uv, co); + } +}; + +/** + * This provider makes vertex groups available as float attributes. + */ +class VertexGroupsAttributeProvider final : public DynamicAttributesProvider { + public: + ReadAttributePtr try_get_for_read(const GeometryComponent &component, + const StringRef attribute_name) const final + { + BLI_assert(component.type() == GeometryComponentType::Mesh); + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + const Mesh *mesh = mesh_component.get_for_read(); + const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as( + attribute_name, -1); + if (vertex_group_index < 0) { + return {}; + } + if (mesh == nullptr || mesh->dvert == nullptr) { + static const float default_value = 0.0f; + return std::make_unique<ConstantReadAttribute>( + ATTR_DOMAIN_POINT, mesh->totvert, CPPType::get<float>(), &default_value); + } + return std::make_unique<VertexWeightReadAttribute>( + mesh->dvert, mesh->totvert, vertex_group_index); + } + + WriteAttributePtr try_get_for_write(GeometryComponent &component, + const StringRef attribute_name) const final + { + BLI_assert(component.type() == GeometryComponentType::Mesh); + MeshComponent &mesh_component = static_cast<MeshComponent &>(component); + Mesh *mesh = mesh_component.get_for_write(); + if (mesh == nullptr) { + return {}; + } + const int vertex_group_index = mesh_component.vertex_group_names().lookup_default_as( + attribute_name, -1); + if (vertex_group_index < 0) { + return {}; + } + if (mesh->dvert == nullptr) { + BKE_object_defgroup_data_create(&mesh->id); + } + else { + /* Copy the data layer if it is shared with some other mesh. */ + mesh->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( + &mesh->vdata, CD_MDEFORMVERT, mesh->totvert); + } + return std::make_unique<blender::bke::VertexWeightWriteAttribute>( + mesh->dvert, mesh->totvert, vertex_group_index); + } + + bool try_delete(GeometryComponent &component, const StringRef attribute_name) const final + { + BLI_assert(component.type() == GeometryComponentType::Mesh); + MeshComponent &mesh_component = static_cast<MeshComponent &>(component); + + const int vertex_group_index = mesh_component.vertex_group_names().pop_default_as( + attribute_name, -1); + if (vertex_group_index < 0) { + return false; + } + Mesh *mesh = mesh_component.get_for_write(); + if (mesh == nullptr) { + return true; + } + if (mesh->dvert == nullptr) { return true; } + for (MDeformVert &dvert : MutableSpan(mesh->dvert, mesh->totvert)) { + MDeformWeight *weight = BKE_defvert_find_index(&dvert, vertex_group_index); + BKE_defvert_remove_group(&dvert, weight); + } + return true; } - return false; + + void list(const GeometryComponent &component, Set<std::string> &r_names) const final + { + BLI_assert(component.type() == GeometryComponentType::Mesh); + const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component); + mesh_component.vertex_group_names().foreach_item( + [&](StringRef name, const int vertex_group_index) { + if (vertex_group_index >= 0) { + r_names.add(name); + } + }); + } + + void supported_domains(Vector<AttributeDomain> &r_domains) const final + { + r_domains.append_non_duplicates(ATTR_DOMAIN_POINT); + } +}; + +/** + * This is a container for multiple attribute providers that are used by one geometry component + * type (e.g. there is a set of attribute providers for mesh components). + */ +class ComponentAttributeProviders { + private: + /** + * Builtin attribute providers are identified by their name. Attribute names that are in this + * map will only be accessed using builtin attribute providers. Therefore, these providers have + * higher priority when an attribute name is looked up. Usually, that means that builtin + * providers are checked before dynamic ones. + */ + Map<std::string, const BuiltinAttributeProvider *> builtin_attribute_providers_; + /** + * An ordered list of dynamic attribute providers. The order is important because that is order + * in which they are checked when an attribute is looked up. + */ + Vector<const DynamicAttributesProvider *> dynamic_attribute_providers_; + /** + * All the domains that are supported by at least one of the providers above. + */ + Vector<AttributeDomain> supported_domains_; + + public: + ComponentAttributeProviders(Span<const BuiltinAttributeProvider *> builtin_attribute_providers, + Span<const DynamicAttributesProvider *> dynamic_attribute_providers) + : dynamic_attribute_providers_(dynamic_attribute_providers) + { + Set<AttributeDomain> domains; + for (const BuiltinAttributeProvider *provider : builtin_attribute_providers) { + /* Use #add_new to make sure that no two builtin attributes have the same name. */ + builtin_attribute_providers_.add_new(provider->name(), provider); + supported_domains_.append_non_duplicates(provider->domain()); + } + for (const DynamicAttributesProvider *provider : dynamic_attribute_providers) { + provider->supported_domains(supported_domains_); + } + } + + const Map<std::string, const BuiltinAttributeProvider *> &builtin_attribute_providers() const + { + return builtin_attribute_providers_; + } + + Span<const DynamicAttributesProvider *> dynamic_attribute_providers() const + { + return dynamic_attribute_providers_; + } + + Span<AttributeDomain> supported_domains() const + { + return supported_domains_; + } +}; + +static float3 get_vertex_position(const MVert &vert) +{ + return float3(vert.co); +} + +static void set_vertex_position(MVert &vert, const float3 &position) +{ + copy_v3_v3(vert.co, position); +} + +static ReadAttributePtr make_vertex_position_read_attribute(const void *data, + const int domain_size) +{ + return std::make_unique<DerivedArrayReadAttribute<MVert, float3, get_vertex_position>>( + ATTR_DOMAIN_POINT, Span<MVert>((const MVert *)data, domain_size)); } -static void get_custom_data_layer_attribute_names(const CustomData &custom_data, - const GeometryComponent &component, - const AttributeDomain domain, - Set<std::string> &r_names) +static WriteAttributePtr make_vertex_position_write_attribute(void *data, const int domain_size) { - for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) { - if (component.attribute_domain_with_type_supported(domain, - static_cast<CustomDataType>(layer.type))) { - r_names.add(layer.name); + return std::make_unique< + DerivedArrayWriteAttribute<MVert, float3, get_vertex_position, set_vertex_position>>( + ATTR_DOMAIN_POINT, MutableSpan<MVert>((MVert *)data, domain_size)); +} + +template<typename T, AttributeDomain Domain> +static ReadAttributePtr make_array_read_attribute(const void *data, const int domain_size) +{ + return std::make_unique<ArrayReadAttribute<T>>(Domain, Span<T>((const T *)data, domain_size)); +} + +template<typename T, AttributeDomain Domain> +static WriteAttributePtr make_array_write_attribute(void *data, const int domain_size) +{ + return std::make_unique<ArrayWriteAttribute<T>>(Domain, MutableSpan<T>((T *)data, domain_size)); +} + +/** + * In this function all the attribute providers for a mesh component are created. Most data in this + * function is statically allocated, because it does not change over time. + */ +static ComponentAttributeProviders create_attribute_providers_for_mesh() +{ + static auto update_custom_data_pointers = [](GeometryComponent &component) { + Mesh *mesh = get_mesh_from_component_for_write(component); + if (mesh != nullptr) { + BKE_mesh_update_customdata_pointers(mesh, false); } - } + }; + +#define MAKE_MUTABLE_CUSTOM_DATA_GETTER(NAME) \ + [](GeometryComponent &component) -> CustomData * { \ + Mesh *mesh = get_mesh_from_component_for_write(component); \ + return mesh ? &mesh->NAME : nullptr; \ + } +#define MAKE_CONST_CUSTOM_DATA_GETTER(NAME) \ + [](const GeometryComponent &component) -> const CustomData * { \ + const Mesh *mesh = get_mesh_from_component_for_read(component); \ + return mesh ? &mesh->NAME : nullptr; \ + } + + static CustomDataAccessInfo corner_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(ldata), + MAKE_CONST_CUSTOM_DATA_GETTER(ldata), + update_custom_data_pointers}; + static CustomDataAccessInfo point_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(vdata), + MAKE_CONST_CUSTOM_DATA_GETTER(vdata), + update_custom_data_pointers}; + static CustomDataAccessInfo edge_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(edata), + MAKE_CONST_CUSTOM_DATA_GETTER(edata), + update_custom_data_pointers}; + static CustomDataAccessInfo polygon_access = {MAKE_MUTABLE_CUSTOM_DATA_GETTER(pdata), + MAKE_CONST_CUSTOM_DATA_GETTER(pdata), + update_custom_data_pointers}; + +#undef MAKE_CONST_CUSTOM_DATA_GETTER +#undef MAKE_MUTABLE_CUSTOM_DATA_GETTER + + static BuiltinCustomDataLayerProvider position("position", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT3, + CD_MVERT, + BuiltinAttributeProvider::NonCreatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::NonDeletable, + point_access, + make_vertex_position_read_attribute, + make_vertex_position_write_attribute); + static MeshUVsAttributeProvider uvs; + static VertexGroupsAttributeProvider vertex_groups; + static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access); + static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access); + static CustomDataAttributeProvider edge_custom_data(ATTR_DOMAIN_EDGE, edge_access); + static CustomDataAttributeProvider polygon_custom_data(ATTR_DOMAIN_POLYGON, polygon_access); + + return ComponentAttributeProviders({&position}, + {&uvs, + &corner_custom_data, + &vertex_groups, + &point_custom_data, + &edge_custom_data, + &polygon_custom_data}); } -/** \} */ +/** + * In this function all the attribute providers for a point cloud component are created. Most data + * in this function is statically allocated, because it does not change over time. + */ +static ComponentAttributeProviders create_attribute_providers_for_point_cloud() +{ + static auto update_custom_data_pointers = [](GeometryComponent &component) { + PointCloudComponent &pointcloud_component = static_cast<PointCloudComponent &>(component); + PointCloud *pointcloud = pointcloud_component.get_for_write(); + if (pointcloud != nullptr) { + BKE_pointcloud_update_customdata_pointers(pointcloud); + } + }; + static CustomDataAccessInfo point_access = { + [](GeometryComponent &component) -> CustomData * { + PointCloudComponent &pointcloud_component = static_cast<PointCloudComponent &>(component); + PointCloud *pointcloud = pointcloud_component.get_for_write(); + return pointcloud ? &pointcloud->pdata : nullptr; + }, + [](const GeometryComponent &component) -> const CustomData * { + const PointCloudComponent &pointcloud_component = static_cast<const PointCloudComponent &>( + component); + const PointCloud *pointcloud = pointcloud_component.get_for_read(); + return pointcloud ? &pointcloud->pdata : nullptr; + }, + update_custom_data_pointers}; + + static BuiltinCustomDataLayerProvider position( + "position", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT3, + CD_PROP_FLOAT3, + BuiltinAttributeProvider::NonCreatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::NonDeletable, + point_access, + make_array_read_attribute<float3, ATTR_DOMAIN_POINT>, + make_array_write_attribute<float3, ATTR_DOMAIN_POINT>); + static BuiltinCustomDataLayerProvider radius( + "radius", + ATTR_DOMAIN_POINT, + CD_PROP_FLOAT, + CD_PROP_FLOAT, + BuiltinAttributeProvider::Creatable, + BuiltinAttributeProvider::Writable, + BuiltinAttributeProvider::Deletable, + point_access, + make_array_read_attribute<float, ATTR_DOMAIN_POINT>, + make_array_write_attribute<float, ATTR_DOMAIN_POINT>); + static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access); + return ComponentAttributeProviders({&position, &radius}, {&point_custom_data}); +} + +} // namespace blender::bke /* -------------------------------------------------------------------- */ /** \name Geometry Component * \{ */ -bool GeometryComponent::attribute_domain_supported(const AttributeDomain UNUSED(domain)) const +const blender::bke::ComponentAttributeProviders *GeometryComponent::get_attribute_providers() const { - return false; + return nullptr; } -bool GeometryComponent::attribute_domain_with_type_supported( - const AttributeDomain UNUSED(domain), const CustomDataType UNUSED(data_type)) const +bool GeometryComponent::attribute_domain_supported(const AttributeDomain domain) const { - return false; + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return false; + } + return providers->supported_domains().contains(domain); } int GeometryComponent::attribute_domain_size(const AttributeDomain UNUSED(domain)) const @@ -627,47 +1345,127 @@ int GeometryComponent::attribute_domain_size(const AttributeDomain UNUSED(domain return 0; } -bool GeometryComponent::attribute_is_builtin(const StringRef UNUSED(attribute_name)) const -{ - return true; -} - ReadAttributePtr GeometryComponent::attribute_try_get_for_read( - const StringRef UNUSED(attribute_name)) const + const StringRef attribute_name) const { + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return {}; + } + const BuiltinAttributeProvider *builtin_provider = + providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr); + if (builtin_provider != nullptr) { + return builtin_provider->try_get_for_read(*this); + } + for (const DynamicAttributesProvider *dynamic_provider : + providers->dynamic_attribute_providers()) { + ReadAttributePtr attribute = dynamic_provider->try_get_for_read(*this, attribute_name); + if (attribute) { + return attribute; + } + } return {}; } -ReadAttributePtr GeometryComponent::attribute_try_adapt_domain(ReadAttributePtr attribute, - const AttributeDomain domain) const +ReadAttributePtr GeometryComponent::attribute_try_adapt_domain( + ReadAttributePtr attribute, const AttributeDomain new_domain) const { - if (attribute && attribute->domain() == domain) { + if (attribute && attribute->domain() == new_domain) { return attribute; } return {}; } -WriteAttributePtr GeometryComponent::attribute_try_get_for_write( - const StringRef UNUSED(attribute_name)) +WriteAttributePtr GeometryComponent::attribute_try_get_for_write(const StringRef attribute_name) { + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return {}; + } + const BuiltinAttributeProvider *builtin_provider = + providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr); + if (builtin_provider != nullptr) { + return builtin_provider->try_get_for_write(*this); + } + for (const DynamicAttributesProvider *dynamic_provider : + providers->dynamic_attribute_providers()) { + WriteAttributePtr attribute = dynamic_provider->try_get_for_write(*this, attribute_name); + if (attribute) { + return attribute; + } + } return {}; } -bool GeometryComponent::attribute_try_delete(const StringRef UNUSED(attribute_name)) +bool GeometryComponent::attribute_try_delete(const StringRef attribute_name) { - return false; + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return {}; + } + const BuiltinAttributeProvider *builtin_provider = + providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr); + if (builtin_provider != nullptr) { + return builtin_provider->try_delete(*this); + } + bool success = false; + for (const DynamicAttributesProvider *dynamic_provider : + providers->dynamic_attribute_providers()) { + success = dynamic_provider->try_delete(*this, attribute_name) || success; + } + return success; } -bool GeometryComponent::attribute_try_create(const StringRef UNUSED(attribute_name), - const AttributeDomain UNUSED(domain), - const CustomDataType UNUSED(data_type)) +bool GeometryComponent::attribute_try_create(const StringRef attribute_name, + const AttributeDomain domain, + const CustomDataType data_type) { + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return {}; + } + const BuiltinAttributeProvider *builtin_provider = + providers->builtin_attribute_providers().lookup_default_as(attribute_name, nullptr); + if (builtin_provider != nullptr) { + if (builtin_provider->domain() != domain) { + return false; + } + if (builtin_provider->data_type() != data_type) { + return false; + } + return builtin_provider->try_create(*this); + } + for (const DynamicAttributesProvider *dynamic_provider : + providers->dynamic_attribute_providers()) { + if (dynamic_provider->try_create(*this, attribute_name, domain, data_type)) { + return true; + } + } return false; } Set<std::string> GeometryComponent::attribute_names() const { - return {}; + using namespace blender::bke; + const ComponentAttributeProviders *providers = this->get_attribute_providers(); + if (providers == nullptr) { + return {}; + } + Set<std::string> names; + for (const BuiltinAttributeProvider *provider : + providers->builtin_attribute_providers().values()) { + if (provider->exists(*this)) { + names.add_new(provider->name()); + } + } + for (const DynamicAttributesProvider *provider : providers->dynamic_attribute_providers()) { + provider->list(*this, names); + } + return names; } bool GeometryComponent::attribute_exists(const blender::StringRef attribute_name) const @@ -701,10 +1499,6 @@ ReadAttributePtr GeometryComponent::attribute_try_get_for_read( const AttributeDomain domain, const CustomDataType data_type) const { - if (!this->attribute_domain_with_type_supported(domain, data_type)) { - return {}; - } - ReadAttributePtr attribute = this->attribute_try_get_for_read(attribute_name); if (!attribute) { return {}; @@ -756,8 +1550,6 @@ ReadAttributePtr GeometryComponent::attribute_get_for_read(const StringRef attri const CustomDataType data_type, const void *default_value) const { - BLI_assert(this->attribute_domain_with_type_supported(domain, data_type)); - ReadAttributePtr attribute = this->attribute_try_get_for_read(attribute_name, domain, data_type); if (attribute) { return attribute; @@ -817,8 +1609,6 @@ OutputAttributePtr GeometryComponent::attribute_try_get_for_output(const StringR const CustomDataType data_type, const void *default_value) { - BLI_assert(this->attribute_domain_with_type_supported(domain, data_type)); - const blender::fn::CPPType *cpp_type = blender::bke::custom_data_type_to_cpp_type(data_type); BLI_assert(cpp_type != nullptr); @@ -946,21 +1736,12 @@ void OutputAttributePtr::apply_span_and_save() /** \name Point Cloud Component * \{ */ -bool PointCloudComponent::attribute_domain_supported(const AttributeDomain domain) const +const blender::bke::ComponentAttributeProviders *PointCloudComponent::get_attribute_providers() + const { - return domain == ATTR_DOMAIN_POINT; -} - -bool PointCloudComponent::attribute_domain_with_type_supported( - const AttributeDomain domain, const CustomDataType data_type) const -{ - return domain == ATTR_DOMAIN_POINT && ELEM(data_type, - CD_PROP_BOOL, - CD_PROP_FLOAT, - CD_PROP_FLOAT2, - CD_PROP_FLOAT3, - CD_PROP_INT32, - CD_PROP_COLOR); + static blender::bke::ComponentAttributeProviders providers = + blender::bke::create_attribute_providers_for_point_cloud(); + return &providers; } int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) const @@ -973,119 +1754,17 @@ int PointCloudComponent::attribute_domain_size(const AttributeDomain domain) con return pointcloud_->totpoint; } -bool PointCloudComponent::attribute_is_builtin(const StringRef attribute_name) const -{ - return attribute_name == "position"; -} - -ReadAttributePtr PointCloudComponent::attribute_try_get_for_read( - const StringRef attribute_name) const -{ - if (pointcloud_ == nullptr) { - return {}; - } - - return read_attribute_from_custom_data( - pointcloud_->pdata, pointcloud_->totpoint, attribute_name, ATTR_DOMAIN_POINT); -} - -WriteAttributePtr PointCloudComponent::attribute_try_get_for_write(const StringRef attribute_name) -{ - PointCloud *pointcloud = this->get_for_write(); - if (pointcloud == nullptr) { - return {}; - } - - return write_attribute_from_custom_data( - pointcloud->pdata, pointcloud->totpoint, attribute_name, ATTR_DOMAIN_POINT, [&]() { - BKE_pointcloud_update_customdata_pointers(pointcloud); - }); -} - -bool PointCloudComponent::attribute_try_delete(const StringRef attribute_name) -{ - if (this->attribute_is_builtin(attribute_name)) { - return false; - } - PointCloud *pointcloud = this->get_for_write(); - if (pointcloud == nullptr) { - return false; - } - delete_named_custom_data_layer(pointcloud->pdata, attribute_name, pointcloud->totpoint); - return true; -} - -static bool custom_data_has_layer_with_name(const CustomData &custom_data, const StringRef name) -{ - for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) { - if (layer.name == name) { - return true; - } - } - return false; -} - -bool PointCloudComponent::attribute_try_create(const StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type) -{ - if (this->attribute_is_builtin(attribute_name)) { - return false; - } - if (!this->attribute_domain_with_type_supported(domain, data_type)) { - return false; - } - PointCloud *pointcloud = this->get_for_write(); - if (pointcloud == nullptr) { - return false; - } - if (custom_data_has_layer_with_name(pointcloud->pdata, attribute_name)) { - return false; - } - - char attribute_name_c[MAX_NAME]; - attribute_name.copy(attribute_name_c); - CustomData_add_layer_named( - &pointcloud->pdata, data_type, CD_DEFAULT, nullptr, pointcloud_->totpoint, attribute_name_c); - return true; -} - -Set<std::string> PointCloudComponent::attribute_names() const -{ - if (pointcloud_ == nullptr) { - return {}; - } - - Set<std::string> names; - get_custom_data_layer_attribute_names(pointcloud_->pdata, *this, ATTR_DOMAIN_POINT, names); - return names; -} - /** \} */ /* -------------------------------------------------------------------- */ /** \name Mesh Component * \{ */ -bool MeshComponent::attribute_domain_supported(const AttributeDomain domain) const +const blender::bke::ComponentAttributeProviders *MeshComponent::get_attribute_providers() const { - return ELEM( - domain, ATTR_DOMAIN_CORNER, ATTR_DOMAIN_POINT, ATTR_DOMAIN_EDGE, ATTR_DOMAIN_POLYGON); -} - -bool MeshComponent::attribute_domain_with_type_supported(const AttributeDomain domain, - const CustomDataType data_type) const -{ - if (!this->attribute_domain_supported(domain)) { - return false; - } - return ELEM(data_type, - CD_PROP_BOOL, - CD_PROP_FLOAT, - CD_PROP_FLOAT2, - CD_PROP_FLOAT3, - CD_PROP_INT32, - CD_PROP_COLOR); + static blender::bke::ComponentAttributeProviders providers = + blender::bke::create_attribute_providers_for_mesh(); + return &providers; } int MeshComponent::attribute_domain_size(const AttributeDomain domain) const @@ -1110,228 +1789,75 @@ int MeshComponent::attribute_domain_size(const AttributeDomain domain) const return 0; } -bool MeshComponent::attribute_is_builtin(const StringRef attribute_name) const -{ - return attribute_name == "position"; -} +namespace blender::bke { -ReadAttributePtr MeshComponent::attribute_try_get_for_read(const StringRef attribute_name) const +template<typename T> +void adapt_mesh_domain_corner_to_point_impl(const Mesh &mesh, + const TypedReadAttribute<T> &attribute, + MutableSpan<T> r_values) { - if (mesh_ == nullptr) { - return {}; - } - - if (attribute_name == "position") { - auto get_vertex_position = [](const MVert &vert) { return float3(vert.co); }; - return std::make_unique< - blender::bke::DerivedArrayReadAttribute<MVert, float3, decltype(get_vertex_position)>>( - ATTR_DOMAIN_POINT, blender::Span(mesh_->mvert, mesh_->totvert), get_vertex_position); - } - - ReadAttributePtr corner_attribute = read_attribute_from_custom_data( - mesh_->ldata, mesh_->totloop, attribute_name, ATTR_DOMAIN_CORNER); - if (corner_attribute) { - return corner_attribute; - } - - const int vertex_group_index = vertex_group_names_.lookup_default(attribute_name, -1); - if (vertex_group_index >= 0) { - return std::make_unique<blender::bke::VertexWeightReadAttribute>( - mesh_->dvert, mesh_->totvert, vertex_group_index); - } + BLI_assert(r_values.size() == mesh.totvert); + attribute_math::DefaultMixer<T> mixer(r_values); - ReadAttributePtr vertex_attribute = read_attribute_from_custom_data( - mesh_->vdata, mesh_->totvert, attribute_name, ATTR_DOMAIN_POINT); - if (vertex_attribute) { - return vertex_attribute; + for (const int loop_index : IndexRange(mesh.totloop)) { + const T value = attribute[loop_index]; + const MLoop &loop = mesh.mloop[loop_index]; + const int point_index = loop.v; + mixer.mix_in(point_index, value); } - - ReadAttributePtr edge_attribute = read_attribute_from_custom_data( - mesh_->edata, mesh_->totedge, attribute_name, ATTR_DOMAIN_EDGE); - if (edge_attribute) { - return edge_attribute; - } - - ReadAttributePtr polygon_attribute = read_attribute_from_custom_data( - mesh_->pdata, mesh_->totpoly, attribute_name, ATTR_DOMAIN_POLYGON); - if (polygon_attribute) { - return polygon_attribute; - } - - return {}; + mixer.finalize(); } -WriteAttributePtr MeshComponent::attribute_try_get_for_write(const StringRef attribute_name) +static ReadAttributePtr adapt_mesh_domain_corner_to_point(const Mesh &mesh, + ReadAttributePtr attribute) { - Mesh *mesh = this->get_for_write(); - if (mesh == nullptr) { - return {}; - } - - const std::function<void()> update_mesh_pointers = [&]() { - BKE_mesh_update_customdata_pointers(mesh, false); - }; - - if (attribute_name == "position") { - CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert); - update_mesh_pointers(); - - auto get_vertex_position = [](const MVert &vert) { return float3(vert.co); }; - auto set_vertex_position = [](MVert &vert, const float3 &co) { copy_v3_v3(vert.co, co); }; - return std::make_unique< - blender::bke::DerivedArrayWriteAttribute<MVert, - float3, - decltype(get_vertex_position), - decltype(set_vertex_position)>>( - ATTR_DOMAIN_POINT, - blender::MutableSpan(mesh_->mvert, mesh_->totvert), - get_vertex_position, - set_vertex_position); - } - - WriteAttributePtr corner_attribute = write_attribute_from_custom_data( - mesh_->ldata, mesh_->totloop, attribute_name, ATTR_DOMAIN_CORNER, update_mesh_pointers); - if (corner_attribute) { - return corner_attribute; - } - - const int vertex_group_index = vertex_group_names_.lookup_default_as(attribute_name, -1); - if (vertex_group_index >= 0) { - if (mesh_->dvert == nullptr) { - BKE_object_defgroup_data_create(&mesh_->id); + ReadAttributePtr new_attribute; + const CustomDataType data_type = attribute->custom_data_type(); + attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) { + /* We compute all interpolated values at once, because for this interpolation, one has to + * iterate over all loops anyway. */ + Array<T> values(mesh.totvert); + adapt_mesh_domain_corner_to_point_impl<T>(mesh, *attribute, values); + new_attribute = std::make_unique<OwnedArrayReadAttribute<T>>(ATTR_DOMAIN_POINT, + std::move(values)); } - else { - /* Copy the data layer if it is shared with some other mesh. */ - mesh_->dvert = (MDeformVert *)CustomData_duplicate_referenced_layer( - &mesh_->vdata, CD_MDEFORMVERT, mesh_->totvert); - } - return std::make_unique<blender::bke::VertexWeightWriteAttribute>( - mesh_->dvert, mesh_->totvert, vertex_group_index); - } - - WriteAttributePtr vertex_attribute = write_attribute_from_custom_data( - mesh_->vdata, mesh_->totvert, attribute_name, ATTR_DOMAIN_POINT, update_mesh_pointers); - if (vertex_attribute) { - return vertex_attribute; - } - - WriteAttributePtr edge_attribute = write_attribute_from_custom_data( - mesh_->edata, mesh_->totedge, attribute_name, ATTR_DOMAIN_EDGE, update_mesh_pointers); - if (edge_attribute) { - return edge_attribute; - } - - WriteAttributePtr polygon_attribute = write_attribute_from_custom_data( - mesh_->pdata, mesh_->totpoly, attribute_name, ATTR_DOMAIN_POLYGON, update_mesh_pointers); - if (polygon_attribute) { - return polygon_attribute; - } - - return {}; + }); + return new_attribute; } -bool MeshComponent::attribute_try_delete(const StringRef attribute_name) -{ - if (this->attribute_is_builtin(attribute_name)) { - return false; - } - Mesh *mesh = this->get_for_write(); - if (mesh == nullptr) { - return false; - } - - delete_named_custom_data_layer(mesh_->ldata, attribute_name, mesh_->totloop); - delete_named_custom_data_layer(mesh_->vdata, attribute_name, mesh_->totvert); - delete_named_custom_data_layer(mesh_->edata, attribute_name, mesh_->totedge); - delete_named_custom_data_layer(mesh_->pdata, attribute_name, mesh_->totpoly); - - const int vertex_group_index = vertex_group_names_.lookup_default_as(attribute_name, -1); - if (vertex_group_index != -1) { - for (MDeformVert &dvert : blender::MutableSpan(mesh_->dvert, mesh_->totvert)) { - MDeformWeight *weight = BKE_defvert_find_index(&dvert, vertex_group_index); - BKE_defvert_remove_group(&dvert, weight); - } - vertex_group_names_.remove_as(attribute_name); - } - - return true; -} +} // namespace blender::bke -bool MeshComponent::attribute_try_create(const StringRef attribute_name, - const AttributeDomain domain, - const CustomDataType data_type) +ReadAttributePtr MeshComponent::attribute_try_adapt_domain(ReadAttributePtr attribute, + const AttributeDomain new_domain) const { - if (this->attribute_is_builtin(attribute_name)) { - return false; + if (!attribute) { + return {}; } - if (!this->attribute_domain_with_type_supported(domain, data_type)) { - return false; + if (attribute->size() == 0) { + return {}; } - Mesh *mesh = this->get_for_write(); - if (mesh == nullptr) { - return false; + const AttributeDomain old_domain = attribute->domain(); + if (old_domain == new_domain) { + return attribute; } - char attribute_name_c[MAX_NAME]; - attribute_name.copy(attribute_name_c); - - switch (domain) { + switch (old_domain) { case ATTR_DOMAIN_CORNER: { - if (custom_data_has_layer_with_name(mesh->ldata, attribute_name)) { - return false; - } - CustomData_add_layer_named( - &mesh->ldata, data_type, CD_DEFAULT, nullptr, mesh->totloop, attribute_name_c); - return true; - } - case ATTR_DOMAIN_POINT: { - if (custom_data_has_layer_with_name(mesh->vdata, attribute_name)) { - return false; - } - if (vertex_group_names_.contains_as(attribute_name)) { - return false; - } - CustomData_add_layer_named( - &mesh->vdata, data_type, CD_DEFAULT, nullptr, mesh->totvert, attribute_name_c); - return true; - } - case ATTR_DOMAIN_EDGE: { - if (custom_data_has_layer_with_name(mesh->edata, attribute_name)) { - return false; - } - CustomData_add_layer_named( - &mesh->edata, data_type, CD_DEFAULT, nullptr, mesh->totedge, attribute_name_c); - return true; - } - case ATTR_DOMAIN_POLYGON: { - if (custom_data_has_layer_with_name(mesh->pdata, attribute_name)) { - return false; + switch (new_domain) { + case ATTR_DOMAIN_POINT: + return blender::bke::adapt_mesh_domain_corner_to_point(*mesh_, std::move(attribute)); + default: + break; } - CustomData_add_layer_named( - &mesh->pdata, data_type, CD_DEFAULT, nullptr, mesh->totpoly, attribute_name_c); - return true; + break; } default: - return false; - } -} - -Set<std::string> MeshComponent::attribute_names() const -{ - if (mesh_ == nullptr) { - return {}; + break; } - Set<std::string> names; - names.add("position"); - for (StringRef name : vertex_group_names_.keys()) { - names.add(name); - } - get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_CORNER, names); - get_custom_data_layer_attribute_names(mesh_->vdata, *this, ATTR_DOMAIN_POINT, names); - get_custom_data_layer_attribute_names(mesh_->edata, *this, ATTR_DOMAIN_EDGE, names); - get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_POLYGON, names); - return names; + return {}; } /** \} */ diff --git a/source/blender/blenkernel/intern/attribute_math.cc b/source/blender/blenkernel/intern/attribute_math.cc new file mode 100644 index 00000000000..4ff3a6ceff5 --- /dev/null +++ b/source/blender/blenkernel/intern/attribute_math.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BKE_attribute_math.hh" + +namespace blender::attribute_math { + +Color4fMixer::Color4fMixer(MutableSpan<Color4f> output_buffer, Color4f default_color) + : buffer_(output_buffer), + default_color_(default_color), + total_weights_(output_buffer.size(), 0.0f) +{ + buffer_.fill(Color4f(0, 0, 0, 0)); +} + +void Color4fMixer::mix_in(const int64_t index, const Color4f &color, const float weight) +{ + BLI_assert(weight >= 0.0f); + Color4f &output_color = buffer_[index]; + output_color.r += color.r * weight; + output_color.g += color.g * weight; + output_color.b += color.b * weight; + output_color.a += color.a * weight; + total_weights_[index] += weight; +} + +void Color4fMixer::finalize() +{ + for (const int64_t i : buffer_.index_range()) { + const float weight = total_weights_[i]; + Color4f &output_color = buffer_[i]; + if (weight > 0.0f) { + const float weight_inv = 1.0f / weight; + output_color.r *= weight_inv; + output_color.g *= weight_inv; + output_color.b *= weight_inv; + output_color.a *= weight_inv; + } + else { + output_color = default_color_; + } + } +} + +} // namespace blender::attribute_math diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index 9e061b1ac69..d826aaf24e3 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -48,6 +48,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_undo_system.h" #include "BLO_readfile.h" #include "BLO_undofile.h" @@ -62,7 +63,7 @@ #define UNDO_DISK 0 bool BKE_memfile_undo_decode(MemFileUndoData *mfu, - const int undo_direction, + const eUndoStepDir undo_direction, const bool use_old_bmain_data, bContext *C) { @@ -80,7 +81,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, } else { struct BlendFileReadParams params = {0}; - params.undo_direction = undo_direction > 0 ? 1 : -1; + params.undo_direction = undo_direction; if (!use_old_bmain_data) { params.skip_flags |= BLO_READ_SKIP_UNDO_OLD_MAIN; } diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 0855db1a943..32710c4fa60 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -57,6 +57,7 @@ #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_studiolight.h" +#include "BKE_undo_system.h" #include "BKE_workspace.h" #include "BLO_readfile.h" @@ -148,7 +149,7 @@ static void setup_app_data(bContext *C, LOAD_UNDO, } mode; - if (params->undo_direction != 0) { + if (params->undo_direction != STEP_INVALID) { BLI_assert(bfd->curscene != NULL); mode = LOAD_UNDO; } @@ -647,6 +648,10 @@ UserDef *BKE_blendfile_userdef_from_defaults(void) BKE_studiolight_default(userdef->light_param, userdef->light_ambient); BKE_preferences_asset_library_default_add(userdef); + /* Enable asset browser features by default for alpha testing. + * BLO_sanitize_experimental_features_userpref_blend() will disable it again for non-alpha + * builds. */ + userdef->experimental.use_asset_browser = true; return userdef; } diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 762ced7dc5f..2ad0ac950d0 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -23,7 +23,7 @@ * - passing output paths to the visitor?, like render out. * - passing sequence strips with many images. * - passing directory paths - visitors don't know which path is a dir or a file. - * */ + */ #include <sys/stat.h> diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 9a954a89cad..59ff59b82e0 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -375,7 +375,7 @@ static int brush_undo_preserve_cb(LibraryIDLinkCallbackData *cb_data) static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) { - /* Whole Brush is preserved accross undo's. */ + /* Whole Brush is preserved across undo-steps. */ BKE_lib_id_swap(NULL, id_new, id_old); /* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid. @@ -410,6 +410,8 @@ IDTypeInfo IDType_ID_BR = { .blend_read_expand = brush_blend_read_expand, .blend_read_undo_preserve = brush_undo_preserve, + + .lib_override_apply_post = NULL, }; static RNG *brush_rng; @@ -973,12 +975,12 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) break; } case GP_BRUSH_PRESET_FILL_AREA: { - brush->size = 20.0f; + brush->size = 5.0f; brush->gpencil_settings->fill_leak = 3; brush->gpencil_settings->fill_threshold = 0.1f; brush->gpencil_settings->fill_simplylvl = 1; - brush->gpencil_settings->fill_factor = 1; + brush->gpencil_settings->fill_factor = 1.0f; brush->gpencil_settings->draw_strength = 1.0f; brush->gpencil_settings->hardeness = 1.0f; @@ -987,6 +989,8 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->draw_smoothlvl = 1; brush->gpencil_settings->draw_subdivide = 1; + brush->gpencil_settings->flag |= GP_BRUSH_FILL_SHOW_EXTENDLINES; + brush->gpencil_settings->icon_id = GP_BRUSH_ICON_FILL; brush->gpencil_tool = GPAINT_TOOL_FILL; brush->gpencil_settings->vertex_mode = GPPAINT_MODE_FILL; diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index fd5cb33f02d..790fb128c7c 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -27,6 +27,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_pointcloud_types.h" #include "BLI_linklist.h" #include "BLI_math.h" @@ -1717,3 +1718,41 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data) memset(data, 0, sizeof(*data)); } + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Point Cloud BVH Building + * \{ */ + +BVHTree *BKE_bvhtree_from_pointcloud_get(BVHTreeFromPointCloud *data, + const PointCloud *pointcloud, + const int tree_type) +{ + BVHTree *tree = BLI_bvhtree_new(pointcloud->totpoint, 0.0f, tree_type, 6); + if (!tree) { + return NULL; + } + + for (int i = 0; i < pointcloud->totpoint; i++) { + BLI_bvhtree_insert(tree, i, pointcloud->co[i], 1); + } + BLI_assert(BLI_bvhtree_get_len(tree) == pointcloud->totpoint); + BLI_bvhtree_balance(tree); + + data->coords = pointcloud->co; + data->tree = tree; + data->nearest_callback = NULL; + + return tree; +} + +void free_bvhtree_from_pointcloud(BVHTreeFromPointCloud *data) +{ + if (data->tree) { + BLI_bvhtree_free(data->tree); + } + memset(data, 0, sizeof(*data)); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index d6c31809a2e..1e2139522f1 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -142,6 +142,8 @@ IDTypeInfo IDType_ID_CF = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* TODO: make this per cache file to avoid global locks. */ diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 0ca22e34973..b0e3743add1 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -203,6 +203,8 @@ IDTypeInfo IDType_ID_CA = { .blend_read_expand = camera_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /** \} */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index c2d6d5c7594..09bd397cc78 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -285,7 +285,7 @@ static int do_step_cloth( mul_m4_v3(ob->obmat, verts->xconst); } - effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights); + effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights, false); if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) { cloth_update_verts(ob, clmd, result); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 58ce7227398..dd0572f9b12 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -362,6 +362,8 @@ IDTypeInfo IDType_ID_GR = { .blend_read_expand = collection_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /** \} */ @@ -1907,7 +1909,7 @@ bool BKE_collection_move(Main *bmain, /** \name Iterators * \{ */ -/* scene collection iteractor */ +/* Scene collection iterator. */ typedef struct CollectionsIteratorData { Scene *scene; @@ -1939,27 +1941,28 @@ static void scene_collections_build_array(Collection *collection, void *data) (*array)++; } -static void scene_collections_array(Scene *scene, Collection ***collections_array, int *tot) +static void scene_collections_array(Scene *scene, + Collection ***r_collections_array, + int *r_collections_array_len) { - Collection *collection; - Collection **array; - - *collections_array = NULL; - *tot = 0; + *r_collections_array = NULL; + *r_collections_array_len = 0; if (scene == NULL) { return; } - collection = scene->master_collection; + Collection *collection = scene->master_collection; BLI_assert(collection != NULL); - scene_collection_callback(collection, scene_collections_count, tot); + scene_collection_callback(collection, scene_collections_count, r_collections_array_len); - if (*tot == 0) { + if (*r_collections_array_len == 0) { return; } - *collections_array = array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray"); + Collection **array = MEM_mallocN(sizeof(Collection *) * (*r_collections_array_len), + "CollectionArray"); + *r_collections_array = array; scene_collection_callback(collection, scene_collections_build_array, &array); } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 0bf27a50a32..d04a27adec8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4693,7 +4693,7 @@ static void pivotcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta copy_m3_m4(rotMat, cob->matrix); normalize_m3(rotMat); - /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldnt */ + /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldn't */ mat3_normalized_to_axis_angle(axis, &angle, rotMat); if (angle) { float dvec[3]; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 65accc66084..6bc385ecd31 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -318,7 +318,7 @@ static eContextResult ctx_data_get(bContext *C, const char *member, bContextData * * Values in order of importance * (0, -1, 1) - Where 1 is highest priority - * */ + */ if (done != 1 && recursion < 1 && C->wm.store) { C->data.recursion = 1; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index ebce28c4e23..5632ae28960 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -327,6 +327,8 @@ IDTypeInfo IDType_ID_CU = { .blend_read_expand = curve_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; static int cu_isectLL(const float v1[3], @@ -2373,7 +2375,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl) * 0,1,2,3,4 --> 1,2,3,4,0 * * this is why we compare last with second last - * */ + */ float vec_1[3] = {0, 1, 0}, vec_2[3] = {0, 1, 0}, angle, ang_fac, cross_tmp[3]; BevPoint *bevp_first; diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c index 4725be6d302..63da7c1dd11 100644 --- a/source/blender/blenkernel/intern/curve_deform.c +++ b/source/blender/blenkernel/intern/curve_deform.c @@ -233,7 +233,7 @@ static bool calc_curve_deform( * Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell * * note: moved functions into quat_apply_track/vec_apply_track - * */ + */ copy_qt_qt(quat, new_quat); copy_v3_v3(cent, co); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 1121df0d568..782b4fc200e 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -212,9 +212,9 @@ static void layerFree_mdeformvert(void *data, int count, int size) /* copy just zeros in this case */ static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, int count) { - int i, size = sizeof(void *); + const int size = sizeof(void *); - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { void **ptr = POINTER_OFFSET(dest, i * size); *ptr = NULL; } @@ -253,15 +253,14 @@ static void layerInterp_mdeformvert(const void **sources, MDeformVert *dvert = dest; struct MDeformWeight_Link *dest_dwlink = NULL; struct MDeformWeight_Link *node; - int i, j, totweight; /* build a list of unique def_nrs for dest */ - totweight = 0; - for (i = 0; i < count; i++) { + int totweight = 0; + for (int i = 0; i < count; i++) { const MDeformVert *source = sources[i]; float interp_weight = weights[i]; - for (j = 0; j < source->totweight; j++) { + for (int j = 0; j < source->totweight; j++) { MDeformWeight *dw = &source->dw[j]; float weight = dw->weight * interp_weight; @@ -311,7 +310,8 @@ static void layerInterp_mdeformvert(const void **sources, if (totweight) { dvert->totweight = totweight; - for (i = 0, node = dest_dwlink; node; node = node->next, i++) { + int i = 0; + for (node = dest_dwlink; node; node = node->next, i++) { if (node->dw.weight > 1.0f) { node->dw.weight = 1.0f; } @@ -416,18 +416,16 @@ static void layerInterp_tface( const void **sources, const float *weights, const float *sub_weights, int count, void *dest) { MTFace *tf = dest; - int i, j, k; float uv[4][2] = {{0.0f}}; - const float *sub_weight; - sub_weight = sub_weights; - for (i = 0; i < count; i++) { + const float *sub_weight = sub_weights; + for (int i = 0; i < count; i++) { const float interp_weight = weights[i]; const MTFace *src = sources[i]; - for (j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) { if (sub_weights) { - for (k = 0; k < 4; k++, sub_weight++) { + for (int k = 0; k < 4; k++, sub_weight++) { madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight); } } @@ -446,9 +444,8 @@ static void layerSwap_tface(void *data, const int *corner_indices) { MTFace *tf = data; float uv[4][2]; - int j; - for (j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) { const int source_index = corner_indices[j]; copy_v2_v2(uv[j], tf->uv[source_index]); } @@ -517,18 +514,16 @@ static void layerInterp_origspace_face( const void **sources, const float *weights, const float *sub_weights, int count, void *dest) { OrigSpaceFace *osf = dest; - int i, j, k; float uv[4][2] = {{0.0f}}; - const float *sub_weight; - sub_weight = sub_weights; - for (i = 0; i < count; i++) { + const float *sub_weight = sub_weights; + for (int i = 0; i < count; i++) { const float interp_weight = weights[i]; const OrigSpaceFace *src = sources[i]; - for (j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) { if (sub_weights) { - for (k = 0; k < 4; k++, sub_weight++) { + for (int k = 0; k < 4; k++, sub_weight++) { madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight); } } @@ -546,9 +541,8 @@ static void layerSwap_origspace_face(void *data, const int *corner_indices) { OrigSpaceFace *osf = data; float uv[4][2]; - int j; - for (j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) { copy_v2_v2(uv[j], osf->uv[corner_indices[j]]); } memcpy(osf->uv, uv, sizeof(osf->uv)); @@ -567,13 +561,11 @@ static void layerDefault_origspace_face(void *data, int count) static void layerSwap_mdisps(void *data, const int *ci) { MDisps *s = data; - float(*d)[3] = NULL; - int corners, cornersize, S; if (s->disps) { int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */ - corners = multires_mdisp_corners(s); - cornersize = s->totdisp / corners; + int corners = multires_mdisp_corners(s); + int cornersize = s->totdisp / corners; if (corners != nverts) { /* happens when face changed vertex count in edit mode @@ -585,9 +577,9 @@ static void layerSwap_mdisps(void *data, const int *ci) return; } - d = MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap"); + float(*d)[3] = MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap"); - for (S = 0; S < corners; S++) { + for (int S = 0; S < corners; S++) { memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize); } @@ -1128,9 +1120,8 @@ static void layerSwap_mcol(void *data, const int *corner_indices) { MCol *mcol = data; MCol col[4]; - int j; - for (j = 0; j < 4; j++) { + for (int j = 0; j < 4; j++) { col[j] = mcol[corner_indices[j]]; } @@ -2064,13 +2055,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, void CustomData_update_typemap(CustomData *data) { - int i, lasttype = -1; + int lasttype = -1; - for (i = 0; i < CD_NUMTYPES; i++) { + for (int i = 0; i < CD_NUMTYPES; i++) { data->typemap[i] = -1; } - for (i = 0; i < data->totlayer; i++) { + for (int i = 0; i < data->totlayer; i++) { const int type = data->layers[i].type; if (type != lasttype) { data->typemap[type] = i; @@ -2097,18 +2088,16 @@ bool CustomData_merge(const struct CustomData *source, { /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; - void *data; - int i, type, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, - flag = 0; + int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; int number = 0, maxnumber = -1; bool changed = false; - for (i = 0; i < source->totlayer; i++) { + for (int i = 0; i < source->totlayer; i++) { layer = &source->layers[i]; /*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/ - type = layer->type; - flag = layer->flag; + int type = layer->type; + int flag = layer->flag; if (type != lasttype) { number = 0; @@ -2136,6 +2125,7 @@ bool CustomData_merge(const struct CustomData *source, continue; } + void *data; switch (alloctype) { case CD_ASSIGN: case CD_REFERENCE: @@ -2518,8 +2508,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, /* Passing a layer-data to copy from with an alloctype that won't copy is * most likely a bug */ - BLI_assert(!layerdata || (alloctype == CD_ASSIGN) || (alloctype == CD_DUPLICATE) || - (alloctype == CD_REFERENCE)); + BLI_assert(!layerdata || ELEM(alloctype, CD_ASSIGN, CD_DUPLICATE, CD_REFERENCE)); if (!typeInfo->defaultname && CustomData_has_layer(data, type)) { return &data->layers[CustomData_get_layer_index(data, type)]; @@ -2616,10 +2605,9 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data, void *CustomData_add_layer( CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem) { - CustomDataLayer *layer; const LayerTypeInfo *typeInfo = layerType_getInfo(type); - layer = customData_add_layer__internal( + CustomDataLayer *layer = customData_add_layer__internal( data, type, alloctype, layerdata, totelem, typeInfo->defaultname); CustomData_update_typemap(data); @@ -2638,9 +2626,8 @@ void *CustomData_add_layer_named(CustomData *data, int totelem, const char *name) { - CustomDataLayer *layer; - - layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name); + CustomDataLayer *layer = customData_add_layer__internal( + data, type, alloctype, layerdata, totelem, name); CustomData_update_typemap(data); if (layer) { @@ -2828,12 +2815,10 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type) void CustomData_free_temporary(CustomData *data, int totelem) { - CustomDataLayer *layer; int i, j; bool changed = false; - for (i = 0, j = 0; i < data->totlayer; i++) { - layer = &data->layers[i]; + CustomDataLayer *layer = &data->layers[i]; if (i != j) { data->layers[j] = data->layers[i]; @@ -3681,10 +3666,8 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data, static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n) { - const LayerTypeInfo *typeInfo; int offset = data->layers[n].offset; - - typeInfo = layerType_getInfo(data->layers[n].type); + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type); if (typeInfo->set_default) { typeInfo->set_default(POINTER_OFFSET(*block, offset), 1); @@ -4050,7 +4033,6 @@ void CustomData_bmesh_interp(CustomData *data, return; } - int i, j; void *source_buf[SOURCE_BUF_SIZE]; const void **sources = (const void **)source_buf; @@ -4071,11 +4053,11 @@ void CustomData_bmesh_interp(CustomData *data, } /* interpolates a layer at a time */ - for (i = 0; i < data->totlayer; i++) { + for (int i = 0; i < data->totlayer; i++) { CustomDataLayer *layer = &data->layers[i]; const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (typeInfo->interp) { - for (j = 0; j < count; j++) { + for (int j = 0; j < count; j++) { sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset); } CustomData_bmesh_interp_n( @@ -4465,7 +4447,6 @@ bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, cons void CustomData_layers__print(CustomData *data) { - printf("{\n"); int i; @@ -4520,10 +4501,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int { CustomDataExternal *external = data->external; CustomDataLayer *layer; - CDataFile *cdf; - CDataFileLayer *blay; char filename[FILE_MAX]; - const LayerTypeInfo *typeInfo; int update = 0; if (!external) { @@ -4532,7 +4510,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int for (int i = 0; i < data->totlayer; i++) { layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (!(mask & CD_TYPE_AS_MASK(layer->type))) { /* pass */ @@ -4551,7 +4529,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int customdata_external_filename(filename, id, external); - cdf = cdf_create(CDF_TYPE_MESH); + CDataFile *cdf = cdf_create(CDF_TYPE_MESH); if (!cdf_read_open(cdf, filename)) { cdf_free(cdf); CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filename); @@ -4560,7 +4538,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int for (int i = 0; i < data->totlayer; i++) { layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (!(mask & CD_TYPE_AS_MASK(layer->type))) { /* pass */ @@ -4569,7 +4547,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int /* pass */ } else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) { - blay = cdf_layer_find(cdf, layer->type, layer->name); + CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name); if (blay) { if (cdf_read_layer(cdf, blay)) { @@ -4596,10 +4574,6 @@ void CustomData_external_write( CustomData *data, ID *id, CustomDataMask mask, int totelem, int free) { CustomDataExternal *external = data->external; - CustomDataLayer *layer; - CDataFile *cdf; - CDataFileLayer *blay; - const LayerTypeInfo *typeInfo; int update = 0; char filename[FILE_MAX]; @@ -4609,8 +4583,8 @@ void CustomData_external_write( /* test if there is anything to write */ for (int i = 0; i < data->totlayer; i++) { - layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + CustomDataLayer *layer = &data->layers[i]; + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if (!(mask & CD_TYPE_AS_MASK(layer->type))) { /* pass */ @@ -4628,11 +4602,11 @@ void CustomData_external_write( CustomData_external_read(data, id, mask, totelem); customdata_external_filename(filename, id, external); - cdf = cdf_create(CDF_TYPE_MESH); + CDataFile *cdf = cdf_create(CDF_TYPE_MESH); for (int i = 0; i < data->totlayer; i++) { - layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + CustomDataLayer *layer = &data->layers[i]; + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) { if (layer->flag & CD_FLAG_IN_MEMORY) { @@ -4654,11 +4628,11 @@ void CustomData_external_write( int i; for (i = 0; i < data->totlayer; i++) { - layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + CustomDataLayer *layer = &data->layers[i]; + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { - blay = cdf_layer_find(cdf, layer->type, layer->name); + CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name); if (cdf_write_layer(cdf, blay)) { if (typeInfo->write(cdf, layer->data, totelem)) { @@ -4682,8 +4656,8 @@ void CustomData_external_write( } for (i = 0; i < data->totlayer; i++) { - layer = &data->layers[i]; - typeInfo = layerType_getInfo(layer->type); + CustomDataLayer *layer = &data->layers[i]; + const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) { if (free) { @@ -4703,15 +4677,13 @@ void CustomData_external_add( CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename) { CustomDataExternal *external = data->external; - CustomDataLayer *layer; - int layer_index; - layer_index = CustomData_get_active_layer_index(data, type); + int layer_index = CustomData_get_active_layer_index(data, type); if (layer_index == -1) { return; } - layer = &data->layers[layer_index]; + CustomDataLayer *layer = &data->layers[layer_index]; if (layer->flag & CD_FLAG_EXTERNAL) { return; @@ -4835,8 +4807,6 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye cd_interp interp_cd = NULL; cd_copy copy_cd = NULL; - void *tmp_dst; - if (!sources) { /* Not supported here, abort. */ return; @@ -4853,7 +4823,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye copy_cd = type_info->copy; } - tmp_dst = MEM_mallocN(data_size, __func__); + void *tmp_dst = MEM_mallocN(data_size, __func__); if (count > 1 && !interp_cd) { if (data_flag) { diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 375792a02c2..58c050493c9 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -488,6 +488,7 @@ void BKE_displist_fill(ListBase *dispbase, while (cont) { int dl_flag_accum = 0; + int dl_rt_accum = 0; cont = 0; totvert = 0; nextcol = 0; @@ -535,6 +536,7 @@ void BKE_displist_fill(ListBase *dispbase, } } dl_flag_accum |= dl->flag; + dl_rt_accum |= dl->rt; } } @@ -544,6 +546,7 @@ void BKE_displist_fill(ListBase *dispbase, dlnew = MEM_callocN(sizeof(DispList), "filldisplist"); dlnew->type = DL_INDEX3; dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE)); + dlnew->rt = (dl_rt_accum & CU_SMOOTH); dlnew->col = colnr; dlnew->nr = totvert; dlnew->parts = tot; @@ -1129,7 +1132,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, * * The right solution would be to COW the Curve data block at the input of the modifier * stack just like what the mesh modifier does. - * */ + */ modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase); } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 811a27c9f3f..4a25b0e9d98 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -3419,7 +3419,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, break; } - /* Set output format, png in case exr isn't supported */ + /* Set output format, PNG in case EXR isn't supported. */ #ifdef WITH_OPENEXR if (format == R_IMF_IMTYPE_OPENEXR) { /* OpenEXR 32-bit float */ ibuf->ftype = IMB_FTYPE_OPENEXR; @@ -5156,7 +5156,8 @@ static int dynamicPaint_prepareEffectStep(struct Depsgraph *depsgraph, /* Init force data if required */ if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { - ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, surface->effector_weights); + ListBase *effectors = BKE_effectors_create( + depsgraph, ob, NULL, surface->effector_weights, false); /* allocate memory for force data (dir vector + strength) */ *force = MEM_mallocN(sizeof(float[4]) * sData->total_points, "PaintEffectForces"); diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 13e9bb1bf24..4104b6080c5 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -270,11 +270,71 @@ void BKE_effector_relations_free(ListBase *lb) } } +/* Check that the force field isn't disabled via its flags. */ +static bool is_effector_enabled(PartDeflect *pd, bool use_rotation) +{ + switch (pd->forcefield) { + case PFIELD_BOID: + case PFIELD_GUIDE: + return true; + + case PFIELD_TEXTURE: + return (pd->flag & PFIELD_DO_LOCATION) != 0 && pd->tex != NULL; + + default: + if (use_rotation) { + return (pd->flag & (PFIELD_DO_LOCATION | PFIELD_DO_ROTATION)) != 0; + } + else { + return (pd->flag & PFIELD_DO_LOCATION) != 0; + } + } +} + +/* Check that the force field won't have zero effect due to strength settings. */ +static bool is_effector_nonzero_strength(PartDeflect *pd) +{ + if (pd->f_strength != 0.0f) { + return true; + } + + if (pd->forcefield == PFIELD_TEXTURE) { + return false; + } + + if (pd->f_noise > 0.0f || pd->f_flow != 0.0f) { + return true; + } + + switch (pd->forcefield) { + case PFIELD_BOID: + case PFIELD_GUIDE: + return true; + + case PFIELD_VORTEX: + return pd->shape != PFIELD_SHAPE_POINT; + + case PFIELD_DRAG: + return pd->f_damp != 0.0f; + + default: + return false; + } +} + +/* Check if the force field will affect its user. */ +static bool is_effector_relevant(PartDeflect *pd, EffectorWeights *weights, bool use_rotation) +{ + return (weights->weight[pd->forcefield] != 0.0f) && is_effector_enabled(pd, use_rotation) && + is_effector_nonzero_strength(pd); +} + /* Create effective list of effectors from relations built beforehand. */ ListBase *BKE_effectors_create(Depsgraph *depsgraph, Object *ob_src, ParticleSystem *psys_src, - EffectorWeights *weights) + EffectorWeights *weights, + bool use_rotation) { Scene *scene = DEG_get_evaluated_scene(depsgraph); ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group); @@ -299,7 +359,8 @@ ListBase *BKE_effectors_create(Depsgraph *depsgraph, } PartDeflect *pd = (relation->pd == relation->psys->part->pd) ? part->pd : part->pd2; - if (weights->weight[pd->forcefield] == 0.0f) { + + if (!is_effector_relevant(pd, weights, use_rotation)) { continue; } @@ -310,7 +371,7 @@ ListBase *BKE_effectors_create(Depsgraph *depsgraph, if (ob == ob_src) { continue; } - if (weights->weight[ob->pd->forcefield] == 0.0f) { + if (!is_effector_relevant(ob->pd, weights, use_rotation)) { continue; } if (ob->pd->shape == PFIELD_SHAPE_POINTS && BKE_object_get_evaluated_mesh(ob) == NULL) { @@ -903,7 +964,9 @@ static void do_texture_effector(EffectorCache *eff, madd_v3_v3fl(force, efd->nor, fac); } - add_v3_v3(total_force, force); + if (eff->pd->flag & PFIELD_DO_LOCATION) { + add_v3_v3(total_force, force); + } } static void do_physical_effector(EffectorCache *eff, EffectorData *efd, @@ -918,6 +981,7 @@ static void do_physical_effector(EffectorCache *eff, float strength = pd->f_strength; float damp = pd->f_damp; float noise_factor = pd->f_noise; + float flow_falloff = efd->falloff; if (noise_factor > 0.0f) { strength += wind_func(rng, noise_factor); @@ -1027,6 +1091,7 @@ static void do_physical_effector(EffectorCache *eff, break; case PFIELD_FLUIDFLOW: zero_v3(force); + flow_falloff = 0; #ifdef WITH_FLUID if (pd->f_source) { float density; @@ -1036,8 +1101,7 @@ static void do_physical_effector(EffectorCache *eff, influence *= density; } mul_v3_fl(force, influence); - /* apply flow */ - madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence); + flow_falloff = influence; } } #endif @@ -1047,9 +1111,8 @@ static void do_physical_effector(EffectorCache *eff, if (pd->flag & PFIELD_DO_LOCATION) { madd_v3_v3fl(total_force, force, 1.0f / point->vel_to_sec); - if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_FLUIDFLOW) == 0 && - pd->f_flow != 0.0f) { - madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff); + if (!ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG) && pd->f_flow != 0.0f) { + madd_v3_v3fl(total_force, point->vel, -pd->f_flow * flow_falloff); } } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index ce710e2f7d4..8e1fa9732ea 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1110,7 +1110,7 @@ void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end) if (fcu->fpt == NULL) { /* No data to unbake. */ - CLOG_ERROR(&LOG, "Error: Curve containts no baked keyframes"); + CLOG_ERROR(&LOG, "Error: Curve contains no baked keyframes"); return; } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 59248e5f9f8..7fe009d51ca 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -3225,7 +3225,7 @@ static void update_effectors( ListBase *effectors; /* make sure smoke flow influence is 0.0f */ fds->effector_weights->weight[PFIELD_FLUIDFLOW] = 0.0f; - effectors = BKE_effectors_create(depsgraph, ob, NULL, fds->effector_weights); + effectors = BKE_effectors_create(depsgraph, ob, NULL, fds->effector_weights, false); if (effectors) { /* Precalculate wind forces. */ diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index df1dbaa905f..25a0259abe3 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -176,6 +176,8 @@ IDTypeInfo IDType_ID_VF = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /***************************** VFont *******************************/ diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index a47a3dbc872..2eaef8fc121 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -19,6 +19,7 @@ #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" #include "BKE_pointcloud.h" +#include "BKE_volume.h" #include "DNA_object_types.h" @@ -52,6 +53,8 @@ GeometryComponent *GeometryComponent::create(GeometryComponentType component_typ return new PointCloudComponent(); case GeometryComponentType::Instances: return new InstancesComponent(); + case GeometryComponentType::Volume: + return new VolumeComponent(); } BLI_assert(false); return nullptr; @@ -202,6 +205,13 @@ const PointCloud *GeometrySet::get_pointcloud_for_read() const return (component == nullptr) ? nullptr : component->get_for_read(); } +/* Returns a read-only volume or null. */ +const Volume *GeometrySet::get_volume_for_read() const +{ + const VolumeComponent *component = this->get_component_for_read<VolumeComponent>(); + return (component == nullptr) ? nullptr : component->get_for_read(); +} + /* Returns true when the geometry set has a point cloud component that has a point cloud. */ bool GeometrySet::has_pointcloud() const { @@ -216,6 +226,13 @@ bool GeometrySet::has_instances() const return component != nullptr && component->instances_amount() >= 1; } +/* Returns true when the geometry set has a volume component that has a volume. */ +bool GeometrySet::has_volume() const +{ + const VolumeComponent *component = this->get_component_for_read<VolumeComponent>(); + return component != nullptr && component->has_volume(); +} + /* Create a new geometry set that only contains the given mesh. */ GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership) { @@ -263,6 +280,13 @@ PointCloud *GeometrySet::get_pointcloud_for_write() return component.get_for_write(); } +/* Returns a mutable volume or null. No ownership is transferred. */ +Volume *GeometrySet::get_volume_for_write() +{ + VolumeComponent &component = this->get_component_for_write<VolumeComponent>(); + return component.get_for_write(); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -353,6 +377,17 @@ void MeshComponent::copy_vertex_group_names_from_object(const Object &object) } } +const blender::Map<std::string, int> &MeshComponent::vertex_group_names() const +{ + return vertex_group_names_; +} + +/* This is only exposed for the internal attribute API. */ +blender::Map<std::string, int> &MeshComponent::vertex_group_names() +{ + return vertex_group_names_; +} + /* Get the mesh from this component. This method can be used by multiple threads at the same * time. Therefore, the returned mesh should not be modified. No ownership is transferred. */ const Mesh *MeshComponent::get_for_read() const @@ -545,6 +580,85 @@ bool InstancesComponent::is_empty() const /** \} */ /* -------------------------------------------------------------------- */ +/** \name Volume Component + * \{ */ + +VolumeComponent::VolumeComponent() : GeometryComponent(GeometryComponentType::Volume) +{ +} + +VolumeComponent::~VolumeComponent() +{ + this->clear(); +} + +GeometryComponent *VolumeComponent::copy() const +{ + VolumeComponent *new_component = new VolumeComponent(); + if (volume_ != nullptr) { + new_component->volume_ = BKE_volume_copy_for_eval(volume_, false); + new_component->ownership_ = GeometryOwnershipType::Owned; + } + return new_component; +} + +void VolumeComponent::clear() +{ + BLI_assert(this->is_mutable()); + if (volume_ != nullptr) { + if (ownership_ == GeometryOwnershipType::Owned) { + BKE_id_free(nullptr, volume_); + } + volume_ = nullptr; + } +} + +bool VolumeComponent::has_volume() const +{ + return volume_ != nullptr; +} + +/* Clear the component and replace it with the new volume. */ +void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership) +{ + BLI_assert(this->is_mutable()); + this->clear(); + volume_ = volume; + ownership_ = ownership; +} + +/* Return the volume and clear the component. The caller takes over responsibility for freeing the + * volume (if the component was responsible before). */ +Volume *VolumeComponent::release() +{ + BLI_assert(this->is_mutable()); + Volume *volume = volume_; + volume_ = nullptr; + return volume; +} + +/* Get the volume from this component. This method can be used by multiple threads at the same + * time. Therefore, the returned volume should not be modified. No ownership is transferred. */ +const Volume *VolumeComponent::get_for_read() const +{ + return volume_; +} + +/* Get the volume from this component. This method can only be used when the component is mutable, + * i.e. it is not shared. The returned volume can be modified. No ownership is transferred. */ +Volume *VolumeComponent::get_for_write() +{ + BLI_assert(this->is_mutable()); + if (ownership_ == GeometryOwnershipType::ReadOnly) { + volume_ = BKE_volume_copy_for_eval(volume_, false); + ownership_ = GeometryOwnershipType::Owned; + } + return volume_; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name C API * \{ */ diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index f68a390db64..3d0152a6c7d 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -93,7 +93,33 @@ static void greasepencil_copy_data(Main *UNUSED(bmain), /* make a copy of source layer and its data */ /* TODO here too could add unused flags... */ - bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src); + bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true); + + /* Apply local layer transform to all frames. Calc the active frame is not enough + * because onion skin can use more frames. This is more slow but required here. */ + if (gpl_dst->actframe != NULL) { + bool transfomed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) || + (!is_one_v3(gpl_dst->scale))); + if (transfomed) { + loc_eul_size_to_mat4( + gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale); + bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0); + bGPDframe *init_gpf = (do_onion) ? gpl_dst->frames.first : gpl_dst->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + mul_m4_v3(gpl_dst->layer_mat, &pt->x); + } + } + /* if not onion, exit loop. */ + if (!do_onion) { + break; + } + } + } + } BLI_addtail(&gpd_dst->layers, gpl_dst); } @@ -303,6 +329,8 @@ IDTypeInfo IDType_ID_GD = { .blend_read_expand = greasepencil_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* ************************************************** */ @@ -581,7 +609,7 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe) } /* Create a copy of the frame */ - new_frame = BKE_gpencil_frame_duplicate(gpl->actframe); + new_frame = BKE_gpencil_frame_duplicate(gpl->actframe, true); /* Find frame to insert it before */ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { @@ -686,6 +714,14 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti /* Enable always affected by scene lights. */ gpl->flag |= GP_LAYER_USE_LIGHTS; + + /* Init transform. */ + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* make this one the active one */ if (setactive) { BKE_gpencil_layer_active_set(gpd, gpl); @@ -815,6 +851,7 @@ bGPDstroke *BKE_gpencil_stroke_new(int mat_idx, int totpoints, short thickness) gps->mat_nr = mat_idx; + gps->dvert = NULL; gps->editcurve = NULL; return gps; @@ -957,7 +994,7 @@ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src, * \param gpf_src: Source grease pencil frame * \return Pointer to new frame */ -bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src) +bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes) { bGPDstroke *gps_dst = NULL; bGPDframe *gpf_dst; @@ -971,12 +1008,14 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src) gpf_dst = MEM_dupallocN(gpf_src); gpf_dst->prev = gpf_dst->next = NULL; - /* copy strokes */ + /* Copy strokes. */ BLI_listbase_clear(&gpf_dst->strokes); - LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { - /* make copy of source stroke */ - gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true); - BLI_addtail(&gpf_dst->strokes, gps_dst); + if (dup_strokes) { + LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) { + /* make copy of source stroke */ + gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true); + BLI_addtail(&gpf_dst->strokes, gps_dst); + } } /* return new frame */ @@ -1010,7 +1049,9 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds * \param gpl_src: Source grease pencil layer * \return Pointer to new layer */ -bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) +bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src, + const bool dup_frames, + const bool dup_strokes) { const bGPDframe *gpf_src; bGPDframe *gpf_dst; @@ -1035,14 +1076,16 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src) /* copy frames */ BLI_listbase_clear(&gpl_dst->frames); - for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) { - /* make a copy of source frame */ - gpf_dst = BKE_gpencil_frame_duplicate(gpf_src); - BLI_addtail(&gpl_dst->frames, gpf_dst); - - /* if source frame was the current layer's 'active' frame, reassign that too */ - if (gpf_src == gpl_dst->actframe) { - gpl_dst->actframe = gpf_dst; + if (dup_frames) { + for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) { + /* make a copy of source frame */ + gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, dup_strokes); + BLI_addtail(&gpl_dst->frames, gpf_dst); + + /* if source frame was the current layer's 'active' frame, reassign that too */ + if (gpf_src == gpl_dst->actframe) { + gpl_dst->actframe = gpf_dst; + } } } @@ -2519,7 +2562,7 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, int cfra) { bGPdata *gpd = (bGPdata *)ob->data; - const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd))); const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0); const bool is_drawing = (gpd->runtime.sbuffer_used > 0); @@ -2541,6 +2584,11 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, continue; } + /* If scale to 0 the layer must be invisible. */ + if (is_zero_v3(gpl->scale)) { + continue; + } + /* Hide the layer if it's defined a view layer filter. This is used to * generate renders, putting only selected GP layers for each View Layer. * This is used only in final render and never in Viewport. */ @@ -2559,6 +2607,15 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer, LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { if (gpf == act_gpf || (gpf->flag & GP_FRAME_SELECT)) { gpf->runtime.onion_id = 0; + if (do_onion) { + if (gpf->framenum < act_gpf->framenum) { + gpf->runtime.onion_id = -1; + } + else { + gpf->runtime.onion_id = 1; + } + } + if (sta_gpf == NULL) { sta_gpf = gpf; } @@ -2759,10 +2816,10 @@ void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_ev * \param gpl: Grease pencil layer * \param diff_mat: Result parent matrix */ -void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, - Object *obact, - bGPDlayer *gpl, - float diff_mat[4][4]) +void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph, + Object *obact, + bGPDlayer *gpl, + float diff_mat[4][4]) { Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact; Object *obparent = gpl->parent; @@ -2771,11 +2828,10 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, /* if not layer parented, try with object parented */ if (obparent_eval == NULL) { - if (ob_eval != NULL) { - if (ob_eval->type == OB_GPENCIL) { - copy_m4_m4(diff_mat, ob_eval->obmat); - return; - } + if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) { + copy_m4_m4(diff_mat, ob_eval->obmat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); + return; } /* not gpencil object */ unit_m4(diff_mat); @@ -2785,6 +2841,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } if (gpl->partype == PARBONE) { @@ -2800,6 +2857,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse); add_v3_v3(diff_mat[3], ob_eval->obmat[3]); } + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat); return; } @@ -2807,11 +2865,11 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph, } /** - * Update parent matrix. + * Update parent matrix and local transforms. * \param depsgraph: Depsgraph * \param ob: Grease pencil object */ -void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) +void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob) { if (ob->type != OB_GPENCIL) { return; @@ -2820,31 +2878,50 @@ void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob) bGPdata *gpd = (bGPdata *)ob->data; float cur_mat[4][4]; + bool changed = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if ((gpl->parent != NULL) && (gpl->actframe != NULL)) { - Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); - /* calculate new matrix */ - if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { - copy_m4_m4(cur_mat, ob_parent->obmat); - } - else if (gpl->partype == PARBONE) { - bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); - if (pchan != NULL) { - copy_m4_m4(cur_mat, ob->imat); - mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + unit_m4(cur_mat); + if (gpl->actframe != NULL) { + if (gpl->parent != NULL) { + Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent); + /* calculate new matrix */ + if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) { + copy_m4_m4(cur_mat, ob_parent->obmat); } - else { - unit_m4(cur_mat); + else if (gpl->partype == PARBONE) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr); + if (pchan != NULL) { + copy_m4_m4(cur_mat, ob->imat); + mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat); + } + else { + unit_m4(cur_mat); + } } + changed = !equals_m4m4(gpl->inverse, cur_mat); } + + /* Calc local layer transform. */ + bool transfomed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || + (!is_one_v3(gpl->scale))); + if (transfomed) { + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + } + /* only redo if any change */ - if (!equals_m4m4(gpl->inverse, cur_mat)) { + if (changed || transfomed) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { bGPDspoint *pt; int i; for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { - mul_m4_v3(gpl->inverse, &pt->x); - mul_m4_v3(cur_mat, &pt->x); + if (changed) { + mul_m4_v3(gpl->inverse, &pt->x); + mul_m4_v3(cur_mat, &pt->x); + } + + if (transfomed) { + mul_m4_v3(gpl->layer_mat, &pt->x); + } } } } @@ -2872,4 +2949,26 @@ int BKE_gpencil_material_find_index_by_name_prefix(Object *ob, const char *name_ return -1; } +/* Create a hash with the list of selected frame number. */ +void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list) +{ + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + + LISTBASE_FOREACH (bGPDlayer *, gpl_iter, &gpd->layers) { + if ((gpl != NULL) && (!is_multiedit) && (gpl != gpl_iter)) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl_iter->frames) { + if (((gpf == gpl->actframe) && (!is_multiedit)) || + ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (!BLI_ghash_lookup(r_list, POINTER_FROM_INT(gpf->framenum))) { + BLI_ghash_insert(r_list, POINTER_FROM_INT(gpf->framenum), gpf); + } + } + } + } +} + /** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 981f5d50353..2ef85439a46 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -1684,11 +1684,12 @@ void BKE_gpencil_stroke_normal(const bGPDstroke *gps, float r_normal[3]) /* Stroke Simplify ------------------------------------- */ -/** Reduce a series of points to a simplified version, but +/** + * Reduce a series of points to a simplified version, but * maintains the general shape of the series * * Ramer - Douglas - Peucker algorithm - * by http ://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm + * by http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm * \param gpd: Grease pencil data-block * \param gps: Grease pencil stroke * \param epsilon: Epsilon value to define precision of the algorithm @@ -3227,6 +3228,45 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a, } } +/* Copy the stroke of the frame to all frames selected (except current). */ +void BKE_gpencil_stroke_copy_to_keyframes( + bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const bool tail) +{ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + BKE_gpencil_frame_selected_hash(gpd, frame_list); + + GHashIterator gh_iter; + GHASH_ITER (gh_iter, frame_list) { + int cfra = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter)); + + if (gpf->framenum != cfra) { + bGPDframe *gpf_new = BKE_gpencil_layer_frame_find(gpl, cfra); + if (gpf_new == NULL) { + gpf_new = BKE_gpencil_frame_addnew(gpl, cfra); + } + + if (gpf_new == NULL) { + continue; + } + + bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(gps, true, true); + if (gps_new == NULL) { + continue; + } + + if (tail) { + BLI_addhead(&gpf_new->strokes, gps_new); + } + else { + BLI_addtail(&gpf_new->strokes, gps_new); + } + } + } + + /* Free hash table. */ + BLI_ghash_free(frame_list, NULL, NULL); +} + /* Stroke Uniform Subdivide ------------------------------------- */ typedef struct tSamplePoint { diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index 1be2cba31b5..8b12e1b5fca 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -701,13 +701,18 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o Object *ob_orig = (Object *)DEG_get_original_id(&ob->id); bGPdata *gpd_orig = (bGPdata *)ob_orig->data; - /* Need check if some layer is parented. */ + /* Need check if some layer is parented or transformed. */ bool do_parent = false; + bool do_transform = false; LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) { if (gpl->parent != NULL) { do_parent = true; break; } + if ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || (!is_one_v3(gpl->scale))) { + do_transform = true; + break; + } } const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval); @@ -715,7 +720,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) && (ob->greasepencil_modifiers.first != NULL) && (!GPENCIL_SIMPLIFY_MODIF(scene))); - if ((!do_modifiers) && (!do_parent)) { + if ((!do_modifiers) && (!do_parent) && (!do_transform)) { return; } DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval); diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index a44b054e366..f76e5a73478 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -197,6 +197,8 @@ IDTypeInfo IDType_ID_HA = { .blend_read_expand = hair_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; static void hair_random(Hair *hair) diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc index cba1726a1b9..afb009b66cd 100644 --- a/source/blender/blenkernel/intern/icons.cc +++ b/source/blender/blenkernel/intern/icons.cc @@ -374,6 +374,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) ID_PRV_CASE(ID_GR, Collection); ID_PRV_CASE(ID_SCE, Scene); ID_PRV_CASE(ID_SCR, bScreen); + ID_PRV_CASE(ID_AC, bAction); #undef ID_PRV_CASE default: break; diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index b0991f1d343..6b164e6bc50 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -92,11 +92,9 @@ IDProperty *IDP_NewIDPArray(const char *name) IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) { /* don't use MEM_dupallocN because this may be part of an array */ - IDProperty *narray, *tmp; - BLI_assert(array->type == IDP_IDPARRAY); - narray = MEM_mallocN(sizeof(IDProperty), __func__); + IDProperty *narray = MEM_mallocN(sizeof(IDProperty), __func__); *narray = *array; narray->data.pointer = MEM_dupallocN(array->data.pointer); @@ -107,7 +105,7 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag) * then free it. this makes for more maintainable * code than simply re-implementing the copy functions * in this loop.*/ - tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag); + IDProperty *tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag); memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty)); MEM_freeN(tmp); } @@ -131,15 +129,13 @@ static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user) /* shallow copies item */ void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item) { - IDProperty *old; - BLI_assert(prop->type == IDP_IDPARRAY); if (index >= prop->len || index < 0) { return; } - old = GETPROP(prop, index); + IDProperty *old = GETPROP(prop, index); if (item != old) { IDP_FreePropertyContent(old); @@ -164,8 +160,6 @@ void IDP_AppendArray(IDProperty *prop, IDProperty *item) void IDP_ResizeIDPArray(IDProperty *prop, int newlen) { - int newsize; - BLI_assert(prop->type == IDP_IDPARRAY); /* first check if the array buffer size has room */ @@ -200,7 +194,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) * system realloc(). * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ - newsize = newlen; + int newsize = newlen; newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize); prop->len = newlen; @@ -218,9 +212,8 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) /* bigger */ IDProperty **array = newarr; IDPropertyTemplate val; - int a; - for (a = prop->len; a < newlen; a++) { + for (int a = prop->len; a < newlen; a++) { val.i = 0; /* silence MSVC warning about uninitialized var when debugging */ array[a] = IDP_New(IDP_GROUP, &val, "IDP_ResizeArray group"); } @@ -228,9 +221,8 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) else { /* smaller */ IDProperty **array = prop->data.pointer; - int a; - for (a = newlen; a < prop->len; a++) { + for (int a = newlen; a < prop->len; a++) { IDP_FreeProperty(array[a]); } } @@ -239,7 +231,6 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) /*this function works for strings too!*/ void IDP_ResizeArray(IDProperty *prop, int newlen) { - int newsize; const bool is_grow = newlen >= prop->len; /* first check if the array buffer size has room */ @@ -257,7 +248,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) * system realloc(). * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ - newsize = newlen; + int newsize = newlen; newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; if (is_grow == false) { @@ -362,10 +353,8 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag) { - IDProperty *newp; - BLI_assert(prop->type == IDP_STRING); - newp = idp_generic_copy(prop, flag); + IDProperty *newp = idp_generic_copy(prop, flag); if (prop->data.pointer) { newp->data.pointer = MEM_dupallocN(prop->data.pointer); @@ -379,10 +368,8 @@ static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag) void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) { - int stlen; - BLI_assert(prop->type == IDP_STRING); - stlen = (int)strlen(st); + int stlen = (int)strlen(st); if (maxlen > 0 && maxlen < stlen) { stlen = maxlen; } @@ -400,11 +387,9 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) void IDP_ConcatStringC(IDProperty *prop, const char *st) { - int newlen; - BLI_assert(prop->type == IDP_STRING); - newlen = prop->len + (int)strlen(st); + int newlen = prop->len + (int)strlen(st); /* we have to remember that prop->len includes the null byte for strings. * so there's no need to add +1 to the resize function.*/ IDP_ResizeArray(prop, newlen); @@ -413,13 +398,11 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st) void IDP_ConcatString(IDProperty *str1, IDProperty *append) { - int newlen; - BLI_assert(append->type == IDP_STRING); /* since ->len for strings includes the NULL byte, we have to subtract one or * we'll get an extra null byte after each concatenation operation.*/ - newlen = str1->len + append->len - 1; + int newlen = str1->len + append->len - 1; IDP_ResizeArray(str1, newlen); strcat(str1->data.pointer, append->data.pointer); } @@ -440,10 +423,8 @@ void IDP_FreeString(IDProperty *prop) static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag) { - IDProperty *newp; - BLI_assert(prop->type == IDP_ID); - newp = idp_generic_copy(prop, flag); + IDProperty *newp = idp_generic_copy(prop, flag); newp->data.pointer = prop->data.pointer; if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { @@ -479,14 +460,12 @@ void IDP_AssignID(IDProperty *prop, ID *id, const int flag) */ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag) { - IDProperty *newp, *link; - BLI_assert(prop->type == IDP_GROUP); - newp = idp_generic_copy(prop, flag); + IDProperty *newp = idp_generic_copy(prop, flag); newp->len = prop->len; newp->subtype = prop->subtype; - for (link = prop->data.group.first; link; link = link->next) { + LISTBASE_FOREACH (IDProperty *, link, &prop->data.group) { BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag)); } @@ -497,13 +476,11 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag) * When values name and types match, copy the values, else ignore */ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src) { - IDProperty *other, *prop; - BLI_assert(dest->type == IDP_GROUP); BLI_assert(src->type == IDP_GROUP); - for (prop = src->data.group.first; prop; prop = prop->next) { - other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name)); + LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) { + IDProperty *other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name)); if (other && prop->type == other->type) { switch (prop->type) { case IDP_INT: @@ -526,12 +503,9 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src) void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_arraylen) { - IDProperty *prop_dst, *prop_dst_next; - const IDProperty *prop_src; - - for (prop_dst = dest->data.group.first; prop_dst; prop_dst = prop_dst_next) { - prop_dst_next = prop_dst->next; - if ((prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name))) { + LISTBASE_FOREACH_MUTABLE (IDProperty *, prop_dst, &src->data.group) { + const IDProperty *prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name); + if (prop_src != NULL) { /* check of we should replace? */ if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) || (do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) && @@ -554,12 +528,11 @@ void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_a */ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) { - IDProperty *loop, *prop; - BLI_assert(dest->type == IDP_GROUP); BLI_assert(src->type == IDP_GROUP); - for (prop = src->data.group.first; prop; prop = prop->next) { + LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) { + IDProperty *loop; for (loop = dest->data.group.first; loop; loop = loop->next) { if (STREQ(loop->name, prop->name)) { BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop)); @@ -612,13 +585,11 @@ void IDP_MergeGroup_ex(IDProperty *dest, const bool do_overwrite, const int flag) { - IDProperty *prop; - BLI_assert(dest->type == IDP_GROUP); BLI_assert(src->type == IDP_GROUP); if (do_overwrite) { - for (prop = src->data.group.first; prop; prop = prop->next) { + LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) { if (prop->type == IDP_GROUP) { IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name); @@ -633,7 +604,7 @@ void IDP_MergeGroup_ex(IDProperty *dest, } } else { - for (prop = src->data.group.first; prop; prop = prop->next) { + LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) { IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name); if (prop_exist != NULL) { if (prop->type == IDP_GROUP) { @@ -741,10 +712,9 @@ IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop, const char *nam * direct data. */ static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user) { - IDProperty *loop; - BLI_assert(prop->type == IDP_GROUP); - for (loop = prop->data.group.first; loop; loop = loop->next) { + + LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) { IDP_FreePropertyContent_ex(loop, do_id_user); } BLI_freelistN(&prop->data.group); @@ -863,14 +833,12 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is } return false; case IDP_GROUP: { - IDProperty *link1, *link2; - if (is_strict && prop1->len != prop2->len) { return false; } - for (link1 = prop1->data.group.first; link1; link1 = link1->next) { - link2 = IDP_GetPropertyFromGroup(prop2, link1->name); + LISTBASE_FOREACH (IDProperty *, link1, &prop1->data.group) { + IDProperty *link2 = IDP_GetPropertyFromGroup(prop2, link1->name); if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) { return false; @@ -1158,11 +1126,10 @@ static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer) /*REMEMBER to set totalen to len in the linking code!!*/ if (prop->data.pointer) { const IDProperty *array = prop->data.pointer; - int a; BLO_write_struct_array(writer, IDProperty, prop->len, array); - for (a = 0; a < prop->len; a++) { + for (int a = 0; a < prop->len; a++) { IDP_WriteProperty_OnlyData(&array[a], writer); } } @@ -1176,9 +1143,7 @@ static void IDP_WriteString(const IDProperty *prop, BlendWriter *writer) static void IDP_WriteGroup(const IDProperty *prop, BlendWriter *writer) { - IDProperty *loop; - - for (loop = prop->data.group.first; loop; loop = loop->next) { + LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) { IDP_BlendWrite(writer, loop); } } @@ -1212,13 +1177,11 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader); static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader) { - IDProperty *array; - /* since we didn't save the extra buffer, set totallen to len */ prop->totallen = prop->len; BLO_read_data_address(reader, &prop->data.pointer); - array = (IDProperty *)prop->data.pointer; + IDProperty *array = (IDProperty *)prop->data.pointer; /* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared * there's not really anything we can do to correct this, at least don't crash */ @@ -1234,14 +1197,12 @@ static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader) static void IDP_DirectLinkArray(IDProperty *prop, BlendDataReader *reader) { - IDProperty **array; - /* since we didn't save the extra buffer, set totallen to len */ prop->totallen = prop->len; if (prop->subtype == IDP_GROUP) { BLO_read_pointer_array(reader, &prop->data.pointer); - array = prop->data.pointer; + IDProperty **array = prop->data.pointer; for (int i = 0; i < prop->len; i++) { IDP_DirectLinkProperty(array[i], reader); @@ -1266,12 +1227,11 @@ static void IDP_DirectLinkString(IDProperty *prop, BlendDataReader *reader) static void IDP_DirectLinkGroup(IDProperty *prop, BlendDataReader *reader) { ListBase *lb = &prop->data.group; - IDProperty *loop; BLO_read_list(reader, lb); /*Link child id properties now*/ - for (loop = prop->data.group.first; loop; loop = loop->next) { + LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) { IDP_DirectLinkProperty(loop, reader); } } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ab57d14d2cf..10f15519ea4 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -338,6 +338,8 @@ IDTypeInfo IDType_ID_IM = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* prototypes */ diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 1ab6e61e20e..d43a0cb3813 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -200,6 +200,8 @@ IDTypeInfo IDType_ID_IP = { .blend_read_expand = ipo_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* *************************************************** */ diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 433d64a5927..540337b84b3 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -223,6 +223,8 @@ IDTypeInfo IDType_ID_KE = { .blend_read_expand = shapekey_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; #define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */ diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 74f78106be5..3d3ade1a529 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -205,6 +205,8 @@ IDTypeInfo IDType_ID_LT = { .blend_read_expand = lattice_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w) diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 13f76b46570..54c2f5f5565 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -112,6 +112,8 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* GS reads the memory pointed at in a specific ordering. @@ -1793,32 +1795,31 @@ static void library_make_local_copying_check(ID *id, return; /* Already checked, nothing else to do. */ } - MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id); + MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->relations_from_pointers, id); BLI_gset_insert(loop_tags, id); - for (; entry != NULL; entry = entry->next) { - - /* Used_to_user stores ID pointer, not pointer to ID pointer. */ - ID *par_id = (ID *)entry->id_pointer; - + for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL; + from_id_entry = from_id_entry->next) { /* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual * relation we want to check is in the other way around. */ - if (entry->usage_flag & IDWALK_CB_LOOPBACK) { + if (from_id_entry->usage_flag & IDWALK_CB_LOOPBACK) { continue; } + ID *from_id = from_id_entry->id_pointer.from; + /* Shape-keys are considered 'private' to their owner ID here, and never tagged * (since they cannot be linked), so we have to switch effective parent to their owner. */ - if (GS(par_id->name) == ID_KE) { - par_id = ((Key *)par_id)->from; + if (GS(from_id->name) == ID_KE) { + from_id = ((Key *)from_id)->from; } - if (par_id->lib == NULL) { + if (from_id->lib == NULL) { /* Local user, early out to avoid some gset querying... */ continue; } - if (!BLI_gset_haskey(done_ids, par_id)) { - if (BLI_gset_haskey(loop_tags, par_id)) { + if (!BLI_gset_haskey(done_ids, from_id)) { + if (BLI_gset_haskey(loop_tags, from_id)) { /* We are in a 'dependency loop' of IDs, this does not say us anything, skip it. * Note that this is the situation that can lead to archipelagoes of linked data-blocks * (since all of them have non-local users, they would all be duplicated, @@ -1827,10 +1828,10 @@ static void library_make_local_copying_check(ID *id, continue; } /* Else, recursively check that user ID. */ - library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids); + library_make_local_copying_check(from_id, loop_tags, id_relations, done_ids); } - if (par_id->tag & LIB_TAG_DOIT) { + if (from_id->tag & LIB_TAG_DOIT) { /* This user will be fully local in future, so far so good, * nothing to do here but check next user. */ } diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index e4094c48368..602c560cedd 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -368,183 +368,249 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain) return success; } -static bool lib_override_hierarchy_recursive_tag(Main *bmain, - ID *id, - const uint tag, - const uint missing_tag, - Library *override_group_lib_reference) +typedef struct LibOverrideGroupTagData { + Main *bmain; + ID *id_root; + uint tag; + uint missing_tag; +} LibOverrideGroupTagData; + +/* Tag all IDs in dependency relationships within an override hierarchy/group. + * + * Requires existing `Main.relations`. + * + * Note: this is typically called to complete `lib_override_linked_group_tag()`. + */ +static bool lib_override_hierarchy_dependencies_recursive_tag(LibOverrideGroupTagData *data) { - void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id); - if (entry_vp == NULL) { - /* Already processed. */ - return (id->tag & tag) != 0; - } + Main *bmain = data->bmain; + ID *id = data->id_root; - /* Note: in case some reference ID is missing from linked data (and therefore its override uses - * a placeholder as reference), use `missing_tag` instead of `tag` for this override. */ - if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) && - id->override_library->reference->lib == override_group_lib_reference) { - if (id->override_library->reference->tag & LIB_TAG_MISSING) { - id->tag |= missing_tag; - } - else { - id->tag |= tag; - } - } + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); + BLI_assert(entry != NULL); + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ + return (*(uint *)&id->tag & data->tag) != 0; + } /* This way we won't process again that ID, should we encounter it again through another - * relationship hierarchy. - * Note that this does not free any memory from relations, so we can still use the entries. - */ - BKE_main_relations_ID_remove(bmain, id); + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; - for (MainIDRelationsEntry *entry = *entry_vp; entry != NULL; entry = entry->next) { - if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as * actual dependencies. */ continue; } /* We only consider IDs from the same library. */ - if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) { - if (lib_override_hierarchy_recursive_tag( - bmain, *entry->id_pointer, tag, missing_tag, override_group_lib_reference) && - override_group_lib_reference == NULL) { - id->tag |= tag; + ID *to_id = *to_id_entry->id_pointer.to; + if (to_id != NULL && to_id->lib == id->lib) { + LibOverrideGroupTagData sub_data = *data; + sub_data.id_root = to_id; + if (lib_override_hierarchy_dependencies_recursive_tag(&sub_data)) { + id->tag |= data->tag; } } } - return (id->tag & tag) != 0; + return (*(uint *)&id->tag & data->tag) != 0; } -/** - * Tag all IDs in given \a bmain that are being used by given \a id_root ID or its dependencies, - * recursively. - * It detects and tag only chains of dependencies marked at both ends by given tag. - * - * This will include all local IDs, and all IDs from the same library as the \a id_root. - * - * \param id_root: The root of the hierarchy of dependencies to be tagged. - * \param do_create_main_relashionships: Whether main relations needs to be created or already - * exist (in any case, they will be freed by this function). - */ -void BKE_lib_override_library_dependencies_tag(Main *bmain, - ID *id_root, - const uint tag, - const bool do_create_main_relashionships) +static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *data) { - if (do_create_main_relashionships) { - BKE_main_relations_create(bmain, 0); + Main *bmain = data->bmain; + ID *id_owner = data->id_root; + BLI_assert(ID_IS_LINKED(id_owner)); + const uint tag = data->tag; + const uint missing_tag = data->missing_tag; + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, + id_owner); + BLI_assert(entry != NULL); + + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ + return; } + /* This way we won't process again that ID, should we encounter it again through another + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; + + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & + (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers), nor + * override references or embedded ID pointers, as actual dependencies. */ + continue; + } - /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shape-key - * has a driver using an armature object's bone, we need to override the shape-key/obdata, - * the objects using them, etc.) */ - lib_override_hierarchy_recursive_tag(bmain, id_root, tag, 0, NULL); + ID *to_id = *to_id_entry->id_pointer.to; + if (ELEM(to_id, NULL, id_owner)) { + continue; + } + /* We only consider IDs from the same library. */ + if (to_id->lib != id_owner->lib) { + continue; + } + BLI_assert(ID_IS_LINKED(to_id)); + + /* We tag all collections and objects for override. And we also tag all other data-blocks which + * would use one of those. + * Note: missing IDs (aka placeholders) are never overridden. */ + if (ELEM(GS(to_id->name), ID_OB, ID_GR)) { + if ((to_id->tag & LIB_TAG_MISSING)) { + to_id->tag |= missing_tag; + } + else { + to_id->tag |= tag; + } + } - BKE_main_relations_free(bmain); + /* Recursively process the dependencies. */ + LibOverrideGroupTagData sub_data = *data; + sub_data.id_root = to_id; + lib_override_linked_group_tag_recursive(&sub_data); + } } -/** - * Tag all IDs in given \a bmain that are part of the same \a id_root liboverride ID group. - * That is, all other liboverride IDs (in)directly used by \a is_root one, and sharing the same - * library for their reference IDs. +/* This will tag at least all 'boundary' linked IDs for a potential override group. + * + * Requires existing `Main.relations`. * - * \param id_root: The root of the hierarchy of liboverride dependencies to be tagged. - * \param do_create_main_relashionships: Whether main relations needs to be created or already - * exist (in any case, they will be freed by this function). + * Note that you will then need to call #lib_override_hierarchy_dependencies_recursive_tag to + * complete tagging of all dependencies within the override group. + * + * We currently only consider Collections and Objects (that are not used as bone shapes) as valid + * boundary IDs to define an override group. */ -void BKE_lib_override_library_override_group_tag(Main *bmain, - ID *id_root, - const uint tag, - const uint missing_tag, - const bool do_create_main_relashionships) +static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) { - if (do_create_main_relashionships) { - BKE_main_relations_create(bmain, 0); + Main *bmain = data->bmain; + ID *id_root = data->id_root; + + if ((id_root->tag & LIB_TAG_MISSING)) { + id_root->tag |= data->missing_tag; + } + else { + id_root->tag |= data->tag; } - /* We tag all liboverride data-blocks from the same library as reference one, - * being used by the root ID. */ - lib_override_hierarchy_recursive_tag( - bmain, id_root, tag, missing_tag, id_root->override_library->reference->lib); + if (ELEM(GS(id_root->name), ID_OB, ID_GR)) { + /* Tag all collections and objects. */ + lib_override_linked_group_tag_recursive(data); - BKE_main_relations_free(bmain); + /* Then, we remove (untag) bone shape objects, you shall never want to directly/explicitly + * override those. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & data->tag)) { + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { + if (pchan->custom != NULL) { + pchan->custom->id.tag &= ~(data->tag | data->missing_tag); + } + } + } + } + } } -static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_data) +static void lib_override_local_group_tag_recursive(LibOverrideGroupTagData *data) { - if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) { - return IDWALK_RET_STOP_RECURSION; + Main *bmain = data->bmain; + ID *id_owner = data->id_root; + BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner)); + const uint tag = data->tag; + const uint missing_tag = data->missing_tag; + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, + id_owner); + BLI_assert(entry != NULL); + + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ + return; } + /* This way we won't process again that ID, should we encounter it again through another + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; + + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & + (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) != 0) { + /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers), nor + * override references or embedded ID pointers, as actual dependencies. */ + continue; + } - ID *id_root = cb_data->user_data; - Library *library_root = id_root->lib; - ID *id = *cb_data->id_pointer; - ID *id_owner = cb_data->id_owner; - - BLI_assert(id_owner == cb_data->id_self); + ID *to_id = *to_id_entry->id_pointer.to; + if (ELEM(to_id, NULL, id_owner)) { + continue; + } + if (!ID_IS_OVERRIDE_LIBRARY(to_id) || ID_IS_LINKED(to_id)) { + continue; + } - if (ELEM(id, NULL, id_owner)) { - return IDWALK_RET_NOP; - } + /* Do not tag 'virtual' overrides (shape keys here, as we already rejected embedded case + * above). */ + if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id)) { + Library *reference_lib = NULL; + if (GS(id_owner->name) == ID_KE) { + reference_lib = ((Key *)id_owner)->from->override_library->reference->lib; + } + else { + reference_lib = id_owner->override_library->reference->lib; + } + if (to_id->override_library->reference->lib != reference_lib) { + /* We do not override data-blocks from other libraries, nor do we process them. */ + continue; + } - BLI_assert(id->lib != NULL); - BLI_assert(id_owner->lib == library_root); + if (to_id->override_library->reference->tag & LIB_TAG_MISSING) { + to_id->tag |= missing_tag; + } + else { + to_id->tag |= tag; + } + } - if (id->tag & LIB_TAG_DOIT) { - /* Already processed and tagged, nothing else to do here. */ - return IDWALK_RET_STOP_RECURSION; + /* Recursively process the dependencies. */ + LibOverrideGroupTagData sub_data = *data; + sub_data.id_root = to_id; + lib_override_local_group_tag_recursive(&sub_data); } +} - if (id->lib != library_root) { - /* We do not override data-blocks from other libraries, nor do we process them. */ - return IDWALK_RET_STOP_RECURSION; - } +/* This will tag all override IDs of an override group defined by the given `id_root`. */ +static void lib_override_local_group_tag(LibOverrideGroupTagData *data) +{ + ID *id_root = data->id_root; + BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root) && !ID_IS_LINKED(id_root)); - /* We tag all collections and objects for override. And we also tag all other data-blocks which - * would use one of those. - * Note: missing IDs (aka placeholders) are never overridden. */ - if (ELEM(GS(id->name), ID_OB, ID_GR) && !(id->tag & LIB_TAG_MISSING)) { - id->tag |= LIB_TAG_DOIT; + if ((id_root->override_library->reference->tag & LIB_TAG_MISSING)) { + id_root->tag |= data->missing_tag; + } + else { + id_root->tag |= data->tag; } - return IDWALK_RET_NOP; + /* Tag all local overrides in id_root's group. */ + lib_override_local_group_tag_recursive(data); } static bool lib_override_library_create_do(Main *bmain, ID *id_root) { - id_root->tag |= LIB_TAG_DOIT; - BKE_main_relations_create(bmain, 0); + LibOverrideGroupTagData data = { + .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; + lib_override_linked_group_tag(&data); - if (ELEM(GS(id_root->name), ID_OB, ID_GR)) { - /* Tag all collections and objects. */ - BKE_library_foreach_ID_link(bmain, - id_root, - lib_override_library_make_tag_ids_cb, - id_root, - IDWALK_READONLY | IDWALK_RECURSE); - - /* Then, we remove (untag) bone shape objects, you shall never want to override those - * (hopefully). */ - LISTBASE_FOREACH (Object *, ob, &bmain->objects) { - if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) { - for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) { - if (pchan->custom != NULL) { - pchan->custom->id.tag &= ~LIB_TAG_DOIT; - } - } - } - } - } + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); + lib_override_hierarchy_dependencies_recursive_tag(&data); - /* Now tag all non-object/collection IDs 'in-between' two tagged ones, as those are part of an - * override chain and therefore also need to be overridden. - * One very common cases are e.g. drivers on geometry or materials of an overridden object, that - * are using another overridden object as parameter. */ - /* Note that this call will also free the main relations data we created above. */ - BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false); + BKE_main_relations_free(bmain); return BKE_lib_override_library_create_from_tag(bmain); } @@ -737,14 +803,21 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); - /* Tag all collections and objects, as well as other IDs using them. */ - id_root->tag |= LIB_TAG_DOIT; ID *id_root_reference = id_root->override_library->reference; - /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag - * linked reference ones to be overridden again. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING, true); + BKE_main_relations_create(bmain, 0); + LibOverrideGroupTagData data = { + .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; + lib_override_local_group_tag(&data); + + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); + data.id_root = id_root_reference; + lib_override_linked_group_tag(&data); + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); + lib_override_hierarchy_dependencies_recursive_tag(&data); + + /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides. */ GHash *linkedref_to_old_override = BLI_ghash_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); ID *id; @@ -755,17 +828,45 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ * same linked ID in a same hierarchy. */ if (!BLI_ghash_haskey(linkedref_to_old_override, id->override_library->reference)) { BLI_ghash_insert(linkedref_to_old_override, id->override_library->reference, id); - id->override_library->reference->tag |= LIB_TAG_DOIT; + if ((id->override_library->reference->tag & LIB_TAG_DOIT) == 0) { + /* We have an override, but now it does not seem to be necessary to override that ID + * anymore. Check if there are some actual overrides from the user, otherwise assume + * that we can get rid of this local override. */ + LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &id->override_library->properties) { + if (op->rna_prop_type != PROP_POINTER) { + id->override_library->reference->tag |= LIB_TAG_DOIT; + break; + } + + bool do_break = false; + LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { + if ((opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) { + id->override_library->reference->tag |= LIB_TAG_DOIT; + do_break = true; + break; + } + } + if (do_break) { + break; + } + } + } } } } FOREACH_MAIN_ID_END; + /* Code above may have added some tags, we need to update this too. */ + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); + lib_override_hierarchy_dependencies_recursive_tag(&data); + + BKE_main_relations_free(bmain); + /* Make new override from linked data. */ /* Note that this call also remaps all pointers of tagged IDs from old override IDs to new * override IDs (including within the old overrides themselves, since those are tagged too * above). */ - const bool success = lib_override_library_create_do(bmain, id_root_reference); + const bool success = BKE_lib_override_library_create_from_tag(bmain); if (!success) { return success; @@ -828,6 +929,23 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ RNA_id_pointer_create(id_override_old, &rnaptr_src); RNA_id_pointer_create(id_override_new, &rnaptr_dst); + /* We remove any operation tagged with `IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE`, + * that way the potentially new pointer will be properly kept, when old one is still valid + * too (typical case: assigning new ID to some usage, while old one remains used elsewhere + * in the override hierarchy). */ + LISTBASE_FOREACH_MUTABLE ( + IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties) { + LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) { + if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) { + lib_override_library_property_operation_clear(opop); + BLI_freelinkN(&op->operations, opop); + } + } + if (BLI_listbase_is_empty(&op->operations)) { + BKE_lib_override_library_property_delete(id_override_new->override_library, op); + } + } + RNA_struct_override_apply( bmain, &rnaptr_dst, &rnaptr_src, NULL, id_override_new->override_library); } @@ -896,11 +1014,13 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root) { BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); - /* Tag all collections and objects, as well as other IDs using them. */ - id_root->tag |= LIB_TAG_DOIT; - /* Tag all library overrides in the chains of dependencies from the given root one. */ - BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_DOIT, true); + BKE_main_relations_create(bmain, 0); + LibOverrideGroupTagData data = { + .bmain = bmain, .id_root = id_root, .tag = LIB_TAG_DOIT, .missing_tag = LIB_TAG_MISSING}; + lib_override_local_group_tag(&data); + + BKE_main_relations_free(bmain); ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { @@ -1558,24 +1678,26 @@ static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root) &ptr_root_lib); bool prop_exists = RNA_path_resolve_property(&ptr_root, op->rna_path, &ptr, &prop); - BLI_assert(prop_exists); - prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib); - if (prop_exists) { - BLI_assert(ELEM(RNA_property_type(prop), PROP_POINTER, PROP_COLLECTION)); - BLI_assert(RNA_property_type(prop) == RNA_property_type(prop_lib)); - if (is_collection) { - ptr.type = RNA_property_pointer_type(&ptr, prop); - ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib); - } - else { - ptr = RNA_property_pointer_get(&ptr, prop); - ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib); - } - if (ptr.owner_id != NULL && ptr_lib.owner_id != NULL) { - BLI_assert(ptr.type == ptr_lib.type); - do_op_delete = !(RNA_struct_is_ID(ptr.type) && ptr.owner_id->override_library != NULL && - ptr.owner_id->override_library->reference == ptr_lib.owner_id); + prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib); + + if (prop_exists) { + BLI_assert(ELEM(RNA_property_type(prop), PROP_POINTER, PROP_COLLECTION)); + BLI_assert(RNA_property_type(prop) == RNA_property_type(prop_lib)); + if (is_collection) { + ptr.type = RNA_property_pointer_type(&ptr, prop); + ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib); + } + else { + ptr = RNA_property_pointer_get(&ptr, prop); + ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib); + } + if (ptr.owner_id != NULL && ptr_lib.owner_id != NULL) { + BLI_assert(ptr.type == ptr_lib.type); + do_op_delete = !(RNA_struct_is_ID(ptr.type) && + ptr.owner_id->override_library != NULL && + ptr.owner_id->override_library->reference == ptr_lib.owner_id); + } } } } @@ -1619,31 +1741,37 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i return; } - void **entry_pp = BLI_ghash_lookup(bmain->relations->id_user_to_used, id_root); - if (entry_pp == NULL) { - /* Already processed. */ + void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root); + if (entry_vp == NULL) { + /* This ID is not used by nor using any other ID. */ + lib_override_library_id_reset_do(bmain, id_root); + return; + } + + MainIDRelationsEntry *entry = *entry_vp; + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ return; } lib_override_library_id_reset_do(bmain, id_root); /* This way we won't process again that ID, should we encounter it again through another - * relationship hierarchy. - * Note that this does not free any memory from relations, so we can still use the entries. - */ - BKE_main_relations_ID_remove(bmain, id_root); + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; - for (MainIDRelationsEntry *entry = *entry_pp; entry != NULL; entry = entry->next) { - if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) { /* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as * actual dependencies. */ continue; } /* We only consider IDs from the same library. */ - if (entry->id_pointer != NULL) { - ID *id_entry = *entry->id_pointer; - if (id_entry->override_library != NULL) { - lib_override_library_id_hierarchy_recursive_reset(bmain, id_entry); + if (*to_id_entry->id_pointer.to != NULL) { + ID *to_id = *to_id_entry->id_pointer.to; + if (to_id->override_library != NULL) { + lib_override_library_id_hierarchy_recursive_reset(bmain, to_id); } } } @@ -1922,7 +2050,9 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain, ID *local) { if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) { - /* This is actually purely local data with an override template, nothing to do here! */ + /* This is actually purely local data with an override template, or one of those embedded IDs + * (root node trees, master collections or shapekeys) that cannot have their own override. + * Nothing to do here! */ return NULL; } diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index e687e94073d..1fd51544ba7 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -237,9 +237,12 @@ static void library_foreach_ID_link(Main *bmain, * but we might as well use it (Main->relations is always assumed valid, * it's responsibility of code creating it to free it, * especially if/when it starts modifying Main database). */ - MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id); - for (; entry != NULL; entry = entry->next) { - BKE_lib_query_foreachid_process(&data, entry->id_pointer, entry->usage_flag); + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, + id); + for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL; + to_id_entry = to_id_entry->next) { + BKE_lib_query_foreachid_process( + &data, to_id_entry->id_pointer.to, to_id_entry->usage_flag); } continue; } @@ -413,13 +416,14 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) return ELEM(id_type_used, ID_MA); case ID_SIM: return ELEM(id_type_used, ID_OB, ID_IM); + case ID_WM: + return ELEM(id_type_used, ID_SCE, ID_WS); case ID_IM: case ID_VF: case ID_TXT: case ID_SO: case ID_AR: case ID_AC: - case ID_WM: case ID_PAL: case ID_PC: case ID_CF: diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 6a560d51362..d2f1196d804 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -84,6 +84,8 @@ IDTypeInfo IDType_ID_LI = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath) diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index a47a0c043ff..4a2afb7f5e6 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -209,6 +209,8 @@ IDTypeInfo IDType_ID_LA = { .blend_read_expand = light_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; Light *BKE_light_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c index 0553c070fdf..4ef3b8c3237 100644 --- a/source/blender/blenkernel/intern/lightprobe.c +++ b/source/blender/blenkernel/intern/lightprobe.c @@ -107,6 +107,8 @@ IDTypeInfo IDType_ID_LP = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type) diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 8542959d4b0..283e2a94732 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -767,6 +767,8 @@ IDTypeInfo IDType_ID_LS = { .blend_read_expand = linestyle_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; static const char *modifier_name[LS_MODIFIER_NUM] = { diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index 4b577ccec2c..6f94b3355fa 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -211,35 +211,51 @@ void BKE_main_unlock(struct Main *bmain) static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data) { - MainIDRelations *rel = cb_data->user_data; + MainIDRelations *bmain_relations = cb_data->user_data; ID *id_self = cb_data->id_self; ID **id_pointer = cb_data->id_pointer; const int cb_flag = cb_data->cb_flag; if (*id_pointer) { - MainIDRelationsEntry *entry, **entry_p; - - entry = BLI_mempool_alloc(rel->entry_pool); - if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) { - entry->next = *entry_p; - } - else { - entry->next = NULL; + MainIDRelationsEntry **entry_p; + + /* Add `id_pointer` as child of `id_self`. */ + { + if (!BLI_ghash_ensure_p( + bmain_relations->relations_from_pointers, id_self, (void ***)&entry_p)) { + *entry_p = MEM_callocN(sizeof(**entry_p), __func__); + (*entry_p)->session_uuid = id_self->session_uuid; + } + else { + BLI_assert((*entry_p)->session_uuid == id_self->session_uuid); + } + MainIDRelationsEntryItem *to_id_entry = BLI_mempool_alloc(bmain_relations->entry_items_pool); + to_id_entry->next = (*entry_p)->to_ids; + to_id_entry->id_pointer.to = id_pointer; + to_id_entry->session_uuid = (*id_pointer != NULL) ? (*id_pointer)->session_uuid : + MAIN_ID_SESSION_UUID_UNSET; + to_id_entry->usage_flag = cb_flag; + (*entry_p)->to_ids = to_id_entry; } - entry->id_pointer = id_pointer; - entry->usage_flag = cb_flag; - *entry_p = entry; - entry = BLI_mempool_alloc(rel->entry_pool); - if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) { - entry->next = *entry_p; - } - else { - entry->next = NULL; + /* Add `id_self` as parent of `id_pointer`. */ + if (*id_pointer != NULL) { + if (!BLI_ghash_ensure_p( + bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p)) { + *entry_p = MEM_callocN(sizeof(**entry_p), __func__); + (*entry_p)->session_uuid = (*id_pointer)->session_uuid; + } + else { + BLI_assert((*entry_p)->session_uuid == (*id_pointer)->session_uuid); + } + MainIDRelationsEntryItem *from_id_entry = BLI_mempool_alloc( + bmain_relations->entry_items_pool); + from_id_entry->next = (*entry_p)->from_ids; + from_id_entry->id_pointer.from = id_self; + from_id_entry->session_uuid = id_self->session_uuid; + from_id_entry->usage_flag = cb_flag; + (*entry_p)->from_ids = from_id_entry; } - entry->id_pointer = (ID **)id_self; - entry->usage_flag = cb_flag; - *entry_p = entry; } return IDWALK_RET_NOP; @@ -253,61 +269,68 @@ void BKE_main_relations_create(Main *bmain, const short flag) } bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__); - bmain->relations->id_used_to_user = BLI_ghash_new( + bmain->relations->relations_from_pointers = BLI_ghash_new( BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - bmain->relations->id_user_to_used = BLI_ghash_new( - BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - bmain->relations->entry_pool = BLI_mempool_create( - sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP); + bmain->relations->entry_items_pool = BLI_mempool_create( + sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP); + + bmain->relations->flag = flag; ID *id; FOREACH_MAIN_ID_BEGIN (bmain, id) { const int idwalk_flag = IDWALK_READONLY | ((flag & MAINIDRELATIONS_INCLUDE_UI) != 0 ? IDWALK_INCLUDE_UI : 0); + + /* Ensure all IDs do have an entry, even if they are not connected to any other. */ + MainIDRelationsEntry **entry_p; + if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) { + *entry_p = MEM_callocN(sizeof(**entry_p), __func__); + (*entry_p)->session_uuid = id->session_uuid; + } + else { + BLI_assert((*entry_p)->session_uuid == id->session_uuid); + } + BKE_library_foreach_ID_link( NULL, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag); } FOREACH_MAIN_ID_END; - - bmain->relations->flag = flag; } void BKE_main_relations_free(Main *bmain) { - if (bmain->relations) { - if (bmain->relations->id_used_to_user) { - BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL); - } - if (bmain->relations->id_user_to_used) { - BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL); + if (bmain->relations != NULL) { + if (bmain->relations->relations_from_pointers != NULL) { + BLI_ghash_free(bmain->relations->relations_from_pointers, NULL, MEM_freeN); } - BLI_mempool_destroy(bmain->relations->entry_pool); + BLI_mempool_destroy(bmain->relations->entry_items_pool); MEM_freeN(bmain->relations); bmain->relations = NULL; } } -/** - * Remove an ID from the relations (the two entries for that ID, not the ID from entries in other - * IDs' relationships). - * - * Does not free any allocated memory. - * Allows to use those relations as a way to mark an ID as already processed, without requiring any - * additional tagging or GSet. - * Obviously, relations should be freed after use then, since this will make them fully invalid. - */ -void BKE_main_relations_ID_remove(Main *bmain, ID *id) +/** Set or clear given `tag` in all relation entries of given `bmain`. */ +void BKE_main_relations_tag_set(struct Main *bmain, + const MainIDRelationsEntryTags tag, + const bool value) { - if (bmain->relations) { - /* Note: we do not free the entries from the mempool, those will be dealt with when finally - * freeing the whole relations. */ - if (bmain->relations->id_used_to_user) { - BLI_ghash_remove(bmain->relations->id_used_to_user, id, NULL, NULL); + if (bmain->relations == NULL) { + return; + } + + GHashIterator *gh_iter; + for (gh_iter = BLI_ghashIterator_new(bmain->relations->relations_from_pointers); + !BLI_ghashIterator_done(gh_iter); + BLI_ghashIterator_step(gh_iter)) { + MainIDRelationsEntry *entry = BLI_ghashIterator_getValue(gh_iter); + if (value) { + entry->tags |= tag; } - if (bmain->relations->id_user_to_used) { - BLI_ghash_remove(bmain->relations->id_user_to_used, id, NULL, NULL); + else { + entry->tags &= ~tag; } } + BLI_ghashIterator_free(gh_iter); } /** diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 04fec1e57c4..83d9449934c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -270,6 +270,8 @@ IDTypeInfo IDType_ID_MSK = { .blend_read_expand = mask_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; static struct { diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 595fd0c9550..69f60ca0384 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -128,8 +128,8 @@ int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const uns } float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, - unsigned int *tot_diff_point, - const unsigned int resol))[2] + const unsigned int resol, + unsigned int *r_tot_diff_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -140,12 +140,12 @@ float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, if (spline->tot_point <= 1) { /* nothing to differentiate */ - *tot_diff_point = 0; + *r_tot_diff_point = 0; return NULL; } /* len+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = tot; + *r_tot_diff_point = tot; diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets"); a = spline->tot_point - 1; @@ -192,11 +192,11 @@ float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, } float (*BKE_mask_spline_differentiate( - MaskSpline *spline, int width, int height, unsigned int *tot_diff_point))[2] + MaskSpline *spline, int width, int height, unsigned int *r_tot_diff_point))[2] { uint resol = BKE_mask_spline_resolution(spline, width, height); - return BKE_mask_spline_differentiate_with_resolution(spline, tot_diff_point, resol); + return BKE_mask_spline_differentiate_with_resolution(spline, resol, r_tot_diff_point); } /* ** feather points self-intersection collapse routine ** */ @@ -507,9 +507,9 @@ void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ static float (*mask_spline_feather_differentiated_points_with_resolution__even( MaskSpline *spline, - unsigned int *tot_feather_point, const unsigned int resol, - const bool do_feather_isect))[2] + const bool do_feather_isect, + unsigned int *r_tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); MaskSplinePoint *point_curr, *point_prev; @@ -569,7 +569,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__even( point_curr++; } - *tot_feather_point = tot; + *r_tot_feather_point = tot; if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) { BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot); @@ -581,9 +581,9 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__even( /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution() ! */ static float (*mask_spline_feather_differentiated_points_with_resolution__double( MaskSpline *spline, - unsigned int *tot_feather_point, const unsigned int resol, - const bool do_feather_isect))[2] + const bool do_feather_isect, + unsigned int *r_tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -594,12 +594,12 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double if (spline->tot_point <= 1) { /* nothing to differentiate */ - *tot_feather_point = 0; + *r_tot_feather_point = 0; return NULL; } /* len+1 because of 'forward_diff_bezier' function */ - *tot_feather_point = tot; + *r_tot_feather_point = tot; feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets"); a = spline->tot_point - 1; @@ -665,7 +665,7 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]); - /* scale by chane in length */ + /* scale by change in length */ len_scalar = len_feather / len_base; dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], @@ -724,24 +724,24 @@ static float (*mask_spline_feather_differentiated_points_with_resolution__double * values align with #BKE_mask_spline_differentiate_with_resolution * when \a resol arguments match. */ -float ( - *BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, - unsigned int *tot_feather_point, - const unsigned int resol, - const bool do_feather_isect))[2] +float (*BKE_mask_spline_feather_differentiated_points_with_resolution( + MaskSpline *spline, + const unsigned int resol, + const bool do_feather_isect, + unsigned int *r_tot_feather_point))[2] { switch (spline->offset_mode) { case MASK_SPLINE_OFFSET_EVEN: return mask_spline_feather_differentiated_points_with_resolution__even( - spline, tot_feather_point, resol, do_feather_isect); + spline, resol, do_feather_isect, r_tot_feather_point); case MASK_SPLINE_OFFSET_SMOOTH: default: return mask_spline_feather_differentiated_points_with_resolution__double( - spline, tot_feather_point, resol, do_feather_isect); + spline, resol, do_feather_isect, r_tot_feather_point); } } -float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2] +float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *r_tot_feather_point))[2] { MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline); @@ -783,7 +783,7 @@ float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_poin } } - *tot_feather_point = tot; + *r_tot_feather_point = tot; return feather; } @@ -793,7 +793,7 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, - unsigned int *tot_feather_point) + unsigned int *r_tot_feather_point) { float *feather, *fp; unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height); @@ -812,7 +812,7 @@ float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, fp[1] = co[1] + n[1] * weight; } - *tot_feather_point = resol; + *r_tot_feather_point = resol; return feather; } @@ -821,7 +821,7 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, int width, int height, - unsigned int *tot_diff_point) + unsigned int *r_tot_diff_point) { MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point); @@ -837,7 +837,7 @@ float *BKE_mask_point_segment_diff(MaskSpline *spline, } /* resol+1 because of 'forward_diff_bezier' function */ - *tot_diff_point = resol + 1; + *r_tot_diff_point = resol + 1; diff_points = fp = MEM_callocN(sizeof(float[2]) * (resol + 1), "mask segment vets"); for (j = 0; j < 2; j++) { diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 583ee8f2857..d29a6e75954 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -646,11 +646,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, const unsigned int resol_b = BKE_mask_spline_feather_resolution(spline, width, height) / 4; const unsigned int resol = CLAMPIS(MAX2(resol_a, resol_b), 4, 512); - diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, resol, &tot_diff_point); if (do_feather) { diff_feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution( - spline, &tot_diff_feather_points, resol, false); + spline, resol, false, &tot_diff_feather_points); BLI_assert(diff_feather_points); } else { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index e892a3f4d53..70906065347 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -274,6 +274,8 @@ IDTypeInfo IDType_ID_MA = { .blend_read_expand = material_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; void BKE_gpencil_material_attr_init(Material *ma) diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 65ec91c57cf..849c7ef57fb 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -204,6 +204,8 @@ IDTypeInfo IDType_ID_MB = { .blend_read_expand = metaball_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* Functions */ diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 051c7e56ef9..1550401cc9c 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -263,7 +263,7 @@ static void build_bvh_spatial(PROCESS *process, * BASED AT CODE (but mostly rewritten) : * C code from the article * "An Implicit Surface Polygonizer" - * by Jules Bloomenthal, jbloom@beauty.gmu.edu + * by Jules Bloomenthal <jbloom@beauty.gmu.edu> * in "Graphics Gems IV", Academic Press, 1994 * * Authored by Jules Bloomenthal, Xerox PARC. diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 950885d2114..c15484f8e72 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -364,6 +364,8 @@ IDTypeInfo IDType_ID_ME = { .blend_read_expand = mesh_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; enum { @@ -939,7 +941,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src, Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL); - me_dst->mselect = MEM_dupallocN(me_dst->mselect); + me_dst->mselect = MEM_dupallocN(me_src->mselect); me_dst->totvert = verts_len; me_dst->totedge = edges_len; @@ -1217,7 +1219,7 @@ int test_index_face(MFace *mface, CustomData *fdata, int mfindex, int nr) } /* Check corrupt cases, bow-tie geometry, - * cant handle these because edge data wont exist so just return 0. */ + * can't handle these because edge data won't exist so just return 0. */ if (nr == 3) { if ( /* real edges */ diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc index 75dd396d10a..ac6dd96ed90 100644 --- a/source/blender/blenkernel/intern/mesh_fair.cc +++ b/source/blender/blenkernel/intern/mesh_fair.cc @@ -475,7 +475,7 @@ static void prefair_and_fair_vertices(FairingContext *fairing_context, /* Fair. */ VoronoiVertexWeight *voronoi_vertex_weights = new VoronoiVertexWeight(fairing_context); - /* TODO: Implemente cotangent loop weights. */ + /* TODO: Implement cotangent loop weights. */ fairing_context->fair_vertices( affected_vertices, depth, voronoi_vertex_weights, uniform_loop_weights); diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 0aaca33124a..0b0aeb50d37 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -263,6 +263,6 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool keep_existing_edges, const bool select mesh->totedge = new_totedge; mesh->medge = new_edges.data(); - /* Explicitely clear edge maps, because that way it can be parallelized. */ + /* Explicitly clear edge maps, because that way it can be parallelized. */ clear_hash_tables(edge_maps); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index e82ed62ed5b..c1ebd06465b 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -362,6 +362,8 @@ IDTypeInfo IDType_ID_MC = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /*********************** movieclip buffer loaders *************************/ diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 441da8b134a..45ac20ef154 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -781,7 +781,7 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene, smd.levels = smd.renderLevels = lvl; smd.quality = 3; if (!is_plain_uv) { - smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; + smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES; } else { smd.uv_smooth = SUBSURF_UV_SMOOTH_NONE; diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index e3d670f7c39..02b9bb852d6 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -201,8 +201,8 @@ static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex /* Repeat a similar operation for all vertices in the queue. */ /* In this case, add to the queue the vertices connected by 2 steps using the diagonals in any - * direction. If a solution exists and intial_vertex was a pole, this is guaranteed that will tag - * all the (0,0) vertices of the grids, and nothing else. */ + * direction. If a solution exists and `initial_vertex` was a pole, this is guaranteed that will + * tag all the (0,0) vertices of the grids, and nothing else. */ /* If it was not a pole, it may or may not find a solution, even if the solution exists. */ while (!BLI_gsqueue_is_empty(queue)) { BMVert *from_v; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.cc index 76885eadaae..e34afd1ce17 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.cc @@ -25,10 +25,10 @@ #include "MEM_guardedalloc.h" -#include <limits.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> +#include <climits> +#include <cstddef> +#include <cstdlib> +#include <cstring> /* Allow using deprecated functionality for .blend file I/O. */ #define DNA_DEPRECATED_ALLOW @@ -109,7 +109,7 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), static void ntree_init_data(ID *id) { bNodeTree *ntree = (bNodeTree *)id; - ntree_set_typeinfo(ntree, NULL); + ntree_set_typeinfo(ntree, nullptr); } static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag) @@ -121,7 +121,7 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; /* in case a running nodetree is copied */ - ntree_dst->execdata = NULL; + ntree_dst->execdata = nullptr; BLI_listbase_clear(&ntree_dst->nodes); BLI_listbase_clear(&ntree_dst->links); @@ -133,17 +133,17 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata, true); BLI_ghash_insert(new_pointers, (void *)node_src, new_node); /* Store mapping to inputs. */ - bNodeSocket *new_input_sock = new_node->inputs.first; - const bNodeSocket *input_sock_src = node_src->inputs.first; - while (new_input_sock != NULL) { + bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first; + const bNodeSocket *input_sock_src = (const bNodeSocket *)node_src->inputs.first; + while (new_input_sock != nullptr) { BLI_ghash_insert(new_pointers, (void *)input_sock_src, new_input_sock); new_input_sock = new_input_sock->next; input_sock_src = input_sock_src->next; } /* Store mapping to outputs. */ - bNodeSocket *new_output_sock = new_node->outputs.first; - const bNodeSocket *output_sock_src = node_src->outputs.first; - while (new_output_sock != NULL) { + bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first; + const bNodeSocket *output_sock_src = (const bNodeSocket *)node_src->outputs.first; + while (new_output_sock != nullptr) { BLI_ghash_insert(new_pointers, (void *)output_sock_src, new_output_sock); new_output_sock = new_output_sock->next; output_sock_src = output_sock_src->next; @@ -153,10 +153,13 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c /* copy links */ BLI_duplicatelist(&ntree_dst->links, &ntree_src->links); LISTBASE_FOREACH (bNodeLink *, link_dst, &ntree_dst->links) { - link_dst->fromnode = BLI_ghash_lookup_default(new_pointers, link_dst->fromnode, NULL); - link_dst->fromsock = BLI_ghash_lookup_default(new_pointers, link_dst->fromsock, NULL); - link_dst->tonode = BLI_ghash_lookup_default(new_pointers, link_dst->tonode, NULL); - link_dst->tosock = BLI_ghash_lookup_default(new_pointers, link_dst->tosock, NULL); + link_dst->fromnode = (bNode *)BLI_ghash_lookup_default( + new_pointers, link_dst->fromnode, nullptr); + link_dst->fromsock = (bNodeSocket *)BLI_ghash_lookup_default( + new_pointers, link_dst->fromsock, nullptr); + link_dst->tonode = (bNode *)BLI_ghash_lookup_default(new_pointers, link_dst->tonode, nullptr); + link_dst->tosock = (bNodeSocket *)BLI_ghash_lookup_default( + new_pointers, link_dst->tosock, nullptr); /* update the link socket's pointer */ if (link_dst->tosock) { link_dst->tosock->link = link_dst; @@ -166,14 +169,18 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c /* copy interface sockets */ BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs); bNodeSocket *sock_dst, *sock_src; - for (sock_dst = ntree_dst->inputs.first, sock_src = ntree_src->inputs.first; sock_dst != NULL; - sock_dst = sock_dst->next, sock_src = sock_src->next) { + for (sock_dst = (bNodeSocket *)ntree_dst->inputs.first, + sock_src = (bNodeSocket *)ntree_src->inputs.first; + sock_dst != nullptr; + sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { node_socket_copy(sock_dst, sock_src, flag_subdata); } BLI_duplicatelist(&ntree_dst->outputs, &ntree_src->outputs); - for (sock_dst = ntree_dst->outputs.first, sock_src = ntree_src->outputs.first; sock_dst != NULL; - sock_dst = sock_dst->next, sock_src = sock_src->next) { + for (sock_dst = (bNodeSocket *)ntree_dst->outputs.first, + sock_src = (bNodeSocket *)ntree_src->outputs.first; + sock_dst != nullptr; + sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { node_socket_copy(sock_dst, sock_src, flag_subdata); } @@ -185,26 +192,29 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c NODE_INSTANCE_HASH_ITER (iter, ntree_src->previews) { bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); - bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter); BKE_node_instance_hash_insert(ntree_dst->previews, key, BKE_node_preview_copy(preview)); } } else { - ntree_dst->previews = NULL; + ntree_dst->previews = nullptr; } /* update node->parent pointers */ - for (bNode *node_dst = ntree_dst->nodes.first, *node_src = ntree_src->nodes.first; node_dst; - node_dst = node_dst->next, node_src = node_src->next) { + for (bNode *node_dst = (bNode *)ntree_dst->nodes.first, + *node_src = (bNode *)ntree_src->nodes.first; + node_dst; + node_dst = (bNode *)node_dst->next, node_src = (bNode *)node_src->next) { if (node_dst->parent) { - node_dst->parent = BLI_ghash_lookup_default(new_pointers, node_dst->parent, NULL); + node_dst->parent = (bNode *)BLI_ghash_lookup_default( + new_pointers, node_dst->parent, nullptr); } } - BLI_ghash_free(new_pointers, NULL, NULL); + BLI_ghash_free(new_pointers, nullptr, nullptr); /* node tree will generate its own interface type */ - ntree_dst->interface_type = NULL; + ntree_dst->interface_type = nullptr; } static void ntree_free_data(ID *id) @@ -223,7 +233,7 @@ static void ntree_free_data(ID *id) break; case NTREE_TEXTURE: ntreeTexEndExecTree(ntree->execdata); - ntree->execdata = NULL; + ntree->execdata = nullptr; break; } } @@ -267,17 +277,18 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { - bNodeSocketValueObject *default_value = sock->default_value; + bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value; BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); break; } case SOCK_IMAGE: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value; BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); break; } case SOCK_COLLECTION: { - bNodeSocketValueCollection *default_value = sock->default_value; + bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *) + sock->default_value; BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); break; } @@ -327,11 +338,10 @@ static void node_foreach_cache(ID *id, void *user_data) { bNodeTree *nodetree = (bNodeTree *)id; - IDCacheKey key = { - .id_session_uuid = id->session_uuid, - .offset_in_ID = offsetof(bNodeTree, previews), - .cache_v = nodetree->previews, - }; + IDCacheKey key = {0}; + key.id_session_uuid = id->session_uuid; + key.offset_in_ID = offsetof(bNodeTree, previews); + key.cache_v = nodetree->previews; /* TODO, see also `direct_link_nodetree()` in readfile.c. */ #if 0 @@ -351,7 +361,7 @@ static void node_foreach_cache(ID *id, static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock) { - if (sock->default_value == NULL) { + if (sock->default_value == nullptr) { return; } @@ -448,7 +458,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) /* could be handlerized at some point, now only 1 exception still */ if ((ntree->type == NTREE_SHADER) && ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) { - BKE_curvemapping_blend_write(writer, node->storage); + BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) { NodeShaderScript *nss = (NodeShaderScript *)node->storage; @@ -462,11 +472,11 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) { - BKE_curvemapping_blend_write(writer, node->storage); + BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } else if ((ntree->type == NTREE_TEXTURE) && (node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) { - BKE_curvemapping_blend_write(writer, node->storage); + BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage); } else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) { /* pass */ @@ -474,7 +484,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree) else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) { /* Simple forward compatibility for fix for T50736. * Not ideal (there is no ideal solution here), but should do for now. */ - NodeGlare *ndg = node->storage; + NodeGlare *ndg = (NodeGlare *)node->storage; /* Not in undo case. */ if (!BLO_write_is_undo(writer)) { switch (ndg->type) { @@ -543,10 +553,10 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres /* Clean up, important in undo case to reduce false detection of changed datablocks. */ ntree->init = 0; /* to set callbacks and force setting types */ ntree->is_updating = false; - ntree->typeinfo = NULL; - ntree->interface_type = NULL; - ntree->progress = NULL; - ntree->execdata = NULL; + ntree->typeinfo = nullptr; + ntree->interface_type = nullptr; + ntree->progress = nullptr; + ntree->execdata = nullptr; BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id); @@ -560,10 +570,11 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock) IDP_BlendDataRead(reader, &sock->prop); BLO_read_data_address(reader, &sock->link); - sock->typeinfo = NULL; + sock->typeinfo = nullptr; BLO_read_data_address(reader, &sock->storage); BLO_read_data_address(reader, &sock->default_value); - sock->cache = NULL; + sock->total_inputs = 0; /* Clear runtime data set before drawing. */ + sock->cache = nullptr; } /* ntree itself has been read! */ @@ -572,18 +583,18 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) /* note: writing and reading goes in sync, for speed */ ntree->init = 0; /* to set callbacks and force setting types */ ntree->is_updating = false; - ntree->typeinfo = NULL; - ntree->interface_type = NULL; + ntree->typeinfo = nullptr; + ntree->interface_type = nullptr; - ntree->progress = NULL; - ntree->execdata = NULL; + ntree->progress = nullptr; + ntree->execdata = nullptr; BLO_read_data_address(reader, &ntree->adt); BKE_animdata_blend_read_data(reader, ntree->adt); BLO_read_list(reader, &ntree->nodes); LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - node->typeinfo = NULL; + node->typeinfo = nullptr; BLO_read_list(reader, &node->inputs); BLO_read_list(reader, &node->outputs); @@ -618,7 +629,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) case CMP_NODE_HUECORRECT: case TEX_NODE_CURVE_RGB: case TEX_NODE_CURVE_TIME: { - BKE_curvemapping_blend_read(reader, node->storage); + BKE_curvemapping_blend_read(reader, (CurveMapping *)node->storage); break; } case SH_NODE_SCRIPT: { @@ -634,22 +645,22 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) case SH_NODE_TEX_IMAGE: { NodeTexImage *tex = (NodeTexImage *)node->storage; tex->iuser.ok = 1; - tex->iuser.scene = NULL; + tex->iuser.scene = nullptr; break; } case SH_NODE_TEX_ENVIRONMENT: { NodeTexEnvironment *tex = (NodeTexEnvironment *)node->storage; tex->iuser.ok = 1; - tex->iuser.scene = NULL; + tex->iuser.scene = nullptr; break; } case CMP_NODE_IMAGE: case CMP_NODE_R_LAYERS: case CMP_NODE_VIEWER: case CMP_NODE_SPLITVIEWER: { - ImageUser *iuser = node->storage; + ImageUser *iuser = (ImageUser *)node->storage; iuser->ok = 1; - iuser->scene = NULL; + iuser->scene = nullptr; break; } case CMP_NODE_CRYPTOMATTE: { @@ -659,9 +670,9 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) break; } case TEX_NODE_IMAGE: { - ImageUser *iuser = node->storage; + ImageUser *iuser = (ImageUser *)node->storage; iuser->ok = 1; - iuser->scene = NULL; + iuser->scene = nullptr; break; } default: @@ -701,7 +712,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) } /* TODO, should be dealt by new generic cache handling of IDs... */ - ntree->previews = NULL; + ntree->previews = nullptr; /* type verification is in lib-link */ } @@ -718,17 +729,18 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { - bNodeSocketValueObject *default_value = sock->default_value; + bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value; BLO_read_id_address(reader, lib, &default_value->value); break; } case SOCK_IMAGE: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value; BLO_read_id_address(reader, lib, &default_value->value); break; } case SOCK_COLLECTION: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *) + sock->default_value; BLO_read_id_address(reader, lib, &default_value->value); break; } @@ -777,7 +789,7 @@ void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree) * first versioning that can change types still without functions that * update the typeinfo pointers. Versioning after lib linking needs * these top be valid. */ - ntreeSetTypes(NULL, ntree); + ntreeSetTypes(nullptr, ntree); /* For nodes with static socket layout, add/remove sockets as needed * to match the static layout. */ @@ -798,21 +810,22 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock) { IDP_BlendReadExpand(expander, sock->prop); - if (sock->default_value != NULL) { + if (sock->default_value != nullptr) { switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { - bNodeSocketValueObject *default_value = sock->default_value; + bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value; BLO_expand(expander, default_value->value); break; } case SOCK_IMAGE: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value; BLO_expand(expander, default_value->value); break; } case SOCK_COLLECTION: { - bNodeSocketValueCollection *default_value = sock->default_value; + bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *) + sock->default_value; BLO_expand(expander, default_value->value); break; } @@ -866,28 +879,30 @@ static void ntree_blend_read_expand(BlendExpander *expander, ID *id) } IDTypeInfo IDType_ID_NT = { - .id_code = ID_NT, - .id_filter = FILTER_ID_NT, - .main_listbase_index = INDEX_ID_NT, - .struct_size = sizeof(bNodeTree), - .name = "NodeTree", - .name_plural = "node_groups", - .translation_context = BLT_I18NCONTEXT_ID_NODETREE, - .flags = 0, - - .init_data = ntree_init_data, - .copy_data = ntree_copy_data, - .free_data = ntree_free_data, - .make_local = NULL, - .foreach_id = node_foreach_id, - .foreach_cache = node_foreach_cache, - - .blend_write = ntree_blend_write, - .blend_read_data = ntree_blend_read_data, - .blend_read_lib = ntree_blend_read_lib, - .blend_read_expand = ntree_blend_read_expand, - - .blend_read_undo_preserve = NULL, + /* id_code */ ID_NT, + /* id_filter */ FILTER_ID_NT, + /* main_listbase_index */ INDEX_ID_NT, + /* struct_size */ sizeof(bNodeTree), + /* name */ "NodeTree", + /* name_plural */ "node_groups", + /* translation_context */ BLT_I18NCONTEXT_ID_NODETREE, + /* flags */ 0, + + /* init_data */ ntree_init_data, + /* copy_data */ ntree_copy_data, + /* free_data */ ntree_free_data, + /* make_local */ nullptr, + /* foreach_id */ node_foreach_id, + /* foreach_cache */ node_foreach_cache, + + /* blend_write */ ntree_blend_write, + /* blend_read_data */ ntree_blend_read_data, + /* blend_read_lib */ ntree_blend_read_lib, + /* blend_read_expand */ ntree_blend_read_expand, + + /* blend_read_undo_preserve */ nullptr, + + /* lib_override_apply_post */ nullptr, }; static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) @@ -947,11 +962,11 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) node_add_sockets_from_type(ntree, node, ntype); - if (ntype->initfunc != NULL) { + if (ntype->initfunc != nullptr) { ntype->initfunc(ntree, node); } - if (ntree->typeinfo->node_add_init != NULL) { + if (ntree->typeinfo->node_add_init != nullptr) { ntree->typeinfo->node_add_init(ntree, node); } @@ -964,10 +979,10 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node) PointerRNA ptr; RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr); - /* XXX Warning: context can be NULL in case nodes are added in do_versions. + /* XXX Warning: context can be nullptr in case nodes are added in do_versions. * Delayed init is not supported for nodes with context-based initfunc_api atm. */ - BLI_assert(C != NULL); + BLI_assert(C != nullptr); ntype->initfunc_api(C, &ptr); } @@ -997,7 +1012,7 @@ static void node_set_typeinfo(const struct bContext *C, /* for nodes saved in older versions storage can get lost, make undefined then */ if (node->flag & NODE_INIT) { if (typeinfo && typeinfo->storagename[0] && !node->storage) { - typeinfo = NULL; + typeinfo = nullptr; } } @@ -1027,7 +1042,7 @@ static void node_socket_set_typeinfo(bNodeTree *ntree, /* deprecated integer type */ sock->type = typeinfo->type; - if (sock->default_value == NULL) { + if (sock->default_value == nullptr) { /* initialize the default_value pointer used by standard socket types */ node_socket_init_default_value(sock); } @@ -1055,24 +1070,24 @@ static void update_typeinfo(Main *bmain, ntree->init |= NTREE_TYPE_INIT; if (treetype && STREQ(ntree->idname, treetype->idname)) { - ntree_set_typeinfo(ntree, unregister ? NULL : treetype); + ntree_set_typeinfo(ntree, unregister ? nullptr : treetype); } /* initialize nodes */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (nodetype && STREQ(node->idname, nodetype->idname)) { - node_set_typeinfo(C, ntree, node, unregister ? NULL : nodetype); + node_set_typeinfo(C, ntree, node, unregister ? nullptr : nodetype); } /* initialize node sockets */ LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (socktype && STREQ(sock->idname, socktype->idname)) { - node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype); } } LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { if (socktype && STREQ(sock->idname, socktype->idname)) { - node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype); } } } @@ -1080,12 +1095,12 @@ static void update_typeinfo(Main *bmain, /* initialize tree sockets */ LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { if (socktype && STREQ(sock->idname, socktype->idname)) { - node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype); } } LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { if (socktype && STREQ(sock->idname, socktype->idname)) { - node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype); + node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype); } } } @@ -1123,22 +1138,20 @@ void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree) } } -static GHash *nodetreetypes_hash = NULL; -static GHash *nodetypes_hash = NULL; -static GHash *nodesockettypes_hash = NULL; +static GHash *nodetreetypes_hash = nullptr; +static GHash *nodetypes_hash = nullptr; +static GHash *nodesockettypes_hash = nullptr; bNodeTreeType *ntreeTypeFind(const char *idname) { - bNodeTreeType *nt; - if (idname[0]) { - nt = BLI_ghash_lookup(nodetreetypes_hash, idname); + bNodeTreeType *nt = (bNodeTreeType *)BLI_ghash_lookup(nodetreetypes_hash, idname); if (nt) { return nt; } } - return NULL; + return nullptr; } void ntreeTypeAdd(bNodeTreeType *nt) @@ -1147,23 +1160,23 @@ void ntreeTypeAdd(bNodeTreeType *nt) /* XXX pass Main to register function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, nt, NULL, NULL, false); + update_typeinfo(G_MAIN, nullptr, nt, nullptr, nullptr, false); } /* callback for hash value free function */ static void ntree_free_type(void *treetype_v) { - bNodeTreeType *treetype = treetype_v; + bNodeTreeType *treetype = (bNodeTreeType *)treetype_v; /* XXX pass Main to unregister function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, treetype, NULL, NULL, true); + update_typeinfo(G_MAIN, nullptr, treetype, nullptr, nullptr, true); MEM_freeN(treetype); } void ntreeTypeFreeLink(const bNodeTreeType *nt) { - BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type); + BLI_ghash_remove(nodetreetypes_hash, nt->idname, nullptr, ntree_free_type); } bool ntreeIsRegistered(bNodeTree *ntree) @@ -1179,13 +1192,13 @@ GHashIterator *ntreeTypeGetIterator(void) bNodeType *nodeTypeFind(const char *idname) { if (idname[0]) { - bNodeType *nt = BLI_ghash_lookup(nodetypes_hash, idname); + bNodeType *nt = (bNodeType *)BLI_ghash_lookup(nodetypes_hash, idname); if (nt) { return nt; } } - return NULL; + return nullptr; } static void free_dynamic_typeinfo(bNodeType *ntype) @@ -1203,18 +1216,18 @@ static void free_dynamic_typeinfo(bNodeType *ntype) /* callback for hash value free function */ static void node_free_type(void *nodetype_v) { - bNodeType *nodetype = nodetype_v; + bNodeType *nodetype = (bNodeType *)nodetype_v; /* XXX pass Main to unregister function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, NULL, nodetype, NULL, true); + update_typeinfo(G_MAIN, nullptr, nullptr, nodetype, nullptr, true); /* XXX deprecated */ if (nodetype->type == NODE_DYNAMIC) { free_dynamic_typeinfo(nodetype); } - /* Can be NULL when the type is not dynamically allocated. */ + /* Can be null when the type is not dynamically allocated. */ if (nodetype->free_self) { nodetype->free_self(nodetype); } @@ -1224,18 +1237,18 @@ void nodeRegisterType(bNodeType *nt) { /* debug only: basic verification of registered types */ BLI_assert(nt->idname[0] != '\0'); - BLI_assert(nt->poll != NULL); + BLI_assert(nt->poll != nullptr); BLI_ghash_insert(nodetypes_hash, nt->idname, nt); /* XXX pass Main to register function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, NULL, nt, NULL, false); + update_typeinfo(G_MAIN, nullptr, nullptr, nt, nullptr, false); } void nodeUnregisterType(bNodeType *nt) { - BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type); + BLI_ghash_remove(nodetypes_hash, nt->idname, nullptr, node_free_type); } bool nodeTypeUndefined(bNode *node) @@ -1253,23 +1266,23 @@ GHashIterator *nodeTypeGetIterator(void) bNodeSocketType *nodeSocketTypeFind(const char *idname) { if (idname[0]) { - bNodeSocketType *st = BLI_ghash_lookup(nodesockettypes_hash, idname); + bNodeSocketType *st = (bNodeSocketType *)BLI_ghash_lookup(nodesockettypes_hash, idname); if (st) { return st; } } - return NULL; + return nullptr; } /* callback for hash value free function */ static void node_free_socket_type(void *socktype_v) { - bNodeSocketType *socktype = socktype_v; + bNodeSocketType *socktype = (bNodeSocketType *)socktype_v; /* XXX pass Main to unregister function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, NULL, NULL, socktype, true); + update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, socktype, true); socktype->free_self(socktype); } @@ -1280,12 +1293,12 @@ void nodeRegisterSocketType(bNodeSocketType *st) /* XXX pass Main to register function? */ /* Probably not. It is pretty much expected we want to update G_MAIN here I think - * or we'd want to update *all* active Mains, which we cannot do anyway currently. */ - update_typeinfo(G_MAIN, NULL, NULL, NULL, st, false); + update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, st, false); } void nodeUnregisterSocketType(bNodeSocketType *st) { - BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type); + BLI_ghash_remove(nodesockettypes_hash, st->idname, nullptr, node_free_socket_type); } bool nodeSocketIsRegistered(bNodeSocket *sock) @@ -1306,13 +1319,13 @@ struct bNodeSocket *nodeFindSocket(const bNode *node, int in_out, const char *id return sock; } } - return NULL; + return nullptr; } /* find unique socket identifier */ static bool unique_identifier_check(void *arg, const char *identifier) { - struct ListBase *lb = arg; + const ListBase *lb = (const ListBase *)arg; LISTBASE_FOREACH (bNodeSocket *, sock, lb) { if (STREQ(sock->identifier, identifier)) { return true; @@ -1343,14 +1356,14 @@ static bNodeSocket *make_socket(bNodeTree *ntree, BLI_uniquename_cb( unique_identifier_check, lb, "socket", '.', auto_identifier, sizeof(auto_identifier)); - bNodeSocket *sock = MEM_callocN(sizeof(bNodeSocket), "sock"); + bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "sock"); sock->in_out = in_out; BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR); sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF); BLI_strncpy(sock->name, name, NODE_MAXSTR); - sock->storage = NULL; + sock->storage = nullptr; sock->flag |= SOCK_COLLAPSED; sock->type = SOCK_CUSTOM; /* int type undefined by default */ @@ -1364,17 +1377,18 @@ static void socket_id_user_increment(bNodeSocket *sock) { switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { - bNodeSocketValueObject *default_value = sock->default_value; + bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value; id_us_plus((ID *)default_value->value); break; } case SOCK_IMAGE: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value; id_us_plus((ID *)default_value->value); break; } case SOCK_COLLECTION: { - bNodeSocketValueCollection *default_value = sock->default_value; + bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *) + sock->default_value; id_us_plus((ID *)default_value->value); break; } @@ -1396,17 +1410,18 @@ static void socket_id_user_decrement(bNodeSocket *sock) { switch ((eNodeSocketDatatype)sock->type) { case SOCK_OBJECT: { - bNodeSocketValueObject *default_value = sock->default_value; + bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value; id_us_min(&default_value->value->id); break; } case SOCK_IMAGE: { - bNodeSocketValueImage *default_value = sock->default_value; + bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value; id_us_min(&default_value->value->id); break; } case SOCK_COLLECTION: { - bNodeSocketValueCollection *default_value = sock->default_value; + bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *) + sock->default_value; id_us_min(&default_value->value->id); break; } @@ -1437,7 +1452,7 @@ void nodeModifySocketType( if (sock->default_value) { socket_id_user_decrement(sock); MEM_freeN(sock->default_value); - sock->default_value = NULL; + sock->default_value = nullptr; } sock->type = type; @@ -1552,7 +1567,7 @@ const char *nodeStaticSocketType(int type, int subtype) case SOCK_COLLECTION: return "NodeSocketCollection"; } - return NULL; + return nullptr; } const char *nodeStaticSocketInterfaceType(int type, int subtype) @@ -1621,7 +1636,7 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) case SOCK_COLLECTION: return "NodeSocketInterfaceCollection"; } - return NULL; + return nullptr; } bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, @@ -1636,7 +1651,7 @@ bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree, if (!idname) { CLOG_ERROR(&LOG, "static node socket type %d undefined", type); - return NULL; + return nullptr; } bNodeSocket *sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name); @@ -1657,7 +1672,7 @@ bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree, if (!idname) { CLOG_ERROR(&LOG, "static node socket type %d undefined", type); - return NULL; + return nullptr; } bNodeSocket *sock = nodeInsertSocket(ntree, node, in_out, idname, next_sock, identifier, name); @@ -1727,23 +1742,23 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node) /* finds a node based on its name */ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name) { - return BLI_findstring(&ntree->nodes, name, offsetof(bNode, name)); + return (bNode *)BLI_findstring(&ntree->nodes, name, offsetof(bNode, name)); } /* Finds a node based on given socket and returns true on success. */ bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex) { - *r_node = NULL; + *r_node = nullptr; LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs; int index = 0; LISTBASE_FOREACH (bNodeSocket *, tsock, sockets) { if (sock == tsock) { - if (r_node != NULL) { + if (r_node != nullptr) { *r_node = node; } - if (r_sockindex != NULL) { + if (r_sockindex != nullptr) { *r_sockindex = index; } return true; @@ -1762,7 +1777,7 @@ bNode *nodeFindRootParent(bNode *node) if (node->parent) { return nodeFindRootParent(node->parent); } - return node->type == NODE_FRAME ? node : NULL; + return node->type == NODE_FRAME ? node : nullptr; } /** @@ -1821,7 +1836,7 @@ static void iter_backwards_ex(const bNodeTree *ntree, { LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) { bNodeLink *link = sock->link; - if (link == NULL) { + if (link == nullptr) { continue; } if ((link->flag & NODE_LINK_VALID) == 0) { @@ -1901,7 +1916,7 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node) bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname) { - bNode *node = MEM_callocN(sizeof(bNode), "new node"); + bNode *node = (bNode *)MEM_callocN(sizeof(bNode), "new node"); BLI_addtail(&ntree->nodes, node); BLI_strncpy(node->idname, idname, sizeof(node->idname)); @@ -1914,7 +1929,7 @@ bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idnam bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type) { - const char *idname = NULL; + const char *idname = nullptr; NODE_TYPES_BEGIN (ntype) { /* do an extra poll here, because some int types are used @@ -1928,7 +1943,7 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type) NODE_TYPES_END; if (!idname) { CLOG_ERROR(&LOG, "static node type %d undefined", type); - return NULL; + return nullptr; } return nodeAddNode(C, ntree, idname); } @@ -1951,7 +1966,7 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, /* XXX some compositor node (e.g. image, render layers) still store * some persistent buffer data here, need to clear this to avoid dangling pointers. */ - sock_dst->cache = NULL; + sock_dst->cache = nullptr; } /* keep socket listorder identical, for copying links */ @@ -1962,7 +1977,7 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, const int flag, const bool unique_name) { - bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node"); + bNode *node_dst = (bNode *)MEM_callocN(sizeof(bNode), "dupli node"); bNodeSocket *sock_dst, *sock_src; bNodeLink *link_dst, *link_src; @@ -1977,14 +1992,18 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, } BLI_duplicatelist(&node_dst->inputs, &node_src->inputs); - for (sock_dst = node_dst->inputs.first, sock_src = node_src->inputs.first; sock_dst != NULL; - sock_dst = sock_dst->next, sock_src = sock_src->next) { + for (sock_dst = (bNodeSocket *)node_dst->inputs.first, + sock_src = (bNodeSocket *)node_src->inputs.first; + sock_dst != nullptr; + sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { node_socket_copy(sock_dst, sock_src, flag); } BLI_duplicatelist(&node_dst->outputs, &node_src->outputs); - for (sock_dst = node_dst->outputs.first, sock_src = node_src->outputs.first; sock_dst != NULL; - sock_dst = sock_dst->next, sock_src = sock_src->next) { + for (sock_dst = (bNodeSocket *)node_dst->outputs.first, + sock_src = (bNodeSocket *)node_src->outputs.first; + sock_dst != nullptr; + sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) { node_socket_copy(sock_dst, sock_src, flag); } @@ -1993,9 +2012,10 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, } BLI_duplicatelist(&node_dst->internal_links, &node_src->internal_links); - for (link_dst = node_dst->internal_links.first, link_src = node_src->internal_links.first; - link_dst != NULL; - link_dst = link_dst->next, link_src = link_src->next) { + for (link_dst = (bNodeLink *)node_dst->internal_links.first, + link_src = (bNodeLink *)node_src->internal_links.first; + link_dst != nullptr; + link_dst = (bNodeLink *)link_dst->next, link_src = (bNodeLink *)link_src->next) { /* This is a bit annoying to do index lookups in a list, but is likely to be faster than * trying to create a hash-map. At least for usual nodes, which only have so much sockets * and internal links. */ @@ -2005,8 +2025,8 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, BLI_assert(to_sock_index != -1); link_dst->fromnode = node_dst; link_dst->tonode = node_dst; - link_dst->fromsock = BLI_findlink(&node_dst->inputs, from_sock_index); - link_dst->tosock = BLI_findlink(&node_dst->outputs, to_sock_index); + link_dst->fromsock = (bNodeSocket *)BLI_findlink(&node_dst->inputs, from_sock_index); + link_dst->tosock = (bNodeSocket *)BLI_findlink(&node_dst->outputs, to_sock_index); } if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { @@ -2017,7 +2037,7 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree, node_src->typeinfo->copyfunc(ntree, node_dst, node_src); } - node_dst->new_node = NULL; + node_dst->new_node = nullptr; /* Only call copy function when a copy is made for the main database, not * for cases like the dependency graph and localization. */ @@ -2040,17 +2060,17 @@ static void node_set_new_pointers(bNode *node_src, bNode *new_node) /* Store mapping to the node itself. */ node_src->new_node = new_node; /* Store mapping to inputs. */ - bNodeSocket *new_input_sock = new_node->inputs.first; - bNodeSocket *input_sock_src = node_src->inputs.first; - while (new_input_sock != NULL) { + bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first; + bNodeSocket *input_sock_src = (bNodeSocket *)node_src->inputs.first; + while (new_input_sock != nullptr) { input_sock_src->new_sock = new_input_sock; new_input_sock = new_input_sock->next; input_sock_src = input_sock_src->next; } /* Store mapping to outputs. */ - bNodeSocket *new_output_sock = new_node->outputs.first; - bNodeSocket *output_sock_src = node_src->outputs.first; - while (new_output_sock != NULL) { + bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first; + bNodeSocket *output_sock_src = (bNodeSocket *)node_src->outputs.first; + while (new_output_sock != nullptr) { output_sock_src->new_sock = new_output_sock; new_output_sock = new_output_sock->next; output_sock_src = output_sock_src->next; @@ -2069,9 +2089,9 @@ bNodeTree *ntreeCopyTree_ex_new_pointers(const bNodeTree *ntree, const bool do_id_user) { bNodeTree *new_ntree = ntreeCopyTree_ex(ntree, bmain, do_id_user); - bNode *new_node = new_ntree->nodes.first; - bNode *node_src = ntree->nodes.first; - while (new_node != NULL) { + bNode *new_node = (bNode *)new_ntree->nodes.first; + bNode *node_src = (bNode *)ntree->nodes.first; + while (new_node != nullptr) { node_set_new_pointers(node_src, new_node); new_node = new_node->next; node_src = node_src->next; @@ -2083,14 +2103,14 @@ bNodeTree *ntreeCopyTree_ex_new_pointers(const bNodeTree *ntree, bNodeLink *nodeAddLink( bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock) { - bNodeLink *link = NULL; + bNodeLink *link = nullptr; /* test valid input */ BLI_assert(fromnode); BLI_assert(tonode); if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) { - link = MEM_callocN(sizeof(bNodeLink), "link"); + link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "link"); if (ntree) { BLI_addtail(&ntree->links, link); } @@ -2101,7 +2121,7 @@ bNodeLink *nodeAddLink( } else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) { /* OK but flip */ - link = MEM_callocN(sizeof(bNodeLink), "link"); + link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "link"); if (ntree) { BLI_addtail(&ntree->links, link); } @@ -2126,7 +2146,7 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link) } if (link->tosock) { - link->tosock->link = NULL; + link->tosock->link = nullptr; } MEM_freeN(link); @@ -2137,10 +2157,7 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link) void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) { - bNodeLink *link, *next; - - for (link = ntree->links.first; link; link = next) { - next = link->next; + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { if (link->fromsock == sock || link->tosock == sock) { nodeRemLink(ntree, link); } @@ -2149,7 +2166,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock) ntree->update |= NTREE_UPDATE_LINKS; } -bool nodeLinkIsHidden(bNodeLink *link) +bool nodeLinkIsHidden(const bNodeLink *link) { return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock); } @@ -2200,7 +2217,7 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node) } } -void nodeToView(bNode *node, float x, float y, float *rx, float *ry) +void nodeToView(const bNode *node, float x, float y, float *rx, float *ry) { if (node->parent) { nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry); @@ -2211,7 +2228,7 @@ void nodeToView(bNode *node, float x, float y, float *rx, float *ry) } } -void nodeFromView(bNode *node, float x, float y, float *rx, float *ry) +void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry) { if (node->parent) { nodeFromView(node->parent, x, y, rx, ry); @@ -2224,10 +2241,10 @@ void nodeFromView(bNode *node, float x, float y, float *rx, float *ry) } } -bool nodeAttachNodeCheck(bNode *node, bNode *parent) +bool nodeAttachNodeCheck(const bNode *node, const bNode *parent) { - for (bNode *parent_recurse = node; parent_recurse; parent_recurse = parent_recurse->parent) { - if (parent_recurse == parent) { + for (const bNode *parent_iter = node; parent_iter; parent_iter = parent_iter->parent) { + if (parent_iter == parent) { return true; } } @@ -2258,7 +2275,7 @@ void nodeDetachNode(struct bNode *node) nodeToView(node, 0.0f, 0.0f, &locx, &locy); node->locx = locx; node->locy = locy; - node->parent = NULL; + node->parent = nullptr; } } @@ -2307,7 +2324,7 @@ void nodePositionRelative(bNode *from_node, void nodePositionPropagate(bNode *node) { LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) { - if (nsock->link != NULL) { + if (nsock->link != nullptr) { bNodeLink *link = nsock->link; nodePositionRelative(link->fromnode, link->tonode, link->fromsock, link->tosock); nodePositionPropagate(link->fromnode); @@ -2317,17 +2334,15 @@ void nodePositionPropagate(bNode *node) bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) { - bNodeTree *ntree; - /* trees are created as local trees for compositor, material or texture nodes, * node groups and other tree types are created as library data. */ - const bool is_embedded = (bmain == NULL); + const bool is_embedded = (bmain == nullptr); int flag = 0; if (is_embedded) { flag |= LIB_ID_CREATE_NO_MAIN; } - ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag); + bNodeTree *ntree = (bNodeTree *)BKE_libblock_alloc(bmain, ID_NT, name, flag); if (is_embedded) { ntree->id.flag |= LIB_EMBEDDED_DATA; } @@ -2347,7 +2362,7 @@ bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_i { const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN; - bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, NULL, flag); + bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, nullptr, flag); return ntree_copy; } bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) @@ -2362,7 +2377,7 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) * using BKE_node_preview_init_tree to set up previews for a whole node tree in advance. * This should be left more to the individual node tree implementations. */ -int BKE_node_preview_used(bNode *node) +bool BKE_node_preview_used(const bNode *node) { /* XXX check for closed nodes? */ return (node->typeinfo->flag & NODE_PREVIEW) != 0; @@ -2371,14 +2386,14 @@ int BKE_node_preview_used(bNode *node) bNodePreview *BKE_node_preview_verify( bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create) { - bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key); + bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_lookup(previews, key); if (!preview) { if (create) { - preview = MEM_callocN(sizeof(bNodePreview), "node preview"); + preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview"); BKE_node_instance_hash_insert(previews, key, preview); } else { - return NULL; + return nullptr; } } @@ -2391,12 +2406,13 @@ bNodePreview *BKE_node_preview_verify( if (preview->rect) { if (preview->xsize != xsize || preview->ysize != ysize) { MEM_freeN(preview->rect); - preview->rect = NULL; + preview->rect = nullptr; } } - if (preview->rect == NULL) { - preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char[4]), "node preview rect"); + if (preview->rect == nullptr) { + preview->rect = (unsigned char *)MEM_callocN(4 * xsize + xsize * ysize * sizeof(char[4]), + "node preview rect"); preview->xsize = xsize; preview->ysize = ysize; } @@ -2407,9 +2423,9 @@ bNodePreview *BKE_node_preview_verify( bNodePreview *BKE_node_preview_copy(bNodePreview *preview) { - bNodePreview *new_preview = MEM_dupallocN(preview); + bNodePreview *new_preview = (bNodePreview *)MEM_dupallocN(preview); if (preview->rect) { - new_preview->rect = MEM_dupallocN(preview->rect); + new_preview->rect = (unsigned char *)MEM_dupallocN(preview->rect); } return new_preview; } @@ -2498,7 +2514,7 @@ void BKE_node_preview_free_tree(bNodeTree *ntree) if (ntree->previews) { BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free); - ntree->previews = NULL; + ntree->previews = nullptr; } } @@ -2517,7 +2533,7 @@ void BKE_node_preview_clear_tree(bNodeTree *ntree) bNodeInstanceHashIterator iter; NODE_INSTANCE_HASH_ITER (iter, ntree->previews) { - bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter); BKE_node_preview_clear(preview); } } @@ -2547,8 +2563,8 @@ void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree) bNodeInstanceHashIterator iter; NODE_INSTANCE_HASH_ITER (iter, from_previews) { bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); - bNodePreview *from = BKE_node_instance_hash_iterator_get_value(&iter); - bNodePreview *to = BKE_node_instance_hash_lookup(to_previews, key); + bNodePreview *from = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter); + bNodePreview *to = (bNodePreview *)BKE_node_instance_hash_lookup(to_previews, key); if (from && to) { node_preview_sync(to, from); @@ -2566,7 +2582,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo /* transfer previews */ to_ntree->previews = from_ntree->previews; - from_ntree->previews = NULL; + from_ntree->previews = nullptr; /* clean up, in case any to_ntree nodes have been removed */ BKE_node_preview_remove_unused(to_ntree); @@ -2576,7 +2592,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo bNodeInstanceHashIterator iter; NODE_INSTANCE_HASH_ITER (iter, from_ntree->previews) { bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter); - bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter); + bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter); /* replace existing previews */ BKE_node_instance_hash_remove( @@ -2584,10 +2600,10 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo BKE_node_instance_hash_insert(to_ntree->previews, key, preview); } - /* Note: NULL free function here, + /* Note: null free function here, * because pointers have already been moved over to to_ntree->previews! */ - BKE_node_instance_hash_free(from_ntree->previews, NULL); - from_ntree->previews = NULL; + BKE_node_instance_hash_free(from_ntree->previews, nullptr); + from_ntree->previews = nullptr; } } } @@ -2633,7 +2649,7 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node) lb = &node->inputs; } else { - lb = NULL; + lb = nullptr; } if (lb) { @@ -2677,7 +2693,7 @@ static void node_free_node(bNodeTree *ntree, bNode *node) /* texture node has bad habit of keeping exec data around */ if (ntree->type == NTREE_TEXTURE && ntree->execdata) { ntreeTexEndExecTree(ntree->execdata); - ntree->execdata = NULL; + ntree->execdata = nullptr; } } @@ -2754,7 +2770,7 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc); if (BKE_animdata_fix_paths_remove((ID *)ntree, prefix)) { - if (bmain != NULL) { + if (bmain != nullptr) { DEG_relations_tag_update(bmain); } } @@ -2826,7 +2842,7 @@ void ntreeFreeLocalTree(bNodeTree *ntree) void ntreeFreeCache(bNodeTree *ntree) { - if (ntree == NULL) { + if (ntree == nullptr) { return; } @@ -2925,7 +2941,7 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id) case ID_SIM: return &((Simulation *)id)->nodetree; default: - return NULL; + return nullptr; } } @@ -2933,10 +2949,10 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id) bNodeTree *ntreeFromID(ID *id) { bNodeTree **nodetree = BKE_ntree_ptr_from_id(id); - return (nodetree != NULL) ? *nodetree : NULL; + return (nodetree != nullptr) ? *nodetree : nullptr; } -/* Finds and returns the datablock that privately owns the given tree, or NULL. */ +/* Finds and returns the datablock that privately owns the given tree, or null. */ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) { ListBase *lists[] = {&bmain->materials, @@ -2946,9 +2962,9 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) &bmain->scenes, &bmain->linestyles, &bmain->simulations, - NULL}; + nullptr}; - for (int i = 0; lists[i] != NULL; i++) { + for (int i = 0; lists[i] != nullptr; i++) { LISTBASE_FOREACH (ID *, id, lists[i]) { if (ntreeFromID(id) == ntree) { return id; @@ -2956,12 +2972,12 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree) } } - return NULL; + return nullptr; } -bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode) +bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode) { - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) { if (node == testnode) { return true; } @@ -2969,9 +2985,9 @@ bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode) return false; } -bool ntreeOutputExists(bNode *node, bNodeSocket *testsock) +bool ntreeOutputExists(const bNode *node, const bNodeSocket *testsock) { - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + LISTBASE_FOREACH (const bNodeSocket *, sock, &node->outputs) { if (sock == testsock) { return true; } @@ -2999,7 +3015,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) * Note: previews are not copied here. */ bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex( - NULL, &ntree->id, NULL, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA)); + nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA)); ltree->id.tag |= LIB_TAG_LOCALIZED; @@ -3012,9 +3028,9 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) /* ensures only a single output node is enabled */ ntreeSetOutput(ntree); - bNode *node_src = ntree->nodes.first; - bNode *node_local = ltree->nodes.first; - while (node_src != NULL) { + bNode *node_src = (bNode *)ntree->nodes.first; + bNode *node_local = (bNode *)ltree->nodes.first; + while (node_src != nullptr) { node_local->original = node_src; node_src = node_src->next; node_local = node_local->next; @@ -3027,7 +3043,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) return ltree; } - return NULL; + return nullptr; } /* sync local composite with real tree */ @@ -3066,11 +3082,11 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree, bNodeSocketType *stype = nodeSocketTypeFind(idname); int own_index = ntree->cur_index++; - if (stype == NULL) { - return NULL; + if (stype == nullptr) { + return nullptr; } - bNodeSocket *sock = MEM_callocN(sizeof(bNodeSocket), "socket template"); + bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "socket template"); BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname)); node_socket_set_typeinfo(ntree, sock, stype); sock->in_out = in_out; @@ -3089,7 +3105,7 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree, sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF); BLI_strncpy(sock->name, name, NODE_MAXSTR); - sock->storage = NULL; + sock->storage = nullptr; sock->flag |= SOCK_COLLAPSED; return sock; @@ -3103,7 +3119,7 @@ bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char * return iosock; } } - return NULL; + return nullptr; } bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree, @@ -3190,7 +3206,7 @@ static void ntree_interface_identifier_base(bNodeTree *ntree, char *base) /* check if the identifier is already in use */ static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier) { - return (RNA_struct_find(identifier) != NULL); + return (RNA_struct_find(identifier) != nullptr); } /* generates the actual unique identifier and ui name and description */ @@ -3206,7 +3222,8 @@ static void ntree_interface_identifier(bNodeTree *ntree, * On top of the sanitized id string add a number suffix if necessary to avoid duplicates. */ identifier[0] = '\0'; - BLI_uniquename_cb(ntree_interface_unique_identifier_check, NULL, base, '_', identifier, maxlen); + BLI_uniquename_cb( + ntree_interface_unique_identifier_check, nullptr, base, '_', identifier, maxlen); sprintf(name, "Node Tree %s Interface", ntree->id.name + 2); sprintf(description, "Interface properties of node group %s", ntree->id.name + 2); @@ -3246,7 +3263,7 @@ static void ntree_interface_type_create(bNodeTree *ntree) } } -StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create) +StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, bool create) { if (ntree->interface_type) { /* strings are generated from base string + ID name, sizes are sufficient */ @@ -3284,7 +3301,7 @@ void ntreeInterfaceTypeFree(bNodeTree *ntree) { if (ntree->interface_type) { RNA_struct_free(&BLENDER_RNA, ntree->interface_type); - ntree->interface_type = NULL; + ntree->interface_type = nullptr; } } @@ -3310,12 +3327,12 @@ bNode *ntreeFindType(const bNodeTree *ntree, int type) } } } - return NULL; + return nullptr; } bool ntreeHasType(const bNodeTree *ntree, int type) { - return ntreeFindType(ntree, type) != NULL; + return ntreeFindType(ntree, type) != nullptr; } bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup) @@ -3333,7 +3350,7 @@ bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup) return false; } -bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) +bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to) { LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { if (link->fromsock == from && link->tosock == to) { @@ -3343,13 +3360,13 @@ bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to) return link; } } - return NULL; + return nullptr; } -int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock) +int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock) { int tot = 0; - LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) { if (link->fromsock == sock || link->tosock == sock) { tot++; } @@ -3359,8 +3376,8 @@ int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock) bNode *nodeGetActive(bNodeTree *ntree) { - if (ntree == NULL) { - return NULL; + if (ntree == nullptr) { + return nullptr; } LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { @@ -3368,7 +3385,7 @@ bNode *nodeGetActive(bNodeTree *ntree) return node; } } - return NULL; + return nullptr; } static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key, @@ -3400,7 +3417,7 @@ static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key, } } } - return NULL; + return nullptr; } /* two active flags, ID nodes have special flag for buttons display */ @@ -3410,14 +3427,14 @@ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype) return node_get_active_id_recursive( ntree->active_viewer_key, NODE_INSTANCE_KEY_BASE, ntree, idtype); } - return NULL; + return nullptr; } bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) { bool ok = false; - if (ntree == NULL) { + if (ntree == nullptr) { return ok; } @@ -3435,11 +3452,11 @@ bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) /* update all groups linked from here * if active ID node has been found already, - * just pass NULL so other matching nodes are deactivated. + * just pass null so other matching nodes are deactivated. */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->type == NODE_GROUP) { - ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : NULL)); + ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : nullptr)); } } @@ -3449,7 +3466,7 @@ bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id) /* two active flags, ID nodes have special flag for buttons display */ void nodeClearActiveID(bNodeTree *ntree, short idtype) { - if (ntree == NULL) { + if (ntree == nullptr) { return; } @@ -3480,7 +3497,7 @@ void nodeSetSelected(bNode *node, bool select) void nodeClearActive(bNodeTree *ntree) { - if (ntree == NULL) { + if (ntree == nullptr) { return; } @@ -3515,7 +3532,7 @@ void nodeSetActive(bNodeTree *ntree, bNode *node) } } -int nodeSocketIsHidden(bNodeSocket *sock) +int nodeSocketIsHidden(const bNodeSocket *sock) { return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0); } @@ -3530,10 +3547,13 @@ void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available) } } -int nodeSocketLinkLimit(struct bNodeSocket *sock) +int nodeSocketLinkLimit(const bNodeSocket *sock) { bNodeSocketType *stype = sock->typeinfo; - if (stype != NULL && stype->use_link_limits_of_type) { + if (sock->flag & SOCK_MULTI_INPUT) { + return 4095; + } + if (stype != nullptr && stype->use_link_limits_of_type) { int limit = (sock->in_out == SOCK_IN) ? stype->input_link_limit : stype->output_link_limit; return limit; } @@ -3553,15 +3573,15 @@ int nodeSocketLinkLimit(struct bNodeSocket *sock) * Currently its only used for ID's, but nodes may one day * reference other pointers which need validation. */ -typedef struct bNodeClipboardExtraInfo { +struct bNodeClipboardExtraInfo { struct bNodeClipboardExtraInfo *next, *prev; ID *id; char id_name[MAX_ID_NAME]; char library_name[FILE_MAX]; -} bNodeClipboardExtraInfo; +}; #endif /* USE_NODE_CB_VALIDATE */ -typedef struct bNodeClipboard { +struct bNodeClipboard { ListBase nodes; #ifdef USE_NODE_CB_VALIDATE @@ -3570,11 +3590,11 @@ typedef struct bNodeClipboard { ListBase links; int type; -} bNodeClipboard; +}; -static bNodeClipboard node_clipboard = {{NULL}}; +static bNodeClipboard node_clipboard = {{nullptr}}; -void BKE_node_clipboard_init(struct bNodeTree *ntree) +void BKE_node_clipboard_init(const struct bNodeTree *ntree) { node_clipboard.type = ntree->type; } @@ -3582,12 +3602,12 @@ void BKE_node_clipboard_init(struct bNodeTree *ntree) void BKE_node_clipboard_clear(void) { LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node_clipboard.links) { - nodeRemLink(NULL, link); + nodeRemLink(nullptr, link); } BLI_listbase_clear(&node_clipboard.links); LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_clipboard.nodes) { - node_free_node(NULL, node); + node_free_node(nullptr, node); } BLI_listbase_clear(&node_clipboard.nodes); @@ -3609,8 +3629,10 @@ bool BKE_node_clipboard_validate(void) BLI_assert(BLI_listbase_count(&node_clipboard.nodes) == BLI_listbase_count(&node_clipboard.nodes_extra_info)); - for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first; node; - node = node->next, node_info = node_info->next) { + for (node = (bNode *)node_clipboard.nodes.first, + node_info = (bNodeClipboardExtraInfo *)node_clipboard.nodes_extra_info.first; + node; + node = (bNode *)node->next, node_info = (bNodeClipboardExtraInfo *)node_info->next) { /* validate the node against the stored node info */ /* re-assign each loop since we may clear, @@ -3621,13 +3643,13 @@ bool BKE_node_clipboard_validate(void) if (node->id) { /* We want to search into current blend file, so using G_MAIN is valid here too. */ ListBase *lb = which_libbase(G_MAIN, GS(node_info->id_name)); - BLI_assert(lb != NULL); + BLI_assert(lb != nullptr); if (BLI_findindex(lb, node_info->id) == -1) { - /* may assign NULL */ - node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2); + /* May assign null. */ + node->id = (ID *)BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2); - if (node->id == NULL) { + if (node->id == nullptr) { ok = false; } } @@ -3642,8 +3664,8 @@ void BKE_node_clipboard_add_node(bNode *node) { #ifdef USE_NODE_CB_VALIDATE /* add extra info */ - bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo), - "bNodeClipboardExtraInfo"); + bNodeClipboardExtraInfo *node_info = (bNodeClipboardExtraInfo *)MEM_mallocN( + sizeof(bNodeClipboardExtraInfo), __func__); node_info->id = node->id; if (node->id) { @@ -3718,11 +3740,11 @@ static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str return hash; } -bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, bNodeTree *ntree, bNode *node) +bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, + const bNodeTree *ntree, + const bNode *node) { - bNodeInstanceKey key; - - key = node_hash_int_str(parent_key, ntree->id.name + 2); + bNodeInstanceKey key = node_hash_int_str(parent_key, ntree->id.name + 2); if (node) { key = node_hash_int_str(key, node->name); @@ -3746,7 +3768,7 @@ static bool node_instance_hash_key_cmp(const void *a, const void *b) bNodeInstanceHash *BKE_node_instance_hash_new(const char *info) { - bNodeInstanceHash *hash = MEM_mallocN(sizeof(bNodeInstanceHash), info); + bNodeInstanceHash *hash = (bNodeInstanceHash *)MEM_mallocN(sizeof(bNodeInstanceHash), info); hash->ghash = BLI_ghash_new( node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash"); return hash; @@ -3754,13 +3776,13 @@ bNodeInstanceHash *BKE_node_instance_hash_new(const char *info) void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp) { - BLI_ghash_free(hash->ghash, NULL, (GHashValFreeFP)valfreefp); + BLI_ghash_free(hash->ghash, nullptr, (GHashValFreeFP)valfreefp); MEM_freeN(hash); } void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value) { - bNodeInstanceHashEntry *entry = value; + bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value; entry->key = key; entry->tag = 0; BLI_ghash_insert(hash->ghash, &entry->key, value); @@ -3775,17 +3797,17 @@ int BKE_node_instance_hash_remove(bNodeInstanceHash *hash, bNodeInstanceKey key, bNodeInstanceValueFP valfreefp) { - return BLI_ghash_remove(hash->ghash, &key, NULL, (GHashValFreeFP)valfreefp); + return BLI_ghash_remove(hash->ghash, &key, nullptr, (GHashValFreeFP)valfreefp); } void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp) { - BLI_ghash_clear(hash->ghash, NULL, (GHashValFreeFP)valfreefp); + BLI_ghash_clear(hash->ghash, nullptr, (GHashValFreeFP)valfreefp); } void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key) { - return BLI_ghash_popkey(hash->ghash, &key, NULL); + return BLI_ghash_popkey(hash->ghash, &key, nullptr); } int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key) @@ -3803,7 +3825,8 @@ void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash) bNodeInstanceHashIterator iter; NODE_INSTANCE_HASH_ITER (iter, hash) { - bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter); + bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *) + BKE_node_instance_hash_iterator_get_value(&iter); value->tag = 0; } @@ -3811,13 +3834,14 @@ void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash) void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value) { - bNodeInstanceHashEntry *entry = value; + bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value; entry->tag = 1; } bool BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key) { - bNodeInstanceHashEntry *entry = BKE_node_instance_hash_lookup(hash, key); + bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)BKE_node_instance_hash_lookup(hash, + key); if (entry) { entry->tag = 1; @@ -3833,13 +3857,14 @@ void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash, /* NOTE: Hash must not be mutated during iterating! * Store tagged entries in a separate list and remove items afterward. */ - bNodeInstanceKey *untagged = MEM_mallocN(sizeof(bNodeInstanceKey) * - BKE_node_instance_hash_size(hash), - "temporary node instance key list"); + bNodeInstanceKey *untagged = (bNodeInstanceKey *)MEM_mallocN( + sizeof(bNodeInstanceKey) * BKE_node_instance_hash_size(hash), + "temporary node instance key list"); bNodeInstanceHashIterator iter; int num_untagged = 0; NODE_INSTANCE_HASH_ITER (iter, hash) { - bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter); + bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *) + BKE_node_instance_hash_iterator_get_value(&iter); if (!value->tag) { untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter); @@ -3893,22 +3918,23 @@ static int node_get_deplist_recurs(bNodeTree *ntree, bNode *node, bNode ***nsort return level; } -void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes) +void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***r_deplist, int *r_deplist_len) { - *totnodes = 0; + *r_deplist_len = 0; /* first clear data */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { node->done = false; - (*totnodes)++; + (*r_deplist_len)++; } - if (*totnodes == 0) { - *deplist = NULL; + if (*r_deplist_len == 0) { + *r_deplist = nullptr; return; } bNode **nsort; - nsort = *deplist = MEM_callocN((*totnodes) * sizeof(bNode *), "sorted node array"); + nsort = *r_deplist = (bNode **)MEM_callocN((*r_deplist_len) * sizeof(bNode *), + "sorted node array"); /* recursive check */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { @@ -3929,7 +3955,7 @@ static void ntree_update_node_level(bNodeTree *ntree) /* recursive check */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->done == 0) { - node->level = node_get_deplist_recurs(ntree, node, NULL); + node->level = node_get_deplist_recurs(ntree, node, nullptr); } } } @@ -3957,7 +3983,7 @@ static void ntree_update_link_pointers(bNodeTree *ntree) /* first clear data */ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - sock->link = NULL; + sock->link = nullptr; } } @@ -3996,7 +4022,7 @@ void ntreeUpdateAllNew(Main *main) } } - ntreeUpdateTree(NULL, ntree); + ntreeUpdateTree(nullptr, ntree); } } FOREACH_NODETREE_END; @@ -4004,7 +4030,7 @@ void ntreeUpdateAllNew(Main *main) void ntreeUpdateAllUsers(Main *main, ID *id) { - if (id == NULL) { + if (id == nullptr) { return; } @@ -4023,7 +4049,7 @@ void ntreeUpdateAllUsers(Main *main, ID *id) } if (need_update) { - ntreeUpdateTree(NULL, ntree); + ntreeUpdateTree(nullptr, ntree); } } FOREACH_NODETREE_END; @@ -4133,7 +4159,7 @@ bool nodeUpdateID(bNodeTree *ntree, ID *id) { bool changed = false; - if (ELEM(NULL, id, ntree)) { + if (ELEM(nullptr, id, ntree)) { return changed; } @@ -4237,7 +4263,7 @@ void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, case ID: \ BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \ ntype->rna_ext.srna = RNA_struct_find(#Category #StructName); \ - BLI_assert(ntype->rna_ext.srna != NULL); \ + BLI_assert(ntype->rna_ext.srna != nullptr); \ RNA_struct_blender_type_set(ntype->rna_ext.srna, ntype); \ break; @@ -4271,15 +4297,16 @@ void node_type_base_custom( node_type_base_defaults(ntype); } +struct SocketTemplateIdentifierCallbackData { + bNodeSocketTemplate *list; + bNodeSocketTemplate *ntemp; +}; + static bool unique_socket_template_identifier_check(void *arg, const char *name) { - bNodeSocketTemplate *ntemp; - struct { - bNodeSocketTemplate *list; - bNodeSocketTemplate *ntemp; - } *data = arg; + SocketTemplateIdentifierCallbackData *data = (SocketTemplateIdentifierCallbackData *)arg; - for (ntemp = data->list; ntemp->type >= 0; ntemp++) { + for (bNodeSocketTemplate *ntemp = data->list; ntemp->type >= 0; ntemp++) { if (ntemp != data->ntemp) { if (STREQ(ntemp->identifier, name)) { return true; @@ -4295,10 +4322,7 @@ static void unique_socket_template_identifier(bNodeSocketTemplate *list, const char defname[], char delim) { - struct { - bNodeSocketTemplate *list; - bNodeSocketTemplate *ntemp; - } data; + SocketTemplateIdentifierCallbackData data; data.list = list; data.ntemp = ntemp; @@ -4448,7 +4472,7 @@ static bool node_undefined_poll(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(node } /* register fallback types used for undefined tree, nodes, sockets */ -static void register_undefined_types(void) +static void register_undefined_types() { /* Note: these types are not registered in the type hashes, * they are just used as placeholders in case the actual types are not registered. @@ -4473,7 +4497,7 @@ static void register_undefined_types(void) NodeSocketTypeUndefined.output_link_limit = 0xFFF; } -static void registerCompositNodes(void) +static void registerCompositNodes() { register_node_type_cmp_group(); @@ -4577,7 +4601,7 @@ static void registerCompositNodes(void) register_node_type_cmp_cornerpin(); } -static void registerShaderNodes(void) +static void registerShaderNodes() { register_node_type_sh_group(); @@ -4674,7 +4698,7 @@ static void registerShaderNodes(void) register_node_type_sh_tex_white_noise(); } -static void registerTextureNodes(void) +static void registerTextureNodes() { register_node_type_tex_group(); @@ -4724,43 +4748,51 @@ static void registerTextureNodes(void) register_node_type_tex_proc_distnoise(); } -static void registerGeometryNodes(void) +static void registerGeometryNodes() { register_node_type_geo_group(); + register_node_type_geo_align_rotation_to_vector(); + register_node_type_geo_attribute_color_ramp(); + register_node_type_geo_attribute_combine_xyz(); register_node_type_geo_attribute_compare(); register_node_type_geo_attribute_fill(); + register_node_type_geo_attribute_math(); + register_node_type_geo_attribute_mix(); + register_node_type_geo_attribute_proximity(); + register_node_type_geo_attribute_randomize(); + register_node_type_geo_attribute_separate_xyz(); register_node_type_geo_attribute_vector_math(); - register_node_type_geo_triangulate(); - register_node_type_geo_edge_split(); - register_node_type_geo_transform(); - register_node_type_geo_subdivision_surface(); register_node_type_geo_boolean(); + register_node_type_geo_collection_info(); + register_node_type_geo_edge_split(); + register_node_type_geo_is_viewport(); + register_node_type_geo_join_geometry(); + register_node_type_geo_object_info(); register_node_type_geo_point_distribute(); register_node_type_geo_point_instance(); - register_node_type_geo_point_separate(); + register_node_type_geo_point_rotate(); register_node_type_geo_point_scale(); + register_node_type_geo_point_separate(); register_node_type_geo_point_translate(); - register_node_type_geo_object_info(); - register_node_type_geo_attribute_randomize(); - register_node_type_geo_attribute_math(); - register_node_type_geo_join_geometry(); - register_node_type_geo_attribute_mix(); - register_node_type_geo_attribute_color_ramp(); - register_node_type_geo_point_rotate(); - register_node_type_geo_align_rotation_to_vector(); + register_node_type_geo_points_to_volume(); + register_node_type_geo_sample_texture(); + register_node_type_geo_subdivision_surface(); + register_node_type_geo_transform(); + register_node_type_geo_triangulate(); + register_node_type_geo_volume_to_mesh(); } -static void registerFunctionNodes(void) +static void registerFunctionNodes() { register_node_type_fn_boolean_math(); + register_node_type_fn_combine_strings(); register_node_type_fn_float_compare(); - register_node_type_fn_switch(); register_node_type_fn_group_instance_id(); - register_node_type_fn_combine_strings(); + register_node_type_fn_input_vector(); register_node_type_fn_object_transforms(); register_node_type_fn_random_float(); - register_node_type_fn_input_vector(); + register_node_type_fn_switch(); } void BKE_node_system_init(void) @@ -4800,8 +4832,8 @@ void BKE_node_system_exit(void) } NODE_TYPES_END; - BLI_ghash_free(nodetypes_hash, NULL, node_free_type); - nodetypes_hash = NULL; + BLI_ghash_free(nodetypes_hash, nullptr, node_free_type); + nodetypes_hash = nullptr; } if (nodesockettypes_hash) { @@ -4815,8 +4847,8 @@ void BKE_node_system_exit(void) } NODE_SOCKET_TYPES_END; - BLI_ghash_free(nodesockettypes_hash, NULL, node_free_socket_type); - nodesockettypes_hash = NULL; + BLI_ghash_free(nodesockettypes_hash, nullptr, node_free_socket_type); + nodesockettypes_hash = nullptr; } if (nodetreetypes_hash) { @@ -4827,8 +4859,8 @@ void BKE_node_system_exit(void) } NODE_TREE_TYPES_END; - BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type); - nodetreetypes_hash = NULL; + BLI_ghash_free(nodetreetypes_hash, nullptr, ntree_free_type); + nodetreetypes_hash = nullptr; } } @@ -4837,58 +4869,58 @@ void BKE_node_system_exit(void) void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain) { - ntreeiter->ngroup = bmain->nodetrees.first; - ntreeiter->scene = bmain->scenes.first; - ntreeiter->mat = bmain->materials.first; - ntreeiter->tex = bmain->textures.first; - ntreeiter->light = bmain->lights.first; - ntreeiter->world = bmain->worlds.first; - ntreeiter->linestyle = bmain->linestyles.first; - ntreeiter->simulation = bmain->simulations.first; + ntreeiter->ngroup = (bNodeTree *)bmain->nodetrees.first; + ntreeiter->scene = (Scene *)bmain->scenes.first; + ntreeiter->mat = (Material *)bmain->materials.first; + ntreeiter->tex = (Tex *)bmain->textures.first; + ntreeiter->light = (Light *)bmain->lights.first; + ntreeiter->world = (World *)bmain->worlds.first; + ntreeiter->linestyle = (FreestyleLineStyle *)bmain->linestyles.first; + ntreeiter->simulation = (Simulation *)bmain->simulations.first; } bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, struct ID **r_id) { if (ntreeiter->ngroup) { - *r_nodetree = ntreeiter->ngroup; + *r_nodetree = (bNodeTree *)ntreeiter->ngroup; *r_id = (ID *)ntreeiter->ngroup; - ntreeiter->ngroup = ntreeiter->ngroup->id.next; + ntreeiter->ngroup = (bNodeTree *)ntreeiter->ngroup->id.next; } else if (ntreeiter->scene) { - *r_nodetree = ntreeiter->scene->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->scene->nodetree; *r_id = (ID *)ntreeiter->scene; - ntreeiter->scene = ntreeiter->scene->id.next; + ntreeiter->scene = (Scene *)ntreeiter->scene->id.next; } else if (ntreeiter->mat) { - *r_nodetree = ntreeiter->mat->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->mat->nodetree; *r_id = (ID *)ntreeiter->mat; - ntreeiter->mat = ntreeiter->mat->id.next; + ntreeiter->mat = (Material *)ntreeiter->mat->id.next; } else if (ntreeiter->tex) { - *r_nodetree = ntreeiter->tex->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->tex->nodetree; *r_id = (ID *)ntreeiter->tex; - ntreeiter->tex = ntreeiter->tex->id.next; + ntreeiter->tex = (Tex *)ntreeiter->tex->id.next; } else if (ntreeiter->light) { - *r_nodetree = ntreeiter->light->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->light->nodetree; *r_id = (ID *)ntreeiter->light; - ntreeiter->light = ntreeiter->light->id.next; + ntreeiter->light = (Light *)ntreeiter->light->id.next; } else if (ntreeiter->world) { - *r_nodetree = ntreeiter->world->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->world->nodetree; *r_id = (ID *)ntreeiter->world; - ntreeiter->world = ntreeiter->world->id.next; + ntreeiter->world = (World *)ntreeiter->world->id.next; } else if (ntreeiter->linestyle) { - *r_nodetree = ntreeiter->linestyle->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->linestyle->nodetree; *r_id = (ID *)ntreeiter->linestyle; - ntreeiter->linestyle = ntreeiter->linestyle->id.next; + ntreeiter->linestyle = (FreestyleLineStyle *)ntreeiter->linestyle->id.next; } else if (ntreeiter->simulation) { - *r_nodetree = ntreeiter->simulation->nodetree; + *r_nodetree = (bNodeTree *)ntreeiter->simulation->nodetree; *r_id = (ID *)ntreeiter->simulation; - ntreeiter->simulation = ntreeiter->simulation->id.next; + ntreeiter->simulation = (Simulation *)ntreeiter->simulation->id.next; } else { return false; @@ -4914,10 +4946,3 @@ void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer } } } - -void BKE_nodetree_shading_params_eval(struct Depsgraph *depsgraph, - bNodeTree *ntree_dst, - const bNodeTree *ntree_src) -{ - DEG_debug_print_eval(depsgraph, __func__, ntree_src->id.name, ntree_dst); -} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 70af46569a8..9b5a1614dc0 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1118,6 +1118,20 @@ static void object_blend_read_expand(BlendExpander *expander, ID *id) } } +static void object_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src)) +{ + Object *object = (Object *)id_dst; + + ListBase pidlist; + BKE_ptcache_ids_from_object(&pidlist, object, NULL, 0); + LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) { + LISTBASE_FOREACH (PointCache *, point_cache, pid->ptcaches) { + point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY; + } + } + BLI_freelistN(&pidlist); +} + IDTypeInfo IDType_ID_OB = { .id_code = ID_OB, .id_filter = FILTER_ID_OB, @@ -1141,6 +1155,8 @@ IDTypeInfo IDType_ID_OB = { .blend_read_expand = object_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = object_lib_override_apply_post, }; void BKE_object_workob_clear(Object *workob) @@ -1506,11 +1522,11 @@ bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData /** * Copy the whole stack of modifiers from one object into another. * - * \warning **Does not** clear modifier stack and related data (particle systems, softbody, + * \warning **Does not** clear modifier stack and related data (particle systems, soft-body, * etc.) in `ob_dst`, if needed calling code must do it. * - * @param do_copy_all If true, even modifiers that should not suport copying (like Hook one) will - * be duplicated. + * \param do_copy_all: If true, even modifiers that should not support copying (like Hook one) + * will be duplicated. */ bool BKE_object_modifier_stack_copy(Object *ob_dst, const Object *ob_src, @@ -3528,9 +3544,6 @@ static void solve_parenting( } } -/** - * \note scene is the active scene while actual_scene is the scene the object resides in. - */ static void object_where_is_calc_ex(Depsgraph *depsgraph, Scene *scene, Object *ob, diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 1d79f871fa2..69442b7646c 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -225,7 +225,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o case OB_GPENCIL: { BKE_gpencil_prepare_eval_data(depsgraph, scene, ob); BKE_gpencil_modifiers_calc(depsgraph, scene, ob); - BKE_gpencil_update_layer_parent(depsgraph, ob); + BKE_gpencil_update_layer_transforms(depsgraph, ob); break; } case OB_HAIR: diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 1d62a1cce2a..d2f4d0702ed 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -140,7 +140,7 @@ static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, fl * instead of Complex.h * in fftw.h "fftw_complex" typedefed as double[2] * below you can see functions are needed to work with such complex numbers. - * */ + */ static void init_complex(fftw_complex cmpl, float real, float image) { cmpl[0] = real; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 7c65f118cf4..3c770a85b2a 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -127,7 +127,7 @@ static void palette_blend_read_data(BlendDataReader *reader, ID *id) static void palette_undo_preserve(BlendLibReader *UNUSED(reader), ID *id_new, ID *id_old) { - /* Whole Palette is preserved accross undo's, and it has no extra pointer, simple. */ + /* Whole Palette is preserved across undo-steps, and it has no extra pointer, simple. */ /* Note: We do not care about potential internal references to self here, Palette has none. */ /* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be * fairly delicate. */ @@ -158,6 +158,8 @@ IDTypeInfo IDType_ID_PAL = { .blend_read_expand = NULL, .blend_read_undo_preserve = palette_undo_preserve, + + .lib_override_apply_post = NULL, }; static void paint_curve_copy_data(Main *UNUSED(bmain), @@ -221,6 +223,8 @@ IDTypeInfo IDType_ID_PC = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100}; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 335913c9b8e..21d1e070389 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -511,6 +511,8 @@ IDTypeInfo IDType_ID_PA = { .blend_read_expand = particle_settings_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; @@ -2302,7 +2304,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, } return; } - /* we cant use the num_dmcache */ + /* we can't use the num_dmcache */ psys_particle_on_dm( psmd->mesh_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco); } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 55d4043f96c..c727a144c87 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1400,8 +1400,9 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra) static void psys_update_effectors(ParticleSimulationData *sim) { BKE_effectors_free(sim->psys->effectors); + bool use_rotation = (sim->psys->part->flag & PART_ROT_DYN) != 0; sim->psys->effectors = BKE_effectors_create( - sim->depsgraph, sim->ob, sim->psys, sim->psys->part->effector_weights); + sim->depsgraph, sim->ob, sim->psys, sim->psys->part->effector_weights, use_rotation); precalc_guides(sim, sim->psys->effectors); } diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc index 7bd14e80333..b9ff2a1179d 100644 --- a/source/blender/blenkernel/intern/pointcloud.cc +++ b/source/blender/blenkernel/intern/pointcloud.cc @@ -190,6 +190,8 @@ IDTypeInfo IDType_ID_PT = { /* blend_read_expand */ pointcloud_blend_read_expand, /* blend_read_undo_preserve */ nullptr, + + /* lib_override_apply_post */ nullptr, }; static void pointcloud_random(PointCloud *pointcloud) diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 586aeb274a5..19078446009 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -1720,7 +1720,7 @@ static void rigidbody_update_sim_ob( ListBase *effectors; /* get effectors present in the group specified by effector_weights */ - effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights); + effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights, false); if (effectors) { float eff_force[3] = {0.0f, 0.0f, 0.0f}; float eff_loc[3], eff_vel[3]; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index b19b0e684b2..25951fa3e6f 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -475,7 +475,7 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE /** * This code is shared by both the regular `foreach_id` looper, and the code trying to restore or - * preserve ID pointers like brushes across undoes. + * preserve ID pointers like brushes across undo-steps. */ typedef enum eSceneForeachUndoPreserveProcess { /* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID @@ -1689,6 +1689,19 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old) } } +static void scene_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src)) +{ + Scene *scene = (Scene *)id_dst; + + if (scene->rigidbody_world != NULL) { + PTCacheID pid; + BKE_ptcache_id_from_rigidbody(&pid, NULL, scene->rigidbody_world); + LISTBASE_FOREACH (PointCache *, point_cache, pid.ptcaches) { + point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY; + } + } +} + IDTypeInfo IDType_ID_SCE = { .id_code = ID_SCE, .id_filter = FILTER_ID_SCE, @@ -1714,6 +1727,8 @@ IDTypeInfo IDType_ID_SCE = { .blend_read_expand = scene_blend_read_expand, .blend_read_undo_preserve = scene_undo_preserve, + + .lib_override_apply_post = scene_lib_override_apply_post, }; const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 52c41c9fd05..80a83aecea8 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -315,6 +315,8 @@ IDTypeInfo IDType_ID_SCR = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* ************ Spacetype/regiontype handling ************** */ @@ -1599,8 +1601,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area) BLO_read_list(reader, &snode->treepath); snode->edittree = NULL; - snode->iofsd = NULL; - BLI_listbase_clear(&snode->linkdrag); + snode->runtime = NULL; } else if (sl->spacetype == SPACE_TEXT) { SpaceText *st = (SpaceText *)sl; diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc index 14e6ce63023..4e0a08455e6 100644 --- a/source/blender/blenkernel/intern/simulation.cc +++ b/source/blender/blenkernel/intern/simulation.cc @@ -173,6 +173,8 @@ IDTypeInfo IDType_ID_SIM = { /* blend_read_expand */ simulation_blend_read_expand, /* blend_read_undo_preserve */ nullptr, + + /* lib_override_apply_post */ nullptr, }; void *BKE_simulation_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 736acd76dfd..de88e8a941c 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -1539,7 +1539,8 @@ static void sb_sfesf_threads_run(struct Depsgraph *depsgraph, * or even be UI option sb->spawn_cf_threads_nopts */ int lowsprings = 100; - ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights); + ListBase *effectors = BKE_effectors_create( + depsgraph, ob, NULL, ob->soft->effector_weights, false); /* figure the number of threads while preventing pretty pointless threading overhead */ totthread = BKE_scene_num_threads(scene); @@ -2300,7 +2301,7 @@ static void softbody_calc_forces( } /* after spring scan because it uses Effoctors too */ - ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights); + ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights, false); if (do_deflector) { float defforce[3]; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 78729fb9261..0c917434bd1 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -221,6 +221,8 @@ IDTypeInfo IDType_ID_SO = { .blend_read_expand = sound_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; #ifdef WITH_AUDASPACE diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index fabf0bb8971..9caeaf05e6a 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -114,6 +114,8 @@ IDTypeInfo IDType_ID_SPK = { .blend_read_expand = speaker_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; void *BKE_speaker_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 9ef2e818293..9bf215515f7 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -258,6 +258,8 @@ IDTypeInfo IDType_ID_TXT = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /** \} */ diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 4c2e4a82acb..ce84bfcd95a 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -226,6 +226,8 @@ IDTypeInfo IDType_ID_TE = { .blend_read_expand = texture_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* Utils for all IDs using those texture slots. */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index e5f9d59270e..d124922acd1 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -587,15 +587,15 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking, { const MovieTrackingSettings *settings = &tracking->settings; + MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase); + MovieTrackingMarker marker; + const float half_pattern_px = settings->default_pattern_size / 2.0f; const float half_search_px = settings->default_search_size / 2.0f; const float pattern_size[2] = {half_pattern_px / width, half_pattern_px / height}; const float search_size[2] = {half_search_px / width, half_search_px / height}; - MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase); - - MovieTrackingMarker marker; memset(&marker, 0, sizeof(marker)); marker.pos[0] = x; marker.pos[1] = y; @@ -665,6 +665,86 @@ void BKE_tracking_track_free(MovieTrackingTrack *track) } } +/* Get frame numbers of the very first and last markers. + * There is no check on whether the marker is enabled or not. */ +void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track, + int *r_first_frame, + int *r_last_frame) +{ + BLI_assert(track->markersnr > 0); + const int last_marker_index = track->markersnr - 1; + *r_first_frame = track->markers[0].framenr; + *r_last_frame = track->markers[last_marker_index].framenr; +} + +/* Find the minimum starting frame and maximum ending frame within given set of + * tracks. + */ +void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ MovieTrackingTrack **tracks, + const int num_tracks, + int *r_first_frame, + int *r_last_frame) +{ + *r_first_frame = INT_MAX; + *r_last_frame = INT_MIN; + for (int i = 0; i < num_tracks; ++i) { + const struct MovieTrackingTrack *track = tracks[i]; + int track_first_frame, track_last_frame; + BKE_tracking_track_first_last_frame_get(track, &track_first_frame, &track_last_frame); + *r_first_frame = min_ii(*r_first_frame, track_first_frame); + *r_last_frame = max_ii(*r_last_frame, track_last_frame); + } +} + +int BKE_tracking_count_selected_tracks_in_list(const ListBase *tracks_list) +{ + int num_selected_tracks = 0; + LISTBASE_FOREACH (const MovieTrackingTrack *, track, tracks_list) { + if (TRACK_SELECTED(track)) { + ++num_selected_tracks; + } + } + return num_selected_tracks; +} + +int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ MovieTracking *tracking) +{ + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + return BKE_tracking_count_selected_tracks_in_list(tracks_list); +} + +MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(MovieTracking *tracking, + int *r_num_tracks) +{ + *r_num_tracks = 0; + + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + if (tracks_list == NULL) { + return NULL; + } + + /* Initialize input. */ + const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking); + if (num_selected_tracks == 0) { + return NULL; + } + + MovieTrackingTrack **source_tracks = MEM_malloc_arrayN( + num_selected_tracks, sizeof(MovieTrackingTrack *), "selected tracks array"); + int source_track_index = 0; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_list) { + if (!TRACK_SELECTED(track)) { + continue; + } + source_tracks[source_track_index] = track; + ++source_track_index; + } + + *r_num_tracks = num_selected_tracks; + + return source_tracks; +} + /* Set flag for all specified track's areas. * * area - which part of marker should be selected. see TRACK_AREA_* constants. @@ -918,6 +998,124 @@ void BKE_tracking_tracks_join(MovieTracking *tracking, BKE_tracking_dopesheet_tag_update(tracking); } +static void accumulate_marker(MovieTrackingMarker *dst_marker, + const MovieTrackingMarker *src_marker) +{ + BLI_assert(dst_marker->framenr == src_marker->framenr); + + if (src_marker->flag & MARKER_DISABLED) { + return; + } + + add_v2_v2(dst_marker->pos, src_marker->pos); + for (int corner = 0; corner < 4; ++corner) { + add_v2_v2(dst_marker->pattern_corners[corner], src_marker->pattern_corners[corner]); + } + add_v2_v2(dst_marker->search_min, src_marker->search_min); + add_v2_v2(dst_marker->search_max, src_marker->search_max); + + BLI_assert(is_finite_v2(src_marker->search_min)); + BLI_assert(is_finite_v2(src_marker->search_max)); + + dst_marker->flag &= ~MARKER_DISABLED; + if ((src_marker->flag & MARKER_TRACKED) == 0) { + dst_marker->flag &= ~MARKER_TRACKED; + } +} + +static void multiply_marker(MovieTrackingMarker *marker, const float multiplier) +{ + mul_v2_fl(marker->pos, multiplier); + for (int corner = 0; corner < 4; ++corner) { + mul_v2_fl(marker->pattern_corners[corner], multiplier); + } + mul_v2_fl(marker->search_min, multiplier); + mul_v2_fl(marker->search_max, multiplier); +} + +/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of + * markers (position, patterns, ...). */ +static void tracking_average_markers(MovieTrackingTrack *dst_track, + /*const*/ MovieTrackingTrack **src_tracks, + const int num_src_tracks) +{ + /* Get global range of frames within which averaging would happen. */ + int first_frame, last_frame; + BKE_tracking_tracks_first_last_frame_minmax( + src_tracks, num_src_tracks, &first_frame, &last_frame); + if (last_frame < first_frame) { + return; + } + const int num_frames = last_frame - first_frame + 1; + + /* Allocate temporary array where averaging will happen into. */ + MovieTrackingMarker *accumulator = MEM_calloc_arrayN( + num_frames, sizeof(MovieTrackingMarker), "tracks average accumulator"); + int *counters = MEM_calloc_arrayN(num_frames, sizeof(int), "tracks accumulator counters"); + for (int frame = first_frame; frame <= last_frame; ++frame) { + const int frame_index = frame - first_frame; + accumulator[frame_index].framenr = frame; + accumulator[frame_index].flag |= (MARKER_DISABLED | MARKER_TRACKED); + } + + /* Accumulate track markers. */ + for (int track_index = 0; track_index < num_src_tracks; ++track_index) { + /*const*/ MovieTrackingTrack *track = src_tracks[track_index]; + for (int frame = first_frame; frame <= last_frame; ++frame) { + MovieTrackingMarker interpolated_marker; + if (!BKE_tracking_marker_get_interpolated(track, frame, &interpolated_marker)) { + continue; + } + const int frame_index = frame - first_frame; + accumulate_marker(&accumulator[frame_index], &interpolated_marker); + ++counters[frame_index]; + } + } + + /* Average and store the result. */ + for (int frame = first_frame; frame <= last_frame; ++frame) { + /* Average. */ + const int frame_index = frame - first_frame; + if (!counters[frame_index]) { + continue; + } + const float multiplier = 1.0f / (float)counters[frame_index]; + multiply_marker(&accumulator[frame_index], multiplier); + /* Store the result. */ + BKE_tracking_marker_insert(dst_track, &accumulator[frame_index]); + } + + /* Free memory. */ + MEM_freeN(accumulator); + MEM_freeN(counters); +} + +/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of + * tracks (track for example, offset). */ +static void tracking_average_tracks(MovieTrackingTrack *dst_track, + /*const*/ MovieTrackingTrack **src_tracks, + const int num_src_tracks) +{ + /* TODO(sergey): Consider averaging weight, stabilization weight, maybe even bundle position. */ + zero_v2(dst_track->offset); + for (int track_index = 0; track_index < num_src_tracks; track_index++) { + add_v2_v2(dst_track->offset, src_tracks[track_index]->offset); + } + mul_v2_fl(dst_track->offset, 1.0f / num_src_tracks); +} + +void BKE_tracking_tracks_average(MovieTrackingTrack *dst_track, + /*const*/ MovieTrackingTrack **src_tracks, + const int num_src_tracks) +{ + if (num_src_tracks == 0) { + return; + } + + tracking_average_markers(dst_track, src_tracks, num_src_tracks); + tracking_average_tracks(dst_track, src_tracks, num_src_tracks); +} + MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking, MovieTrackingObject *object, const char *name) @@ -1224,8 +1422,6 @@ MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track, /* put new marker */ track->markers[a + 1] = *marker; - track->last_marker = a + 1; - return &track->markers[a + 1]; } @@ -1314,51 +1510,47 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event) } } +/** + * Get marker closest to the given frame number. + * + * If there is maker with exact frame number it returned. + * Otherwise, marker with highest frame number but lower than the requested + * frame is returned if such marker exists. Otherwise, the marker with lowest + * frame number greater than the requested frame number is returned. + * + * This function has complexity of `O(log number_of_markers)`. + */ MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr) { - int a = track->markersnr - 1; + const int num_markers = track->markersnr; - if (!track->markersnr) { + if (num_markers == 0) { + BLI_assert(!"Detected degenerated track, should never happen."); return NULL; } - /* approximate pre-first framenr marker with first marker */ - if (framenr < track->markers[0].framenr) { - return &track->markers[0]; - } + int left_boundary = 0; + int right_boundary = num_markers; + while (left_boundary < right_boundary) { + const int median_index = (left_boundary + right_boundary) / 2; + MovieTrackingMarker *marker = &track->markers[median_index]; - if (track->last_marker < track->markersnr) { - a = track->last_marker; - } - - if (track->markers[a].framenr <= framenr) { - while (a < track->markersnr && track->markers[a].framenr <= framenr) { - if (track->markers[a].framenr == framenr) { - track->last_marker = a; - - return &track->markers[a]; - } - a++; + if (marker->framenr == framenr) { + return marker; } - /* if there's no marker for exact position, use nearest marker from left side */ - return &track->markers[a - 1]; - } - - while (a >= 0 && track->markers[a].framenr >= framenr) { - if (track->markers[a].framenr == framenr) { - track->last_marker = a; - - return &track->markers[a]; + if (marker->framenr < framenr) { + left_boundary = median_index + 1; + } + else { + BLI_assert(marker->framenr > framenr); + right_boundary = median_index - 1; } - - a--; } - /* if there's no marker for exact position, use nearest marker from left side */ - return &track->markers[a]; + const int closest_index = clamp_i(right_boundary, 0, num_markers - 1); - return NULL; + return &track->markers[closest_index]; } MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr) @@ -1389,6 +1581,84 @@ MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int f return marker; } +static const MovieTrackingMarker *get_usable_marker_for_interpolation( + struct MovieTrackingTrack *track, + const MovieTrackingMarker *anchor_marker, + const int direction) +{ + BLI_assert(direction == -1 || direction == 1); + + const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1; + const MovieTrackingMarker *current_marker = anchor_marker; + + while (current_marker >= track->markers && current_marker <= last_marker) { + if ((current_marker->flag & MARKER_DISABLED) == 0) { + return current_marker; + } + current_marker += direction; + } + + return NULL; +} + +bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track, + const int framenr, + struct MovieTrackingMarker *r_marker) +{ + const MovieTrackingMarker *closest_marker = BKE_tracking_marker_get(track, framenr); + if (closest_marker == NULL) { + return false; + } + if (closest_marker->framenr == framenr && (closest_marker->flag & MARKER_DISABLED) == 0) { + *r_marker = *closest_marker; + return true; + } + + const MovieTrackingMarker *left_marker = get_usable_marker_for_interpolation( + track, closest_marker, -1); + if (left_marker == NULL) { + return false; + } + + const MovieTrackingMarker *right_marker = get_usable_marker_for_interpolation( + track, closest_marker + 1, 1); + if (right_marker == NULL) { + return false; + } + + if (left_marker == right_marker) { + *r_marker = *left_marker; + return true; + } + + const float factor = (float)(framenr - left_marker->framenr) / + (right_marker->framenr - left_marker->framenr); + + interp_v2_v2v2(r_marker->pos, left_marker->pos, right_marker->pos, factor); + + for (int i = 0; i < 4; i++) { + interp_v2_v2v2(r_marker->pattern_corners[i], + left_marker->pattern_corners[i], + right_marker->pattern_corners[i], + factor); + } + + interp_v2_v2v2(r_marker->search_min, left_marker->search_min, right_marker->search_min, factor); + interp_v2_v2v2(r_marker->search_max, left_marker->search_max, right_marker->search_max, factor); + + r_marker->framenr = framenr; + r_marker->flag = 0; + + if (framenr == left_marker->framenr) { + r_marker->flag = left_marker->flag; + } + else if (framenr == right_marker->framenr) { + r_marker->flag = right_marker->flag; + } + + return true; +} + void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker, float min[2], float max[2]) @@ -1683,7 +1953,6 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTra /* Put new marker to an array. */ plane_track->markers[a + 1] = *plane_marker; - plane_track->last_marker = a + 1; return &plane_track->markers[a + 1]; } diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c index 6f58416924f..46589a578a8 100644 --- a/source/blender/blenkernel/intern/tracking_stabilize.c +++ b/source/blender/blenkernel/intern/tracking_stabilize.c @@ -311,11 +311,7 @@ static void retrieve_next_lower_usable_frame( * translation stabilization, which has an enabled tracking marker at this very * frame. We search both for the next lower and next higher position, to allow * the caller to interpolate gaps and to extrapolate at the ends of the - * definition range. - * - * NOTE: Regarding performance note that the individual tracks will cache the - * last search position. - */ + * definition range. */ static void find_next_working_frames(StabContext *ctx, int framenr, int *next_lower, diff --git a/source/blender/blenkernel/intern/tracking_test.cc b/source/blender/blenkernel/intern/tracking_test.cc index 6afcf6872eb..a3845dcad8f 100644 --- a/source/blender/blenkernel/intern/tracking_test.cc +++ b/source/blender/blenkernel/intern/tracking_test.cc @@ -5,15 +5,23 @@ #include "DNA_tracking_types.h" #include "BKE_tracking.h" +#include "BLI_float2.hh" + +namespace blender { namespace { class TrackingTest : public ::testing::Test { protected: - MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track, int frame_number) + MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track, + int frame_number, + const float2 &position = float2(0.0f, 0.0f), + int flag = 0) { MovieTrackingMarker marker = {{0.0f}}; + copy_v2_v2(marker.pos, position); marker.framenr = frame_number; + marker.flag = flag; return BKE_tracking_marker_insert(track, &marker); } }; @@ -22,24 +30,58 @@ class TrackingTest : public ::testing::Test { TEST_F(TrackingTest, BKE_tracking_marker_get) { - MovieTrackingTrack track = {nullptr}; + { + MovieTrackingTrack track = {nullptr}; - addMarkerToTrack(&track, 1); - addMarkerToTrack(&track, 10); + addMarkerToTrack(&track, 10); - { - const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1); - EXPECT_NE(marker, nullptr); - EXPECT_EQ(marker->framenr, 1); + EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 20), &track.markers[0]); + + BKE_tracking_track_free(&track); } { - const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5); - EXPECT_NE(marker, nullptr); - EXPECT_EQ(marker->framenr, 1); + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1); + addMarkerToTrack(&track, 10); + + { + const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1); + EXPECT_NE(marker, nullptr); + EXPECT_EQ(marker->framenr, 1); + } + + { + const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5); + EXPECT_NE(marker, nullptr); + EXPECT_EQ(marker->framenr, 1); + } + + BKE_tracking_track_free(&track); } - BKE_tracking_track_free(&track); + { + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1); + addMarkerToTrack(&track, 2); + addMarkerToTrack(&track, 10); + + EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 1), &track.markers[0]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 2), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 3), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 9), &track.markers[1]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[2]); + EXPECT_EQ(BKE_tracking_marker_get(&track, 11), &track.markers[2]); + + BKE_tracking_track_free(&track); + } + } } TEST_F(TrackingTest, BKE_tracking_marker_get_exact) @@ -62,3 +104,107 @@ TEST_F(TrackingTest, BKE_tracking_marker_get_exact) BKE_tracking_track_free(&track); } + +TEST_F(TrackingTest, BKE_tracking_marker_get_interpolated) +{ + /* Simple case, no disabled markers in a way. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f)); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f)); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 1); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 10); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 4); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f); + } + + BKE_tracking_track_free(&track); + } + + /* More comprehensive test, which resembles real-life tracking scenario better. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f)); + addMarkerToTrack(&track, 2, float2(0.0f, 0.0f), MARKER_DISABLED); + addMarkerToTrack(&track, 9, float2(0.0f, 0.0f), MARKER_DISABLED); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f)); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 1); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 10); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 4); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 9, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.framenr, 9); + EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.888888f, 1.4444444f), 1e-6f); + } + + BKE_tracking_track_free(&track); + } + + /* Tracked/keyframed flag check. */ + { + MovieTrackingTrack track = {nullptr}; + + addMarkerToTrack(&track, 1, float2(1.0f, 5.0f), MARKER_TRACKED); + addMarkerToTrack(&track, 10, float2(2.0f, 1.0f), MARKER_TRACKED); + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED); + } + + { + MovieTrackingMarker interpolated_marker; + EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker)); + EXPECT_EQ(interpolated_marker.flag, 0); + } + + BKE_tracking_track_free(&track); + } +} + +} // namespace blender diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index e78576206de..bb871e84c7b 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -176,8 +176,12 @@ static bool undosys_step_encode(bContext *C, Main *bmain, UndoStack *ustack, Und return ok; } -static void undosys_step_decode( - bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us, int dir, bool is_final) +static void undosys_step_decode(bContext *C, + Main *bmain, + UndoStack *ustack, + UndoStep *us, + const eUndoStepDir dir, + bool is_final) { CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name); @@ -251,42 +255,10 @@ static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty) BLI_assert(!BLI_listbase_is_empty(&ustack->steps)); } } - -/* Return whether `us_item` is before (-1), after (1) or same as (0) `us_anchor` step. */ -static int undosys_stack_order(const UndoStack *ustack, - const UndoStep *us_anchor, - const UndoStep *us_item) -{ - const int index_anchor = BLI_findindex(&ustack->steps, us_anchor); - const int index_item = BLI_findindex(&ustack->steps, us_item); - BLI_assert(index_anchor >= 0); - BLI_assert(index_item >= 0); - - return (index_item == index_anchor) ? 0 : (index_item < index_anchor) ? -1 : 1; -} - -# define ASSERT_VALID_UNDO_STEP(_ustack, _us_undo) \ - { \ - const UndoStep *_us_anchor = (_ustack)->step_active; \ - BLI_assert(_us_anchor == NULL || \ - (undosys_stack_order((_ustack), _us_anchor, (_us_undo)) <= 0)); \ - } \ - (void)0 - -# define ASSERT_VALID_REDO_STEP(_ustack, _us_redo) \ - { \ - const UndoStep *_us_anchor = (_ustack)->step_active; \ - BLI_assert(_us_anchor == NULL || \ - (undosys_stack_order((_ustack), _us_anchor, (_us_redo)) >= 0)); \ - } \ - (void)0 - #else static void undosys_stack_validate(UndoStack *UNUSED(ustack), bool UNUSED(expect_non_empty)) { } -# define ASSERT_VALID_UNDO_STEP(_ustack, _us_undo) -# define ASSERT_VALID_REDO_STEP(_ustack, _us_redo) #endif UndoStack *BKE_undosys_stack_create(void) @@ -315,7 +287,7 @@ void BKE_undosys_stack_clear(UndoStack *ustack) void BKE_undosys_stack_clear_active(UndoStack *ustack) { - /* Remove active and all following undos. */ + /* Remove active and all following undo-steps. */ UndoStep *us = ustack->step_active; if (us) { @@ -545,7 +517,7 @@ UndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack, retval |= UNDO_PUSH_RET_OVERRIDE_CHANGED; } - /* Remove all undos after (also when 'ustack->step_active == NULL'). */ + /* Remove all undo-steps after (also when 'ustack->step_active == NULL'). */ while (ustack->steps.last != ustack->step_active) { UndoStep *us_iter = ustack->steps.last; undosys_step_free_and_unlink(ustack, us_iter); @@ -586,7 +558,7 @@ UndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack, BLI_strncpy(us->name, name, sizeof(us->name)); } us->type = ut; - /* True by default, code needs to explicitely set it to false if necessary. */ + /* True by default, code needs to explicitly set it to false if necessary. */ us->use_old_bmain_data = true; /* Initialized, not added yet. */ @@ -701,37 +673,91 @@ UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut) return NULL; } -bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, - bContext *C, - UndoStep *us, - bool use_skip) +/** + * Return direction of the undo/redo from `us_reference` (or `ustack->step_active` if NULL), and + * `us_target`. + * + * \note If `us_reference` and `us_target` are the same, we consider this is an undo. + * + * \return -1 for undo, 1 for redo, 0 in case of error. + */ +eUndoStepDir BKE_undosys_step_calc_direction(const UndoStack *ustack, + const UndoStep *us_target, + const UndoStep *us_reference) +{ + if (us_reference == NULL) { + us_reference = ustack->step_active; + } + + BLI_assert(us_reference != NULL); + + /* Note that we use heuristics to make this lookup as fast as possible in most common cases, + * assuming that: + * - Most cases are just undo or redo of one step from active one. + * - Otherwise, it is typically faster to check future steps since active one is usually close + * to the end of the list, rather than its start. */ + /* NOTE: in case target step is the active one, we assume we are in an undo case... */ + if (ELEM(us_target, us_reference, us_reference->prev)) { + return STEP_UNDO; + } + if (us_target == us_reference->next) { + return STEP_REDO; + } + + /* Search forward, and then backward. */ + for (UndoStep *us_iter = us_reference->next; us_iter != NULL; us_iter = us_iter->next) { + if (us_iter == us_target) { + return STEP_REDO; + } + } + for (UndoStep *us_iter = us_reference->prev; us_iter != NULL; us_iter = us_iter->prev) { + if (us_iter == us_target) { + return STEP_UNDO; + } + } + + BLI_assert(!"Target undo step not found, this should not happen and may indicate an undo stack corruption"); + return STEP_INVALID; +} + +/** + * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one. + * + * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the + * active step. + * + * \note In case `use_skip` is true, the final target will always be **beyond** the given one (if + * the given one has to be skipped). + * + * \param us_reference If NULL, will be set to current active step in the undo stack. Otherwise, it + * is assumed to match the current state, and will be used as basis for the + * undo/redo process (i.e. all steps in-between `us_reference` and `us_target` + * will be processed). + */ +bool BKE_undosys_step_load_data_ex(UndoStack *ustack, + bContext *C, + UndoStep *us_target, + UndoStep *us_reference, + const bool use_skip) { UNDO_NESTED_ASSERT(false); - if (us == NULL) { - CLOG_ERROR(&LOG, "called with a NULL step"); + if (us_target == NULL) { + CLOG_ERROR(&LOG, "called with a NULL target step"); return false; } undosys_stack_validate(ustack, true); - /* We expect to get next-from-actual-target step here (i.e. active step in case we only undo - * once)? - * FIXME: this is very confusing now that we may have to undo several steps anyway, this function - * should just get the target final step, not assume that it is getting the active one by default - * (or the step after the target one when undoing more than one step). */ - UndoStep *us_target = us->prev; - if (us_target == NULL) { - CLOG_ERROR(&LOG, "could not find a valid target step"); + if (us_reference == NULL) { + us_reference = ustack->step_active; + } + if (us_reference == NULL) { + CLOG_ERROR(&LOG, "could not find a valid initial active target step as reference"); return false; } - ASSERT_VALID_UNDO_STEP(ustack, us_target); - /* This will be active once complete. */ - UndoStep *us_active = us_target; - if (use_skip) { - while (us_active && us_active->skip) { - us_active = us_active->prev; - } - } + /* This considers we are in undo case if both `us_target` and `us_reference` are the same. */ + const eUndoStepDir undo_dir = BKE_undosys_step_calc_direction(ustack, us_target, us_reference); + BLI_assert(undo_dir != STEP_INVALID); /* This will be the active step once the undo process is complete. * @@ -740,7 +766,7 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, UndoStep *us_target_active = us_target; if (use_skip) { while (us_target_active != NULL && us_target_active->skip) { - us_target_active = us_target_active->prev; + us_target_active = (undo_dir == -1) ? us_target_active->prev : us_target_active->next; } } if (us_target_active == NULL) { @@ -748,42 +774,47 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, return false; } - CLOG_INFO( - &LOG, 1, "addr=%p, name='%s', type='%s'", us_target, us_target->name, us_target->type->name); + CLOG_INFO(&LOG, + 1, + "addr=%p, name='%s', type='%s', undo_dir=%d", + us_target, + us_target->name, + us_target->type->name, + undo_dir); - /* Undo steps until we reach original given target, if we do have a current active step. + /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped), from + * given reference step. * * NOTE: Unlike with redo case, where we can expect current active step to fully reflect current * data status, in undo case we also do reload the active step. * FIXME: this feels weak, and should probably not be actually needed? Or should also be done in * redo case? */ - if (ustack->step_active != NULL) { - for (UndoStep *us_iter = ustack->step_active; us_iter != us_target; us_iter = us_iter->prev) { - BLI_assert(us_iter != NULL); - undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, false); - ustack->step_active = us_iter; - } - } + bool is_processing_extra_skipped_steps = false; + for (UndoStep *us_iter = (undo_dir == -1) ? us_reference : us_reference->next; us_iter != NULL; + us_iter = (undo_dir == -1) ? us_iter->prev : us_iter->next) { + BLI_assert(us_iter != NULL); - /* Undo target step, and all potential extra ones if some steps have to be 'skipped'. */ - for (UndoStep *us_iter = us_target; us_iter != NULL; us_iter = us_iter->prev) { const bool is_final = (us_iter == us_target_active); - if (!is_final) { + if (!is_final && is_processing_extra_skipped_steps) { BLI_assert(us_iter->skip == true); CLOG_INFO(&LOG, 2, - "undo continue with skip addr=%p, name='%s', type='%s'", + "undo/redo continue with skip addr=%p, name='%s', type='%s'", us_iter, us_iter->name, us_iter->type->name); } - undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, is_final); + undosys_step_decode(C, G_MAIN, ustack, us_iter, undo_dir, is_final); ustack->step_active = us_iter; + if (us_iter == us_target) { + is_processing_extra_skipped_steps = true; + } + if (is_final) { - /* Undo process is finished and successful. */ + /* Undo/Redo process is finished and successful. */ return true; } } @@ -793,139 +824,117 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, return false; } -bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us) -{ - return BKE_undosys_step_undo_with_data_ex(ustack, C, us, true); -} - -bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C) +/** + * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one. + */ +bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us_target) { - return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active); + /* Note that here we do not skip 'skipped' steps by default. */ + return BKE_undosys_step_load_data_ex(ustack, C, us_target, NULL, false); } -void BKE_undosys_step_undo_from_index(UndoStack *ustack, bContext *C, int index) +/** + * Undo/Redo until the step matching given `index` in the undo stack becomes the active (currently + * loaded) one. + */ +void BKE_undosys_step_load_from_index(UndoStack *ustack, bContext *C, const int index) { - UndoStep *us = BLI_findlink(&ustack->steps, index); - BLI_assert(us->skip == false); - BKE_undosys_step_load_data(ustack, C, us); + UndoStep *us_target = BLI_findlink(&ustack->steps, index); + BLI_assert(us_target->skip == false); + BKE_undosys_step_load_data(ustack, C, us_target); } -bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack, +/** + * Undo until `us_target` step becomes the active (currently loaded) one. + * + * \warning This function assumes that the given target step is _before_ current active one. + * + * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the + * active step. + * + * \note In case `use_skip` is true, the final target will always be **before** the given one (if + * the given one has to be skipped). + */ +bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack, bContext *C, - UndoStep *us, + UndoStep *us_target, bool use_skip) { - UNDO_NESTED_ASSERT(false); - if (us == NULL) { - CLOG_ERROR(&LOG, "called with a NULL step"); - return false; - } - undosys_stack_validate(ustack, true); + /* In case there is no active step, we consider we just load given step, so reference must be + * itself (due to weird 'load current active step in undo case' thing, see comments in + * #BKE_undosys_step_load_data_ex). */ + UndoStep *us_reference = ustack->step_active != NULL ? ustack->step_active : us_target; - /* We expect to get previous-from-actual-target step here (i.e. active step in case we only redo - * once)? - * FIXME: this is very confusing now that we may have to redo several steps anyway, this function - * should just get the target final step, not assume that it is getting the active one by default - * (or the step before the target one when redoing more than one step). */ - UndoStep *us_target = us->next; - if (us_target == NULL) { - CLOG_ERROR(&LOG, "could not find a valid target step"); - return false; - } - ASSERT_VALID_REDO_STEP(ustack, us_target); + BLI_assert(BKE_undosys_step_calc_direction(ustack, us_target, us_reference) == -1); - /* This will be the active step once the redo process is complete. - * - * In case we do skip 'skipped' steps, the final active step may be several steps forward the one - * passed as parameter. */ - UndoStep *us_target_active = us_target; - if (use_skip) { - while (us_target_active != NULL && us_target_active->skip) { - us_target_active = us_target_active->next; - } - } - if (us_target_active == NULL) { - CLOG_ERROR(&LOG, "could not find a valid final active target step"); - return false; - } + return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip); +} - CLOG_INFO( - &LOG, 1, "addr=%p, name='%s', type='%s'", us_target, us_target->name, us_target->type->name); +/** + * Undo until `us_target` step becomes the active (currently loaded) one. + * + * \note See #BKE_undosys_step_undo_with_data_ex for details. + */ +bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target) +{ + return BKE_undosys_step_undo_with_data_ex(ustack, C, us_target, true); +} - /* Redo steps until we reach original given target, if we do have a current active step. */ +/** + * Undo one step from current active (currently loaded) one. + */ +bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C) +{ if (ustack->step_active != NULL) { - for (UndoStep *us_iter = ustack->step_active->next; us_iter != us_target; - us_iter = us_iter->next) { - BLI_assert(us_iter != NULL); - undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, false); - ustack->step_active = us_iter; - } + return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active->prev); } - - /* Redo target step, and all potential extra ones if some steps have to be 'skipped'. */ - for (UndoStep *us_iter = us_target; us_iter != NULL; us_iter = us_iter->next) { - const bool is_final = (us_iter == us_target_active); - - if (!is_final) { - BLI_assert(us_iter->skip == true); - CLOG_INFO(&LOG, - 2, - "redo continue with skip addr=%p, name='%s', type='%s'", - us_iter, - us_iter->name, - us_iter->type->name); - } - - undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, is_final); - ustack->step_active = us_iter; - - if (is_final) { - /* Redo process is finished and successful. */ - return true; - } - } - - BLI_assert( - !"This should never be reached, either undo stack is corrupted, or code above is buggy"); return false; } -bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us) +/** + * Redo until `us_target` step becomes the active (currently loaded) one. + * + * \warning This function assumes that the given target step is _after_ current active one. + * + * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the + * active step. + * + * \note In case `use_skip` is true, the final target will always be **after** the given one (if + * the given one has to be skipped). + */ +bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack, + bContext *C, + UndoStep *us_target, + bool use_skip) { - return BKE_undosys_step_redo_with_data_ex(ustack, C, us, true); + /* In case there is no active step, we consider we just load given step, so reference must be + * the previous one. */ + UndoStep *us_reference = ustack->step_active != NULL ? ustack->step_active : us_target->prev; + + BLI_assert(BKE_undosys_step_calc_direction(ustack, us_target, us_reference) == 1); + + return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip); } -bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C) +/** + * Redo until `us_target` step becomes the active (currently loaded) one. + * + * \note See #BKE_undosys_step_redo_with_data_ex for details. + */ +bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target) { - return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active); + return BKE_undosys_step_redo_with_data_ex(ustack, C, us_target, true); } -bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us) +/** + * Redo one step from current active one. + */ +bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C) { - UNDO_NESTED_ASSERT(false); - const int index_active = BLI_findindex(&ustack->steps, ustack->step_active); - const int index_target = BLI_findindex(&ustack->steps, us); - BLI_assert(!ELEM(-1, index_active, index_target)); - bool ok = true; - - if (index_target < index_active) { - uint i = index_active - index_target; - while (i-- && ok) { - ok = BKE_undosys_step_undo_with_data_ex(ustack, C, ustack->step_active, false); - } - } - else if (index_target > index_active) { - uint i = index_target - index_active; - while (i-- && ok) { - ok = BKE_undosys_step_redo_with_data_ex(ustack, C, ustack->step_active, false); - } - } - - if (ok) { - BLI_assert(ustack->step_active == us); + if (ustack->step_active != NULL) { + return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active->next); } - - return ok; + return false; } /** diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index b55f80c6473..e98fae9d92a 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -1167,8 +1167,7 @@ bool BKE_unit_replace_string( /* Replace # with add sign when there is no operator between it and the next number. * * "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3" - * - * */ + */ { char *str_found = str; const char *ch = str; diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 9e7a3736141..edf40ab3861 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -128,7 +128,7 @@ static struct VolumeFileCache { std::lock_guard<std::mutex> lock(mutex); return simplified_grids.lookup_or_add_cb(simplify_level, [&]() { const float resolution_factor = 1.0f / (1 << simplify_level); - const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid); + const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid); return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor); }); } @@ -145,7 +145,7 @@ static struct VolumeFileCache { /* Has the grid tree been loaded? */ bool is_loaded; - /* Error message if an error occured during loading. */ + /* Error message if an error occurred while loading. */ std::string error_msg; /* User counting. */ int num_metadata_users; @@ -523,6 +523,8 @@ static void volume_copy_data(Main *UNUSED(bmain), volume_dst->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector, grids_src); } #endif + + volume_dst->batch_cache = nullptr; } static void volume_free_data(ID *id) @@ -642,6 +644,8 @@ IDTypeInfo IDType_ID_VO = { /* blend_read_expand */ volume_blend_read_expand, /* blend_read_undo_preserve */ nullptr, + + /* lib_override_apply_post */ nullptr, }; void BKE_volume_init_grids(Volume *volume) @@ -1233,39 +1237,39 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid) } #ifdef WITH_OPENVDB -VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase::Ptr &grid) +VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid) { - if (grid->isType<openvdb::FloatGrid>()) { + if (grid.isType<openvdb::FloatGrid>()) { return VOLUME_GRID_FLOAT; } - if (grid->isType<openvdb::Vec3fGrid>()) { + if (grid.isType<openvdb::Vec3fGrid>()) { return VOLUME_GRID_VECTOR_FLOAT; } - if (grid->isType<openvdb::BoolGrid>()) { + if (grid.isType<openvdb::BoolGrid>()) { return VOLUME_GRID_BOOLEAN; } - if (grid->isType<openvdb::DoubleGrid>()) { + if (grid.isType<openvdb::DoubleGrid>()) { return VOLUME_GRID_DOUBLE; } - if (grid->isType<openvdb::Int32Grid>()) { + if (grid.isType<openvdb::Int32Grid>()) { return VOLUME_GRID_INT; } - if (grid->isType<openvdb::Int64Grid>()) { + if (grid.isType<openvdb::Int64Grid>()) { return VOLUME_GRID_INT64; } - if (grid->isType<openvdb::Vec3IGrid>()) { + if (grid.isType<openvdb::Vec3IGrid>()) { return VOLUME_GRID_VECTOR_INT; } - if (grid->isType<openvdb::Vec3dGrid>()) { + if (grid.isType<openvdb::Vec3dGrid>()) { return VOLUME_GRID_VECTOR_DOUBLE; } - if (grid->isType<openvdb::StringGrid>()) { + if (grid.isType<openvdb::StringGrid>()) { return VOLUME_GRID_STRING; } - if (grid->isType<openvdb::MaskGrid>()) { + if (grid.isType<openvdb::MaskGrid>()) { return VOLUME_GRID_MASK; } - if (grid->isType<openvdb::points::PointDataGrid>()) { + if (grid.isType<openvdb::points::PointDataGrid>()) { return VOLUME_GRID_POINTS; } return VOLUME_GRID_UNKNOWN; @@ -1276,7 +1280,7 @@ VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid) { #ifdef WITH_OPENVDB const openvdb::GridBase::Ptr grid = volume_grid->grid(); - return BKE_volume_grid_type_openvdb(grid); + return BKE_volume_grid_type_openvdb(*grid); #else UNUSED_VARS(volume_grid); #endif diff --git a/source/blender/blenkernel/intern/volume_to_mesh.cc b/source/blender/blenkernel/intern/volume_to_mesh.cc new file mode 100644 index 00000000000..7ab67516242 --- /dev/null +++ b/source/blender/blenkernel/intern/volume_to_mesh.cc @@ -0,0 +1,183 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <vector> + +#include "BLI_float3.hh" +#include "BLI_span.hh" +#include "BLI_utildefines.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_volume_types.h" + +#include "BKE_mesh.h" +#include "BKE_volume.h" + +#ifdef WITH_OPENVDB +# include <openvdb/tools/GridTransformer.h> +# include <openvdb/tools/VolumeToMesh.h> +#endif + +#include "BKE_volume_to_mesh.hh" + +namespace blender::bke { + +#ifdef WITH_OPENVDB + +struct VolumeToMeshOp { + const openvdb::GridBase &base_grid; + const VolumeToMeshResolution resolution; + const float threshold; + const float adaptivity; + std::vector<openvdb::Vec3s> verts; + std::vector<openvdb::Vec3I> tris; + std::vector<openvdb::Vec4I> quads; + + template<typename GridType> bool operator()() + { + if constexpr (std::is_scalar_v<typename GridType::ValueType>) { + this->generate_mesh_data<GridType>(); + return true; + } + return false; + } + + template<typename GridType> void generate_mesh_data() + { + const GridType &grid = static_cast<const GridType &>(base_grid); + + if (this->resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_GRID) { + this->grid_to_mesh(grid); + return; + } + + const float resolution_factor = this->compute_resolution_factor(base_grid); + typename GridType::Ptr temp_grid = this->create_grid_with_changed_resolution( + grid, resolution_factor); + this->grid_to_mesh(*temp_grid); + } + + template<typename GridType> + typename GridType::Ptr create_grid_with_changed_resolution(const GridType &old_grid, + const float resolution_factor) + { + BLI_assert(resolution_factor > 0.0f); + + openvdb::Mat4R xform; + xform.setToScale(openvdb::Vec3d(resolution_factor)); + openvdb::tools::GridTransformer transformer{xform}; + + typename GridType::Ptr new_grid = GridType::create(); + transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid); + new_grid->transform() = old_grid.transform(); + new_grid->transform().preScale(1.0f / resolution_factor); + return new_grid; + } + + float compute_resolution_factor(const openvdb::GridBase &grid) const + { + const openvdb::Vec3s voxel_size{grid.voxelSize()}; + const float current_voxel_size = std::max({voxel_size[0], voxel_size[1], voxel_size[2]}); + const float desired_voxel_size = this->compute_desired_voxel_size(grid); + return current_voxel_size / desired_voxel_size; + } + + float compute_desired_voxel_size(const openvdb::GridBase &grid) const + { + if (this->resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + return this->resolution.settings.voxel_size; + } + const openvdb::CoordBBox coord_bbox = base_grid.evalActiveVoxelBoundingBox(); + const openvdb::BBoxd bbox = grid.transform().indexToWorld(coord_bbox); + const float max_extent = bbox.extents()[bbox.maxExtent()]; + const float voxel_size = max_extent / this->resolution.settings.voxel_amount; + return voxel_size; + } + + template<typename GridType> void grid_to_mesh(const GridType &grid) + { + openvdb::tools::volumeToMesh( + grid, this->verts, this->tris, this->quads, this->threshold, this->adaptivity); + + /* Better align generated mesh with volume (see T85312). */ + openvdb::Vec3s offset = grid.voxelSize() / 2.0f; + for (openvdb::Vec3s &position : this->verts) { + position += offset; + } + } +}; + +static Mesh *new_mesh_from_openvdb_data(Span<openvdb::Vec3s> verts, + Span<openvdb::Vec3I> tris, + Span<openvdb::Vec4I> quads) +{ + const int tot_loops = 3 * tris.size() + 4 * quads.size(); + const int tot_polys = tris.size() + quads.size(); + + Mesh *mesh = BKE_mesh_new_nomain(verts.size(), 0, 0, tot_loops, tot_polys); + + /* Write vertices. */ + for (const int i : verts.index_range()) { + const blender::float3 co = blender::float3(verts[i].asV()); + copy_v3_v3(mesh->mvert[i].co, co); + } + + /* Write triangles. */ + for (const int i : tris.index_range()) { + mesh->mpoly[i].loopstart = 3 * i; + mesh->mpoly[i].totloop = 3; + for (int j = 0; j < 3; j++) { + /* Reverse vertex order to get correct normals. */ + mesh->mloop[3 * i + j].v = tris[i][2 - j]; + } + } + + /* Write quads. */ + const int poly_offset = tris.size(); + const int loop_offset = tris.size() * 3; + for (const int i : quads.index_range()) { + mesh->mpoly[poly_offset + i].loopstart = loop_offset + 4 * i; + mesh->mpoly[poly_offset + i].totloop = 4; + for (int j = 0; j < 4; j++) { + /* Reverse vertex order to get correct normals. */ + mesh->mloop[loop_offset + 4 * i + j].v = quads[i][3 - j]; + } + } + + BKE_mesh_calc_edges(mesh, false, false); + BKE_mesh_calc_normals(mesh); + return mesh; +} + +Mesh *volume_to_mesh(const openvdb::GridBase &grid, + const VolumeToMeshResolution &resolution, + const float threshold, + const float adaptivity) +{ + const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid); + + VolumeToMeshOp to_mesh_op{grid, resolution, threshold, adaptivity}; + if (!BKE_volume_grid_type_operation(grid_type, to_mesh_op)) { + return nullptr; + } + + return new_mesh_from_openvdb_data(to_mesh_op.verts, to_mesh_op.tris, to_mesh_op.quads); +} + +#endif /* WITH_OPENVDB */ + +} // namespace blender::bke diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index 291116556c3..5a101cf009b 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -192,6 +192,8 @@ IDTypeInfo IDType_ID_WS = { .blend_read_expand = workspace_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 8fe7653fc25..a2ce37a5d90 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -206,6 +206,8 @@ IDTypeInfo IDType_ID_WO = { .blend_read_expand = world_blend_read_expand, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; World *BKE_world_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h index 7257be66b79..79c16e321be 100644 --- a/source/blender/blenkernel/nla_private.h +++ b/source/blender/blenkernel/nla_private.h @@ -106,14 +106,10 @@ typedef struct NlaEvalChannel { int index; bool is_array; - bool in_blend; char mix_mode; - struct NlaEvalChannel *next_blend; - NlaEvalChannelSnapshot *blend_snapshot; - - /* Mask of array items controlled by NLA. */ - NlaValidMask valid; + /* Associated with the RNA property's value(s), marks which elements are affected by NLA. */ + NlaValidMask domain; /* Base set of values. */ NlaEvalChannelSnapshot base_snapshot; @@ -186,6 +182,15 @@ void nladata_flush_channels(PointerRNA *ptr, NlaEvalSnapshot *snapshot, const bool flush_to_original); +void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapshot); + +void nlasnapshot_blend(NlaEvalData *eval_data, + NlaEvalSnapshot *lower_snapshot, + NlaEvalSnapshot *upper_snapshot, + const short upper_blendmode, + const float upper_influence, + NlaEvalSnapshot *r_blended_snapshot); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index c8e7fea6601..35c5221efa3 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -125,7 +125,7 @@ float *tracking_track_get_mask_for_region(int frame_width, const float region_max[2], MovieTrackingTrack *track); -/*********************** Frame accessr *************************/ +/*********************** Frame Accessor *************************/ struct libmv_FrameAccessor; diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 74a491898b6..df80e720363 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -20,7 +20,7 @@ /** \file * \ingroup bli * \brief File and directory operations. - * */ + */ #pragma once @@ -88,10 +88,10 @@ typedef enum eFileAttributes { FILE_ATTR_TEMPORARY = 1 << 7, /* Used for temporary storage. */ FILE_ATTR_SPARSE_FILE = 1 << 8, /* Sparse File. */ FILE_ATTR_OFFLINE = 1 << 9, /* Data is not immediately available. */ - FILE_ATTR_ALIAS = 1 << 10, /* Mac Alias or Windows Lnk. File-based redirection. */ - FILE_ATTR_REPARSE_POINT = 1 << 11, /* File has associated reparse point. */ + FILE_ATTR_ALIAS = 1 << 10, /* Mac Alias or Windows LNK. File-based redirection. */ + FILE_ATTR_REPARSE_POINT = 1 << 11, /* File has associated re-parse point. */ FILE_ATTR_SYMLINK = 1 << 12, /* Reference to another file. */ - FILE_ATTR_JUNCTION_POINT = 1 << 13, /* Folder Symlink. */ + FILE_ATTR_JUNCTION_POINT = 1 << 13, /* Folder Symbolic-link. */ FILE_ATTR_MOUNT_POINT = 1 << 14, /* Volume mounted as a folder. */ FILE_ATTR_HARDLINK = 1 << 15, /* Duplicated directory entry. */ } eFileAttributes; diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh index 2a5320e4c35..84dd0e358a2 100644 --- a/source/blender/blenlib/BLI_float2.hh +++ b/source/blender/blenlib/BLI_float2.hh @@ -29,6 +29,14 @@ struct float2 { { } + explicit float2(float value) : x(value), y(value) + { + } + + explicit float2(int value) : x(value), y(value) + { + } + float2(float x, float y) : x(x), y(y) { } @@ -52,6 +60,11 @@ struct float2 { return len_v2(*this); } + float length_squared() const + { + return len_squared_v2(*this); + } + float2 &operator+=(const float2 &other) { x += other.x; diff --git a/source/blender/blenlib/BLI_fnmatch.h b/source/blender/blenlib/BLI_fnmatch.h index d09a14621d8..2d0c13bc423 100644 --- a/source/blender/blenlib/BLI_fnmatch.h +++ b/source/blender/blenlib/BLI_fnmatch.h @@ -16,7 +16,7 @@ * Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. * * NOTE: The canonical source of this file is maintained with the GNU C Library. - * Bugs can be reported to bug-glibc@prep.ai.mit.edu. + * Bugs can be reported to <bug-glibc@prep.ai.mit.edu>. */ #pragma once diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h index 51833d081d0..f6075367ac5 100644 --- a/source/blender/blenlib/BLI_math.h +++ b/source/blender/blenlib/BLI_math.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 0ec65999006..c862290b262 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index b007dd7cfed..e881f1a0e4e 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -12,8 +12,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 9e613270538..26d2f1fcb29 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h index d5e4eedb1a6..2aff629def8 100644 --- a/source/blender/blenlib/BLI_math_color_blend.h +++ b/source/blender/blenlib/BLI_math_color_blend.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index c0a9ea91e75..d767c2924d1 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once @@ -826,6 +825,11 @@ MINLINE float shell_v2v2_mid_normalized_to_dist(const float a[2], const float b[ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]); +/********************************** Geodesics *********************************/ + +float geodesic_distance_propagate_across_triangle( + const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2); + /**************************** Inline Definitions ******************************/ #if BLI_MATH_DO_INLINE diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index 506386f8d25..70f56d15164 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index d971f48c4cf..eac7f25f11a 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -17,7 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index 15d4dc21f8d..fe995b2e46e 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once @@ -178,7 +177,7 @@ typedef enum eEulerRotationOrders { EULER_ORDER_YZX, EULER_ORDER_ZXY, EULER_ORDER_ZYX, - /* there are 6 more entries with dulpicate entries included */ + /* There are 6 more entries with duplicate entries included. */ } eEulerRotationOrders; void eulO_to_quat(float quat[4], const float eul[3], const short order); diff --git a/source/blender/blenlib/BLI_math_solvers.h b/source/blender/blenlib/BLI_math_solvers.h index 9b2d1eedec7..13481e27e2a 100644 --- a/source/blender/blenlib/BLI_math_solvers.h +++ b/source/blender/blenlib/BLI_math_solvers.h @@ -15,7 +15,7 @@ * * The Original Code is Copyright (C) 2015 by Blender Foundation * All rights reserved. - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_statistics.h b/source/blender/blenlib/BLI_math_statistics.h index ad6cb1a3c1e..6e818f5c8df 100644 --- a/source/blender/blenlib/BLI_math_statistics.h +++ b/source/blender/blenlib/BLI_math_statistics.h @@ -15,7 +15,7 @@ * * The Original Code is Copyright (C) 2015 by Blender Foundation * All rights reserved. - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 16585e34419..bb1e1a1c38d 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ #pragma once diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh index ddda3edf2ff..a7996939bb1 100644 --- a/source/blender/blenlib/BLI_mesh_intersect.hh +++ b/source/blender/blenlib/BLI_mesh_intersect.hh @@ -95,7 +95,7 @@ struct Plane { /* Test equality on the exact fields. */ bool operator==(const Plane &other) const; - /* Hash onthe exact fields. */ + /* Hash on the exact fields. */ uint64_t hash() const; void make_canonical(); @@ -144,7 +144,7 @@ struct Face : NonCopyable { /* Test equality of verts, in same positions. */ bool operator==(const Face &other) const; - /* Test equaliy faces allowing cyclic shifts. */ + /* Test equality faces allowing cyclic shifts. */ bool cyclic_equal(const Face &other) const; FacePos next_pos(FacePos p) const diff --git a/source/blender/blenlib/BLI_mmap.h b/source/blender/blenlib/BLI_mmap.h new file mode 100644 index 00000000000..4920152c9d1 --- /dev/null +++ b/source/blender/blenlib/BLI_mmap.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +#pragma once + +/** \file + * \ingroup bli + */ + +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Memory-mapped file IO that implements all the OS-specific details and error handling. */ + +struct BLI_mmap_file; + +typedef struct BLI_mmap_file BLI_mmap_file; + +/* Prepares an opened file for memory-mapped IO. + * May return NULL if the operation fails. + * Note that this seeks to the end of the file to determine its length. */ +BLI_mmap_file *BLI_mmap_open(int fd) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; + +/* Reads length bytes from file at the given offset into dest. + * Returns whether the operation was successful (may fail when reading beyond the file + * end or when IO errors occur). */ +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) + ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) ATTR_WARN_UNUSED_RESULT; + +void BLI_mmap_free(BLI_mmap_file *file) ATTR_NONNULL(1); + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index ff1f6af9573..2740e3740f2 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -40,7 +40,7 @@ extern "C" { #if defined(__linux__) || defined(__GNU__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ defined(__FreeBSD_kernel__) || defined(__HAIKU__) -/* Linux-i386, Linux-Alpha, Linux-ppc */ +/* Linux-i386, Linux-Alpha, Linux-PPC */ # include <stdint.h> /* XXX */ diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h index 8dd0706e1e2..0d5b2e6e2df 100644 --- a/source/blender/blenlib/BLI_system.h +++ b/source/blender/blenlib/BLI_system.h @@ -49,7 +49,7 @@ void BLI_hostname_get(char *buffer, size_t bufsize); size_t BLI_system_memory_max_in_megabytes(void); int BLI_system_memory_max_in_megabytes_int(void); -/* getpid */ +/* For `getpid`. */ #ifdef WIN32 # define BLI_SYSTEM_PID_H <process.h> diff --git a/source/blender/blenlib/BLI_task.hh b/source/blender/blenlib/BLI_task.hh index 0da03d84793..8e963c958b2 100644 --- a/source/blender/blenlib/BLI_task.hh +++ b/source/blender/blenlib/BLI_task.hh @@ -22,15 +22,15 @@ #ifdef WITH_TBB /* Quiet top level deprecation message, unrelated to API usage here. */ -# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 - # if defined(WIN32) && !defined(NOMINMAX) /* TBB includes Windows.h which will define min/max macros causing issues * when we try to use std::min and std::max later on. */ # define NOMINMAX # define TBB_MIN_MAX_CLEANUP # endif -# include <tbb/tbb.h> +# include <tbb/blocked_range.h> +# include <tbb/parallel_for.h> +# include <tbb/parallel_for_each.h> # ifdef WIN32 /* We cannot keep this defined, since other parts of the code deal with this on their own, leading * to multiple define warnings unless we un-define this, however we can only undefine this if we diff --git a/source/blender/blenlib/BLI_voronoi_2d.h b/source/blender/blenlib/BLI_voronoi_2d.h index 92c7d367b48..0e27229352f 100644 --- a/source/blender/blenlib/BLI_voronoi_2d.h +++ b/source/blender/blenlib/BLI_voronoi_2d.h @@ -50,7 +50,7 @@ typedef struct VoronoiEdge { /* point on Voronoi place on the right side of edge */ float right[2]; - /* directional coeffitients satisfying equation y = f * x + g (edge lies on this line) */ + /* Directional coefficients satisfying equation `y = f * x + g` (edge lies on this line). */ float f, g; /* some edges consist of two parts, diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index dc4d6d8fce4..f771d26baab 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -64,7 +64,7 @@ extern "C" { # define S_ISDIR(x) (((x)&_S_IFDIR) == _S_IFDIR) #endif -/* defines for using ISO C++ conformant names */ +/* Defines for using ISO C++ conferment names. */ #if !defined(_MSC_VER) || _MSC_VER < 1900 # define snprintf _snprintf #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 45a1054fb53..363d3003b3c 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC intern/BLI_memblock.c intern/BLI_memiter.c intern/BLI_mempool.c + intern/BLI_mmap.c intern/BLI_timer.c intern/DLRB_tree.c intern/array_store.c @@ -243,6 +244,7 @@ set(SRC BLI_mempool.h BLI_mesh_boolean.hh BLI_mesh_intersect.hh + BLI_mmap.h BLI_mpq2.hh BLI_mpq3.hh BLI_multi_value_map.hh diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c index fe3ec368379..cc01693422c 100644 --- a/source/blender/blenlib/intern/BLI_filelist.c +++ b/source/blender/blenlib/intern/BLI_filelist.c @@ -369,7 +369,7 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st, int yesterday_yday = 0; if (r_is_today || r_is_yesterday) { - /* Localtime() has only one buffer so need to get data out before called again. */ + /* `localtime()` has only one buffer so need to get data out before called again. */ const time_t ts_now = time(NULL); struct tm *today = localtime(&ts_now); diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 0f90ad3a490..a0e94e00634 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -94,7 +94,7 @@ struct BVHTree { BVHNode *nodearray; /* pre-alloc branch nodes */ BVHNode **nodechild; /* pre-alloc children for nodes */ float *nodebv; /* pre-alloc bounding-volumes for nodes */ - float epsilon; /* epslion is used for inflation of the k-dop */ + float epsilon; /* Epsilon is used for inflation of the K-DOP. */ int totleaf; /* leafs */ int totbranch; axis_t start_axis, stop_axis; /* bvhtree_kdop_axes array indices according to axis */ @@ -365,7 +365,7 @@ static void create_kdop_hull( int k; axis_t axis_iter; - /* don't init boudings for the moving case */ + /* Don't initialize bounds for the moving case */ if (!moving) { node_minmax_init(tree, node); } @@ -573,9 +573,9 @@ typedef struct BVHBuildHelper { int tree_type; int totleafs; - /** Min number of leafs that are archievable from a node at depth N */ + /** Min number of leafs that are achievable from a node at depth `N`. */ int leafs_per_child[32]; - /** Number of nodes at depth N (tree_type^N) */ + /** Number of nodes at depth `N (tree_type^N)`. */ int branches_on_level[32]; /** Number of leafs that are placed on the level that is not 100% filled */ @@ -1312,7 +1312,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap_ex( bool use_threading = (flag & BVH_OVERLAP_USE_THREADING) != 0 && (tree1->totleaf > KDOPBVH_THREAD_LEAF_THRESHOLD); - /* `RETURN_PAIRS` was not implemented without `max_interations`. */ + /* 'RETURN_PAIRS' was not implemented without 'max_interactions'. */ BLI_assert(overlap_pairs || max_interactions); const int root_node_len = BLI_bvhtree_overlap_thread_num(tree1); diff --git a/source/blender/blenlib/intern/BLI_mmap.c b/source/blender/blenlib/intern/BLI_mmap.c new file mode 100644 index 00000000000..2fd162de22c --- /dev/null +++ b/source/blender/blenlib/intern/BLI_mmap.c @@ -0,0 +1,237 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bli + */ + +#include "BLI_mmap.h" +#include "BLI_fileops.h" +#include "BLI_listbase.h" +#include "MEM_guardedalloc.h" + +#include <string.h> + +#ifndef WIN32 +# include <signal.h> +# include <stdlib.h> +# include <sys/mman.h> // for mmap +# include <unistd.h> // for read close +#else +# include "BLI_winstuff.h" +# include <io.h> // for open close read +#endif + +struct BLI_mmap_file { + /* The address to which the file was mapped. */ + char *memory; + + /* The length of the file (and therefore the mapped region). */ + size_t length; + + /* Platform-specific handle for the mapping. */ + void *handle; + + /* Flag to indicate IO errors. Needs to be volatile since it's being set from + * within the signal handler, which is not part of the normal execution flow. */ + volatile bool io_error; +}; + +#ifndef WIN32 +/* When using memory-mapped files, any IO errors will result in a SIGBUS signal. + * Therefore, we need to catch that signal and stop reading the file in question. + * To do so, we keep a list of all current FileDatas that use memory-mapped files, + * and if a SIGBUS is caught, we check if the failed address is inside one of the + * mapped regions. + * If it is, we set a flag to indicate a failed read and remap the memory in + * question to a zero-backed region in order to avoid additional signals. + * The code that actually reads the memory area has to check whether the flag was + * set after it's done reading. + * If the error occurred outside of a memory-mapped region, we call the previous + * handler if one was configured and abort the process otherwise. + */ + +struct error_handler_data { + ListBase open_mmaps; + char configured; + void (*next_handler)(int, siginfo_t *, void *); +} error_handler = {0}; + +static void sigbus_handler(int sig, siginfo_t *siginfo, void *ptr) +{ + /* We only handle SIGBUS here for now. */ + BLI_assert(sig == SIGBUS); + + char *error_addr = (char *)siginfo->si_addr; + /* Find the file that this error belongs to. */ + LISTBASE_FOREACH (LinkData *, link, &error_handler.open_mmaps) { + BLI_mmap_file *file = link->data; + + /* Is the address where the error occurred in this file's mapped range? */ + if (error_addr >= file->memory && error_addr < file->memory + file->length) { + file->io_error = true; + + /* Replace the mapped memory with zeroes. */ + const void *mapped_memory = mmap( + file->memory, file->length, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (mapped_memory == MAP_FAILED) { + fprintf(stderr, "SIGBUS handler: Error replacing mapped file with zeros\n"); + } + + return; + } + } + + /* Fall back to other handler if there was one. */ + if (error_handler.next_handler) { + error_handler.next_handler(sig, siginfo, ptr); + } + else { + fprintf(stderr, "Unhandled SIGBUS caught\n"); + abort(); + } +} + +/* Ensures that the error handler is set up and ready. */ +static bool sigbus_handler_setup(void) +{ + if (!error_handler.configured) { + struct sigaction newact = {0}, oldact = {0}; + + newact.sa_sigaction = sigbus_handler; + newact.sa_flags = SA_SIGINFO; + + if (sigaction(SIGBUS, &newact, &oldact)) { + return false; + } + + /* Remember the previously configured handler to fall back to it if the error + * does not belong to any of the mapped files. */ + error_handler.next_handler = oldact.sa_sigaction; + error_handler.configured = 1; + } + + return true; +} + +/* Adds a file to the list that the error handler checks. */ +static void sigbus_handler_add(BLI_mmap_file *file) +{ + BLI_addtail(&error_handler.open_mmaps, BLI_genericNodeN(file)); +} + +/* Removes a file from the list that the error handler checks. */ +static void sigbus_handler_remove(BLI_mmap_file *file) +{ + LinkData *link = BLI_findptr(&error_handler.open_mmaps, file, offsetof(LinkData, data)); + BLI_freelinkN(&error_handler.open_mmaps, link); +} +#endif + +BLI_mmap_file *BLI_mmap_open(int fd) +{ + void *memory, *handle = NULL; + size_t length = BLI_lseek(fd, 0, SEEK_END); + +#ifndef WIN32 + /* Ensure that the SIGBUS handler is configured. */ + if (!sigbus_handler_setup()) { + return NULL; + } + + /* Map the given file to memory. */ + memory = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0); + if (memory == MAP_FAILED) { + return NULL; + } +#else + /* Convert the POSIX-style file descriptor to a Windows handle. */ + void *file_handle = (void *)_get_osfhandle(fd); + /* Memory mapping on Windows is a two-step process - first we create a mapping, + * then we create a view into that mapping. + * In our case, one view that spans the entire file is enough. */ + handle = CreateFileMapping(file_handle, NULL, PAGE_READONLY, 0, 0, NULL); + if (handle == NULL) { + return NULL; + } + memory = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0); + if (memory == NULL) { + CloseHandle(handle); + return NULL; + } +#endif + + /* Now that the mapping was successful, allocate memory and set up the BLI_mmap_file. */ + BLI_mmap_file *file = MEM_callocN(sizeof(BLI_mmap_file), __func__); + file->memory = memory; + file->handle = handle; + file->length = length; + +#ifndef WIN32 + /* Register the file with the error handler. */ + sigbus_handler_add(file); +#endif + + return file; +} + +bool BLI_mmap_read(BLI_mmap_file *file, void *dest, size_t offset, size_t length) +{ + /* If a previous read has already failed or we try to read past the end, + * don't even attempt to read any further. */ + if (file->io_error || (offset + length > file->length)) { + return false; + } + +#ifndef WIN32 + /* If an error occurs in this call, sigbus_handler will be called and will set + * file->io_error to true. */ + memcpy(dest, file->memory + offset, length); +#else + /* On Windows, we use exception handling to be notified of errors. */ + __try { + memcpy(dest, file->memory + offset, length); + } + __except (GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ? EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { + file->io_error = true; + return false; + } +#endif + + return !file->io_error; +} + +void *BLI_mmap_get_pointer(BLI_mmap_file *file) +{ + return file->memory; +} + +void BLI_mmap_free(BLI_mmap_file *file) +{ +#ifndef WIN32 + munmap((void *)file->memory, file->length); + sigbus_handler_remove(file); +#else + UnmapViewOfFile(file->memory); + CloseHandle(file->handle); +#endif + + MEM_freeN(file); +} diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c index 847cb42186a..08164e75009 100644 --- a/source/blender/blenlib/intern/array_store.c +++ b/source/blender/blenlib/intern/array_store.c @@ -533,7 +533,7 @@ static void bchunk_list_calc_trim_len(const BArrayInfo *info, data_trim_len = data_trim_len - data_last_chunk_len; if (data_last_chunk_len) { if (data_last_chunk_len < info->chunk_byte_size_min) { - /* may be zero and thats OK */ + /* May be zero and that's OK. */ data_trim_len -= info->chunk_byte_size; data_last_chunk_len += info->chunk_byte_size; } diff --git a/source/blender/blenlib/intern/bitmap_draw_2d.c b/source/blender/blenlib/intern/bitmap_draw_2d.c index 33250105c79..9d3b66d72d7 100644 --- a/source/blender/blenlib/intern/bitmap_draw_2d.c +++ b/source/blender/blenlib/intern/bitmap_draw_2d.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c index 9840dc77148..84b3f728884 100644 --- a/source/blender/blenlib/intern/boxpack_2d.c +++ b/source/blender/blenlib/intern/boxpack_2d.c @@ -385,7 +385,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r box++; /* next box, needed for the loop below */ /* ...done packing the first box */ - /* Main boxpacking loop */ + /* Main box-packing loop */ for (box_index = 1; box_index < len; box_index++, box++) { /* These floats are used for sorting re-sorting */ @@ -414,8 +414,7 @@ void BLI_box_pack_2d(BoxPack *boxarray, const uint len, float *r_tot_x, float *r /* This vert has a free quadrant * Test if we can place the box here - * vert->free & quad_flags[j] - Checks - * */ + * `vert->free & quad_flags[j]` - Checks. */ for (j = 0; (j < 4) && isect; j++) { if (vert->free & quad_flag(j)) { diff --git a/source/blender/blenlib/intern/convexhull_2d.c b/source/blender/blenlib/intern/convexhull_2d.c index a3d24787d27..cb4ef54bfb7 100644 --- a/source/blender/blenlib/intern/convexhull_2d.c +++ b/source/blender/blenlib/intern/convexhull_2d.c @@ -28,7 +28,7 @@ #include "BLI_strict_flags.h" #include "BLI_utildefines.h" -/* Copyright 2001, softSurfer (www.softsurfer.com) +/* Copyright 2001, softSurfer (http://www.softsurfer.com) * This code may be freely used and modified for any purpose * providing that this copyright notice is included with it. * SoftSurfer makes no warranty for this code, and cannot be held diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc index f0b65a55816..06a749ab921 100644 --- a/source/blender/blenlib/intern/delaunay_2d.cc +++ b/source/blender/blenlib/intern/delaunay_2d.cc @@ -561,14 +561,14 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen const vec2<double> &uco = u->co.approx; const vec2<double> &vco = v->co.approx; int strokew = e->input_ids == nullptr ? thin_line : thick_line; - f << "<line fill=\"none\" stroke=\"black\" stroke-width=\"" << strokew << "\" x1=\"" + f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\"" << SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\"" << SY(vco[1]) << "\">\n"; f << " <title>" << vertname(u) << vertname(v) << "</title>\n"; f << "</line>\n"; if (draw_edge_labels) { f << "<text x=\"" << SX((uco[0] + vco[0]) / 2) << "\" y=\"" << SY((uco[1] + vco[1]) / 2) - << "\" font-size=\"small\">"; + << R"(" font-size="small">)"; f << vertname(u) << vertname(v) << sename(&e->symedges[0]) << sename(&e->symedges[1]) << "</text>\n"; } @@ -576,13 +576,13 @@ template<typename T> void cdt_draw(const std::string &label, const CDTArrangemen int i = 0; for (const CDTVert<T> *v : cdt.verts) { - f << "<circle fill=\"black\" cx=\"" << SX(v->co.approx[0]) << "\" cy=\"" << SY(v->co.approx[1]) + f << R"(<circle fill="black" cx=")" << SX(v->co.approx[0]) << "\" cy=\"" << SY(v->co.approx[1]) << "\" r=\"" << vert_radius << "\">\n"; f << " <title>[" << i << "]" << v->co.approx << "</title>\n"; f << "</circle>\n"; if (draw_vert_labels) { f << "<text x=\"" << SX(v->co.approx[0]) + vert_radius << "\" y=\"" - << SY(v->co.approx[1]) - vert_radius << "\" font-size=\"small\">[" << i << "]</text>\n"; + << SY(v->co.approx[1]) - vert_radius << R"(" font-size="small">[)" << i << "]</text>\n"; } ++i; } @@ -754,7 +754,7 @@ template<> CDTVert<double>::CDTVert(const vec2<double> &pt) { this->co.exact = pt; this->co.approx = pt; - this->co.abs_approx = pt; /* Not used, so does't matter. */ + this->co.abs_approx = pt; /* Not used, so doesn't matter. */ this->input_ids = nullptr; this->symedge = nullptr; this->index = -1; @@ -1411,12 +1411,12 @@ void dc_tri(CDTArrangement<T> *cdt, /* Guibas-Stolfi Divide-and_Conquer algorithm. */ template<typename T> void dc_triangulate(CDTArrangement<T> *cdt, Array<SiteInfo<T>> &sites) { - /* Compress sites in place to eliminted verts that merge to others. */ + /* Compress sites in place to eliminated verts that merge to others. */ int i = 0; int j = 0; int nsites = sites.size(); while (j < nsites) { - /* Invariante: sites[0..i-1] have non-merged verts from 0..(j-1) in them. */ + /* Invariant: `sites[0..i-1]` have non-merged verts from `0..(j-1)` in them. */ sites[i] = sites[j++]; if (sites[i].v->merge_to_index < 0) { i++; @@ -1500,7 +1500,7 @@ template<typename T> static void re_delaunay_triangulate(CDTArrangement<T> *cdt, cse = ss; } } - /* Add diagonals necessary to make abc a triangle. */ + /* Add diagonals necessary to make `abc` a triangle. */ CDTEdge<T> *ebc = nullptr; CDTEdge<T> *eca = nullptr; if (!exists_edge(b, c)) { diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc index eb15a51366e..13a2341a9d5 100644 --- a/source/blender/blenlib/intern/dot_export.cc +++ b/source/blender/blenlib/intern/dot_export.cc @@ -275,10 +275,10 @@ NodeWithSocketsRef::NodeWithSocketsRef(Node &node, { std::stringstream ss; - ss << "<<table border=\"0\" cellspacing=\"3\">"; + ss << R"(<<table border="0" cellspacing="3">)"; /* Header */ - ss << "<tr><td colspan=\"3\" align=\"center\"><b>"; + ss << R"(<tr><td colspan="3" align="center"><b>)"; ss << ((name.size() == 0) ? "No Name" : name); ss << "</b></td></tr>"; @@ -291,7 +291,7 @@ NodeWithSocketsRef::NodeWithSocketsRef(Node &node, if (name.size() == 0) { name = "No Name"; } - ss << "<td align=\"left\" port=\"in" << i << "\">"; + ss << R"(<td align="left" port="in)" << i << "\">"; ss << name; ss << "</td>"; } @@ -304,7 +304,7 @@ NodeWithSocketsRef::NodeWithSocketsRef(Node &node, if (name.size() == 0) { name = "No Name"; } - ss << "<td align=\"right\" port=\"out" << i << "\">"; + ss << R"(<td align="right" port="out)" << i << "\">"; ss << name; ss << "</td>"; } diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 301d9dc2296..e755a8e75b5 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -307,7 +307,7 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) /* Extract the first 256 character from TTF */ lcode = charcode = FT_Get_First_Char(face, &glyph_index); - /* No charmap found from the ttf so we need to figure it out */ + /* No `charmap` found from the TTF so we need to figure it out. */ if (glyph_index == 0) { FT_CharMap found = NULL; FT_CharMap charmap; diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index 118d19418d4..ae34074e804 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -41,7 +41,7 @@ struct QueueChunk { struct _GSQueue { struct QueueChunk *chunk_first; /* first active chunk to pop from */ - struct QueueChunk *chunk_last; /* flast active chunk to push onto */ + struct QueueChunk *chunk_last; /* last active chunk to push onto */ struct QueueChunk *chunk_free; /* free chunks to reuse */ size_t chunk_first_index; /* index into 'chunk_first' */ size_t chunk_last_index; /* index into 'chunk_last' */ diff --git a/source/blender/blenlib/intern/jitter_2d.c b/source/blender/blenlib/intern/jitter_2d.c index c92aeddb27d..068cb3d2f70 100644 --- a/source/blender/blenlib/intern/jitter_2d.c +++ b/source/blender/blenlib/intern/jitter_2d.c @@ -179,7 +179,7 @@ void BLI_jitter_init(float (*jitarr)[2], int num) MEM_freeN(jit2); - /* finally, move jittertab to be centered around (0, 0) */ + /* Finally, move jitter to be centered around (0, 0). */ for (i = 0; i < num; i++) { jitarr[i][0] -= 0.5f; jitarr[i][1] -= 0.5f; diff --git a/source/blender/blenlib/intern/kdtree_impl.h b/source/blender/blenlib/intern/kdtree_impl.h index 26b2228cdbc..c92dc2e95a3 100644 --- a/source/blender/blenlib/intern/kdtree_impl.h +++ b/source/blender/blenlib/intern/kdtree_impl.h @@ -158,7 +158,7 @@ static uint kdtree_balance(KDTreeNode *nodes, uint nodes_len, uint axis, const u return 0 + ofs; } - /* quicksort style sorting around median */ + /* Quick-sort style sorting around median. */ left = 0; right = nodes_len - 1; median = nodes_len / 2; diff --git a/source/blender/blenlib/intern/list_sort_impl.h b/source/blender/blenlib/intern/list_sort_impl.h index 46738803ee8..8f979ba5b0b 100644 --- a/source/blender/blenlib/intern/list_sort_impl.h +++ b/source/blender/blenlib/intern/list_sort_impl.h @@ -205,7 +205,7 @@ BLI_INLINE list_node *sweep_up(struct SortInfo *si, list_node *list, unsigned in * The 'ranks' array essentially captures the recursion stack of a mergesort. * The merge tree is built in a bottom-up manner. The control loop for * updating the 'ranks' array is analogous to incrementing a binary integer, - * and the `O(n)` time for counting upto n translates to `O(n)` merges when + * and the `O(n)` time for counting `upto` n translates to `O(n)` merges when * inserting `rank-0` lists. * When we plug in the sizes of the lists involved in those merges, * we get the `O(n log n)` time for the sort. diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index 2bf06371740..1137c4114a5 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 1dc7c21f1d4..28aa81e5858 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli @@ -380,7 +379,7 @@ MINLINE float fractf(float a) return a - floorf(a); } -/* Adapted from godotengine math_funcs.h. */ +/* Adapted from godot-engine math_funcs.h. */ MINLINE float wrapf(float value, float max, float min) { float range = max - min; @@ -717,7 +716,7 @@ MALWAYS_INLINE __m128 _bli_math_improve_5throot_solution(const __m128 old_result __m128 approx2 = _mm_mul_ps(old_result, old_result); __m128 approx4 = _mm_mul_ps(approx2, approx2); __m128 t = _mm_div_ps(x, approx4); - __m128 summ = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(4.0f), old_result), t); /* fma */ + __m128 summ = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(4.0f), old_result), t); /* FMA. */ return _mm_mul_ps(summ, _mm_set1_ps(1.0f / 5.0f)); } diff --git a/source/blender/blenlib/intern/math_bits_inline.c b/source/blender/blenlib/intern/math_bits_inline.c index ba18bb73850..1b381dccbfd 100644 --- a/source/blender/blenlib/intern/math_bits_inline.c +++ b/source/blender/blenlib/intern/math_bits_inline.c @@ -12,8 +12,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_boolean.cc b/source/blender/blenlib/intern/math_boolean.cc index a345bc1d0af..6d4806a3fbc 100644 --- a/source/blender/blenlib/intern/math_boolean.cc +++ b/source/blender/blenlib/intern/math_boolean.cc @@ -160,7 +160,7 @@ static RobustInitCaller init_caller; * Carnegie Mellon University * 5000 Forbes Avenue * Pittsburgh, Pennsylvania 15213-3891 - * jrs@cs.cmu.edu + * <jrs@cs.cmu.edu> * * This file contains C implementation of algorithms for exact addition * and multiplication of floating-point numbers, and predicates for diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 31ee81de40e..8fd2802a547 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_color_blend_inline.c b/source/blender/blenlib/intern/math_color_blend_inline.c index 7ad4f0d9585..53257cc9285 100644 --- a/source/blender/blenlib/intern/math_color_blend_inline.c +++ b/source/blender/blenlib/intern/math_color_blend_inline.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index 1264620cf36..26828cb8717 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli @@ -42,7 +41,7 @@ MALWAYS_INLINE __m128 srgb_to_linearrgb_v4_simd(const __m128 c) __m128 cmp = _mm_cmplt_ps(c, _mm_set1_ps(0.04045f)); __m128 lt = _mm_max_ps(_mm_mul_ps(c, _mm_set1_ps(1.0f / 12.92f)), _mm_set1_ps(0.0f)); __m128 gtebase = _mm_mul_ps(_mm_add_ps(c, _mm_set1_ps(0.055f)), - _mm_set1_ps(1.0f / 1.055f)); /* fma */ + _mm_set1_ps(1.0f / 1.055f)); /* FMA. */ __m128 gte = _bli_math_fastpow24(gtebase); return _bli_math_blend_sse(cmp, lt, gte); } diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 3cc4d03d547..5d78bb0b901 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli @@ -1439,12 +1438,12 @@ int isect_line_sphere_v3(const float l1[3], /* adapted for use in blender by Campbell Barton - 2011 * * atelier iebele abel - 2001 - * atelier@iebele.nl + * <atelier@iebele.nl> * http://www.iebele.nl * * sphere_line_intersection function adapted from: * http://astronomy.swin.edu.au/pbourke/geometry/sphereline - * Paul Bourke pbourke@swin.edu.au + * Paul Bourke <pbourke@swin.edu.au> */ const float ldir[3] = { @@ -3887,7 +3886,7 @@ void interp_weights_quad_v3(float w[4], * - 0 if the point is outside of triangle. * - 1 if the point is inside triangle. * - 2 if it's on the edge. - * */ + */ int barycentric_inside_triangle_v2(const float w[3]) { if (IN_RANGE(w[0], 0.0f, 1.0f) && IN_RANGE(w[1], 0.0f, 1.0f) && IN_RANGE(w[2], 0.0f, 1.0f)) { @@ -5234,7 +5233,7 @@ void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const f len = sqrtf(x * x + y * y + z * z); if (len > 0.0f) { if (UNLIKELY(x == 0.0f && y == 0.0f)) { - *r_u = 0.0f; /* othwise domain error */ + *r_u = 0.0f; /* Otherwise domain error. */ } else { *r_u = (1.0f - atan2f(x, y) / (float)M_PI) / 2.0f; @@ -5837,7 +5836,7 @@ bool form_factor_visible_quad(const float p[3], return true; } -/* altivec optimization, this works, but is unused */ +/* `AltiVec` optimization, this works, but is unused. */ #if 0 # include <Accelerate/Accelerate.h> @@ -6126,7 +6125,7 @@ bool is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], bool is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) { - /* linetests, the 2 diagonals have to instersect to be convex */ + /* Line-tests, the 2 diagonals have to intersect to be convex. */ return (isect_seg_seg_v2(v1, v3, v2, v4) > 0); } @@ -6234,7 +6233,7 @@ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]) return (1.0f / 3.0f) * 0.75f; } if (tan_dot < -1.0f + eps) { - /* parallele tangents (half-circle) */ + /* Parallel tangents (half-circle). */ return (1.0f / 2.0f); } @@ -6246,3 +6245,56 @@ float cubic_tangent_factor_circle_v3(const float tan_l[3], const float tan_r[3]) const float angle_cos = cosf(angle); return ((1.0f - angle_cos) / (angle_sin * 2.0f)) / angle_sin; } + +/** + * Utility for computing approximate geodesic distances on triangle meshes. + * + * Given triangle with vertex coordinates v0, v1, v2, and known geodesic distances + * dist1 and dist2 at v1 and v2, estimate a geodesic distance at vertex v0. + * + * From "Dart Throwing on Surfaces", EGSR 2009. Section 7, Geodesic Dart Throwing. + */ +float geodesic_distance_propagate_across_triangle( + const float v0[3], const float v1[3], const float v2[3], const float dist1, const float dist2) +{ + /* Vectors along triangle edges. */ + float v10[3], v12[3]; + sub_v3_v3v3(v10, v0, v1); + sub_v3_v3v3(v12, v2, v1); + + if (dist1 != 0.0f && dist2 != 0.0f) { + /* Local coordinate system in the triangle plane. */ + float u[3], v[3], n[3]; + const float d12 = normalize_v3_v3(u, v12); + + if (d12 * d12 > 0.0f) { + cross_v3_v3v3(n, v12, v10); + normalize_v3(n); + cross_v3_v3v3(v, n, u); + + /* v0 in local coordinates */ + const float v0_[2] = {dot_v3v3(v10, u), fabsf(dot_v3v3(v10, v))}; + + /* Compute virtual source point in local coordinates, that we estimate the geodesic + * distance is being computed from. See figure 9 in the paper for the derivation. */ + const float a = 0.5f * (1.0f + (dist1 * dist1 - dist2 * dist2) / (d12 * d12)); + const float hh = dist1 * dist1 - a * a * d12 * d12; + + if (hh > 0.0f) { + const float h = sqrtf(hh); + const float S_[2] = {a * d12, -h}; + + /* Only valid if the line between the source point and v0 crosses + * the edge between v1 and v2. */ + const float x_intercept = S_[0] + h * (v0_[0] - S_[0]) / (v0_[1] + h); + if (x_intercept >= 0.0f && x_intercept <= d12) { + return len_v2v2(S_, v0_); + } + } + } + } + + /* Fall back to Dijsktra approximation in trivial case, or if no valid source + * point found that connects to v0 across the triangle. */ + return min_ff(dist1 + len_v3(v10), dist2 + len_v3v3(v0, v2)); +} diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index db317f5e81d..23c351026f2 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 3cec3db9806..163a3ab5fe3 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -139,10 +139,10 @@ BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, y1 = j + m; CLAMP(y1, 0, height - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, - * better precalc these */ + /* Normally we could do this: + * `w = P(n-a) * P(b-m);` + * except that would call `P()` 16 times per pixel therefor `pow()` 64 times, + * better pre-calculate these. */ w = wx * wy[m + 1]; if (float_output) { diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 19828e69638..57fe99ce019 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -594,7 +594,7 @@ float quat_split_swing_and_twist(const float q_in[4], int axis, float r_swing[4] BLI_assert(fabsf(r_swing[axis + 1]) < BLI_ASSERT_UNIT_EPSILON); } - /* Output twist last just in case q ovelaps r_twist. */ + /* Output twist last just in case q overlaps r_twist. */ if (r_twist) { r_twist[0] = cos_t; zero_v3(r_twist + 1); @@ -1581,7 +1581,7 @@ void quat_to_compatible_eul(float eul[3], const float oldrot[3], const float qua * was adapted from * ANSI C code from the article * "Euler Angle Conversion" - * by Ken Shoemake, shoemake@graphics.cis.upenn.edu + * by Ken Shoemake <shoemake@graphics.cis.upenn.edu> * in "Graphics Gems IV", Academic Press, 1994 * for use in Blender */ diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index e366d834fc4..85900dc32a6 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -15,7 +15,7 @@ * * The Original Code is Copyright (C) 2015 by Blender Foundation. * All rights reserved. - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_statistics.c b/source/blender/blenlib/intern/math_statistics.c index 18affbed708..b90ac99dbfe 100644 --- a/source/blender/blenlib/intern/math_statistics.c +++ b/source/blender/blenlib/intern/math_statistics.c @@ -15,7 +15,7 @@ * * The Original Code is Copyright (C) 2015 by Blender Foundation. * All rights reserved. - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_vec.cc b/source/blender/blenlib/intern/math_vec.cc index 84fa6c69d17..1d138d0b0f4 100644 --- a/source/blender/blenlib/intern/math_vec.cc +++ b/source/blender/blenlib/intern/math_vec.cc @@ -104,7 +104,7 @@ mpq2::isect_result mpq2::isect_seg_seg(const mpq2 &v1, } else { ans.lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div; - /* Avoid dividing mu by div: it is expensive in multiprecision. */ + /* Avoid dividing mu by div: it is expensive in multi-precision. */ mpq_class mudiv = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])); if (ans.lambda >= 0 && ans.lambda <= 1 && ((div > 0 && mudiv >= 0 && mudiv <= div) || (div < 0 && mudiv <= 0 && mudiv >= div))) { diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index da16fb4a9fb..a21e0c8f092 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index f17b7535258..ead354c2d87 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -17,8 +17,7 @@ * All rights reserved. * * The Original Code is: some of this file. - * - * */ + */ /** \file * \ingroup bli diff --git a/source/blender/blenlib/intern/mesh_boolean.cc b/source/blender/blenlib/intern/mesh_boolean.cc index 88d90a7816f..6ca5be743f0 100644 --- a/source/blender/blenlib/intern/mesh_boolean.cc +++ b/source/blender/blenlib/intern/mesh_boolean.cc @@ -27,10 +27,14 @@ # include "BLI_array.hh" # include "BLI_assert.h" # include "BLI_delaunay_2d.h" +# include "BLI_double3.hh" +# include "BLI_float3.hh" # include "BLI_hash.hh" +# include "BLI_kdopbvh.h" # include "BLI_map.hh" # include "BLI_math.h" # include "BLI_math_boolean.hh" +# include "BLI_math_geom.h" # include "BLI_math_mpq.hh" # include "BLI_mesh_intersect.hh" # include "BLI_mpq3.hh" @@ -45,6 +49,7 @@ # include "BLI_mesh_boolean.hh" // # define PERFDEBUG + namespace blender::meshintersect { /** @@ -2328,159 +2333,216 @@ static const char *bool_optype_name(BoolOpType op) } } -static mpq3 calc_point_inside_tri(const Face &tri) +static double3 calc_point_inside_tri_db(const Face &tri) { const Vert *v0 = tri.vert[0]; const Vert *v1 = tri.vert[1]; const Vert *v2 = tri.vert[2]; - mpq3 ans = v0->co_exact / 3 + v1->co_exact / 3 + v2->co_exact / 3; + double3 ans = v0->co / 3 + v1->co / 3 + v2->co / 3; return ans; } +class InsideShapeTestData { + public: + const IMesh &tm; + std::function<int(int)> shape_fn; + int nshapes; + /* A per-shape vector of parity of hits of that shape. */ + Array<int> hit_parity; + + InsideShapeTestData(const IMesh &tm, std::function<int(int)> shape_fn, int nshapes) + : tm(tm), shape_fn(shape_fn), nshapes(nshapes) + { + } +}; -/** - * Return the Generalized Winding Number of point \a testp with respect to the - * volume implied by the faces for which shape_fn returns the value shape. - * See "Robust Inside-Outside Segmentation using Generalized Winding Numbers" - * by Jacobson, Kavan, and Sorkine-Hornung. - * This is like a winding number in that if it is positive, the point - * is inside the volume. But it is tolerant of not-completely-watertight - * volumes, still doing a passable job of classifying inside/outside - * as we intuitively understand that to mean. - * - * TOOD: speed up this calculation using the hierarchical algorithm in that paper. - */ -static double generalized_winding_number(const IMesh &tm, - std::function<int(int)> shape_fn, - const double3 &testp, - int shape) +static void inside_shape_callback(void *userdata, + int index, + const BVHTreeRay *ray, + BVHTreeRayHit *UNUSED(hit)) { - constexpr int dbg_level = 0; + const int dbg_level = 0; if (dbg_level > 0) { - std::cout << "GENERALIZED_WINDING_NUMBER testp = " << testp << ", shape = " << shape << "\n"; + std::cout << "inside_shape_callback, index = " << index << "\n"; } - double gwn = 0; - for (int t : tm.face_index_range()) { - const Face *f = tm.face(t); - const Face &tri = *f; - if (shape_fn(tri.orig) == shape) { - if (dbg_level > 0) { - std::cout << "accumulate for tri t = " << t << " = " << f << "\n"; - } - const Vert *v0 = tri.vert[0]; - const Vert *v1 = tri.vert[1]; - const Vert *v2 = tri.vert[2]; - double3 a = v0->co - testp; - double3 b = v1->co - testp; - double3 c = v2->co - testp; - /* Calculate the solid angle of abc relative to origin. - * See "The Solid Angle of a Plane Triangle" by Oosterom and Strackee - * for the derivation of the formula. */ - double alen = a.length(); - double blen = b.length(); - double clen = c.length(); - double3 bxc = double3::cross_high_precision(b, c); - double num = double3::dot(a, bxc); - double denom = alen * blen * clen + double3::dot(a, b) * clen + double3::dot(a, c) * blen + - double3::dot(b, c) * alen; - if (denom == 0.0) { - if (dbg_level > 0) { - std::cout << "denom == 0, skipping this tri\n"; - } - continue; - } - double x = atan2(num, denom); - double fgwn = 2.0 * x; - if (dbg_level > 0) { - std::cout << "tri contributes " << fgwn << "\n"; - } - gwn += fgwn; - } + InsideShapeTestData *data = static_cast<InsideShapeTestData *>(userdata); + const Face &tri = *data->tm.face(index); + int shape = data->shape_fn(tri.orig); + if (shape == -1) { + return; + } + float dist; + float fv0[3]; + float fv1[3]; + float fv2[3]; + for (int i = 0; i < 3; ++i) { + fv0[i] = float(tri.vert[0]->co[i]); + fv1[i] = float(tri.vert[1]->co[i]); + fv2[i] = float(tri.vert[2]->co[i]); } - gwn = gwn / (M_PI * 4.0); if (dbg_level > 0) { - std::cout << "final gwn = " << gwn << "\n"; + std::cout << " fv0=(" << fv0[0] << "," << fv0[1] << "," << fv0[2] << ")\n"; + std::cout << " fv1=(" << fv1[0] << "," << fv1[1] << "," << fv1[2] << ")\n"; + std::cout << " fv2=(" << fv2[0] << "," << fv2[1] << "," << fv2[2] << ")\n"; + } + if (isect_ray_tri_epsilon_v3( + ray->origin, ray->direction, fv0, fv1, fv2, &dist, NULL, FLT_EPSILON)) { + /* Count parity as +1 if ray is in the same direction as tri's normal, + * and -1 if the directions are opposite. */ + double3 o_db{double(ray->origin[0]), double(ray->origin[1]), double(ray->origin[2])}; + int parity = orient3d(tri.vert[0]->co, tri.vert[1]->co, tri.vert[2]->co, o_db); + if (dbg_level > 0) { + std::cout << "origin at " << o_db << ", parity = " << parity << "\n"; + } + data->hit_parity[shape] += parity; } - return gwn; } /** - * Return true if point \a testp is inside the volume implied by the - * faces for which the shape_fn returns the value shape. - * If \a high_confidence is true then we want a higher degree - * of "insideness" than if it is false. + * Test the triangle with index \a t_index to see which shapes it is inside, + * and fill in \a in_shape with a confidence value between 0 and 1 that says + * how likely we think it is that it is inside. + * This is done by casting some rays from just on the positive side of a test + * face in various directions and summing the parity of crossing faces of each face. + * + * \param tree: Contains all the triangles of \a tm and can be used for fast ray-casting. */ -static bool point_is_inside_shape(const IMesh &tm, - std::function<int(int)> shape_fn, - const double3 &testp, - int shape, - bool high_confidence) +static void test_tri_inside_shapes(const IMesh &tm, + std::function<int(int)> shape_fn, + int nshapes, + int test_t_index, + BVHTree *tree, + Array<float> &in_shape) { - double gwn = generalized_winding_number(tm, shape_fn, testp, shape); - /* Due to floating point error, an outside point should get a value - * of zero for gwn, but may have a very slightly positive value instead. - * It is not important to get this epsilon very small, because practical - * cases of interest will have gwn at least 0.2 if it is not zero. */ - if (high_confidence) { - return (gwn > 0.9); + const int dbg_level = 0; + if (dbg_level > 0) { + std::cout << "test_point_inside_shapes, t_index = " << test_t_index << "\n"; + } + Face &tri_test = *tm.face(test_t_index); + int shape = shape_fn(tri_test.orig); + if (shape == -1) { + in_shape.fill(0.0f); + return; + } + double3 test_point = calc_point_inside_tri_db(tri_test); + /* Offset the test point a tiny bit in the tri_test normal direction. */ + tri_test.populate_plane(false); + double3 norm = tri_test.plane->norm.normalized(); + const double offset_amount = 1e-5; + double3 offset_test_point = test_point + offset_amount * norm; + if (dbg_level > 0) { + std::cout << "test tri is in shape " << shape << "\n"; + std::cout << "test point = " << test_point << "\n"; + std::cout << "offset_test_point = " << offset_test_point << "\n"; + } + /* Try six test rays almost along orthogonal axes. + * Perturb their directions slightly to make it less likely to hit a seam. + * Ray-cast assumes they have unit length, so use r1 near 1 and + * ra near 0.5, and rb near .01, but normalized so `sqrt(r1^2 + ra^2 + rb^2) == 1`. */ + constexpr int num_rays = 6; + constexpr float r1 = 0.9987025295199663f; + constexpr float ra = 0.04993512647599832f; + constexpr float rb = 0.009987025295199663f; + const float test_rays[num_rays][3] = { + {r1, ra, rb}, {-r1, -ra, -rb}, {rb, r1, ra}, {-rb, -r1, -ra}, {ra, rb, r1}, {-ra, -rb, -r1}}; + InsideShapeTestData data(tm, shape_fn, nshapes); + data.hit_parity = Array<int>(nshapes, 0); + Array<int> count_insides(nshapes, 0); + const float co[3] = { + float(offset_test_point[0]), float(offset_test_point[1]), float(offset_test_point[2])}; + for (int i = 0; i < num_rays; ++i) { + if (dbg_level > 0) { + std::cout << "shoot ray " << i << "(" << test_rays[i][0] << "," << test_rays[i][1] << "," + << test_rays[i][2] << ")\n"; + } + BLI_bvhtree_ray_cast_all(tree, co, test_rays[i], 0.0f, FLT_MAX, inside_shape_callback, &data); + if (dbg_level > 0) { + std::cout << "ray " << i << " result:"; + for (int j = 0; j < nshapes; ++j) { + std::cout << " " << data.hit_parity[j]; + } + std::cout << "\n"; + } + for (int j = 0; j < nshapes; ++j) { + if (j != shape && data.hit_parity[j] > 0) { + ++count_insides[j]; + } + } + data.hit_parity.fill(0); + } + for (int j = 0; j < nshapes; ++j) { + if (j == shape) { + in_shape[j] = 1.0f; /* Let's say a shape is always inside itself. */ + } + else { + in_shape[j] = float(count_insides[j]) / float(num_rays); + } + if (dbg_level > 0) { + std::cout << "shape " << j << " inside = " << in_shape[j] << "\n"; + } } - - return (gwn > 0.01); } /** - * Use the Generalized Winding Number method for deciding if a patch of the + * Use the RayCast method for deciding if a triangle of the * mesh is supposed to be included or excluded in the boolean result, * and return the mesh that is the boolean result. + * The reason this is done on a triangle-by-triangle basis is that + * when the input is not PWN, some patches can be both inside and outside + * some shapes (e.g., a plane cutting through Suzanne's open eyes). */ -static IMesh gwn_boolean(const IMesh &tm, - BoolOpType op, - int nshapes, - std::function<int(int)> shape_fn, - const PatchesInfo &pinfo, - IMeshArena *arena) +static IMesh raycast_boolean(const IMesh &tm, + BoolOpType op, + int nshapes, + std::function<int(int)> shape_fn, + IMeshArena *arena) { constexpr int dbg_level = 0; if (dbg_level > 0) { - std::cout << "GWN_BOOLEAN\n"; + std::cout << "RAYCAST_BOOLEAN\n"; } IMesh ans; + + /* Build a BVH tree of tm's triangles. + * We could possibly reuse the BVH tree(s) build in TriOverlaps in + * the mesh intersect function. A future TODO. */ + BVHTree *tree = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 8); + for (int i : tm.face_index_range()) { + const Face *f = tm.face(i); + float t_cos[9]; + for (int j = 0; j < 3; ++j) { + const Vert *v = f->vert[j]; + for (int k = 0; k < 3; ++k) { + t_cos[3 * j + k] = float(v->co[k]); + } + } + BLI_bvhtree_insert(tree, i, t_cos, 3); + } + BLI_bvhtree_balance(tree); + Vector<Face *> out_faces; out_faces.reserve(tm.face_size()); + Array<float> in_shape(nshapes, 0); Array<int> winding(nshapes, 0); - for (int p : pinfo.index_range()) { - const Patch &patch = pinfo.patch(p); - /* For test triangle, choose one in the middle of patch list - * as the ones near the beginning may be very near other patches. */ - int test_t_index = patch.tri(patch.tot_tri() / 2); - Face &tri_test = *tm.face(test_t_index); - /* Assume all triangles in a patch are in the same shape. */ - int shape = shape_fn(tri_test.orig); + for (int t : tm.face_index_range()) { + Face &tri = *tm.face(t); + int shape = shape_fn(tri.orig); if (dbg_level > 0) { - std::cout << "process patch " << p << " = " << patch << "\n"; - std::cout << "test tri = " << test_t_index << " = " << &tri_test << "\n"; + std::cout << "process triangle " << t << " = " << &tri << "\n"; std::cout << "shape = " << shape << "\n"; } - if (shape == -1) { - continue; - } - mpq3 test_point = calc_point_inside_tri(tri_test); - double3 test_point_db(test_point[0].get_d(), test_point[1].get_d(), test_point[2].get_d()); - if (dbg_level > 0) { - std::cout << "test point = " << test_point_db << "\n"; - } + test_tri_inside_shapes(tm, shape_fn, nshapes, t, tree, in_shape); for (int other_shape = 0; other_shape < nshapes; ++other_shape) { if (other_shape == shape) { continue; } - /* The point_is_inside_shape function has to approximate if the other - * shape is not PWN. For most operations, even a hint of being inside + /* The in_shape array has a confidence value for "insideness". + * For most operations, even a hint of being inside * gives good results, but when shape is a cutter in a Difference * operation, we want to be pretty sure that the point is inside other_shape. * E.g., T75827. */ bool need_high_confidence = (op == BoolOpType::Difference) && (shape != 0); - bool inside = point_is_inside_shape( - tm, shape_fn, test_point_db, other_shape, need_high_confidence); + bool inside = in_shape[other_shape] >= (need_high_confidence ? 0.5f : 0.1f); if (dbg_level > 0) { std::cout << "test point is " << (inside ? "inside" : "outside") << " other_shape " << other_shape << "\n"; @@ -2503,29 +2565,26 @@ static IMesh gwn_boolean(const IMesh &tm, std::cout << winding[i] << " "; } std::cout << "\niv0=" << in_output_volume_0 << ", iv1=" << in_output_volume_1 << "\n"; - std::cout << "result for patch " << p << ": remove=" << do_remove << ", flip=" << do_flip + std::cout << "result for tri " << t << ": remove=" << do_remove << ", flip=" << do_flip << "\n"; } if (!do_remove) { - for (int t : patch.tris()) { - Face *f = tm.face(t); - if (!do_flip) { - out_faces.append(f); - } - else { - Face &tri = *f; - /* We need flipped version of f. */ - Array<const Vert *> flipped_vs = {tri[0], tri[2], tri[1]}; - Array<int> flipped_e_origs = {tri.edge_orig[2], tri.edge_orig[1], tri.edge_orig[0]}; - Array<bool> flipped_is_intersect = { - tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]}; - Face *flipped_f = arena->add_face( - flipped_vs, f->orig, flipped_e_origs, flipped_is_intersect); - out_faces.append(flipped_f); - } + if (!do_flip) { + out_faces.append(&tri); + } + else { + /* We need flipped version of tri. */ + Array<const Vert *> flipped_vs = {tri[0], tri[2], tri[1]}; + Array<int> flipped_e_origs = {tri.edge_orig[2], tri.edge_orig[1], tri.edge_orig[0]}; + Array<bool> flipped_is_intersect = { + tri.is_intersect[2], tri.is_intersect[1], tri.is_intersect[0]}; + Face *flipped_f = arena->add_face( + flipped_vs, tri.orig, flipped_e_origs, flipped_is_intersect); + out_faces.append(flipped_f); } } } + BLI_bvhtree_free(tree); ans.set_faces(out_faces); return ans; } @@ -3109,6 +3168,14 @@ static Vector<Face *> merge_tris_for_face(Vector<int> tris, return ans; } +static bool approx_in_line(const double3 &a, const double3 &b, const double3 &c) +{ + double3 vec1 = b - a; + double3 vec2 = c - b; + double cos_ang = double3::dot(vec1.normalized(), vec2.normalized()); + return fabs(cos_ang - 1.0) < 1e-4; +} + /** * Return an array, paralleling imesh_out.vert, saying which vertices can be dissolved. * A vertex v can be dissolved if (a) it is not an input vertex; (b) it has valence 2; @@ -3161,8 +3228,11 @@ static Array<bool> find_dissolve_verts(IMesh &imesh_out, int *r_count_dissolve) const std::pair<const Vert *, const Vert *> &nbrs = neighbors[v_out]; if (nbrs.first != nullptr) { BLI_assert(nbrs.second != nullptr); - dissolve[v_out] = true; - ++count; + const Vert *v_v_out = imesh_out.vert(v_out); + if (approx_in_line(nbrs.first->co, v_v_out->co, nbrs.second->co)) { + dissolve[v_out] = true; + ++count; + } } } } @@ -3339,30 +3409,27 @@ IMesh boolean_trimesh(IMesh &tm_in, double topo_time = PIL_check_seconds_timer(); std::cout << " topology built, time = " << topo_time - intersect_time << "\n"; # endif - PatchesInfo pinfo = find_patches(tm_si, tm_si_topo); + bool pwn = is_pwn(tm_si, tm_si_topo); # ifdef PERFDEBUG - double patch_time = PIL_check_seconds_timer(); - std::cout << " patches found, time = " << patch_time - topo_time << "\n"; + double pwn_time = PIL_check_seconds_timer(); + std::cout << " pwn checked, time = " << pwn_time - topo_time << "\n"; # endif IMesh tm_out; - if (!is_pwn(tm_si, tm_si_topo)) { -# ifdef PERFDEBUG - double pwn_check_time = PIL_check_seconds_timer(); - std::cout << " pwn checked (not pwn), time = " << pwn_check_time - patch_time << "\n"; -# endif + if (!pwn) { if (dbg_level > 0) { - std::cout << "Input is not PWN, using gwn method\n"; + std::cout << "Input is not PWN, using raycast method\n"; } - tm_out = gwn_boolean(tm_si, op, nshapes, shape_fn, pinfo, arena); + tm_out = raycast_boolean(tm_si, op, nshapes, shape_fn, arena); # ifdef PERFDEBUG - double gwn_time = PIL_check_seconds_timer(); - std::cout << " gwn, time = " << gwn_time - pwn_check_time << "\n"; + double raycast_time = PIL_check_seconds_timer(); + std::cout << " raycast_boolean done, time = " << raycast_time - pwn_time << "\n"; # endif } else { + PatchesInfo pinfo = find_patches(tm_si, tm_si_topo); # ifdef PERFDEBUG - double pwn_time = PIL_check_seconds_timer(); - std::cout << " pwn checked (ok), time = " << pwn_time - patch_time << "\n"; + double patch_time = PIL_check_seconds_timer(); + std::cout << " patches found, time = " << patch_time - pwn_time << "\n"; # endif CellsInfo cinfo = find_cells(tm_si, tm_si_topo, pinfo); if (dbg_level > 0) { diff --git a/source/blender/blenlib/intern/mesh_intersect.cc b/source/blender/blenlib/intern/mesh_intersect.cc index 85a6ab42013..b2b8dd4e900 100644 --- a/source/blender/blenlib/intern/mesh_intersect.cc +++ b/source/blender/blenlib/intern/mesh_intersect.cc @@ -1055,25 +1055,22 @@ static std::ostream &operator<<(std::ostream &os, const CoplanarClusterInfo &cli enum ITT_value_kind { INONE, IPOINT, ISEGMENT, ICOPLANAR }; struct ITT_value { - mpq3 p1; /* Only relevant for IPOINT and ISEGMENT kind. */ - mpq3 p2; /* Only relevant for ISEGMENT kind. */ - int t_source; /* Index of the source triangle that intersected the target one. */ - enum ITT_value_kind kind; + mpq3 p1; /* Only relevant for IPOINT and ISEGMENT kind. */ + mpq3 p2; /* Only relevant for ISEGMENT kind. */ + int t_source = -1; /* Index of the source triangle that intersected the target one. */ + enum ITT_value_kind kind = INONE; - ITT_value() : t_source(-1), kind(INONE) - { - } - ITT_value(ITT_value_kind k) : t_source(-1), kind(k) + ITT_value() = default; + explicit ITT_value(ITT_value_kind k) : kind(k) { } ITT_value(ITT_value_kind k, int tsrc) : t_source(tsrc), kind(k) { } - ITT_value(ITT_value_kind k, const mpq3 &p1) : p1(p1), t_source(-1), kind(k) + ITT_value(ITT_value_kind k, const mpq3 &p1) : p1(p1), kind(k) { } - ITT_value(ITT_value_kind k, const mpq3 &p1, const mpq3 &p2) - : p1(p1), p2(p2), t_source(-1), kind(k) + ITT_value(ITT_value_kind k, const mpq3 &p1, const mpq3 &p2) : p1(p1), p2(p2), kind(k) { } ITT_value(const ITT_value &other) @@ -1385,7 +1382,7 @@ static ITT_value itt_canon2(const mpq3 &p1, return ITT_value(ISEGMENT, intersect_1, intersect_2); } -/* Helper function for intersect_tri_tri. Args have been canonicalized for triangle 1. */ +/* Helper function for intersect_tri_tri. Arguments have been canonicalized for triangle 1. */ static ITT_value itt_canon1(const mpq3 &p1, const mpq3 &q1, @@ -2026,7 +2023,7 @@ class TriOverlaps { if (dbg_level > 0) { std::cout << "TriOverlaps construction\n"; } - /* Tree type is 8 => octtree; axis = 6 => using XYZ axes only. */ + /* Tree type is 8 => octree; axis = 6 => using XYZ axes only. */ tree_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6); /* In the common case of a binary boolean and no self intersection in * each shape, we will use two trees and simple bounding box overlap. */ @@ -2378,7 +2375,7 @@ static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo, } } } - /* Use CDT to subdivide the cluster triangles and the points and segs in itts. */ + /* Use CDT to subdivide the cluster triangles and the points and segments in itts. */ CDT_data cd_data = prepare_cdt_input_for_cluster(tm, clinfo, c, itts); do_cdt(cd_data); return cd_data; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 5636ffafb6a..b076d0f09c1 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -459,7 +459,7 @@ static wchar_t *next_slash(wchar_t *path) return slash; } -/* adds a slash if the unc path points sto a share */ +/* Adds a slash if the UNC path points to a share. */ static void BLI_path_add_slash_to_share(wchar_t *uncpath) { wchar_t *slash_after_server = next_slash(uncpath + 2); @@ -1279,7 +1279,7 @@ void BLI_setenv(const char *env, const char *val) uputenv(env, val); #else - /* linux/osx/bsd */ + /* Linux/macOS/BSD */ if (val) { setenv(env, val, 1); } @@ -1375,7 +1375,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, c } } else { - return; /* string is NULL, probably shouldnt happen but return anyway */ + return; /* string is NULL, probably shouldn't happen but return anyway */ } /* Resolve relative references */ @@ -1650,7 +1650,7 @@ bool BLI_path_filename_ensure(char *filepath, size_t maxlen, const char *filenam * - Wont create any directories. * - Doesn't use CWD, or deal with relative paths. * - Only fill's in \a dir and \a file when they are non NULL. - * */ + */ void BLI_split_dirfile( const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen) { diff --git a/source/blender/blenlib/intern/polyfill_2d.c b/source/blender/blenlib/intern/polyfill_2d.c index fe9fa514e08..dadef979b09 100644 --- a/source/blender/blenlib/intern/polyfill_2d.c +++ b/source/blender/blenlib/intern/polyfill_2d.c @@ -253,7 +253,7 @@ static uint kdtree2d_balance_recursive( return 0 + ofs; } - /* quicksort style sorting around median */ + /* Quick-sort style sorting around median. */ neg = 0; pos = totnode - 1; median = totnode / 2; @@ -284,7 +284,7 @@ static uint kdtree2d_balance_recursive( } } - /* set node and sort subnodes */ + /* Set node and sort sub-nodes. */ node = &nodes[median]; node->axis = axis; axis = !axis; diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index 2a520516418..8c9a229860e 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -526,10 +526,10 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl if (eve->poly_nr == nr) { if (eve->f != SF_VERT_ZERO_LEN) { verts++; - eve->f = SF_VERT_NEW; /* flag for connectedges later on */ + eve->f = SF_VERT_NEW; /* Flag for connect edges later on. */ sc->vert = eve; sc->edge_first = sc->edge_last = NULL; - /* Note, debug print only will work for curve polyfill, union is in use for mesh */ + /* Note, debug print only will work for curve poly-fill, union is in use for mesh. */ /* if (even->tmp.v == NULL) eve->tmp.u = verts; */ sc++; } @@ -609,7 +609,7 @@ static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int fl sc = scdata; for (a = 0; a < verts; a++) { /* printf("VERTEX %d index %d\n", a, sc->vert->tmp.u); */ - /* set connectflags */ + /* Set connect-flags. */ for (ed1 = sc->edge_first; ed1; ed1 = eed_next) { eed_next = ed1->next; if (ed1->v1->edge_tot == 1 || ed1->v2->edge_tot == 1) { diff --git a/source/blender/blenlib/intern/scanfill_utils.c b/source/blender/blenlib/intern/scanfill_utils.c index b49239547c2..ec0f8659395 100644 --- a/source/blender/blenlib/intern/scanfill_utils.c +++ b/source/blender/blenlib/intern/scanfill_utils.c @@ -244,7 +244,7 @@ static bool scanfill_preprocess_self_isect(ScanFillContext *sf_ctx, continue; } - /* maintain coorect terminating edge */ + /* Maintain correct terminating edge. */ if (pi->edge_last == eed) { pi->edge_last = NULL; } diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index d1e133318ba..bb00755e901 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -30,7 +30,7 @@ #include <sys/stat.h> #if defined(__NetBSD__) || defined(__DragonFly__) || defined(__HAIKU__) -/* Other modern unix os's should probably use this also */ +/* Other modern unix OS's should probably use this also. */ # include <sys/statvfs.h> # define USE_STATFS_STATVFS #endif @@ -113,7 +113,7 @@ double BLI_dir_free_space(const char *dir) char tmp[4]; tmp[0] = '\\'; - tmp[1] = 0; /* Just a failsafe */ + tmp[1] = 0; /* Just a fail-safe. */ if (ELEM(dir[0] == '/', '\\')) { tmp[0] = '\\'; tmp[1] = 0; diff --git a/source/blender/blenlib/intern/string_search.cc b/source/blender/blenlib/intern/string_search.cc index a45909f92d8..a09aa7a4bc2 100644 --- a/source/blender/blenlib/intern/string_search.cc +++ b/source/blender/blenlib/intern/string_search.cc @@ -447,7 +447,7 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d for (const int score : result_indices_by_score.keys()) { found_scores.append(score); } - std::sort(found_scores.begin(), found_scores.end(), std::greater<int>()); + std::sort(found_scores.begin(), found_scores.end(), std::greater<>()); /* Add results to output vector in correct order. First come the results with the best match * score. Results with the same score are in the order they have been added to the search. */ diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index a637a5f24e6..7aa5930b4ad 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -225,8 +225,7 @@ int BLI_utf8_invalid_strip(char *str, size_t length) return tot; } -/* compatible with BLI_strncpy, but esnure no partial utf8 chars */ - +/** Compatible with #BLI_strncpy, but ensure no partial UTF8 chars. */ #define BLI_STR_UTF8_CPY(dst, src, maxncpy) \ { \ size_t utf8_size; \ diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 8e3d489fbb3..e32f310549c 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -71,7 +71,7 @@ int BLI_cpu_support_sse2(void) #endif } -/* Windows stackwalk lives in system_win32.c */ +/* Windows stack-walk lives in system_win32.c */ #if !defined(_MSC_VER) /** * Write a backtrace into a file for systems which support it. diff --git a/source/blender/blenlib/intern/system_win32.c b/source/blender/blenlib/intern/system_win32.c index be2195d679d..7572936592e 100644 --- a/source/blender/blenlib/intern/system_win32.c +++ b/source/blender/blenlib/intern/system_win32.c @@ -386,7 +386,6 @@ void BLI_system_backtrace(FILE *fp) bli_windows_system_backtrace_threads(fp); } bli_windows_system_backtrace_modules(fp); - fputc(0, fp); /* Give our selves a nice zero terminator for later on */ } void BLI_windows_handle_exception(EXCEPTION_POINTERS *exception) diff --git a/source/blender/blenlib/intern/task_graph.cc b/source/blender/blenlib/intern/task_graph.cc index 4f112c5b2c8..32450c16630 100644 --- a/source/blender/blenlib/intern/task_graph.cc +++ b/source/blender/blenlib/intern/task_graph.cc @@ -28,10 +28,7 @@ #include <vector> #ifdef WITH_TBB -/* Quiet top level deprecation message, unrelated to API usage here. */ -# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 # include <tbb/flow_graph.h> -# include <tbb/tbb.h> #endif /* Task Graph */ @@ -70,7 +67,7 @@ struct TaskNode { #ifdef WITH_TBB tbb_node(task_graph->tbb_graph, tbb::flow::unlimited, - std::bind(&TaskNode::run, this, std::placeholders::_1)), + [&](const tbb::flow::continue_msg input) { run(input); }), #endif run_func(run_func), task_data(task_data), diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 10f15f8749c..00ba659a9c8 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -34,9 +34,9 @@ #include "BLI_threads.h" #ifdef WITH_TBB -/* Quiet top level deprecation message, unrelated to API usage here. */ -# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 -# include <tbb/tbb.h> +# include <tbb/blocked_range.h> +# include <tbb/task_arena.h> +# include <tbb/task_group.h> #endif /* Task diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index c2498de1af8..a27241e91dd 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -32,9 +32,10 @@ #include "atomic_ops.h" #ifdef WITH_TBB -/* Quiet top level deprecation message, unrelated to API usage here. */ -# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 -# include <tbb/tbb.h> +# include <tbb/blocked_range.h> +# include <tbb/enumerable_thread_specific.h> +# include <tbb/parallel_for.h> +# include <tbb/parallel_reduce.h> #endif #ifdef WITH_TBB diff --git a/source/blender/blenlib/intern/task_scheduler.cc b/source/blender/blenlib/intern/task_scheduler.cc index b0245da0385..b22334a5676 100644 --- a/source/blender/blenlib/intern/task_scheduler.cc +++ b/source/blender/blenlib/intern/task_scheduler.cc @@ -26,10 +26,10 @@ #include "BLI_threads.h" #ifdef WITH_TBB -/* Quiet top level deprecation message, unrelated to API usage here. */ -# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 -# include <tbb/tbb.h> +/* Need to include at least one header to get the version define. */ +# include <tbb/blocked_range.h> # if TBB_INTERFACE_VERSION_MAJOR >= 10 +# include <tbb/global_control.h> # define WITH_TBB_GLOBAL_CONTROL # endif #endif diff --git a/source/blender/blenlib/intern/threads.cc b/source/blender/blenlib/intern/threads.cc index 0b88cf53442..35097013439 100644 --- a/source/blender/blenlib/intern/threads.cc +++ b/source/blender/blenlib/intern/threads.cc @@ -289,9 +289,8 @@ void BLI_threadpool_clear(ListBase *threadbase) void BLI_threadpool_end(ListBase *threadbase) { - /* only needed if there's actually some stuff to end - * this way we don't end up decrementing thread_levels on an empty threadbase - * */ + /* Only needed if there's actually some stuff to end + * this way we don't end up decrementing thread_levels on an empty `threadbase`. */ if (threadbase == nullptr || BLI_listbase_is_empty(threadbase)) { return; } @@ -469,7 +468,7 @@ void BLI_spin_lock(SpinLock *spin) #elif defined(_MSC_VER) while (InterlockedExchangeAcquire(spin, 1)) { while (*spin) { - /* Spin-lock hint for processors with hyperthreading. */ + /* Spin-lock hint for processors with hyper-threading. */ YieldProcessor(); } } diff --git a/source/blender/blenlib/intern/voxel.c b/source/blender/blenlib/intern/voxel.c index eac01a0e2aa..c0c895654e3 100644 --- a/source/blender/blenlib/intern/voxel.c +++ b/source/blender/blenlib/intern/voxel.c @@ -54,12 +54,14 @@ BLI_INLINE int FLOORI(float x) return ((x >= 0.0f) || (float)r == x) ? r : (r - 1); } -/* clamp function, cannot use the CLAMPIS macro, +/** + * clamp function, cannot use the CLAMPIS macro, * it sometimes returns unwanted results apparently related to - * gcc optimization flag -fstrict-overflow which is enabled at -O2 + * gcc optimization flag `-fstrict-overflow` which is enabled at `-O2` * * this causes the test (x + 2) < 0 with int x == 2147483647 to return false (x being an integer, - * x + 2 should wrap around to -2147483647 so the test < 0 should return true, which it doesn't) */ + * x + 2 should wrap around to -2147483647 so the test < 0 should return true, which it doesn't). + */ BLI_INLINE int64_t _clamp(int a, int b, int c) { return (a < b) ? b : ((a > c) ? c : a); diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index 487afc095f9..d00e8bf55fd 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -1661,10 +1661,10 @@ void rand_delaunay_test(int test_kind, } } for (int i = 0; i < size; ++i) { - /* Horizontal edges: connect p(i,0) to p(i,size-1). */ + /* Horizontal edges: connect `p(i,0)` to `p(i,size-1)`. */ in.edge[i].first = i * size; in.edge[i].second = i * size + size - 1; - /* Vertical edges: conntect p(0,i) to p(size-1,i). */ + /* Vertical edges: connect `p(0,i)` to `p(size-1,i)`. */ in.edge[size + i].first = i; in.edge[size + i].second = (size - 1) * size + i; } @@ -1695,7 +1695,7 @@ void rand_delaunay_test(int test_kind, in.vert[ib][1] = T(sin(angle2)); in.vert[ic][0] = T((param * cos(angle3))); in.vert[ic][1] = T((param * sin(angle3))); - /* Put the coordinates in ccw order. */ + /* Put the coordinates in CCW order. */ in.face[i].append(ia); int orient = orient2d(in.vert[ia], in.vert[ib], in.vert[ic]); if (orient >= 0) { diff --git a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc index 3c9d12c7178..8bf5dd0bc9b 100644 --- a/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_polyfill_2d_test.cc @@ -291,7 +291,7 @@ static void test_polyfill_template_main(const char *id, (void)0 /* -------------------------------------------------------------------- */ -/* visualisation functions (not needed for testing) */ +/* visualization functions (not needed for testing) */ #ifdef USE_OBJ_PREVIEW static void polyfill_to_obj(const char *id, @@ -491,7 +491,7 @@ TEST(polyfill2d, Spiral) TEST_POLYFILL_TEMPLATE_STATIC(poly, false); } -/* Test case from http:# www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */ +/* Test case from http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml */ TEST(polyfill2d, TestFlipCode) { const float poly[][2] = { @@ -561,7 +561,7 @@ TEST(polyfill2d, SelfOverlap) TEST_POLYFILL_TEMPLATE_STATIC(poly, true); } -/* Test case from http:# www.davdata.nl/math/polygons.html */ +/* Test case from http://www.davdata.nl/math/polygons.html */ TEST(polyfill2d, TestDavData) { const float poly[][2] = { @@ -573,7 +573,7 @@ TEST(polyfill2d, TestDavData) TEST_POLYFILL_TEMPLATE_STATIC(poly, false); } -/* Issue 815, http:# code.google.com/p/libgdx/issues/detail?id=815 */ +/* Issue 815, http://code.google.com/p/libgdx/issues/detail?id=815 */ TEST(polyfill2d, Issue815) { const float poly[][2] = { @@ -589,7 +589,7 @@ TEST(polyfill2d, Issue815) TEST_POLYFILL_TEMPLATE_STATIC(poly, false); } -/* Issue 207, comment #1, http:# code.google.com/p/libgdx/issues/detail?id=207#c1 */ +/* Issue 207, comment #1, http://code.google.com/p/libgdx/issues/detail?id=207#c1 */ TEST(polyfill2d, Issue207_1) { const float poly[][2] = { @@ -608,8 +608,8 @@ TEST(polyfill2d, Issue207_1) TEST_POLYFILL_TEMPLATE_STATIC(poly, true); } -/* Issue 207, comment #11, http:# code.google.com/p/libgdx/issues/detail?id=207#c11 */ -/* Also on issue 1081, http:# code.google.com/p/libgdx/issues/detail?id=1081 */ +/* Issue 207, comment #11, http://code.google.com/p/libgdx/issues/detail?id=207#c11 */ +/* Also on issue 1081, http://code.google.com/p/libgdx/issues/detail?id=1081 */ TEST(polyfill2d, Issue207_11) { const float poly[][2] = { @@ -628,7 +628,7 @@ TEST(polyfill2d, Issue207_11) TEST_POLYFILL_TEMPLATE_STATIC(poly, false); } -/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407 */ +/* Issue 1407, http://code.google.com/p/libgdx/issues/detail?id=1407 */ TEST(polyfill2d, Issue1407) { const float poly[][2] = { @@ -640,7 +640,7 @@ TEST(polyfill2d, Issue1407) TEST_POLYFILL_TEMPLATE_STATIC(poly, false); } -/* Issue 1407, http:# code.google.com/p/libgdx/issues/detail?id=1407, */ +/* Issue 1407, http://code.google.com/p/libgdx/issues/detail?id=1407, */ /* with an additional point to show what is happening. */ TEST(polyfill2d, Issue1407_pt) { diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 1d7c5d8a1d3..c7f02de21ea 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -84,8 +84,8 @@ struct BlendFileReadParams { uint skip_flags : 3; /* eBLOReadSkip */ uint is_startup : 1; - /** Whether we are reading the memfile for an undo (< 0) or a redo (> 0). */ - int undo_direction : 2; + /** Whether we are reading the memfile for an undo or a redo. */ + int undo_direction; /* eUndoStepDir */ }; /* skip reading some data-block types (may want to skip screen data too). */ @@ -129,11 +129,13 @@ BlendHandle *BLO_blendhandle_from_memory(const void *mem, int memsize); struct LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, - int *tot_names); + + const bool use_assets_only, + int *r_tot_names); struct LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, - int *tot_info_items); -struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev); + int *r_tot_info_items); +struct LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev); struct LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh); void BLO_blendhandle_close(BlendHandle *bh); diff --git a/source/blender/blenloader/intern/blend_validate.c b/source/blender/blenloader/intern/blend_validate.c index c281e2fa643..7261db5d3a6 100644 --- a/source/blender/blenloader/intern/blend_validate.c +++ b/source/blender/blenloader/intern/blend_validate.c @@ -23,7 +23,7 @@ * \note Does not *fix* anything, only reports found errors. */ -#include <string.h> /* for strrchr strncmp strstr */ +#include <string.h> /* for #strrchr #strncmp #strstr */ #include "BLI_utildefines.h" @@ -112,7 +112,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports) } int totnames = 0; - LinkNode *names = BLO_blendhandle_get_datablock_names(bh, GS(id->name), &totnames); + LinkNode *names = BLO_blendhandle_get_datablock_names(bh, GS(id->name), false, &totnames); for (; id != NULL; id = id->next) { if (id->lib == NULL) { is_valid = false; diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index 296480fc2e4..19033ba9bf1 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -135,9 +135,13 @@ void BLO_blendhandle_print_sizes(BlendHandle *bh, void *fp) * \param bh: The blendhandle to access. * \param ofblocktype: The type of names to get. * \param tot_names: The length of the returned list. + * \param use_assets_only: Only list IDs marked as assets. * \return A BLI_linklist of strings. The string links should be freed with #MEM_freeN(). */ -LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, int *tot_names) +LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, + int ofblocktype, + const bool use_assets_only, + int *r_tot_names) { FileData *fd = (FileData *)bh; LinkNode *names = NULL; @@ -147,6 +151,9 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, for (bhead = blo_bhead_first(fd); bhead; bhead = blo_bhead_next(fd, bhead)) { if (bhead->code == ofblocktype) { const char *idname = blo_bhead_id_name(fd, bhead); + if (use_assets_only && blo_bhead_id_asset_data_address(fd, bhead) == NULL) { + continue; + } BLI_linklist_prepend(&names, BLI_strdup(idname + 2)); tot++; @@ -156,7 +163,7 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, } } - *tot_names = tot; + *r_tot_names = tot; return names; } @@ -170,7 +177,9 @@ LinkNode *BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, * \return A BLI_linklist of BLODataBlockInfo *. The links and #BLODataBlockInfo.asset_data should * be freed with MEM_freeN. */ -LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, int *tot_info_items) +LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, + int ofblocktype, + int *r_tot_info_items) { FileData *fd = (FileData *)bh; LinkNode *infos = NULL; @@ -201,7 +210,7 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, i } } - *tot_info_items = tot; + *r_tot_info_items = tot; return infos; } @@ -211,10 +220,10 @@ LinkNode *BLO_blendhandle_get_datablock_info(BlendHandle *bh, int ofblocktype, i * * \param bh: The blendhandle to access. * \param ofblocktype: The type of names to get. - * \param tot_prev: The length of the returned list. + * \param r_tot_prev: The length of the returned list. * \return A BLI_linklist of PreviewImage. The PreviewImage links should be freed with malloc. */ -LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *tot_prev) +LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *r_tot_prev) { FileData *fd = (FileData *)bh; LinkNode *previews = NULL; @@ -236,6 +245,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to case ID_OB: /* fall through */ case ID_GR: /* fall through */ case ID_SCE: /* fall through */ + case ID_AC: /* fall through */ new_prv = MEM_callocN(sizeof(PreviewImage), "newpreview"); BLI_linklist_prepend(&previews, new_prv); tot++; @@ -294,7 +304,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to } } - *tot_prev = tot; + *r_tot_prev = tot; return previews; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b61abd4ed06..c90572a68a6 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -68,6 +68,7 @@ #include "BLI_math.h" #include "BLI_memarena.h" #include "BLI_mempool.h" +#include "BLI_mmap.h" #include "BLI_threads.h" #include "BLT_translation.h" @@ -93,6 +94,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_undo_system.h" #include "BKE_workspace.h" #include "DRW_engine.h" @@ -1179,6 +1181,53 @@ static ssize_t fd_read_from_memory(FileData *filedata, return readsize; } +/* Memory-mapped file reading. + * By using mmap(), we can map a file so that it can be treated like normal memory, + * meaning that we can just read from it with memcpy() etc. + * This avoids system call overhead and can significantly speed up file loading. + */ + +static ssize_t fd_read_from_mmap(FileData *filedata, + void *buffer, + size_t size, + bool *UNUSED(r_is_memchunck_identical)) +{ + /* don't read more bytes than there are available in the buffer */ + size_t readsize = MIN2(size, (size_t)(filedata->buffersize - filedata->file_offset)); + + if (!BLI_mmap_read(filedata->mmap_file, buffer, filedata->file_offset, readsize)) { + return 0; + } + + filedata->file_offset += readsize; + + return readsize; +} + +static off64_t fd_seek_from_mmap(FileData *filedata, off64_t offset, int whence) +{ + off64_t new_pos; + if (whence == SEEK_CUR) { + new_pos = filedata->file_offset + offset; + } + else if (whence == SEEK_SET) { + new_pos = offset; + } + else if (whence == SEEK_END) { + new_pos = filedata->buffersize + offset; + } + else { + return -1; + } + + if (new_pos < 0 || new_pos > filedata->buffersize) { + return -1; + } + + filedata->file_offset = new_pos; + return filedata->file_offset; +} + /* MemFile reading. */ static ssize_t fd_read_from_memfile(FileData *filedata, @@ -1246,12 +1295,12 @@ static ssize_t fd_read_from_memfile(FileData *filedata, seek += readsize; if (r_is_memchunck_identical != NULL) { /* `is_identical` of current chunk represents whether it changed compared to previous undo - * step. this is fine in redo case (filedata->undo_direction > 0), but not in undo case, - * where we need an extra flag defined when saving the next (future) step after the one we - * want to restore, as we are supposed to 'come from' that future undo step, and not the - * one before current one. */ - *r_is_memchunck_identical &= filedata->undo_direction > 0 ? chunk->is_identical : - chunk->is_identical_future; + * step. this is fine in redo case, but not in undo case, where we need an extra flag + * defined when saving the next (future) step after the one we want to restore, as we are + * supposed to 'come from' that future undo step, and not the one before current one. */ + *r_is_memchunck_identical &= filedata->undo_direction == STEP_REDO ? + chunk->is_identical : + chunk->is_identical_future; } } while (totread < size); @@ -1306,6 +1355,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, { FileDataReadFn *read_fn = NULL; FileDataSeekFn *seek_fn = NULL; /* Optional. */ + size_t buffersize = 0; + BLI_mmap_file *mmap_file = NULL; gzFile gzfile = (gzFile)Z_NULL; @@ -1322,14 +1373,21 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, return NULL; } - BLI_lseek(file, 0, SEEK_SET); - /* Regular file. */ if (memcmp(header, "BLENDER", sizeof(header)) == 0) { read_fn = fd_read_data_from_file; seek_fn = fd_seek_data_from_file; + + mmap_file = BLI_mmap_open(file); + if (mmap_file != NULL) { + read_fn = fd_read_from_mmap; + seek_fn = fd_seek_from_mmap; + buffersize = BLI_lseek(file, 0, SEEK_END); + } } + BLI_lseek(file, 0, SEEK_SET); + /* Gzip file. */ errno = 0; if ((read_fn == NULL) && @@ -1363,6 +1421,8 @@ static FileData *blo_filedata_from_file_descriptor(const char *filepath, fd->read = read_fn; fd->seek = seek_fn; + fd->mmap_file = mmap_file; + fd->buffersize = buffersize; return fd; } @@ -1531,6 +1591,11 @@ void blo_filedata_free(FileData *fd) fd->buffer = NULL; } + if (fd->mmap_file) { + BLI_mmap_free(fd->mmap_file); + fd->mmap_file = NULL; + } + /* Free all BHeadN data blocks */ #ifndef NDEBUG BLI_freelistN(&fd->bhead_list); @@ -1718,25 +1783,25 @@ BlendThumbnail *BLO_thumbnail_from_file(const char *filepath) /** \name Old/New Pointer Map * \{ */ -/* only direct databocks */ +/* Only direct data-blocks. */ static void *newdataadr(FileData *fd, const void *adr) { return oldnewmap_lookup_and_inc(fd->datamap, adr, true); } -/* only direct databocks */ +/* Only direct data-blocks. */ static void *newdataadr_no_us(FileData *fd, const void *adr) { return oldnewmap_lookup_and_inc(fd->datamap, adr, false); } -/* direct datablocks with global linking */ +/* Direct datablocks with global linking. */ void *blo_read_get_new_globaldata_address(FileData *fd, const void *adr) { return oldnewmap_lookup_and_inc(fd->globmap, adr, true); } -/* used to restore packed data after undo */ +/* Used to restore packed data after undo. */ static void *newpackedadr(FileData *fd, const void *adr) { if (fd->packedmap && adr) { @@ -2336,11 +2401,12 @@ static int direct_link_id_restore_recalc(const FileData *fd, /* Tags that were set between the target state and the current state, * that we need to perform again. */ - if (fd->undo_direction < 0) { + if (fd->undo_direction == STEP_UNDO) { /* Undo: tags from target to the current state. */ recalc |= id_current->recalc_up_to_undo_push; } else { + BLI_assert(fd->undo_direction == STEP_REDO); /* Redo: tags from current to the target state. */ recalc |= id_target->recalc_up_to_undo_push; } @@ -3852,6 +3918,26 @@ static void lib_link_all(FileData *fd, Main *bmain) } FOREACH_MAIN_ID_END; +#ifndef NDEBUG + /* Double check we do not have any 'need link' tag remaining, this should never be the case once + * this function has run. */ + FOREACH_MAIN_ID_BEGIN (bmain, id) { + BLI_assert((id->tag & LIB_TAG_NEED_LINK) == 0); + } + FOREACH_MAIN_ID_END; +#endif +} + +/** + * Checks to perform after `lib_link_all`. + * Those operations cannot perform properly in a split bmain case, since some data from other + * bmain's (aka libraries) may not have been processed yet. + */ +static void after_liblink_merged_bmain_process(Main *bmain) +{ + /* We only expect a merged Main here, not a split one. */ + BLI_assert((bmain->prev == NULL) && (bmain->next == NULL)); + /* Check for possible cycles in scenes' 'set' background property. */ lib_link_scenes_check_set(bmain); @@ -3862,15 +3948,6 @@ static void lib_link_all(FileData *fd, Main *bmain) /* We have to rebuild that runtime information *after* all data-blocks have been properly linked. */ BKE_main_collections_parent_relations_rebuild(bmain); - -#ifndef NDEBUG - /* Double check we do not have any 'need link' tag remaining, this should never be the case once - * this function has run. */ - FOREACH_MAIN_ID_BEGIN (bmain, id) { - BLI_assert((id->tag & LIB_TAG_NEED_LINK) == 0); - } - FOREACH_MAIN_ID_END; -#endif } /** \} */ @@ -4093,6 +4170,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) blo_join_main(&mainlist); lib_link_all(fd, bfd->main); + after_liblink_merged_bmain_process(bfd->main); /* Skip in undo case. */ if (fd->memfile == NULL) { @@ -5041,6 +5119,7 @@ static void library_link_end(Main *mainl, mainl = NULL; /* blo_join_main free's mainl, cant use anymore */ lib_link_all(*fd, mainvar); + after_liblink_merged_bmain_process(mainvar); /* Some versioning code does expect some proper userrefcounting, e.g. in conversion from * groups to collections... We could optimize out that first call when we are reading a diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index c724cc32051..e007d42b283 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -41,6 +41,7 @@ struct Object; struct OldNewMap; struct ReportList; struct UserDef; +struct BLI_mmap_file; typedef struct IDNameLib_Map IDNameLib_Map; @@ -83,13 +84,14 @@ typedef struct FileData { /** Regular file reading. */ int filedes; - /** Variables needed for reading from memory / stream. */ + /** Variables needed for reading from memory / stream / memory-mapped files. */ const char *buffer; + struct BLI_mmap_file *mmap_file; /** Variables needed for reading from memfile (undo). */ struct MemFile *memfile; /** Whether we are undoing (< 0) or redoing (> 0), used to choose which 'unchanged' flag to use * to detect unchanged data from memfile. */ - short undo_direction; + int undo_direction; /* eUndoStepDir */ /** Variables needed for reading from file. */ gzFile gzfiledes; diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 767f24cf175..3b9ad64770d 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -339,7 +339,7 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo NodeImageMultiFile *nimf = node->storage; bNodeSocket *sock; - /* CMP_NODE_OUTPUT_MULTI_FILE has been redeclared as CMP_NODE_OUTPUT_FILE */ + /* CMP_NODE_OUTPUT_MULTI_FILE has been re-declared as CMP_NODE_OUTPUT_FILE */ node->type = CMP_NODE_OUTPUT_FILE; /* initialize the node-wide image format from render data, if available */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index df9268f0da1..d8ab8d6f32a 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1190,7 +1190,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } - /* Remove old deprecated region from filebrowsers */ + /* Remove old deprecated region from file-browsers. */ else if (sl->spacetype == SPACE_FILE) { LISTBASE_FOREACH (ARegion *, region, regionbase) { if (region->regiontype == RGN_TYPE_CHANNELS) { @@ -1657,7 +1657,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "falloff_angle")) { for (Brush *br = bmain->brushes.first; br; br = br->id.next) { br->falloff_angle = DEG2RADF(80); - /* These flags are used for new feautres. They are not related to falloff_angle */ + /* These flags are used for new features. They are not related to `falloff_angle`. */ br->flag &= ~(BRUSH_INVERT_TO_SCRAPE_FILL | BRUSH_ORIGINAL_PLANE | BRUSH_GRAB_ACTIVE_VERTEX | BRUSH_SCENE_SPACING | BRUSH_FRONTFACE_FALLOFF); } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 7dc2c9e86ee..0e90d9b6045 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -1390,7 +1390,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } } - /* Cleanup deprecated flag from particlesettings data-blocks. */ + /* Cleanup deprecated flag from particle-settings data-blocks. */ for (ParticleSettings *part = bmain->particles.first; part; part = part->id.next) { part->draw &= ~PART_DRAW_EMITTER; } @@ -2110,7 +2110,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } for (Tex *tex = bmain->textures.first; tex; tex = tex->id.next) { - /* Removed envmap, pointdensity, voxeldata, ocean textures. */ + /* Removed environment map, point-density, voxel-data, ocean textures. */ if (ELEM(tex->type, 10, 14, 15, 16)) { tex->type = 0; } @@ -4303,7 +4303,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - /* Elatic deform brush */ + /* Elastic deform brush */ for (Brush *br = bmain->brushes.first; br; br = br->id.next) { if (br->ob_mode & OB_MODE_SCULPT && br->elastic_deform_volume_preservation == 0.0f) { br->elastic_deform_volume_preservation = 0.5f; diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 60256359ea0..78d60715aa5 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -475,7 +475,7 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { bGPDframe *gpf = gpl->frames.first; if (gpf && gpf->framenum > scene->r.sfra) { - bGPDframe *gpf_dup = BKE_gpencil_frame_duplicate(gpf); + bGPDframe *gpf_dup = BKE_gpencil_frame_duplicate(gpf, true); gpf_dup->framenum = scene->r.sfra; BLI_addhead(&gpl->frames, gpf_dup); } @@ -499,7 +499,7 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) /** * Make sure Emission Alpha fcurve and drivers is properly mapped after the Emission Strength * got introduced. - * */ + */ /** * Effectively we are replacing the (animation of) node socket input 18 with 19. @@ -510,7 +510,7 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports)) * * The for loop for the input ids is at the top level otherwise we lose the animation * keyframe data. - * */ + */ for (int input_id = 21; input_id >= 18; input_id--) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type == NTREE_SHADER) { @@ -658,7 +658,7 @@ static void do_versions_291_fcurve_handles_limit(FCurve *fcu) { uint i = 1; for (BezTriple *bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) { - /* Only adjust bezier keyframes. */ + /* Only adjust bezier key-frames. */ if (bezt->ipo != BEZT_IPO_BEZ) { continue; } @@ -735,6 +735,23 @@ static void version_node_socket_name(bNodeTree *ntree, } } +static void version_node_join_geometry_for_multi_input_socket(bNodeTree *ntree) +{ + LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) { + if (link->tonode->type == GEO_NODE_JOIN_GEOMETRY && !(link->tosock->flag & SOCK_MULTI_INPUT)) { + link->tosock = link->tonode->inputs.first; + } + } + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_JOIN_GEOMETRY) { + bNodeSocket *socket = node->inputs.first; + socket->flag |= SOCK_MULTI_INPUT; + socket->limit = 4095; + nodeRemoveSocket(ntree, node, socket->next); + } + } +} + /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) { @@ -1097,10 +1114,10 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 291, 5)) { - /* Fix fcurves to allow for new bezier handles behaviour (T75881 and D8752). */ + /* Fix fcurves to allow for new bezier handles behavior (T75881 and D8752). */ for (bAction *act = bmain->actions.first; act; act = act->id.next) { for (FCurve *fcu = act->curves.first; fcu; fcu = fcu->next) { - /* Only need to fix Bezier curves with at least 2 keyframes. */ + /* Only need to fix Bezier curves with at least 2 key-frames. */ if (fcu->totvert < 2 || fcu->bezt == NULL) { continue; } @@ -1548,7 +1565,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } - if (!MAIN_VERSION_ATLEAST(bmain, 292, 13)) { + if (!MAIN_VERSION_ATLEAST(bmain, 293, 1)) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type == NTREE_GEOMETRY) { version_node_socket_name(ntree, GEO_NODE_BOOLEAN, "Geometry A", "Geometry 1"); @@ -1573,7 +1590,8 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 292, 14)) { + if ((!MAIN_VERSION_ATLEAST(bmain, 292, 14)) || + ((bmain->versionfile == 293) && (!MAIN_VERSION_ATLEAST(bmain, 293, 1)))) { FOREACH_NODETREE_BEGIN (bmain, ntree, id) { if (ntree->type != NTREE_GEOMETRY) { continue; @@ -1590,28 +1608,112 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) FOREACH_NODETREE_END; } - /** - * Versioning code until next subversion bump goes here. - * - * \note Be sure to check when bumping the version: - * - "versioning_userdef.c", #blo_do_versions_userdef - * - "versioning_userdef.c", #do_versions_theme - * - * \note Keep this message at the bottom of the function. - */ - { - /* Keep this block, even when empty. */ + if (!MAIN_VERSION_ATLEAST(bmain, 293, 1)) { + /* Grease pencil layer transform matrix. */ + if (!DNA_struct_elem_find(fd->filesdna, "bGPDlayer", "float", "location[0]")) { + LISTBASE_FOREACH (bGPdata *, gpd, &bmain->gpencils) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + zero_v3(gpl->location); + zero_v3(gpl->rotation); + copy_v3_fl(gpl->scale, 1.0f); + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + } + } + } + /* Fix Fill factor for grease pencil fill brushes. */ + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if ((brush->gpencil_settings) && (brush->gpencil_settings->fill_factor == 0.0f)) { + brush->gpencil_settings->fill_factor = 1.0f; + } + } + } + + if (!MAIN_VERSION_ATLEAST(bmain, 293, 3)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type != NTREE_GEOMETRY) { + continue; + } + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_POINT_INSTANCE && node->storage == NULL) { + NodeGeometryPointInstance *data = (NodeGeometryPointInstance *)MEM_callocN( + sizeof(NodeGeometryPointInstance), __func__); + data->instance_type = node->custom1; + data->flag = (node->custom2 ? 0 : GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION); + node->storage = data; + } + } + } + FOREACH_NODETREE_END; + } - /* UV/Image Max resolution images in image editor. */ + if (!MAIN_VERSION_ATLEAST(bmain, 293, 4)) { + /* Add support for all operations to the "Attribute Math" node. */ + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == GEO_NODE_ATTRIBUTE_MATH) { + NodeAttributeMath *data = (NodeAttributeMath *)node->storage; + data->input_type_c = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + } + } + } + } + FOREACH_NODETREE_END; + } + + if (!MAIN_VERSION_ATLEAST(bmain, 293, 5)) { + /* Change Nishita sky model Altitude unit. */ + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_SHADER) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (node->type == SH_NODE_TEX_SKY && node->storage) { + NodeTexSky *tex = (NodeTexSky *)node->storage; + tex->altitude *= 1000.0f; + } + } + } + } + FOREACH_NODETREE_END; + } + + if (!MAIN_VERSION_ATLEAST(bmain, 293, 6)) { LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) { + /* UV/Image Max resolution images in image editor. */ if (space->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)space; sima->iuser.flag |= IMA_SHOW_MAX_RESOLUTION; } + /* Enable Outliner render visibility column. */ + else if (space->spacetype == SPACE_OUTLINER) { + SpaceOutliner *space_outliner = (SpaceOutliner *)space; + space_outliner->show_restrict_flags |= SO_RESTRICT_RENDER; + } } } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 293, 7)) { + FOREACH_NODETREE_BEGIN (bmain, ntree, id) { + if (ntree->type == NTREE_GEOMETRY) { + version_node_join_geometry_for_multi_input_socket(ntree); + } + } + FOREACH_NODETREE_END; + } + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #blo_do_versions_userdef + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + } } diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 631abe10ddc..816b90491aa 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -1420,7 +1420,7 @@ void do_versions_after_linking_cycles(Main *bmain) } if (!MAIN_VERSION_ATLEAST(bmain, 280, 64)) { - /* Unfiy Cycles and Eevee settings. */ + /* Unify Cycles and Eevee settings. */ Scene *scene = bmain->scenes.first; const char *engine = (scene) ? scene->r.engine : "CYCLES"; diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index 322830282e9..3d39181cd32 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -273,6 +273,15 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme) { /* Keep this block, even when empty. */ FROM_DEFAULT_V4_UCHAR(space_properties.active); + + FROM_DEFAULT_V4_UCHAR(space_info.info_error); + FROM_DEFAULT_V4_UCHAR(space_info.info_warning); + FROM_DEFAULT_V4_UCHAR(space_info.info_info); + FROM_DEFAULT_V4_UCHAR(space_info.info_debug); + FROM_DEFAULT_V4_UCHAR(space_info.info_debug_text); + FROM_DEFAULT_V4_UCHAR(space_info.info_property); + FROM_DEFAULT_V4_UCHAR(space_info.info_error); + FROM_DEFAULT_V4_UCHAR(space_info.info_operator); } #undef FROM_DEFAULT_V4_UCHAR @@ -827,6 +836,13 @@ void blo_do_versions_userdef(UserDef *userdef) } } + if (!USER_VERSION_ATLEAST(293, 2)) { + /* Enable asset browser features by default for alpha testing. + * BLO_sanitize_experimental_features_userpref_blend() will disable it again for non-alpha + * builds. */ + userdef->experimental.use_asset_browser = true; + } + /** * Versioning code until next subversion bump goes here. * @@ -838,6 +854,9 @@ void blo_do_versions_userdef(UserDef *userdef) */ { /* Keep this block, even when empty. */ + if (userdef->gizmo_size_navigate_v3d == 0) { + userdef->gizmo_size_navigate_v3d = 80; + } } LISTBASE_FOREACH (bTheme *, btheme, &userdef->themes) { diff --git a/source/blender/blentranslation/intern/blt_lang.c b/source/blender/blentranslation/intern/blt_lang.c index bd0352d3e80..97a1a83792a 100644 --- a/source/blender/blentranslation/intern/blt_lang.c +++ b/source/blender/blentranslation/intern/blt_lang.c @@ -48,10 +48,6 @@ #include "MEM_guardedalloc.h" -/* Cached IME support flags */ -static bool ime_is_lang_supported = false; -static void blt_lang_check_ime_supported(void); - #ifdef WITH_INTERNATIONAL # include "BLI_fileops.h" @@ -205,7 +201,7 @@ void BLT_lang_init(void) const char *const messagepath = BKE_appdir_folder_id(BLENDER_DATAFILES, "locale"); #endif - /* Make sure LANG is correct and wouldn't cause #std::rumtime_error. */ + /* Make sure LANG is correct and wouldn't cause #std::runtime_error. */ #ifndef _WIN32 /* TODO(sergey): This code only ensures LANG is set properly, so later when * Cycles will try to use file system API from boost there will be no runtime @@ -286,7 +282,6 @@ void BLT_lang_set(const char *str) #else (void)str; #endif - blt_lang_check_ime_supported(); IMB_thumb_clear_translations(); } @@ -380,24 +375,13 @@ void BLT_lang_locale_explode(const char *locale, } } -/** - * Test if the translation context allows IME input - used to - * avoid weird character drawing if IME inputs non-ascii chars. - */ -static void blt_lang_check_ime_supported(void) -{ -#ifdef WITH_INPUT_IME - const char *uilng = BLT_lang_get(); - ime_is_lang_supported = STR_ELEM(uilng, "zh_CN", "zh_TW", "ja_JP"); -#else - ime_is_lang_supported = false; -#endif -} - +/* Note that "lang" here is the _output_ display language. We used to restrict + * IME for keyboard _input_ language because our multilingual font was only used + * when some output languages were selected. That font is used all the time now. */ bool BLT_lang_is_ime_supported(void) { #ifdef WITH_INPUT_IME - return ime_is_lang_supported; + return true; #else return false; #endif diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 9899d67c008..65f3d8bbad3 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -238,7 +238,6 @@ typedef struct BMesh { uint use_toolflags : 1; int toolflag_index; - struct BMOperator *currentop; CustomData vdata, edata, ldata, pdata; diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index b913bdd12e4..cf907862120 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -2158,7 +2158,7 @@ BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEd l_f1->next->prev = l_f2->prev; l_f2->prev->next = l_f1->next; - /* if l_f1 was baseloop, make l_f1->next the base. */ + /* If `l_f1` was base-loop, make `l_f1->next` the base. */ if (BM_FACE_FIRST_LOOP(f1) == l_f1) { BM_FACE_FIRST_LOOP(f1) = l_f1->next; } diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index ec97ea51047..51a6ada6c42 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -450,7 +450,7 @@ void BM_mesh_edgeloops_calc_order(BMesh *UNUSED(bm), ListBase *eloops, const boo } mul_v3_fl(cent, 1.0f / (float)tot); - /* find far outest loop */ + /* Find the furthest out loop. */ { BMEdgeLoopStore *el_store_best = NULL; float len_best_sq = -1.0f; diff --git a/source/blender/bmesh/intern/bmesh_error.h b/source/blender/bmesh/intern/bmesh_error.h index 1837ad8dd71..41d02e334fb 100644 --- a/source/blender/bmesh/intern/bmesh_error.h +++ b/source/blender/bmesh/intern/bmesh_error.h @@ -25,7 +25,7 @@ /*----------- bmop error system ----------*/ /* pushes an error onto the bmesh error stack. - * if msg is null, then the default message for the errorcode is used.*/ + * if msg is null, then the default message for the `errcode` is used. */ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg); /* gets the topmost error from the stack. @@ -33,7 +33,7 @@ void BMO_error_raise(BMesh *bm, BMOperator *owner, int errcode, const char *msg) int BMO_error_get(BMesh *bm, const char **msg, BMOperator **op); bool BMO_error_occurred(BMesh *bm); -/* same as geterror, only pops the error off the stack as well */ +/* Same as #BMO_error_get, only pops the error off the stack as well. */ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op); void BMO_error_clear(BMesh *bm); diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index a15408d43be..6857a1f3929 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -342,8 +342,12 @@ static void mdisp_axis_from_quad(const float v1[3], normalize_v3(r_axis_y); } -/* tl is loop to project onto, l is loop whose internal displacement, co, is being - * projected. x and y are location in loop's mdisps grid of point co. */ +/** + * \param l_src: is loop whose internal displacement. + * \param l_dst: is loop to project onto. + * \param p: The point being projected. + * \param r_axis_x, r_axis_y: The location in loop's #CD_MDISPS grid of point `p`. + */ static bool mdisp_in_mdispquad(BMLoop *l_src, BMLoop *l_dst, const float l_dst_f_center[3], diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 44e3ef6e6ee..c81d4f9b67c 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -177,7 +177,7 @@ void *BM_iter_as_arrayN(BMesh *bm, BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); - /* we can't rely on coun't being set */ + /* We can't rely on #BMIter.count being set. */ switch (itype) { case BM_VERTS_OF_MESH: iter.count = bm->totvert; diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 4c72b802396..8e5ed9c3bf0 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -802,7 +802,7 @@ void BM_edge_calc_rotate(BMEdge *e, const bool ccw, BMLoop **r_l1, BMLoop **r_l2 /* we know this will work */ BM_edge_face_pair(e, &fa, &fb); - /* so we can use ccw variable correctly, + /* so we can use `ccw` variable correctly, * otherwise we could use the edges verts direct */ BM_edge_ordered_verts(e, &v1, &v2); @@ -886,7 +886,7 @@ bool BM_edge_rotate_check_degenerate(BMEdge *e, BMLoop *l1, BMLoop *l2) /* verts from the loops passed */ BMVert *v1, *v2; - /* these are the opposite verts - the verts that _would_ be used if 'ccw' was inverted*/ + /* These are the opposite verts - the verts that _would_ be used if `ccw` was inverted. */ BMVert *v1_alt, *v2_alt; /* this should have already run */ @@ -1070,7 +1070,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f BM_face_normal_flip(bm, fb); if (ccw) { - /* needed otherwise ccw toggles direction */ + /* Needed otherwise `ccw` toggles direction */ e_new->l = e_new->l->radial_next; } } diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index d8cdff1a4cc..bccac006e8e 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -54,7 +54,8 @@ #include "DNA_modifier_types.h" -/* The formatting of these bmesh operators is parsed by +/** + * The formatting of these bmesh operators is parsed by * 'doc/python_api/rst_from_bmesh_opdefines.py' * for use in python docs, so reStructuredText may be used * rather than doxygen syntax. @@ -65,8 +66,7 @@ * """ * Region Extend. * - * paragraph1, Extends bleh bleh bleh. - * Bleh Bleh bleh. + * paragraph1, Extends on the title above. * * Another paragraph. * @@ -731,7 +731,7 @@ static BMOpDefine bmo_edgenet_fill_def = { * * - One single loop; an edge is added to connect the ends * - Two loops; two edges are added to connect the endpoints (based on the - * shortest distance between each endpont). + * shortest distance between each endpoint). */ static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", @@ -1268,7 +1268,7 @@ static BMOpDefine bmo_subdivide_edges_def = { {"quad_corner_type", BMO_OP_SLOT_INT, {(int)BMO_OP_SLOT_SUBTYPE_INT_ENUM}, bmo_enum_subdivide_edges_quad_corner_type}, /* quad corner type */ {"use_grid_fill", BMO_OP_SLOT_BOOL}, /* fill in fully-selected faces with a grid */ {"use_single_edge", BMO_OP_SLOT_BOOL}, /* tessellate the case of one edge selected in a quad or triangle */ - {"use_only_quads", BMO_OP_SLOT_BOOL}, /* only subdivide quads (for loopcut) */ + {"use_only_quads", BMO_OP_SLOT_BOOL}, /* Only subdivide quads (for loop-cut). */ {"use_sphere", BMO_OP_SLOT_BOOL}, /* for making new primitives only */ {"use_smooth_even", BMO_OP_SLOT_BOOL}, /* maintain even offset when smoothing */ {{'\0'}}, @@ -1394,7 +1394,7 @@ static BMOpDefine bmo_duplicate_def = { /* slots_out */ {{"geom_orig.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - /* facemap maps from source faces to dupe + /* face_map maps from source faces to dupe * faces, and from dupe faces to source faces */ {"vert_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, {"edge_map.out", BMO_OP_SLOT_MAPPING, {(int)BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 2f7d91c78c4..2d9e244e54d 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -24,7 +24,7 @@ /*--------defines/enumerations for specific operators-------*/ -/*quad innervert values*/ +/* Quad `innervert` values. */ enum { SUBD_CORNER_INNERVERT, SUBD_CORNER_PATH, diff --git a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c index 1d000b3b232..dcf9717465c 100644 --- a/source/blender/bmesh/intern/bmesh_polygon_edgenet.c +++ b/source/blender/bmesh/intern/bmesh_polygon_edgenet.c @@ -1566,7 +1566,7 @@ bool BM_face_split_edgenet_connect_islands(BMesh *bm, for (uint g_index = 1; g_index < group_arr_len; g_index++) { struct EdgeGroupIsland *g = group_arr[g_index]; - /* the range of verts this group uses in 'verts_arr' (not uncluding the last index) */ + /* The range of verts this group uses in 'verts_arr' (not including the last index). */ vert_range[0] = vert_range[1]; vert_range[1] += g->vert_len; diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index ef4a9c9de1c..cfdce0b749b 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -143,7 +143,7 @@ void bmesh_disk_vert_replace(BMEdge *e, BMVert *v_dst, BMVert *v_src) * * The loop cycle keeps track of a faces vertices and edges. It should be noted that the * direction of a loop cycle is either CW or CCW depending on the face normal, and is - * not oriented to the faces editedges. + * not oriented to the faces edit-edges. * * Functions relating to this cycle: * - bmesh_cycle_XXX family of functions. @@ -537,7 +537,7 @@ int bmesh_radial_length(const BMLoop *l) do { if (UNLIKELY(!l_iter)) { - /* radial cycle is broken (not a circulat loop) */ + /* Radial cycle is broken (not a circular loop). */ BMESH_ASSERT(0); return 0; } diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index a973e12a4c7..22ee8809a19 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -122,7 +122,7 @@ enum { BMW_CONNECTED_VERTEX, /* end of array index enum vals */ - /* do not intitialze function pointers and struct size in BMW_init */ + /* Do not initialize function pointers and struct size in #BMW_init. */ BMW_CUSTOM, BMW_MAXWALKERS, }; diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index c23551ecca7..647a22baaeb 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -29,7 +29,7 @@ #include "bmesh.h" #include "intern/bmesh_walkers_private.h" -/* pop into stack memory (common operation) */ +/* Pop into stack memory (common operation). */ #define BMW_state_remove_r(walker, owalk) \ { \ memcpy(owalk, BMW_current_state(walker), sizeof(*(owalk))); \ @@ -86,7 +86,7 @@ static bool bmw_mask_check_face(BMWalker *walker, BMFace *f) static bool bmw_edge_is_wire(const BMWalker *walker, const BMEdge *e) { if (walker->flag & BMW_FLAG_TEST_HIDDEN) { - /* check if this is a wire edge, ignoring hidden faces */ + /* Check if this is a wire edge, ignoring hidden faces. */ if (BM_edge_is_wire(e)) { return true; } @@ -137,8 +137,7 @@ static void bmw_VertShellWalker_begin(BMWalker *walker, void *data) switch (h->htype) { case BM_VERT: { - /* starting the walk at a vert, add all the edges - * to the worklist */ + /* Starting the walk at a vert, add all the edges to the work-list. */ v = (BMVert *)h; BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { bmw_VertShellWalker_visitEdge(walker, e); @@ -147,8 +146,7 @@ static void bmw_VertShellWalker_begin(BMWalker *walker, void *data) } case BM_EDGE: { - /* starting the walk at an edge, add the single edge - * to the worklist */ + /* Starting the walk at an edge, add the single edge to the work-list. */ e = (BMEdge *)h; bmw_VertShellWalker_visitEdge(walker, e); break; @@ -201,7 +199,7 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) BMW_state_remove(walker); - /* find the next edge whose other vertex has not been visite */ + /* Find the next edge whose other vertex has not been visited. */ curedge = shellWalk.curedge; do { if (!BLI_gset_haskey(walker->visit_set, curedge)) { @@ -212,11 +210,11 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) v_old = BM_edge_other_vert(curedge, shellWalk.base); - /* push a new state onto the stac */ + /* Push a new state onto the stack. */ newState = BMW_state_add(walker); BLI_gset_insert(walker->visit_set, curedge); - /* populate the new stat */ + /* Populate the new state. */ newState->base = v_old; newState->curedge = curedge; @@ -266,8 +264,7 @@ static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data) switch (h->htype) { case BM_LOOP: { - /* starting the walk at a vert, add all the edges - * to the worklist */ + /* Starting the walk at a vert, add all the edges to the work-list. */ BMLoop *l = (BMLoop *)h; bmw_LoopShellWalker_visitLoop(walker, l); break; @@ -292,7 +289,7 @@ static void bmw_LoopShellWalker_begin(BMWalker *walker, void *data) case BM_FACE: { BMFace *f = (BMFace *)h; BMLoop *l = BM_FACE_FIRST_LOOP(f); - /* walker will handle other loops within the face */ + /* Walker will handle other loops within the face. */ bmw_LoopShellWalker_visitLoop(walker, l); break; } @@ -312,7 +309,7 @@ static void bmw_LoopShellWalker_step_impl(BMWalker *walker, BMLoop *l) BMEdge *e_edj_pair[2]; int i; - /* seems paranoid, but one caller also walks edges */ + /* Seems paranoid, but one caller also walks edges. */ BLI_assert(l->head.htype == BM_LOOP); bmw_LoopShellWalker_visitLoop(walker, l->next); @@ -409,7 +406,7 @@ static void bmw_LoopShellWireWalker_visitVert(BMWalker *walker, BMVert *v, const bmw_LoopShellWalker_visitEdgeWire(walker, e); - /* check if we step onto a non-wire vertex */ + /* Check if we step onto a non-wire vertex. */ v_other = BM_edge_other_vert(e, v); BM_ITER_ELEM (l, &iter, v_other, BM_LOOPS_OF_VERT) { @@ -463,7 +460,7 @@ static void bmw_LoopShellWireWalker_begin(BMWalker *walker, void *data) break; } case BM_FACE: { - /* wire verts will be walked over */ + /* Wire verts will be walked over. */ break; } default: @@ -581,12 +578,12 @@ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) BMwConnectedVertexWalker *vwalk; if (BLI_gset_haskey(walker->visit_set, v)) { - /* already visited */ + /* Already visited. */ return; } if (!bmw_mask_check_vert(walker, v)) { - /* not flagged for walk */ + /* Not flagged for walk. */ return; } @@ -670,10 +667,9 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) BMEdge *e; BMFace *f; BMLoop *l; - /* int found = 0; */ memcpy(&owalk, BMW_current_state(walker), sizeof(owalk)); - /* normally we'd remove here, but delay until after error checking */ + /* Normally we'd remove here, but delay until after error checking. */ iwalk = &owalk; l = iwalk->curloop; @@ -681,7 +677,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) v = BM_edge_other_vert(e, iwalk->lastv); - /* pop off current state */ + /* Pop off current state. */ BMW_state_remove(walker); f = l->f; @@ -699,7 +695,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) } } else { - /* treat non-manifold edges as boundaries */ + /* Treat non-manifold edges as boundaries. */ f = l->f; e = l->e; break; @@ -717,9 +713,16 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) iwalk = BMW_state_add(walker); iwalk->base = owalk.base; - // if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) - // iwalk->curloop = l->radial_next; - iwalk->curloop = l; // else iwalk->curloop = l; +#if 0 + if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) { + iwalk->curloop = l->radial_next; + } + else { + iwalk->curloop = l; + } +#else + iwalk->curloop = l; +#endif iwalk->lastv = v; return owalk.curloop; @@ -763,7 +766,7 @@ static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold) l_iter = l_first = BM_FACE_FIRST_LOOP(iwalk->cur); do { - /* could skip loop here too, but don't add unless we need it */ + /* Could skip loop here too, but don't add unless we need it. */ if (!bmw_mask_check_edge(walker, l_iter->e)) { continue; } @@ -772,7 +775,7 @@ static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold) if (only_manifold && (l_iter->radial_next != l_iter)) { int face_count = 1; - /* check other faces (not this one), ensure only one other can be walked onto. */ + /* Check other faces (not this one), ensure only one other Can be walked onto. */ l_radial_iter = l_iter->radial_next; do { if (bmw_mask_check_face(walker, l_radial_iter->f)) { @@ -796,7 +799,7 @@ static void *bmw_IslandWalker_step_ex(BMWalker *walker, bool only_manifold) continue; } - /* saves checking BLI_gset_haskey below (manifold edges there's a 50% chance) */ + /* Saves checking #BLI_gset_haskey below (manifold edges there's a 50% chance). */ if (f == iwalk->cur) { continue; } @@ -947,12 +950,12 @@ static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data) } if (f_best) { - /* only use hub selection for 5+ sides else this could + /* Only use hub selection for 5+ sides else this could * conflict with normal edge loop selection. */ lwalk->f_hub = f_best->len > 4 ? f_best : NULL; } else { - /* edge doesn't have any faces connected to it */ + /* Edge doesn't have any faces connected to it. */ lwalk->f_hub = NULL; } } @@ -960,7 +963,7 @@ static void bmw_EdgeLoopWalker_begin(BMWalker *walker, void *data) lwalk->f_hub = NULL; } - /* rewind */ + /* Rewind. */ while ((owalk_pt = BMW_current_state(walker))) { owalk = *((BMwEdgeLoopWalker *)owalk_pt); BMW_walk(walker); @@ -1007,7 +1010,7 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) nexte = BM_edge_exists(v, l->v); if (bmw_mask_check_edge(walker, nexte) && !BLI_gset_haskey(walker->visit_set, nexte) && - /* never step onto a boundary edge, this gives odd-results */ + /* Never step onto a boundary edge, this gives odd-results. */ (BM_edge_is_boundary(nexte) == false)) { lwalk = BMW_state_add(walker); lwalk->cur = nexte; @@ -1024,7 +1027,7 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) else if (l == NULL) { /* WIRE EDGE */ BMIter eiter; - /* match trunk: mark all connected wire edges */ + /* Match trunk: mark all connected wire edges. */ for (int i = 0; i < 2; i++) { v = i ? e->v2 : e->v1; @@ -1051,9 +1054,8 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) vert_edge_tot = BM_vert_edge_count_nonwire(v); - /* Typical loopiong over edges in the middle of a mesh */ - /* However, why use 2 here at all? - * I guess for internal ngon loops it can be useful. Antony R. */ + /* Typical looping over edges in the middle of a mesh. + * Why use 2 here at all? - for internal ngon loops it can be useful. */ if (ELEM(vert_edge_tot, 4, 2)) { int i_opposite = vert_edge_tot / 2; int i = 0; @@ -1094,15 +1096,15 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) vert_edge_tot = BM_vert_edge_count_nonwire(v); - /* check if we should step, this is fairly involved */ + /* Check if we should step, this is fairly involved. */ if ( - /* walk over boundary of faces but stop at corners */ + /* Walk over boundary of faces but stop at corners. */ (owalk.is_single == false && vert_edge_tot > 2) || - /* initial edge was a boundary, so is this edge and vertex is only a part of this face - * this lets us walk over the boundary of an ngon which is handy */ + /* Initial edge was a boundary, so is this edge and vertex is only a part of this face + * this lets us walk over the boundary of an ngon which is handy. */ (owalk.is_single == true && vert_edge_tot == 2 && BM_edge_is_boundary(e))) { - /* find next boundary edge in the fan */ + /* Find next boundary edge in the fan. */ do { l = BM_loop_other_edge_loop(l, v); if (BM_edge_is_manifold(l->e)) { @@ -1148,14 +1150,16 @@ static void *bmw_EdgeLoopWalker_step(BMWalker *walker) * * Starts at a tool-flagged face and walks over the face loop * Conditions for starting and stepping the face loop have been - * tuned in an attempt to match the face loops built by EditMesh + * tuned in an attempt to match the face loops built by edit-mesh * \{ */ -/* Check whether the face loop should includes the face specified - * by the given BMLoop */ +/** + * Check whether the face loop should includes the face specified + * by the given #BMLoop. + */ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) { - /* face must have degree 4 */ + /* Face must have degree 4. */ if (l->f->len != 4) { return false; } @@ -1164,7 +1168,7 @@ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) return false; } - /* the face must not have been already visited */ + /* The face must not have been already visited. */ if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) { return false; } @@ -1172,23 +1176,22 @@ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) return true; } -/* Check whether the face loop can start from the given edge */ +/* Check whether the face loop can start from the given edge. */ static bool bmw_FaceLoopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e) { - /* There is no face loop starting from a wire edge */ + /* There is no face loop starting from a wire edge. */ if (BM_edge_is_wire(e)) { return false; } - /* Don't start a loop from a boundary edge if it cannot - * be extended to cover any faces */ + /* Don't start a loop from a boundary edge if it cannot be extended to cover any faces. */ if (BM_edge_is_boundary(e)) { if (!bmw_FaceLoopWalker_include_face(walker, e->l)) { return false; } } - /* Don't start a face loop from non-manifold edges */ + /* Don't start a face loop from non-manifold edges. */ if (!BM_edge_is_manifold(e)) { return false; } @@ -1212,7 +1215,7 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) lwalk->no_calc = false; BLI_gset_insert(walker->visit_set, lwalk->l->f); - /* rewind */ + /* Rewind. */ while ((owalk_pt = BMW_current_state(walker))) { owalk = *((BMwFaceLoopWalker *)owalk_pt); BMW_walk(walker); @@ -1277,7 +1280,7 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) lwalk->no_calc = false; } - /* both may already exist */ + /* Both may already exist. */ BLI_gset_add(walker->visit_set_alt, l->e); BLI_gset_add(walker->visit_set, l->f); } @@ -1312,7 +1315,7 @@ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data) BLI_gset_insert(walker->visit_set, lwalk->l->e); - /* rewind */ + /* Rewind. */ while ((owalk_pt = BMW_current_state(walker))) { owalk = *((BMwEdgeringWalker *)owalk_pt); BMW_walk(walker); @@ -1370,10 +1373,10 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) e = l->e; if (!EDGE_CHECK(e)) { - /* walker won't traverse to a non-manifold edge, but may + /* Walker won't traverse to a non-manifold edge, but may * be started on one, and should not traverse *away* from * a non-manifold edge (non-manifold edges are never in an - * edge ring with manifold edges */ + * edge ring with manifold edges. */ return e; } @@ -1394,7 +1397,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) i -= 2; } } - /* only walk to manifold edge */ + /* Only walk to manifold edge. */ if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e)) #else @@ -1404,7 +1407,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) if ((l->f->len != 4) || !EDGE_CHECK(l->e) || !bmw_mask_check_face(walker, l->f)) { l = owalk.l->next->next; } - /* only walk to manifold edge */ + /* Only walk to manifold edge. */ if ((l->f->len == 4) && EDGE_CHECK(l->e) && !BLI_gset_haskey(walker->visit_set, l->e)) #endif { @@ -1547,8 +1550,8 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker) return l; } - /* go over loops around l->v and nl->v and see which ones share l and nl's - * mloopuv's coordinates. in addition, push on l->next if necessary */ + /* Go over loops around `l->v` and `l->next->v` and see which ones share `l` and `l->next` + * UV's coordinates. in addition, push on `l->next` if necessary. */ for (i = 0; i < 2; i++) { BMIter liter; BMLoop *l_pivot, *l_radial; @@ -1600,7 +1603,7 @@ static BMWalker bmw_VertShellWalker_Type = { bmw_VertShellWalker_yield, sizeof(BMwShellWalker), BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_LoopShellWalker_Type = { @@ -1610,7 +1613,7 @@ static BMWalker bmw_LoopShellWalker_Type = { bmw_LoopShellWalker_yield, sizeof(BMwLoopShellWalker), BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_LoopShellWireWalker_Type = { @@ -1620,7 +1623,7 @@ static BMWalker bmw_LoopShellWireWalker_Type = { bmw_LoopShellWireWalker_yield, sizeof(BMwLoopShellWireWalker), BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_FaceShellWalker_Type = { @@ -1630,7 +1633,7 @@ static BMWalker bmw_FaceShellWalker_Type = { bmw_FaceShellWalker_yield, sizeof(BMwShellWalker), BMW_BREADTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_IslandboundWalker_Type = { @@ -1640,7 +1643,7 @@ static BMWalker bmw_IslandboundWalker_Type = { bmw_IslandboundWalker_yield, sizeof(BMwIslandboundWalker), BMW_DEPTH_FIRST, - BM_FACE, /* valid restrict masks */ + BM_FACE, /* Valid restrict masks. */ }; static BMWalker bmw_IslandWalker_Type = { @@ -1650,17 +1653,17 @@ static BMWalker bmw_IslandWalker_Type = { bmw_IslandWalker_yield, sizeof(BMwIslandWalker), BMW_BREADTH_FIRST, - BM_EDGE | BM_FACE, /* valid restrict masks */ + BM_EDGE | BM_FACE, /* Valid restrict masks. */ }; static BMWalker bmw_IslandManifoldWalker_Type = { BM_FACE, bmw_IslandWalker_begin, - bmw_IslandManifoldWalker_step, /* only difference with BMW_ISLAND */ + bmw_IslandManifoldWalker_step, /* Only difference with #BMW_ISLAND. */ bmw_IslandWalker_yield, sizeof(BMwIslandWalker), BMW_BREADTH_FIRST, - BM_EDGE | BM_FACE, /* valid restrict masks */ + BM_EDGE | BM_FACE, /* Valid restrict masks. */ }; static BMWalker bmw_EdgeLoopWalker_Type = { @@ -1671,7 +1674,7 @@ static BMWalker bmw_EdgeLoopWalker_Type = { sizeof(BMwEdgeLoopWalker), BMW_DEPTH_FIRST, 0, - /* valid restrict masks */ /* could add flags here but so far none are used */ + /* Valid restrict masks. */ /* Could add flags here but so far none are used. */ }; static BMWalker bmw_FaceLoopWalker_Type = { @@ -1682,7 +1685,7 @@ static BMWalker bmw_FaceLoopWalker_Type = { sizeof(BMwFaceLoopWalker), BMW_DEPTH_FIRST, 0, - /* valid restrict masks */ /* could add flags here but so far none are used */ + /* Valid restrict masks. */ /* Could add flags here but so far none are used. */ }; static BMWalker bmw_EdgeringWalker_Type = { @@ -1692,7 +1695,7 @@ static BMWalker bmw_EdgeringWalker_Type = { bmw_EdgeringWalker_yield, sizeof(BMwEdgeringWalker), BMW_DEPTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_EdgeboundaryWalker_Type = { @@ -1712,7 +1715,7 @@ static BMWalker bmw_UVEdgeWalker_Type = { bmw_UVEdgeWalker_yield, sizeof(BMwUVEdgeWalker), BMW_DEPTH_FIRST, - BM_EDGE, /* valid restrict masks */ + BM_EDGE, /* Valid restrict masks. */ }; static BMWalker bmw_ConnectedVertexWalker_Type = { @@ -1722,23 +1725,23 @@ static BMWalker bmw_ConnectedVertexWalker_Type = { bmw_ConnectedVertexWalker_yield, sizeof(BMwConnectedVertexWalker), BMW_BREADTH_FIRST, - BM_VERT, /* valid restrict masks */ + BM_VERT, /* Valid restrict masks. */ }; BMWalker *bm_walker_types[] = { - &bmw_VertShellWalker_Type, /* BMW_VERT_SHELL */ - &bmw_LoopShellWalker_Type, /* BMW_LOOP_SHELL */ - &bmw_LoopShellWireWalker_Type, /* BMW_LOOP_SHELL_WIRE */ - &bmw_FaceShellWalker_Type, /* BMW_FACE_SHELL */ - &bmw_EdgeLoopWalker_Type, /* BMW_EDGELOOP */ - &bmw_FaceLoopWalker_Type, /* BMW_FACELOOP */ - &bmw_EdgeringWalker_Type, /* BMW_EDGERING */ - &bmw_EdgeboundaryWalker_Type, /* BMW_EDGEBOUNDARY */ - &bmw_UVEdgeWalker_Type, /* BMW_LOOPDATA_ISLAND */ - &bmw_IslandboundWalker_Type, /* BMW_ISLANDBOUND */ - &bmw_IslandWalker_Type, /* BMW_ISLAND */ - &bmw_IslandManifoldWalker_Type, /* BMW_ISLAND_MANIFOLD */ - &bmw_ConnectedVertexWalker_Type, /* BMW_CONNECTED_VERTEX */ + &bmw_VertShellWalker_Type, /* #BMW_VERT_SHELL */ + &bmw_LoopShellWalker_Type, /* #BMW_LOOP_SHELL */ + &bmw_LoopShellWireWalker_Type, /* #BMW_LOOP_SHELL_WIRE */ + &bmw_FaceShellWalker_Type, /* #BMW_FACE_SHELL */ + &bmw_EdgeLoopWalker_Type, /* #BMW_EDGELOOP */ + &bmw_FaceLoopWalker_Type, /* #BMW_FACELOOP */ + &bmw_EdgeringWalker_Type, /* #BMW_EDGERING */ + &bmw_EdgeboundaryWalker_Type, /* #BMW_EDGEBOUNDARY */ + &bmw_UVEdgeWalker_Type, /* #BMW_LOOPDATA_ISLAND */ + &bmw_IslandboundWalker_Type, /* #BMW_ISLANDBOUND */ + &bmw_IslandWalker_Type, /* #BMW_ISLAND */ + &bmw_IslandManifoldWalker_Type, /* #BMW_ISLAND_MANIFOLD */ + &bmw_ConnectedVertexWalker_Type, /* #BMW_CONNECTED_VERTEX */ }; const int bm_totwalkers = ARRAY_SIZE(bm_walker_types); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 8c2e820df63..da2603ad8cd 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -55,7 +55,7 @@ static bool UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f) BMLoop *l2, *l3; BMFace *f2; - /* checks if there are any unmarked boundary edges in the face regio */ + /* Checks if there are any unmarked boundary edges in the face region. */ BMW_init(®walker, bm, @@ -159,7 +159,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } BLI_array_clear(faces); - faces = NULL; /* forces different allocatio */ + faces = NULL; /* Forces different allocation. */ BMW_init(®walker, bm, diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 6e968d58631..c128872be07 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -109,7 +109,7 @@ static BMEdge *bmo_edge_copy(BMOperator *op, BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst); BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src); - /* add to new/old edge map if necassary */ + /* Add to new/old edge map if necessary. */ if (rlen < 2) { /* not sure what non-manifold cases of greater than three * radial should do. */ diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index 3aad37b3b02..df15778558b 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -326,8 +326,8 @@ static void bm_grid_fill_array(BMesh *bm, v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP); v_grid[(y * xtot) + x] = v; - /* interpolate only along one axis, this could be changed - * but from user pov gives predictable results since these are selected loop */ + /* Interpolate only along one axis, this could be changed + * but from user POV gives predictable results since these are selected loop. */ if (use_vert_interp) { const float *w = weight_table[XY(x, y)]; diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index 009c4f1f2c5..3869a0678e2 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -967,7 +967,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) is_mid = false; } - /* distable gives odd results at times, see T39288. */ + /* Disable since this gives odd results at times, see T39288. */ #if 0 else if (compare_v3v3(f_a->no, f_b->no, 0.001f) == false) { /* epsilon increased to fix T32329. */ diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 1da4be57568..086114f64e9 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -66,7 +66,7 @@ static float quad_calc_error(const float v1[3], error += diff; } - /* Colinearity */ + /* Co-linearity */ { float edge_vecs[4][3]; float diff; diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c index 8e7bfbb649d..3311ffefb0d 100644 --- a/source/blender/bmesh/operators/bmo_normals.c +++ b/source/blender/bmesh/operators/bmo_normals.c @@ -29,7 +29,7 @@ #include "intern/bmesh_operators_private.h" /* own include */ -/********* righthand faces implementation ****** */ +/********* Right-hand faces implementation ****** */ #define FACE_FLAG (1 << 0) #define FACE_FLIP (1 << 1) diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index d661859c8e3..8e088683d62 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -962,7 +962,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) BM_mesh_calc_uvs_sphere(bm, FACE_MARK, cd_loop_uv_offset); } - /* and now do imat */ + /* Now apply the inverse matrix. */ BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { if (BMO_vert_flag_test(bm, eve, VERT_MARK)) { mul_m4_v3(mat, eve->co); @@ -1585,9 +1585,9 @@ void BM_mesh_calc_uvs_cone(BMesh *bm, float inv_mat[4][4]; int loop_index; - /* Transform the upvector like we did the cone itself, without location. */ + /* Transform the up-vector like we did the cone itself, without location. */ mul_mat3_m4_v3(mat, local_up); - /* Remove global scaling... */ + /* Remove global scaling. */ normalize_v3(local_up); invert_m4_m4(inv_mat, mat); diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 02f17ea5d4a..361b10520da 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -387,7 +387,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMIter iter; BMVert *v; - BMLoop *l /* , *firstl = NULL */; + BMLoop *l; CDBlockBytes min, max; int i; diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 8b2f9478aab..be996e6ffe4 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -51,13 +51,13 @@ typedef struct SubDParams { BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ float fractal_ofs[3]; - /* rumtime storage for shape key */ + /* Runtime storage for shape key. */ struct { int cd_vert_shape_offset; int cd_vert_shape_offset_tmp; int totlayer; - /* shapekey holding displaced vertex coordinates for current geometry */ + /* Shape-key holding displaced vertex coordinates for current geometry. */ int tmpkey; } shape_info; @@ -1094,7 +1094,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } } - /* obvously don't test for other patterns matching */ + /* Obviously don't test for other patterns matching. */ continue; } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index cd12a260f82..0de909b5556 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -235,7 +235,7 @@ typedef struct BoundVert { /** Is this boundvert the side of the custom profile's start. */ bool is_profile_start; char _pad[3]; - /** Length of seam starting from current boundvert to next boundvert with ccw ordering. */ + /** Length of seam starting from current boundvert to next boundvert with CCW ordering. */ int seam_len; /** Same as seam_len but defines length of sharp edges. */ int sharp_len; @@ -807,6 +807,9 @@ static bool contig_ldata_across_edge(BMesh *bm, BMEdge *e, BMFace *f1, BMFace *f } BMVert *v1 = lef1->v; BMVert *v2 = lef2->v; + if (v1 == v2) { + return false; + } BLI_assert((v1 == e->v1 && v2 == e->v2) || (v1 == e->v2 && v2 == e->v1)); UNUSED_VARS_NDEBUG(v1, v2); BMLoop *lv1f1 = lef1; @@ -1958,7 +1961,7 @@ static bool make_unit_square_map(const float va[3], /** * Like make_unit_square_map, but this one makes a matrix that transforms the * (1,1,1) corner of a unit cube into an arbitrary corner with corner vert d - * and verts around it a, b, c (in ccw order, viewed from d normal dir). + * and verts around it a, b, c (in CCW order, viewed from d normal dir). * The matrix mat is calculated to map: * (1,0,0) -> va * (0,1,0) -> vb @@ -1966,9 +1969,9 @@ static bool make_unit_square_map(const float va[3], * (1,1,1) -> vd * We want M to make M*A=B where A has the left side above, as columns * and B has the right side as columns - both extended into homogeneous coords. - * So M = B*(Ainverse). Doing Ainverse by hand gives the code below. - * The cols of M are 1/2{va-vb+vc-vd}, 1/2{-va+vb-vc+vd}, 1/2{-va-vb+vc+vd}, - * and 1/2{va+vb+vc-vd} + * So `M = B*(Ainverse)`. Doing `Ainverse` by hand gives the code below. + * The cols of M are `1/2{va-vb+vc-vd}`, `1/2{-va+vb-vc+vd}`, `1/2{-va-vb+vc+vd}`, + * and `1/2{va+vb+vc-vd}` * and Blender matrices have cols at m[i][*]. */ static void make_unit_cube_map( @@ -3433,7 +3436,7 @@ static EdgeHalf *next_edgehalf_bev(BevelParams *bp, } normalize_v3(dir_new_edge); - /* Use this edge if it is the most parallel to the orignial so far. */ + /* Use this edge if it is the most parallel to the original so far. */ float new_dot = dot_v3v3(dir_new_edge, dir_start_edge); if (new_dot > best_dot) { second_best_dot = best_dot; /* For remembering if the choice was too close. */ @@ -4674,7 +4677,7 @@ static VMesh *pipe_adj_vmesh(BevelParams *bp, BevVert *bv, BoundVert *vpipe) f = (float)k / (float)ns; /* Ring runs along the pipe, so segment is used here. */ } - /* Place the vertex by interpolatin between the two profile points using the factor. */ + /* Place the vertex by interpolating between the two profile points using the factor. */ interp_v3_v3v3(mesh_vert(vm, i, j, k)->co, profile_point_pipe1, profile_point_pipe2, f); } else { @@ -6375,7 +6378,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) go_ccw = (e->fnext != f); } else { - go_ccw = true; /* Going ccw around bv to trace this corner. */ + go_ccw = true; /* Going CCW around bv to trace this corner. */ } } else if (eprev->prev == e) { @@ -6385,7 +6388,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) /* Edges in face are non-contiguous in our ordering around bv. * Which way should we go when going from eprev to e? */ if (count_ccw_edges_between(eprev, e) < count_ccw_edges_between(e, eprev)) { - /* Go counterclockewise from eprev to e. */ + /* Go counter-clockwise from eprev to e. */ go_ccw = true; } else { @@ -6419,7 +6422,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) BLI_array_append(ee, bme); } while (v != vend) { - /* Check for special case: multisegment 3rd face opposite a beveled edge with no vmesh. */ + /* Check for special case: multi-segment 3rd face opposite a beveled edge with no vmesh. */ bool corner3special = (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev); if (go_ccw) { int i = v->index; @@ -7227,17 +7230,17 @@ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bo * B * </pre> * - * where edges are A, B, and C, following a face around vertices a, b, c, d. - * th1 is angle abc and th2 is angle bcd; - * and the argument EdgeHalf eb is B, going from b to c. + * where edges are A, B, and C, following a face around vertices `a, b, c, d`. + * `th1` is angle `abc` and th2 is angle `bcd`; + * and the argument `EdgeHalf eb` is B, going from b to c. * In general case, edge offset specs for A, B, C have - * the form ka*t, kb*t, kc*t where ka, kb, kc are some factors + * the form `ka*t`, `kb*t`, `kc*t` where `ka`, `kb`, `kc` are some factors * (may be 0) and t is the current bp->offset. * We want to calculate t at which the clone of B parallel * to it collapses. This can be calculated using trig. * Another case of geometry collision that can happen is - * When B slides along A because A is unbeveled. - * Then it might collide with a. Similarly for B sliding along C. + * When B slides along A because A is un-beveled. + * Then it might collide with a. Similarly for B sliding along C. */ static float geometry_collide_offset(BevelParams *bp, EdgeHalf *eb) { @@ -7566,7 +7569,7 @@ void BM_mesh_bevel(BMesh *bm, } } - /* Perhaps clamp offset to avoid geometry colliisions. */ + /* Perhaps clamp offset to avoid geometry collisions. */ if (limit_offset) { bevel_limit_offset(&bp, bm); diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 60c49587387..92ca8e38737 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -294,8 +294,7 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, /* subtract existing cost to further differentiate edges from one another * * keep topology cost below 0.0 so their values don't interfere with quadric cost, - * (and they get handled first). - * */ + * (and they get handled first). */ if (vweights == NULL) { cost = bm_decim_build_edge_cost_single_squared__topology(e) - cost; } @@ -1319,9 +1318,9 @@ void BM_mesh_decimate_collapse(BMesh *bm, UNUSED_VARS(do_triangulate); #endif - /* alloc vars */ + /* Allocate variables. */ vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__); - /* since some edges may be degenerate, we might be over allocing a little here */ + /* Since some edges may be degenerate, we might be over allocating a little here. */ eheap = BLI_heap_new_ex(bm->totedge); eheap_table = MEM_mallocN(sizeof(HeapNode *) * bm->totedge, __func__); tot_edge_orig = bm->totedge; diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 94a578fe1d7..2254b46f860 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -188,7 +188,7 @@ static void mul_v2_m3v3_center(float r[2], static bool bm_loop_collapse_is_degenerate(BMLoop *l_ear) { - /* calculate relative to the centeral vertex for higher precision */ + /* Calculate relative to the central vertex for higher precision. */ const float *center = l_ear->v->co; float tri_2d[3][2]; diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index 1ab37ec0684..51af4d24e52 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -295,7 +295,7 @@ static LinkNode *bm_edgenet_path_calc(BMEdge *e, vn_1->flag = vn_2->flag = (f_index == -1) ? VNINFO_FLAG_IS_MIXFACE : 0; - /* prime the searchlist */ + /* Prime the search-list. */ BLI_linklist_prepend_pool(&v_ls_prev, e->v1, path_pool); BLI_linklist_prepend_pool(&v_ls_prev, e->v2, path_pool); diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c index db05abe0e48..81b016e9601 100644 --- a/source/blender/bmesh/tools/bmesh_intersect.c +++ b/source/blender/bmesh/tools/bmesh_intersect.c @@ -1036,7 +1036,7 @@ bool BM_mesh_intersect(BMesh *bm, #endif if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) { - /* keep original geometrty for raycast callbacks */ + /* Keep original geometry for ray-cast callbacks. */ float **cos; int i, j; @@ -1546,7 +1546,7 @@ bool BM_mesh_intersect(BMesh *bm, bool do_remove, do_flip; { - /* for now assyme this is an OK face to test with (not degenerate!) */ + /* For now assume this is an OK face to test with (not degenerate!) */ BMFace *f = ftable[groups_array[fg]]; float co[3]; int hits; diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index 79c1ebcfe9f..6c8d372f587 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -268,8 +268,8 @@ extern "C" { * When an ExecutionGroup schedules a Chunk the schedule method of the WorkScheduler * The Workscheduler determines if the chunk can be run on an OpenCLDevice * (and that there are available OpenCLDevice). - * If this is the case the chunk will be added to the worklist for OpenCLDevice's - * otherwise the chunk will be added to the worklist of CPUDevices. + * If this is the case the chunk will be added to the work-list for OpenCLDevice's + * otherwise the chunk will be added to the work-list of CPUDevices. * * A thread will read the work-list and sends a workpackage to its device. * @@ -298,7 +298,7 @@ extern "C" { /** * \brief The main method that is used to execute the compositor tree. - * It can be executed during editing (blenkernel/node.c) or rendering + * It can be executed during editing (blenkernel/node.cc) or rendering * (renderer/pipeline.c) * * \param rd: [struct RenderData] diff --git a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp index 3c2bf0aad07..92b334fddb9 100644 --- a/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorCorrectionNode.cpp @@ -32,9 +32,9 @@ void ColorCorrectionNode::convertToOperations(NodeConverter &converter, ColorCorrectionOperation *operation = new ColorCorrectionOperation(); operation->setData((NodeColorCorrection *)editorNode->storage); - operation->setRedChannelEnabled((editorNode->custom1 & 1) > 0); - operation->setGreenChannelEnabled((editorNode->custom1 & 2) > 0); - operation->setBlueChannelEnabled((editorNode->custom1 & 4) > 0); + operation->setRedChannelEnabled((editorNode->custom1 & 1) != 0); + operation->setGreenChannelEnabled((editorNode->custom1 & 2) != 0); + operation->setBlueChannelEnabled((editorNode->custom1 & 4) != 0); converter.addOperation(operation); converter.mapInputSocket(getInputSocket(0), operation->getInputSocket(0)); diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 4e81a412c29..13bdabcdfd8 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -239,7 +239,7 @@ void KeyingNode::convertToOperations(NodeConverter &converter, converter.mapInputSocket(inputScreen, keyingOperation->getInputSocket(1)); if (keying_data->blur_pre) { - /* chroma preblur operation for input of keying operation */ + /* Chroma pre-blur operation for input of keying operation. */ NodeOperationOutput *preBluredImage = setupPreBlur( converter, inputImage, keying_data->blur_pre); converter.addLink(preBluredImage, keyingOperation->getInputSocket(0)); diff --git a/source/blender/compositor/operations/COM_BokehImageOperation.h b/source/blender/compositor/operations/COM_BokehImageOperation.h index 01ffa026152..2d775bdf738 100644 --- a/source/blender/compositor/operations/COM_BokehImageOperation.h +++ b/source/blender/compositor/operations/COM_BokehImageOperation.h @@ -55,7 +55,7 @@ class BokehImageOperation : public NodeOperation { NodeBokehImage *m_data; /** - * \brief precalced center of the image + * \brief precalculate center of the image */ float m_center[2]; @@ -87,7 +87,7 @@ class BokehImageOperation : public NodeOperation { /** * \brief determine the coordinate of a flap corner. * - * \param r: result in bokehimage space are stored [x,y] + * \param r: result in bokeh-image space are stored [x,y] * \param flapNumber: the flap number to calculate * \param distance: the lens distance is used to simulate lens shifts */ diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp index 29e18047578..52de0198a00 100644 --- a/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.cpp @@ -61,11 +61,10 @@ void ChromaMatteOperation::executePixelSampled(float output[4], this->m_inputImageProgram->readSampled(inImage, x, y, sampler); /* Store matte(alpha) value in [0] to go with - * COM_SetAlphaMultiplyOperation and the Value output. - */ + * #COM_SetAlphaMultiplyOperation and the Value output. */ - /* Algorithm from book "Video Demistified," does not include the spill reduction part */ - /* find theta, the angle that the color space should be rotated based on key */ + /* Algorithm from book "Video Demystified", does not include the spill reduction part. */ + /* Find theta, the angle that the color space should be rotated based on key. */ /* rescale to -1.0..1.0 */ // inImage[0] = (inImage[0] * 2.0f) - 1.0f; // UNUSED diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cpp b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp index 07466cdeccd..ccd291697cf 100644 --- a/source/blender/compositor/operations/COM_CryptomatteOperation.cpp +++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cpp @@ -49,7 +49,7 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat for (size_t i = 0; i < inputs.size(); i++) { inputs[i]->read(input, x, y, data); if (i == 0) { - /* Write the frontmost object as false color for picking. */ + /* Write the front-most object as false color for picking. */ output[0] = input[0]; uint32_t m3hash; ::memcpy(&m3hash, &input[0], sizeof(uint32_t)); diff --git a/source/blender/compositor/operations/COM_DotproductOperation.cpp b/source/blender/compositor/operations/COM_DotproductOperation.cpp index 750e4308d11..5914be21453 100644 --- a/source/blender/compositor/operations/COM_DotproductOperation.cpp +++ b/source/blender/compositor/operations/COM_DotproductOperation.cpp @@ -39,7 +39,7 @@ void DotproductOperation::deinitExecution() this->m_input2Operation = nullptr; } -/** \todo: current implementation is the inverse of a dotproduct. not 'logically' correct +/** \todo current implementation is the inverse of a dot-product. not 'logically' correct */ void DotproductOperation::executePixelSampled(float output[4], float x, diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index fbbd373ba09..b548a684ba5 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -1256,7 +1256,7 @@ void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float * * Each version has slightly different criteria for detecting an edge pixel. */ - if (this->m_adjecentOnly) { // if "adjacent only" inner edge mode is turned on + if (this->m_adjacentOnly) { // if "adjacent only" inner edge mode is turned on if (this->m_keepInside) { // if "keep inside" buffer edge mode is turned on do_adjacentKeepBorders(t, rw, limask, lomask, lres, res, rsize); } @@ -1313,7 +1313,7 @@ DoubleEdgeMaskOperation::DoubleEdgeMaskOperation() this->addOutputSocket(COM_DT_VALUE); this->m_inputInnerMask = nullptr; this->m_inputOuterMask = nullptr; - this->m_adjecentOnly = false; + this->m_adjacentOnly = false; this->m_keepInside = false; this->setComplex(true); } diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h index e53aa7eb8aa..813f5009815 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.h @@ -27,7 +27,7 @@ class DoubleEdgeMaskOperation : public NodeOperation { */ SocketReader *m_inputOuterMask; SocketReader *m_inputInnerMask; - bool m_adjecentOnly; + bool m_adjacentOnly; bool m_keepInside; float *m_cachedInstance; @@ -56,9 +56,9 @@ class DoubleEdgeMaskOperation : public NodeOperation { ReadBufferOperation *readOperation, rcti *output); - void setAdjecentOnly(bool adjecentOnly) + void setAdjecentOnly(bool adjacentOnly) { - this->m_adjecentOnly = adjecentOnly; + this->m_adjacentOnly = adjacentOnly; } void setKeepInside(bool keepInside) { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index c47d3b52beb..4d3efec7c85 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -42,7 +42,8 @@ void *GaussianAlphaXBlurOperation::initializeTileData(rcti * /*rect*/) void GaussianAlphaXBlurOperation::initExecution() { - /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + /* Until we support size input - comment this. */ + // BlurBaseOperation::initExecution(); initMutex(); diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index 7a0dff73941..a722a879b8d 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -42,7 +42,8 @@ void *GaussianAlphaYBlurOperation::initializeTileData(rcti * /*rect*/) void GaussianAlphaYBlurOperation::initExecution() { - /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + /* Until we support size input - comment this. */ + // BlurBaseOperation::initExecution(); initMutex(); diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp index 948e69bf8eb..76a66727a75 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cpp +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -705,7 +705,7 @@ void MixMultiplyOperation::executePixelSampled(float output[4], clampIfNeeded(output); } -/* ******** Mix Ovelray Operation ******** */ +/* ******** Mix Overlay Operation ******** */ MixOverlayOperation::MixOverlayOperation() { diff --git a/source/blender/compositor/operations/COM_TonemapOperation.h b/source/blender/compositor/operations/COM_TonemapOperation.h index 3870593b423..cb8816b93b3 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.h +++ b/source/blender/compositor/operations/COM_TonemapOperation.h @@ -22,7 +22,7 @@ #include "DNA_node_types.h" /** - * \brief temporarily storage during execution of Tonemap + * \brief temporarily storage during execution of Tone-map * \ingroup operation */ typedef struct AvgLogLum { diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index f7b908deaf4..d6894dfc8ad 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -589,7 +589,7 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, printf("Found uninitialized speed in vector buffer... fixed.\n"); } - /* min speed? then copy speedbuffer to recalculate speed vectors */ + /* Min speed? then copy speed-buffer to recalculate speed vectors. */ if (nbd->minspeed) { float minspeed = (float)nbd->minspeed; float minspeedsq = minspeed * minspeed; @@ -619,7 +619,7 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, SWAP(float *, minvecbufrect, vecbufrect); } - /* make vertex buffer with averaged speed and zvalues */ + /* Make vertex buffer with averaged speed and Z-values. */ rectvz = (float *)MEM_callocN(sizeof(float[4]) * (xsize + 1) * (ysize + 1), "vertices"); dvz = rectvz; for (y = 0; y <= ysize; y++) { @@ -728,7 +728,8 @@ void zbuf_accumulate_vecblur(NodeBlurData *nbd, antialias_tagbuf(xsize, ysize, rectmove); - /* has to become static, the init-jit calls a random-seed, screwing up texture noise node */ + /* Has to become static, the jitter initialization calls a random-seed, + * screwing up texture noise node. */ if (firsttime) { firsttime = 0; BLI_jitter_init(jit, 256); diff --git a/source/blender/datatoc/CMakeLists.txt b/source/blender/datatoc/CMakeLists.txt index 27dc01f1750..8411a1a468e 100644 --- a/source/blender/datatoc/CMakeLists.txt +++ b/source/blender/datatoc/CMakeLists.txt @@ -53,7 +53,7 @@ if(NOT WITH_HEADLESS) include_directories(${PNG_INCLUDE_DIRS}) if(NOT APPLE) - # APPLE plaform uses full paths for linking libraries. + # APPLE platform uses full paths for linking libraries. link_directories(${PNG_LIBPATH} ${ZLIB_LIBPATH}) endif() diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index c3304cd80ff..d8dc66883a0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -178,7 +178,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) if (id_node->components.is_empty() && deg_copy_on_write_is_needed(id_type)) { ComponentNode *comp_cow = id_node->add_component(NodeType::COPY_ON_WRITE); OperationNode *op_cow = comp_cow->add_operation( - function_bind(deg_evaluate_copy_on_write, _1, id_node), + [id_node](::Depsgraph *depsgraph) { deg_evaluate_copy_on_write(depsgraph, id_node); }, OperationCode::COPY_ON_WRITE, "", -1); @@ -696,7 +696,9 @@ void DepsgraphNodeBuilder::build_object(int base_index, add_operation_node(&object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL, - function_bind(BKE_object_sync_to_original, _1, object_cow)); + [object_cow](::Depsgraph *depsgraph) { + BKE_object_sync_to_original(depsgraph, object_cow); + }); } void DepsgraphNodeBuilder::build_object_from_layer(int base_index, @@ -725,16 +727,15 @@ void DepsgraphNodeBuilder::build_object_flags(int base_index, Object *object_cow = get_cow_datablock(object); const bool is_from_set = (linked_state == DEG_ID_LINKED_VIA_SET); /* TODO(sergey): Is this really best component to be used? */ - add_operation_node(&object->id, - NodeType::OBJECT_FROM_LAYER, - OperationCode::OBJECT_BASE_FLAGS, - function_bind(BKE_object_eval_eval_base_flags, - _1, - scene_cow, - view_layer_index_, - object_cow, - base_index, - is_from_set)); + add_operation_node( + &object->id, + NodeType::OBJECT_FROM_LAYER, + OperationCode::OBJECT_BASE_FLAGS, + [view_layer_index = view_layer_index_, scene_cow, object_cow, base_index, is_from_set]( + ::Depsgraph *depsgraph) { + BKE_object_eval_eval_base_flags( + depsgraph, scene_cow, view_layer_index, object_cow, base_index, is_from_set); + }); } void DepsgraphNodeBuilder::build_object_proxy_from(Object *object, bool is_object_visible) @@ -853,34 +854,38 @@ void DepsgraphNodeBuilder::build_object_transform(Object *object) op_node = add_operation_node(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT); op_node->set_as_entry(); /* Local transforms (from transform channels - loc/rot/scale + deltas). */ - add_operation_node(&object->id, - NodeType::TRANSFORM, - OperationCode::TRANSFORM_LOCAL, - function_bind(BKE_object_eval_local_transform, _1, ob_cow)); + add_operation_node( + &object->id, + NodeType::TRANSFORM, + OperationCode::TRANSFORM_LOCAL, + [ob_cow](::Depsgraph *depsgraph) { BKE_object_eval_local_transform(depsgraph, ob_cow); }); /* Object parent. */ if (object->parent != nullptr) { - add_operation_node(&object->id, - NodeType::TRANSFORM, - OperationCode::TRANSFORM_PARENT, - function_bind(BKE_object_eval_parent, _1, ob_cow)); + add_operation_node( + &object->id, + NodeType::TRANSFORM, + OperationCode::TRANSFORM_PARENT, + [ob_cow](::Depsgraph *depsgraph) { BKE_object_eval_parent(depsgraph, ob_cow); }); } /* Object constraints. */ if (object->constraints.first != nullptr) { build_object_constraints(object); } /* Rest of transformation update. */ - add_operation_node(&object->id, - NodeType::TRANSFORM, - OperationCode::TRANSFORM_EVAL, - function_bind(BKE_object_eval_uber_transform, _1, ob_cow)); + add_operation_node( + &object->id, + NodeType::TRANSFORM, + OperationCode::TRANSFORM_EVAL, + [ob_cow](::Depsgraph *depsgraph) { BKE_object_eval_uber_transform(depsgraph, ob_cow); }); /* Operation to take of rigid body simulation. soft bodies and other friends * in the context of point cache invalidation. */ add_operation_node(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT); /* Object transform is done. */ - op_node = add_operation_node(&object->id, - NodeType::TRANSFORM, - OperationCode::TRANSFORM_FINAL, - function_bind(BKE_object_eval_transform_final, _1, ob_cow)); + op_node = add_operation_node( + &object->id, + NodeType::TRANSFORM, + OperationCode::TRANSFORM_FINAL, + [ob_cow](::Depsgraph *depsgraph) { BKE_object_eval_transform_final(depsgraph, ob_cow); }); op_node->set_as_exit(); } @@ -904,12 +909,14 @@ void DepsgraphNodeBuilder::build_object_transform(Object *object) void DepsgraphNodeBuilder::build_object_constraints(Object *object) { /* create node for constraint stack */ - add_operation_node( - &object->id, - NodeType::TRANSFORM, - OperationCode::TRANSFORM_CONSTRAINTS, - function_bind( - BKE_object_eval_constraints, _1, get_cow_datablock(scene_), get_cow_datablock(object))); + Scene *scene_cow = get_cow_datablock(scene_); + Object *object_cow = get_cow_datablock(object); + add_operation_node(&object->id, + NodeType::TRANSFORM, + OperationCode::TRANSFORM_CONSTRAINTS, + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_object_eval_constraints(depsgraph, scene_cow, object_cow); + }); } void DepsgraphNodeBuilder::build_object_pointcache(Object *object) @@ -922,7 +929,9 @@ void DepsgraphNodeBuilder::build_object_pointcache(Object *object) add_operation_node(&object->id, NodeType::POINT_CACHE, OperationCode::POINT_CACHE_RESET, - function_bind(BKE_object_eval_ptcache_reset, _1, scene_cow, object_cow)); + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_object_eval_ptcache_reset(depsgraph, scene_cow, object_cow); + }); } /** @@ -950,10 +959,10 @@ void DepsgraphNodeBuilder::build_animdata(ID *id) operation_node = add_operation_node(id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY); operation_node->set_as_entry(); /* All the evaluation nodes. */ - add_operation_node(id, - NodeType::ANIMATION, - OperationCode::ANIMATION_EVAL, - function_bind(BKE_animsys_eval_animdata, _1, id_cow)); + add_operation_node( + id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL, [id_cow](::Depsgraph *depsgraph) { + BKE_animsys_eval_animdata(depsgraph, id_cow); + }); /* Explicit exit operation. */ operation_node = add_operation_node(id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT); operation_node->set_as_exit(); @@ -989,10 +998,11 @@ void DepsgraphNodeBuilder::build_animation_images(ID *id) { if (BKE_image_user_id_has_animation(id)) { ID *id_cow = get_cow_id(id); - add_operation_node(id, - NodeType::IMAGE_ANIMATION, - OperationCode::IMAGE_ANIMATION, - function_bind(BKE_image_user_id_eval_animation, _1, id_cow)); + add_operation_node( + id, + NodeType::IMAGE_ANIMATION, + OperationCode::IMAGE_ANIMATION, + [id_cow](::Depsgraph *depsgraph) { BKE_image_user_id_eval_animation(depsgraph, id_cow); }); } } @@ -1020,12 +1030,15 @@ void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve, int driver_index * has not yet been allocated at this point we can't. As a workaround * the animation systems allocates an array so we can do a fast lookup * with the driver index. */ - ensure_operation_node(id, - NodeType::PARAMETERS, - OperationCode::DRIVER, - function_bind(BKE_animsys_eval_driver, _1, id_cow, driver_index, fcurve), - fcurve->rna_path ? fcurve->rna_path : "", - fcurve->array_index); + ensure_operation_node( + id, + NodeType::PARAMETERS, + OperationCode::DRIVER, + [id_cow, driver_index, fcurve](::Depsgraph *depsgraph) { + BKE_animsys_eval_driver(depsgraph, id_cow, driver_index, fcurve); + }, + fcurve->rna_path ? fcurve->rna_path : "", + fcurve->array_index); build_driver_variables(id, fcurve); } @@ -1103,10 +1116,11 @@ void DepsgraphNodeBuilder::build_world(World *world) add_id_node(&world->id); World *world_cow = get_cow_datablock(world); /* Shading update. */ - add_operation_node(&world->id, - NodeType::SHADING, - OperationCode::WORLD_UPDATE, - function_bind(BKE_world_eval, _1, world_cow)); + add_operation_node( + &world->id, + NodeType::SHADING, + OperationCode::WORLD_UPDATE, + [world_cow](::Depsgraph *depsgraph) { BKE_world_eval(depsgraph, world_cow); }); build_idproperties(world->id.properties); /* Animation. */ build_animdata(&world->id); @@ -1142,16 +1156,19 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) * instead? */ /* Init/rebuild operation. */ - add_operation_node(&scene->id, - NodeType::TRANSFORM, - OperationCode::RIGIDBODY_REBUILD, - function_bind(BKE_rigidbody_rebuild_sim, _1, scene_cow)); - /* Do-sim operation. */ - OperationNode *sim_node = add_operation_node( + add_operation_node( &scene->id, NodeType::TRANSFORM, - OperationCode::RIGIDBODY_SIM, - function_bind(BKE_rigidbody_eval_simulation, _1, scene_cow)); + OperationCode::RIGIDBODY_REBUILD, + [scene_cow](::Depsgraph *depsgraph) { BKE_rigidbody_rebuild_sim(depsgraph, scene_cow); }); + /* Do-sim operation. */ + OperationNode *sim_node = add_operation_node(&scene->id, + NodeType::TRANSFORM, + OperationCode::RIGIDBODY_SIM, + [scene_cow](::Depsgraph *depsgraph) { + BKE_rigidbody_eval_simulation(depsgraph, + scene_cow); + }); sim_node->set_as_entry(); sim_node->set_as_exit(); sim_node->owner->entry_operation = sim_node; @@ -1173,12 +1190,13 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* Create operation for flushing results. */ /* Object's transform component - where the rigidbody operation * lives. */ - add_operation_node( - &object->id, - NodeType::TRANSFORM, - OperationCode::RIGIDBODY_TRANSFORM_COPY, - function_bind( - BKE_rigidbody_object_sync_transforms, _1, scene_cow, get_cow_datablock(object))); + Object *object_cow = get_cow_datablock(object); + add_operation_node(&object->id, + NodeType::TRANSFORM, + OperationCode::RIGIDBODY_TRANSFORM_COPY, + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_rigidbody_object_sync_transforms(depsgraph, scene_cow, object_cow); + }); } FOREACH_COLLECTION_OBJECT_RECURSIVE_END; } @@ -1219,9 +1237,10 @@ void DepsgraphNodeBuilder::build_particle_systems(Object *object, bool is_object Object *ob_cow = get_cow_datablock(object); OperationNode *op_node; - op_node = add_operation_node(psys_comp, - OperationCode::PARTICLE_SYSTEM_INIT, - function_bind(BKE_particle_system_eval_init, _1, ob_cow)); + op_node = add_operation_node( + psys_comp, OperationCode::PARTICLE_SYSTEM_INIT, [ob_cow](::Depsgraph *depsgraph) { + BKE_particle_system_eval_init(depsgraph, ob_cow); + }); op_node->set_as_entry(); /* Build all particle systems. */ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { @@ -1278,7 +1297,9 @@ void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *particle_se add_operation_node(&particle_settings->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_RESET, - function_bind(BKE_particle_settings_eval_reset, _1, particle_settings_cow)); + [particle_settings_cow](::Depsgraph *depsgraph) { + BKE_particle_settings_eval_reset(depsgraph, particle_settings_cow); + }); op_node = add_operation_node( &particle_settings->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL); op_node->set_as_exit(); @@ -1323,11 +1344,12 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob op_node = add_operation_node(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT); op_node->set_as_entry(); /* Geometry evaluation. */ - op_node = add_operation_node( - &object->id, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - function_bind(BKE_object_eval_uber_data, _1, scene_cow, object_cow)); + op_node = add_operation_node(&object->id, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_object_eval_uber_data(depsgraph, scene_cow, object_cow); + }); op_node->set_as_exit(); /* Materials. */ build_materials(object->mat, object->totcol); @@ -1337,10 +1359,11 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob build_object_data_geometry_datablock((ID *)object->data, is_object_visible); build_dimensions(object); /* Batch cache. */ - add_operation_node(&object->id, - NodeType::BATCH_CACHE, - OperationCode::GEOMETRY_SELECT_UPDATE, - function_bind(BKE_object_select_update, _1, object_cow)); + add_operation_node( + &object->id, + NodeType::BATCH_CACHE, + OperationCode::GEOMETRY_SELECT_UPDATE, + [object_cow](::Depsgraph *depsgraph) { BKE_object_select_update(depsgraph, object_cow); }); } void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool is_object_visible) @@ -1368,7 +1391,9 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL, - function_bind(BKE_mesh_eval_geometry, _1, (Mesh *)obdata_cow)); + [obdata_cow](::Depsgraph *depsgraph) { + BKE_mesh_eval_geometry(depsgraph, (Mesh *)obdata_cow); + }); op_node->set_as_entry(); break; } @@ -1378,11 +1403,12 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool break; } case ID_CU: { - op_node = add_operation_node( - obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata_cow)); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_curve_eval_geometry(depsgraph, (Curve *)obdata_cow); + }); op_node->set_as_entry(); /* Make sure objects used for bevel.taper are in the graph. * NOTE: This objects might be not linked to the scene. */ @@ -1399,22 +1425,25 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool break; } case ID_LT: { - op_node = add_operation_node( - obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - function_bind(BKE_lattice_eval_geometry, _1, (Lattice *)obdata_cow)); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_lattice_eval_geometry(depsgraph, (Lattice *)obdata_cow); + }); op_node->set_as_entry(); break; } case ID_GD: { /* GPencil evaluation operations. */ - op_node = add_operation_node( - obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - function_bind(BKE_gpencil_frame_active_set, _1, (bGPdata *)obdata_cow)); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_gpencil_frame_active_set(depsgraph, + (bGPdata *)obdata_cow); + }); op_node->set_as_entry(); break; } @@ -1430,11 +1459,12 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool } case ID_VO: { /* Volume frame update. */ - op_node = add_operation_node( - obdata, - NodeType::GEOMETRY, - OperationCode::GEOMETRY_EVAL, - function_bind(BKE_volume_eval_geometry, _1, (Volume *)obdata_cow)); + op_node = add_operation_node(obdata, + NodeType::GEOMETRY, + OperationCode::GEOMETRY_EVAL, + [obdata_cow](::Depsgraph *depsgraph) { + BKE_volume_eval_geometry(depsgraph, (Volume *)obdata_cow); + }); op_node->set_as_entry(); break; } @@ -1450,7 +1480,9 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool add_operation_node(obdata, NodeType::BATCH_CACHE, OperationCode::GEOMETRY_SELECT_UPDATE, - function_bind(BKE_object_data_select_update, _1, obdata_cow)); + [obdata_cow](::Depsgraph *depsgraph) { + BKE_object_data_select_update(depsgraph, obdata_cow); + }); } void DepsgraphNodeBuilder::build_armature(bArmature *armature) @@ -1466,7 +1498,9 @@ void DepsgraphNodeBuilder::build_armature(bArmature *armature) add_operation_node(&armature->id, NodeType::ARMATURE, OperationCode::ARMATURE_EVAL, - function_bind(BKE_armature_refresh_layer_used, _1, armature_cow)); + [armature_cow](::Depsgraph *depsgraph) { + BKE_armature_refresh_layer_used(depsgraph, armature_cow); + }); build_armature_bones(&armature->bonebase); } @@ -1506,7 +1540,7 @@ void DepsgraphNodeBuilder::build_light(Light *lamp) add_operation_node(&lamp->id, NodeType::SHADING, OperationCode::LIGHT_UPDATE, - function_bind(BKE_light_eval, _1, lamp_cow)); + [lamp_cow](::Depsgraph *depsgraph) { BKE_light_eval(depsgraph, lamp_cow); }); } void DepsgraphNodeBuilder::build_nodetree_socket(bNodeSocket *socket) @@ -1534,7 +1568,6 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) } /* nodetree itself */ add_id_node(&ntree->id); - bNodeTree *ntree_cow = get_cow_datablock(ntree); /* General parameters. */ build_parameters(&ntree->id); build_idproperties(ntree->id.properties); @@ -1542,12 +1575,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_animdata(&ntree->id); /* Shading update. */ add_operation_node(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE); - /* NOTE: We really pass original and CoW node trees here, this is how the - * callback works. Ideally we need to find a better way for that. */ - add_operation_node(&ntree->id, - NodeType::SHADING_PARAMETERS, - OperationCode::MATERIAL_UPDATE, - function_bind(BKE_nodetree_shading_params_eval, _1, ntree_cow, ntree)); + add_operation_node(&ntree->id, NodeType::SHADING_PARAMETERS, OperationCode::MATERIAL_UPDATE); /* nodetree's nodes... */ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { build_idproperties(bnode->prop); @@ -1626,10 +1654,11 @@ void DepsgraphNodeBuilder::build_material(Material *material) add_id_node(&material->id); Material *material_cow = get_cow_datablock(material); /* Shading update. */ - add_operation_node(&material->id, - NodeType::SHADING, - OperationCode::MATERIAL_UPDATE, - function_bind(BKE_material_eval, _1, material_cow)); + add_operation_node( + &material->id, + NodeType::SHADING, + OperationCode::MATERIAL_UPDATE, + [material_cow](::Depsgraph *depsgraph) { BKE_material_eval(depsgraph, material_cow); }); build_idproperties(material->id.properties); /* Material animation. */ build_animdata(&material->id); @@ -1714,7 +1743,9 @@ void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file) add_operation_node(cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE, - function_bind(BKE_cachefile_eval, bmain_, _1, cache_file_cow)); + [bmain = bmain_, cache_file_cow](::Depsgraph *depsgraph) { + BKE_cachefile_eval(bmain, depsgraph, cache_file_cow); + }); } void DepsgraphNodeBuilder::build_mask(Mask *mask) @@ -1729,15 +1760,16 @@ void DepsgraphNodeBuilder::build_mask(Mask *mask) build_animdata(mask_id); build_parameters(mask_id); /* Animation based on mask's shapes. */ - add_operation_node(mask_id, - NodeType::ANIMATION, - OperationCode::MASK_ANIMATION, - function_bind(BKE_mask_eval_animation, _1, mask_cow)); + add_operation_node( + mask_id, + NodeType::ANIMATION, + OperationCode::MASK_ANIMATION, + [mask_cow](::Depsgraph *depsgraph) { BKE_mask_eval_animation(depsgraph, mask_cow); }); /* Final mask evaluation. */ - add_operation_node(mask_id, - NodeType::PARAMETERS, - OperationCode::MASK_EVAL, - function_bind(BKE_mask_eval_update, _1, mask_cow)); + add_operation_node( + mask_id, NodeType::PARAMETERS, OperationCode::MASK_EVAL, [mask_cow](::Depsgraph *depsgraph) { + BKE_mask_eval_update(depsgraph, mask_cow); + }); /* Build parents. */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { @@ -1781,12 +1813,16 @@ void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip) add_operation_node(clip_id, NodeType::PARAMETERS, OperationCode::MOVIECLIP_EVAL, - function_bind(BKE_movieclip_eval_update, _1, bmain_, clip_cow)); + [bmain = bmain_, clip_cow](::Depsgraph *depsgraph) { + BKE_movieclip_eval_update(depsgraph, bmain, clip_cow); + }); add_operation_node(clip_id, NodeType::BATCH_CACHE, OperationCode::MOVIECLIP_SELECT_UPDATE, - function_bind(BKE_movieclip_eval_selection_update, _1, clip_cow)); + [clip_cow](::Depsgraph *depsgraph) { + BKE_movieclip_eval_selection_update(depsgraph, clip_cow); + }); } void DepsgraphNodeBuilder::build_lightprobe(LightProbe *probe) @@ -1826,7 +1862,9 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound) add_operation_node(&sound->id, NodeType::AUDIO, OperationCode::SOUND_EVAL, - function_bind(BKE_sound_evaluate, _1, bmain_, sound_cow)); + [bmain = bmain_, sound_cow](::Depsgraph *depsgraph) { + BKE_sound_evaluate(depsgraph, bmain, sound_cow); + }); build_idproperties(sound->id.properties); build_animdata(&sound->id); build_parameters(&sound->id); @@ -1849,7 +1887,9 @@ void DepsgraphNodeBuilder::build_simulation(Simulation *simulation) add_operation_node(&simulation->id, NodeType::SIMULATION, OperationCode::SIMULATION_EVAL, - function_bind(BKE_simulation_data_update, _1, scene_cow, simulation_cow)); + [scene_cow, simulation_cow](::Depsgraph *depsgraph) { + BKE_simulation_data_update(depsgraph, scene_cow, simulation_cow); + }); } void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) @@ -1865,7 +1905,9 @@ void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) add_operation_node(&scene->id, NodeType::SEQUENCER, OperationCode::SEQUENCES_EVAL, - function_bind(BKE_scene_eval_sequencer_sequences, _1, scene_cow)); + [scene_cow](::Depsgraph *depsgraph) { + BKE_scene_eval_sequencer_sequences(depsgraph, scene_cow); + }); /* Make sure data for sequences is in the graph. */ Sequence *seq; SEQ_ALL_BEGIN (scene->ed, seq) { @@ -1904,7 +1946,9 @@ void DepsgraphNodeBuilder::build_scene_audio(Scene *scene) add_operation_node(&scene->id, NodeType::AUDIO, OperationCode::AUDIO_VOLUME, - function_bind(BKE_scene_update_tag_audio_volume, _1, scene_cow)); + [scene_cow](::Depsgraph *depsgraph) { + BKE_scene_update_tag_audio_volume(depsgraph, scene_cow); + }); } void DepsgraphNodeBuilder::build_scene_speakers(Scene * /*scene*/, ViewLayer *view_layer) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 8ba4b4a427f..13caba67713 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -66,16 +66,18 @@ void DepsgraphNodeBuilder::build_pose_constraints(Object *object, data.builder = this; data.is_parent_visible = is_object_visible; BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data); + /* Create node for constraint stack. */ + Scene *scene_cow = get_cow_datablock(scene_); + Object *object_cow = get_cow_datablock(object); add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_CONSTRAINTS, - function_bind(BKE_pose_constraints_evaluate, - _1, - get_cow_datablock(scene_), - get_cow_datablock(object), - pchan_index)); + [scene_cow, object_cow, pchan_index](::Depsgraph *depsgraph) { + BKE_pose_constraints_evaluate( + depsgraph, scene_cow, object_cow, pchan_index); + }); } /* IK Solver Eval Steps */ @@ -96,16 +98,17 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bC int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan); BLI_assert(rootchan_index != -1); + /* Operation node for evaluating/running IK Solver. */ + Scene *scene_cow = get_cow_datablock(scene_); + Object *object_cow = get_cow_datablock(object); add_operation_node(&object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_IK_SOLVER, - function_bind(BKE_pose_iktree_evaluate, - _1, - get_cow_datablock(scene_), - get_cow_datablock(object), - rootchan_index)); + [scene_cow, object_cow, rootchan_index](::Depsgraph *depsgraph) { + BKE_pose_iktree_evaluate(depsgraph, scene_cow, object_cow, rootchan_index); + }); } /* Spline IK Eval Steps */ @@ -130,15 +133,17 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object, * start. */ int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan); BLI_assert(rootchan_index != -1); + + Scene *scene_cow = get_cow_datablock(scene_); + Object *object_cow = get_cow_datablock(object); add_operation_node(&object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_SPLINE_IK_SOLVER, - function_bind(BKE_pose_splineik_evaluate, - _1, - get_cow_datablock(scene_), - get_cow_datablock(object), - rootchan_index)); + [scene_cow, object_cow, rootchan_index](::Depsgraph *depsgraph) { + BKE_pose_splineik_evaluate( + depsgraph, scene_cow, object_cow, rootchan_index); + }); } /* Pose/Armature Bones Graph */ @@ -193,23 +198,30 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) op_node = add_operation_node(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT, - function_bind(BKE_pose_eval_init, _1, scene_cow, object_cow)); + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_pose_eval_init(depsgraph, scene_cow, object_cow); + }); op_node->set_as_entry(); op_node = add_operation_node(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK, - function_bind(BKE_pose_eval_init_ik, _1, scene_cow, object_cow)); + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_pose_eval_init_ik(depsgraph, scene_cow, object_cow); + }); add_operation_node(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP, - function_bind(BKE_pose_eval_cleanup, _1, scene_cow, object_cow)); - - op_node = add_operation_node(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_DONE, - function_bind(BKE_pose_eval_done, _1, object_cow)); + [scene_cow, object_cow](::Depsgraph *depsgraph) { + BKE_pose_eval_cleanup(depsgraph, scene_cow, object_cow); + }); + + op_node = add_operation_node( + &object->id, + NodeType::EVAL_POSE, + OperationCode::POSE_DONE, + [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_done(depsgraph, object_cow); }); op_node->set_as_exit(); /* Bones. */ int pchan_index = 0; @@ -223,7 +235,9 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) NodeType::BONE, pchan->name, OperationCode::BONE_POSE_PARENT, - function_bind(BKE_pose_eval_bone, _1, scene_cow, object_cow, pchan_index)); + [scene_cow, object_cow, pchan_index](::Depsgraph *depsgraph) { + BKE_pose_eval_bone(depsgraph, scene_cow, object_cow, pchan_index); + }); /* NOTE: Dedicated noop for easier relationship construction. */ add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY); @@ -232,16 +246,20 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) NodeType::BONE, pchan->name, OperationCode::BONE_DONE, - function_bind(BKE_pose_bone_done, _1, object_cow, pchan_index)); + [object_cow, pchan_index](::Depsgraph *depsgraph) { + BKE_pose_bone_done(depsgraph, object_cow, pchan_index); + }); /* B-Bone shape computation - the real last step if present. */ if (check_pchan_has_bbone(object, pchan)) { - op_node = add_operation_node( - &object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_SEGMENTS, - function_bind(BKE_pose_eval_bbone_segments, _1, object_cow, pchan_index)); + op_node = add_operation_node(&object->id, + NodeType::BONE, + pchan->name, + OperationCode::BONE_SEGMENTS, + [object_cow, pchan_index](::Depsgraph *depsgraph) { + BKE_pose_eval_bbone_segments( + depsgraph, object_cow, pchan_index); + }); } op_node->set_as_exit(); @@ -304,10 +322,11 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object, bool is_object_visibl if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { BKE_pose_update_constraint_flags(object->pose); } - op_node = add_operation_node(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_INIT, - function_bind(BKE_pose_eval_proxy_init, _1, object_cow)); + op_node = add_operation_node( + &object->id, + NodeType::EVAL_POSE, + OperationCode::POSE_INIT, + [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_proxy_init(depsgraph, object_cow); }); op_node->set_as_entry(); int pchan_index = 0; @@ -318,12 +337,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object, bool is_object_visibl /* Bone is ready for solvers. */ add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY); /* Bone is fully evaluated. */ - op_node = add_operation_node( - &object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_DONE, - function_bind(BKE_pose_eval_proxy_copy_bone, _1, object_cow, pchan_index)); + op_node = add_operation_node(&object->id, + NodeType::BONE, + pchan->name, + OperationCode::BONE_DONE, + [object_cow, pchan_index](::Depsgraph *depsgraph) { + BKE_pose_eval_proxy_copy_bone( + depsgraph, object_cow, pchan_index); + }); op_node->set_as_exit(); /* Custom properties. */ @@ -343,11 +364,14 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object, bool is_object_visibl op_node = add_operation_node(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP, - function_bind(BKE_pose_eval_proxy_cleanup, _1, object_cow)); - op_node = add_operation_node(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_DONE, - function_bind(BKE_pose_eval_proxy_done, _1, object_cow)); + [object_cow](::Depsgraph *depsgraph) { + BKE_pose_eval_proxy_cleanup(depsgraph, object_cow); + }); + op_node = add_operation_node( + &object->id, + NodeType::EVAL_POSE, + OperationCode::POSE_DONE, + [object_cow](::Depsgraph *depsgraph) { BKE_pose_eval_proxy_done(depsgraph, object_cow); }); op_node->set_as_exit(); } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index b1fd86f13bc..29aa05b83db 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -160,11 +160,12 @@ void DepsgraphNodeBuilder::build_view_layer(Scene *scene, build_scene_sequencer(scene); } /* Collections. */ - add_operation_node( - &scene->id, - NodeType::LAYER_COLLECTIONS, - OperationCode::VIEW_LAYER_EVAL, - function_bind(BKE_layer_eval_view_layer_indexed, _1, scene_cow, view_layer_index_)); + add_operation_node(&scene->id, + NodeType::LAYER_COLLECTIONS, + OperationCode::VIEW_LAYER_EVAL, + [view_layer_index = view_layer_index_, scene_cow](::Depsgraph *depsgraph) { + BKE_layer_eval_view_layer_indexed(depsgraph, scene_cow, view_layer_index); + }); /* Parameters evaluation for scene relations mainly. */ build_scene_compositor(scene); build_scene_parameters(scene); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 463efe52375..96b4da34347 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -1238,7 +1238,7 @@ void DepsgraphRelationBuilder::build_constraints(ID *id, // TODO: loc vs rot vs scale? if (&ct->tar->id == id) { /* Constraint targeting own object: - * - This case is fine IFF we're dealing with a bone + * - This case is fine IF we're dealing with a bone * constraint pointing to its own armature. In that * case, it's just transform -> bone. * - If however it is a real self targeting case, just @@ -1814,7 +1814,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) RELATION_FLAG_GODMODE); } - /* Final transform is whetever solver gave to us. */ + /* Final transform is whatever the solver gave to us. */ if (object->rigidbody_object->type == RBO_TYPE_ACTIVE) { /* We do not have to update the objects final transform after the simulation if it is * passive or controlled by the animation system in blender. @@ -2496,7 +2496,7 @@ void DepsgraphRelationBuilder::build_material(Material *material) /* Animated / driven parameters (without nodetree). */ OperationKey material_key(&material->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE); ComponentKey parameters_key(&material->id, NodeType::PARAMETERS); - add_relation(parameters_key, material_key, "Material's paramters"); + add_relation(parameters_key, material_key, "Material's parameters"); /* material's nodetree */ if (material->nodetree != nullptr) { diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index a0cbbbc163d..9afae0f2c22 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -184,7 +184,7 @@ static void deg_debug_graphviz_legend(DotExportContext &ctx) std::stringstream ss; ss << "<"; - ss << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">"; + ss << R"(<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">)"; ss << "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>"; #ifdef COLOR_SCHEME_NODE_CLASS diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc index 0cdd627dd44..df343a3eb28 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc @@ -87,7 +87,7 @@ string gnuplotify_name(const string &name) for (int i = 0; i < length; i++) { const char ch = name[i]; if (ch == '_') { - result += "\\\\\\"; + result += R"(\\\)"; } result += ch; } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index e472d82f2ee..34465c12914 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -193,6 +193,32 @@ bool deg_iterator_components_step(BLI_Iterator *iter) } } + /* The volume component. */ + if (data->geometry_component_id == 2) { + data->geometry_component_id++; + + /* Don't use a temporary object for this component, when the owner is a volume object. */ + if (data->geometry_component_owner->type == OB_VOLUME) { + iter->current = data->geometry_component_owner; + return true; + } + + const VolumeComponent *component = geometry_set->get_component_for_read<VolumeComponent>(); + if (component != nullptr) { + const Volume *volume = component->get_for_read(); + + if (volume != nullptr) { + Object *temp_object = &data->temp_geometry_component_object; + *temp_object = *data->geometry_component_owner; + temp_object->type = OB_VOLUME; + temp_object->data = (void *)volume; + temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; + iter->current = temp_object; + return true; + } + } + } + data->geometry_component_owner = nullptr; return false; } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h index 007236e7890..d16f5b9b5ce 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h @@ -46,7 +46,7 @@ class SceneBackup { * * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency * graph will be gone. This means we don't need to compare original scene pointer, or worry about - * freeing those if they cant' be restored: we just copy them over to a new scene. */ + * freeing those if they can't be restored: we just copy them over to a new scene. */ void *sound_scene; void *playback_handle; void *sound_scrub_handle; diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index c4d36685bb8..e2d3b3fc36f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -88,7 +88,7 @@ struct IDNode : public Node { * which could be "stale" pointer. */ uint id_orig_session_uuid; - /* Evaluated datablock. + /* Evaluated data-block. * Will be covered by the copy-on-write system if the ID Type needs it. */ ID *id_cow; @@ -107,7 +107,7 @@ struct IDNode : public Node { eDepsNode_LinkedState_Type linked_state; - /* Indicates the datablock is visible in the evaluated scene. */ + /* Indicates the data-block is visible in the evaluated scene. */ bool is_directly_visible; /* For the collection type of ID, denotes whether collection was fully diff --git a/source/blender/draw/engines/eevee/eevee_cryptomatte.c b/source/blender/draw/engines/eevee/eevee_cryptomatte.c index b47e8c5f081..13a3f1766a9 100644 --- a/source/blender/draw/engines/eevee/eevee_cryptomatte.c +++ b/source/blender/draw/engines/eevee/eevee_cryptomatte.c @@ -363,7 +363,7 @@ static void eevee_cryptomatte_download_buffer(EEVEE_Data *vedata, GPUFrameBuffer download_buffer); /* Integrate download buffer into the accum buffer. - * The download buffer contains upto 3 floats per pixel (one float per cryptomatte layer. + * The download buffer contains up to 3 floats per pixel (one float per cryptomatte layer. * * NOTE: here we deviate from the cryptomatte standard. During integration the standard always * sort the samples by its weight to make sure that samples with the lowest weight diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index 47068d0b843..b453df284ed 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -130,7 +130,7 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData * } EEVEE_ObjectKey key, *key_p; - /* Small hack to avoid another comparisson. */ + /* Small hack to avoid another comparison. */ key.ob = (Object *)((char *)ob + hair); DupliObject *dup = DRW_object_get_dupli(ob); if (dup) { diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index ca583143572..698b959f1a9 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -242,7 +242,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } { - /* Perform min/max downsample */ + /* Perform min/max down-sample. */ DRW_PASS_CREATE(psl->maxz_downlevel_ps, downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(EEVEE_shaders_effect_maxz_downlevel_sh_get(), psl->maxz_downlevel_ps); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &txl->maxzbuffer); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index c6760de5cfa..802b47b61a4 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -319,7 +319,7 @@ static void eevee_draw_scene(void *vedata) EEVEE_renderpasses_output_accumulate(sldata, vedata, false); /* Transparent */ - /* TODO(fclem): should be its own Framebuffer. + /* TODO(fclem): should be its own Frame-buffer. * This is needed because dualsource blending only works with 1 color buffer. */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 040aa8c8d9c..c4973dc2e8b 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -99,9 +99,9 @@ typedef struct EEVEE_LightBake { GPUTexture *rt_color; /** Target cube depth texture. */ GPUTexture *rt_depth; - /** Target cube framebuffers. */ + /** Target cube frame-buffers. */ GPUFrameBuffer *rt_fb[6]; - /** Storage framebuffer. */ + /** Storage frame-buffer. */ GPUFrameBuffer *store_fb; /** Cube render target resolution. */ int rt_res; @@ -135,7 +135,7 @@ typedef struct EEVEE_LightBake { int grid_curr; /** The current light bounce being evaluated. */ int bounce_curr, bounce_len; - /** Resolution of the Visibility shadowmap. */ + /** Resolution of the Visibility shadow-map. */ float vis_res; /** Result of previous light bounce. */ GPUTexture *grid_prev; @@ -163,7 +163,7 @@ typedef struct EEVEE_LightBake { /** For only handling the resources. */ bool resource_only; bool own_resources; - /** If the lightcache was created for baking, it's first owned by the baker. */ + /** If the light-cache was created for baking, it's first owned by the baker. */ bool own_light_cache; /** ms. delay the start of the baking to not slowdown interactions (TODO remove) */ int delay; @@ -907,7 +907,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph); lbake->sldata = sldata; - /* Disable all effects BUT high bitdepth shadows. */ + /* Disable all effects BUT high bit-depth shadows. */ scene_eval->eevee.flag &= SCE_EEVEE_SHADOW_HIGH_BITDEPTH; scene_eval->eevee.taa_samples = 1; scene_eval->eevee.gi_irradiance_smoothing = 0.0f; @@ -980,7 +980,7 @@ static void eevee_lightbake_copy_irradiance(EEVEE_LightBake *lbake, LightCache * { DRW_TEXTURE_FREE_SAFE(lbake->grid_prev); - /* Copy texture by reading back and reuploading it. */ + /* Copy texture by reading back and re-uploading it. */ float *tex = GPU_texture_read(lcache->grid_tx.tex, GPU_DATA_FLOAT, 0); lbake->grid_prev = DRW_texture_create_2d_array(lbake->irr_size[0], lbake->irr_size[1], @@ -1330,7 +1330,7 @@ void EEVEE_lightbake_update(void *custom_data) EEVEE_LightBake *lbake = (EEVEE_LightBake *)custom_data; Scene *scene_orig = lbake->scene; - /* If a new lightcache was created, free the old one and reference the new. */ + /* If a new light-cache was created, free the old one and reference the new. */ if (lbake->lcache && scene_orig->eevee.light_cache_data != lbake->lcache) { if (scene_orig->eevee.light_cache_data != NULL) { EEVEE_lightcache_free(scene_orig->eevee.light_cache_data); @@ -1353,7 +1353,7 @@ static bool lightbake_do_sample(EEVEE_LightBake *lbake, Depsgraph *depsgraph = lbake->depsgraph; - /* TODO: make DRW manager instanciable (and only lock on drawing) */ + /* TODO: make DRW manager instantiable (and only lock on drawing) */ eevee_lightbake_context_enable(lbake); DRW_custom_pipeline(&draw_engine_eevee_type, depsgraph, render_callback, lbake); lbake->done += 1; diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index 3671bea9ac0..395d4dc790d 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -704,11 +704,11 @@ static void lightbake_planar_ensure_view(EEVEE_PlanarReflection *eplanar, static void eevee_lightprobes_extract_from_cache(EEVEE_LightProbesInfo *pinfo, LightCache *lcache) { /* copy the entire cache for now (up to MAX_PROBE) */ - /* TODO Frutum cull to only add visible probes. */ + /* TODO: frustum cull to only add visible probes. */ memcpy(pinfo->probe_data, lcache->cube_data, sizeof(EEVEE_LightProbe) * max_ii(1, min_ii(lcache->cube_len, MAX_PROBE))); - /* TODO compute the max number of grid based on sample count. */ + /* TODO: compute the max number of grid based on sample count. */ memcpy(pinfo->grid_data, lcache->grid_data, sizeof(EEVEE_LightGrid) * max_ii(1, min_ii(lcache->grid_len, MAX_GRID))); @@ -1041,7 +1041,7 @@ void EEVEE_lightbake_filter_glossy(EEVEE_ViewLayerData *sldata, pinfo->layer = probe_idx * 6; pinfo->roughness = i / (float)maxlevel; pinfo->roughness *= pinfo->roughness; /* Disney Roughness */ - pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */ + pinfo->roughness *= pinfo->roughness; /* Distribute Roughness across lod more evenly. */ CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */ #if 1 /* Variable Sample count and bias (fast) */ diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c index 628941f68a2..a9998b33b7e 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.c +++ b/source/blender/draw/engines/eevee/eevee_lookdev.c @@ -344,7 +344,7 @@ void EEVEE_lookdev_draw(EEVEE_Data *vedata) DRW_view_set_active(effects->lookdev_view); - /* Find the right framebuffers to render to. */ + /* Find the right frame-buffers to render to. */ GPUFrameBuffer *fb = (effects->target_buffer == fbl->effect_color_fb) ? fbl->main_fb : fbl->effect_fb; diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c index b74cb6c7687..18645fea5e0 100644 --- a/source/blender/draw/engines/eevee/eevee_lut_gen.c +++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c @@ -22,7 +22,7 @@ * EEVEE LUT generation: * * Routine to generate the LUT used by eevee stored in eevee_lut.h - * Theses functions are not to be used in the final executable. + * These functions are not to be used in the final executable. */ #include "DRW_render.h" diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 273521b0b28..5f2821730f1 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -234,7 +234,7 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, } { - /* Update noise Framebuffer. */ + /* Update noise Frame-buffer. */ GPU_framebuffer_ensure_config( &fbl->update_noise_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE_LAYER(e_data.util_tex, 2)}); @@ -415,7 +415,7 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { /* Renderpass accumulation. */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL; - /* Create an instance of each of theses passes and link them together. */ + /* Create an instance of each of these passes and link them together. */ DRWPass *passes[] = { psl->material_ps, psl->material_cull_ps, diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 8dcab579603..0a79d9466e9 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -476,7 +476,7 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata) if (vbo) { /* Use the vbo to perform the copy on the GPU. */ GPU_vertbuf_use(vbo); - /* Perform a copy to avoid loosing it after RE_engine_frame_set(). */ + /* Perform a copy to avoid losing it after RE_engine_frame_set(). */ mb_geom->vbo[mb_step] = vbo = GPU_vertbuf_duplicate(vbo); /* Find and replace "pos" attrib name. */ GPUVertFormat *format = (GPUVertFormat *)GPU_vertbuf_get_format(vbo); diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index fd96a076c68..a3b581357e0 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -273,7 +273,7 @@ void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data * if (fbl->ao_accum_fb != NULL) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - /* Update the min_max/horizon buffers so the refracion materials appear in it. */ + /* Update the min_max/horizon buffers so the refraction materials appear in it. */ EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 9702db5fecc..e48f5f9dd32 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -518,7 +518,7 @@ typedef struct EEVEE_LightsInfo { struct EEVEE_Shadow shadow_data[MAX_SHADOW]; struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE]; struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE]; - /* Additionnal rendering info for cascade. */ + /* Additional rendering info for cascade. */ struct EEVEE_ShadowCascadeRender shadow_cascade_render[MAX_SHADOW_CASCADE]; /* Back index in light_data. */ uchar shadow_cube_light_indices[MAX_SHADOW_CUBE]; @@ -716,7 +716,7 @@ typedef struct EEVEE_EffectsInfo { CameraParams past_cam_params; CameraParams current_cam_params; char motion_blur_step; /* Which step we are evaluating. */ - int motion_blur_max; /* Maximum distance in pixels a motion blured pixel can cover. */ + int motion_blur_max; /* Maximum distance in pixels a motion-blurred pixel can cover. */ float motion_blur_near_far[2]; /* Camera near/far clip distances (positive). */ bool cam_params_init; /* TODO(fclem): Only used in render mode for now. @@ -766,7 +766,7 @@ typedef struct EEVEE_EffectsInfo { struct GPUTexture *source_buffer; /* latest updated texture */ struct GPUFrameBuffer *target_buffer; /* next target to render to */ struct GPUTexture *final_tx; /* Final color to transform to display color space. */ - struct GPUFrameBuffer *final_fb; /* Framebuffer with final_tx as attachment. */ + struct GPUFrameBuffer *final_fb; /* Frame-buffer with final_tx as attachment. */ } EEVEE_EffectsInfo; /* ***************** COMMON DATA **************** */ @@ -1431,7 +1431,7 @@ static const float texcomat[4][4] = { {0.5f, 0.5f, 0.5f, 1.0f}, }; -/* Cubemap Matrices */ +/* Cube-map Matrices */ static const float cubefacemat[6][4][4] = { /* Pos X */ {{0.0f, 0.0f, -1.0f, 0.0f}, diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index bb974688404..72b12f6daeb 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl DRW_render_instance_buffer_finish(); /* Need to be called after DRW_render_instance_buffer_finish() */ - /* Also we weed to have a correct fbo bound for DRW_hair_update */ + /* Also we weed to have a correct FBO bound for DRW_hair_update */ GPU_framebuffer_bind(fbl->main_fb); DRW_hair_update(); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c index 52160248d75..9dec551e4b9 100644 --- a/source/blender/draw/engines/eevee/eevee_renderpasses.c +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -449,8 +449,8 @@ void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) (stl->g_data->render_passes & EEVEE_RENDERPASSES_LIGHT_PASS) : stl->g_data->render_passes; - bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) > 0; - bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && + bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) != 0; + bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) != 0 && DRW_state_is_opengl_render(); UNUSED_VARS(needs_color_transfer); diff --git a/source/blender/draw/engines/eevee/eevee_sampling.c b/source/blender/draw/engines/eevee/eevee_sampling.c index 253dae79902..aa11f072fa5 100644 --- a/source/blender/draw/engines/eevee/eevee_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_sampling.c @@ -69,11 +69,11 @@ void EEVEE_sample_rectangle(int sample_ofs, BLI_halton_2d(ht_primes, ht_offset, sample_ofs, ht_point); - /* Decorelate AA and shadow samples. (see T68594) */ + /* De-correlate AA and shadow samples. (see T68594) */ ht_point[0] = fmod(ht_point[0] * 1151.0, 1.0); ht_point[1] = fmod(ht_point[1] * 1069.0, 1.0); - /* Change ditribution center to be 0,0 */ + /* Change distribution center to be 0,0 */ ht_point[0] = (ht_point[0] > 0.5f) ? ht_point[0] - 1.0f : ht_point[0]; ht_point[1] = (ht_point[1] > 0.5f) ? ht_point[1] - 1.0f : ht_point[1]; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index ed7d53b51af..1465c9dd84c 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -106,7 +106,7 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) GPU_framebuffer_texture_attach(fbl->main_fb, effects->ssr_specrough_input, 2, 0); - /* Raytracing output */ + /* Ray-tracing output. */ effects->ssr_hit_output = DRW_texture_pool_query_2d( tracing_res[0], tracing_res[1], GPU_RG16I, &draw_engine_eevee_type); effects->ssr_pdf_output = DRW_texture_pool_query_2d( diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c index 7a277c18f01..82b2395cc6e 100644 --- a/source/blender/draw/engines/eevee/eevee_shaders.c +++ b/source/blender/draw/engines/eevee/eevee_shaders.c @@ -85,7 +85,7 @@ static struct { struct GPUShader *lookdev_background; struct GPUShader *update_noise_sh; - /* Downsample Depth */ + /* Down-sample Depth */ struct GPUShader *minz_downlevel_sh; struct GPUShader *maxz_downlevel_sh; struct GPUShader *minz_downdepth_sh; @@ -96,7 +96,7 @@ static struct { struct GPUShader *minz_copydepth_sh; struct GPUShader *maxz_copydepth_sh; - /* Simple Downsample */ + /* Simple Down-sample */ struct GPUShader *downsample_sh; struct GPUShader *downsample_cube_sh; @@ -258,7 +258,7 @@ static void eevee_shader_library_ensure(void) { if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); - /* NOTE: Theses needs to be ordered by dependencies. */ + /* NOTE: These need to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_math_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_math_geom_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); @@ -438,7 +438,7 @@ GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void) } /* -------------------------------------------------------------------- */ -/** \name Downsampling +/** \name Down-sampling * \{ */ GPUShader *EEVEE_shaders_effect_downsample_sh_get(void) diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c index fa5afd60235..e29830defff 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows.c +++ b/source/blender/draw/engines/eevee/eevee_shadows.c @@ -141,7 +141,7 @@ void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob) } if (ob->base_flag & BASE_FROM_DUPLI) { - /* Duplis will always refresh the shadowmaps as if they were deleted each frame. */ + /* Duplis will always refresh the shadow-maps as if they were deleted each frame. */ /* TODO(fclem): fix this. */ update = true; } @@ -259,7 +259,7 @@ void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) BoundSphere *bsphere = linfo->shadow_bounds; /* Search for deleted shadow casters or if shcaster WAS in shadow radius. */ for (int i = 0; i < backbuffer->count; i++) { - /* If the shadowcaster has been deleted or updated. */ + /* If the shadow-caster has been deleted or updated. */ if (BLI_BITMAP_TEST(backbuffer->update, i)) { for (int j = 0; j < linfo->cube_len; j++) { if (!BLI_BITMAP_TEST(&linfo->sh_cube_update[0], j)) { @@ -273,7 +273,7 @@ void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) /* Search for updates in current shadow casters. */ bbox = frontbuffer->bbox; for (int i = 0; i < frontbuffer->count; i++) { - /* If the shadowcaster has been updated. */ + /* If the shadow-caster has been updated. */ if (BLI_BITMAP_TEST(frontbuffer->update, i)) { for (int j = 0; j < linfo->cube_len; j++) { if (!BLI_BITMAP_TEST(&linfo->sh_cube_update[0], j)) { diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c index 246bc18b71a..6cb4b39fafa 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows_cascade.c +++ b/source/blender/draw/engines/eevee/eevee_shadows_cascade.c @@ -330,7 +330,7 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, DRW_debug_sphere(center, csm_render->radius[c], dbg_col); #endif - /* Project into lightspace */ + /* Project into light-space. */ mul_m4_v3(viewmat, center); /* Snap projection center to nearest texel to cancel shimmering. */ @@ -376,7 +376,7 @@ static void eevee_shadow_cascade_setup(EEVEE_LightsInfo *linfo, #endif } - /* Bias is in clipspace, divide by range. */ + /* Bias is in clip-space, divide by range. */ shdw_data->bias = csm_render->original_bias * 0.05f / fabsf(sh_far - sh_near); shdw_data->near = sh_near; shdw_data->far = sh_far; diff --git a/source/blender/draw/engines/eevee/eevee_shadows_cube.c b/source/blender/draw/engines/eevee/eevee_shadows_cube.c index 19b86476c29..89caa0dd193 100644 --- a/source/blender/draw/engines/eevee/eevee_shadows_cube.c +++ b/source/blender/draw/engines/eevee/eevee_shadows_cube.c @@ -142,7 +142,7 @@ static void eevee_ensure_cube_views( float winmat[4][4]; float side = near; - /* TODO shadowcube array. */ + /* TODO: shadow-cube array. */ if (true) { /* This half texel offset is used to ensure correct filtering between faces. */ /* FIXME: This exhibit float precision issue with lower cube_res. diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl index 312d9f63ce0..0aa54715460 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl @@ -60,7 +60,7 @@ vec2 sample_weights(float center_depth, float sample_motion_length, float offset_length) { - /* Clasify foreground/background. */ + /* Classify foreground/background. */ vec2 depth_weight = depth_compare(center_depth, sample_depth); /* Weight if sample is overlapping or under the center pixel. */ vec2 spread_weight = spread_compare(center_motion_length, sample_motion_length, offset_length); @@ -211,16 +211,16 @@ void main() float w = 1.0 / (50.0 * float(KERNEL) * 4.0); accum_bg += center_color * w; w_accum.x += w; - /* Note: In Jimenez's presentation, they used center sample. - * We use background color as it contains more informations for foreground + /* NOTE: In Jimenez's presentation, they used center sample. + * We use background color as it contains more information for foreground * elements that have not enough weights. - * Yield beter blur in complex motion. */ + * Yield better blur in complex motion. */ center_color = accum_bg / w_accum.x; #endif /* Merge background. */ accum += accum_bg; w_accum.y += w_accum.x; - /* Balance accumulation for failled samples. + /* Balance accumulation for failed samples. * We replace the missing foreground by the background. */ float blend_fac = saturate(1.0 - w_accum.y / w_accum.z); fragColor = (accum / w_accum.z) + center_color * blend_fac; diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index 5f14f590128..aebd1c3aef3 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -238,7 +238,7 @@ vec3 raycast(int index, #endif } - /* Discard backface hits. Only do this if the ray traveled enough to avoid loosing intricate + /* Discard backface hits. Only do this if the ray traveled enough to avoid losing intricate * contact reflections. This is only used for SSReflections. */ if (discard_backface && prev_delta < 0.0 && curr_time > 4.1) { hit = false; diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 1b331052a06..adb21540afb 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -108,7 +108,7 @@ static void external_engine_init(void *vedata) const DRWContextState *draw_ctx = DRW_context_state_get(); ARegion *region = draw_ctx->region; - /* Depth prepass */ + /* Depth pre-pass. */ if (!e_data.depth_sh) { const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[GPU_SHADER_CFG_DEFAULT]; diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index f2472699300..33b91efc848 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -365,7 +365,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd, DRW_shgroup_call_procedural_triangles(grp, NULL, 1); if (gpl->blend_mode == eGplBlendMode_HardLight) { - /* We cannot do custom blending on MultiTarget framebuffers. + /* We cannot do custom blending on Multi-Target frame-buffers. * Workaround by doing 2 passes. */ grp = DRW_shgroup_create(sh, tgp_layer->blend_ps); DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL); diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 153dcfb6ea7..e738b0d063c 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -214,6 +214,7 @@ void GPENCIL_cache_init(void *ved) NULL : false; pd->do_onion = show_onion && !hide_overlay && !playing; + pd->playing = playing; /* Save simplify flags (can change while drawing, so it's better to save). */ Scene *scene = draw_ctx->scene; pd->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, playing); @@ -241,6 +242,7 @@ void GPENCIL_cache_init(void *ved) pd->simplify_fill = false; pd->simplify_fx = false; pd->fade_layer_opacity = -1.0f; + pd->playing = false; } { @@ -279,7 +281,7 @@ void GPENCIL_cache_init(void *ved) }); } else { - /* Free uneeded buffers. */ + /* Free unneeded buffers. */ GPU_FRAMEBUFFER_FREE_SAFE(fbl->snapshot_fb); DRW_TEXTURE_FREE_SAFE(txl->snapshot_depth_tx); DRW_TEXTURE_FREE_SAFE(txl->snapshot_color_tx); @@ -331,7 +333,7 @@ void GPENCIL_cache_init(void *ved) pd->dof_params[0] = -focus_dist * pd->dof_params[1]; } else { - /* Disable DoF blur scalling. */ + /* Disable DoF blur scaling. */ pd->camera = NULL; } } @@ -344,7 +346,7 @@ typedef struct gpIterPopulateData { GPENCIL_PrivateData *pd; GPENCIL_MaterialPool *matpool; DRWShadingGroup *grp; - /* Last material UBO bound. Used to avoid uneeded buffer binding. */ + /* Last material UBO bound. Used to avoid unneeded buffer binding. */ GPUUniformBuf *ubo_mat; GPUUniformBuf *ubo_lights; /* Last texture bound. */ @@ -383,7 +385,7 @@ static void gpencil_drawcall_flush(gpIterPopulateData *iter) iter->vcount = 0; } -/* Group drawcalls that are consecutive and with the same type. Reduces GPU driver overhead. */ +/* Group draw-calls that are consecutive and with the same type. Reduces GPU driver overhead. */ static void gpencil_drawcall_add( gpIterPopulateData *iter, struct GPUBatch *geom, bool instancing, int v_first, int v_count) { @@ -397,7 +399,7 @@ static void gpencil_drawcall_add( #endif int last = iter->vfirst + iter->vcount; - /* Interupt drawcall grouping if the sequence is not consecutive. */ + /* Interrupt draw-call grouping if the sequence is not consecutive. */ if ((geom != iter->geom) || (v_first - last > 3)) { gpencil_drawcall_flush(iter); } @@ -617,6 +619,15 @@ void GPENCIL_cache_populate(void *ved, Object *ob) /* Special case for rendering onion skin. */ bGPdata *gpd = (bGPdata *)ob->data; bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS); + gpd->runtime.playing = (short)pd->playing; + + /* When render in background the active frame could not be properly set due thread priority + * better set again. This is not required in viewport. */ + if (txl->render_depth_tx) { + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + gpl->actframe = BKE_gpencil_layer_frame_get(gpl, pd->cfra, GP_GETFRAME_USE_PREV); + } + } /* When render in background the active frame could not be properly set due thread priority * better set again. This is not required in viewport. */ @@ -675,7 +686,7 @@ void GPENCIL_cache_finish(void *ved) /* Sort object by decreasing Z to avoid most of alpha ordering issues. */ gpencil_object_cache_sort(pd); - /* Create framebuffers only if needed. */ + /* Create frame-buffers only if needed. */ if (pd->tobjects.first) { eGPUTextureFormat format = pd->use_signed_fb ? GPU_RGBA16F : GPU_R11F_G11F_B10F; diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index d0bd56b42dd..5ceb909bc88 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -110,7 +110,7 @@ BLI_STATIC_ASSERT_ALIGN(gpLight, 16) typedef struct GPENCIL_MaterialPool { /* Linklist. */ struct GPENCIL_MaterialPool *next; - /* GPU representatin of materials. */ + /* GPU representation of materials. */ gpMaterial mat_data[GP_MATERIAL_BUFFER_LEN]; /* Matching ubo. */ struct GPUUniformBuf *ubo; @@ -122,7 +122,7 @@ typedef struct GPENCIL_MaterialPool { } GPENCIL_MaterialPool; typedef struct GPENCIL_LightPool { - /* GPU representatin of materials. */ + /* GPU representation of materials. */ gpLight light_data[GPENCIL_LIGHT_BUFFER_LEN]; /* Matching ubo. */ struct GPUUniformBuf *ubo; @@ -151,7 +151,7 @@ typedef struct GPENCIL_tVfx { /** Linklist */ struct GPENCIL_tVfx *next; DRWPass *vfx_ps; - /* Framebuffer reference since it may not be allocated yet. */ + /* Frame-buffer reference since it may not be allocated yet. */ GPUFrameBuffer **target_fb; } GPENCIL_tVfx; @@ -342,6 +342,8 @@ typedef struct GPENCIL_PrivateData { /* Display onion skinning */ bool do_onion; + /* Playing animation */ + bool playing; /* simplify settings */ bool simplify_fill; bool simplify_fx; @@ -350,7 +352,7 @@ typedef struct GPENCIL_PrivateData { bool use_lighting; /* Use physical lights or just ambient lighting. */ bool use_lights; - /* Do we need additional framebuffers? */ + /* Do we need additional frame-buffers? */ bool use_layer_fb; bool use_object_fb; bool use_mask_fb; diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 9ac9a4dc078..b597a786e86 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -47,7 +47,7 @@ void GPENCIL_render_init(GPENCIL_Data *vedata, const float *viewport_size = DRW_viewport_size_get(); const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]}; - /* Set the pers & view matrix. */ + /* Set the perspective & view matrix. */ float winmat[4][4], viewmat[4][4], viewinv[4][4]; struct Object *camera = DEG_get_evaluated_object(depsgraph, RE_GetCamera(engine->re)); diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index cb65fbd6ae7..0b66141e51a 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -235,7 +235,7 @@ static void gpencil_vfx_rim(RimShaderFxData *fx, Object *ob, gpIterVfxData *iter DRW_shgroup_call_procedural_triangles(grp, NULL, 1); if (fx->mode == eShaderFxRimMode_Overlay) { - /* We cannot do custom blending on MultiTarget framebuffers. + /* We cannot do custom blending on multi-target frame-buffers. * Workaround by doing 2 passes. */ grp = DRW_shgroup_create_sub(grp); DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL); @@ -363,7 +363,7 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData copy_v2_v2(wave_ofs, wave_dir); SWAP(float, wave_ofs[0], wave_ofs[1]); wave_ofs[1] *= -1.0f; - /* Keep world space scalling and aspect ratio. */ + /* Keep world space scaling and aspect ratio. */ mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor)); mul_v2_v2(wave_dir, vp_size); mul_v2_fl(wave_ofs, fx->amplitude * distance_factor); @@ -397,7 +397,7 @@ static void gpencil_vfx_shadow(ShadowShaderFxData *fx, Object *ob, gpIterVfxData unit_m4(uv_mat); zero_v2(wave_ofs); - /* We reseted the uv_mat so we need to accound for the rotation in the */ + /* We reset the uv_mat so we need to account for the rotation in the */ copy_v2_fl2(tmp, 0.0f, blur_size[1]); rotate_v2_v2fl(blur_dir, tmp, -fx->rotation); mul_v2_v2(blur_dir, vp_size_inv); @@ -515,7 +515,7 @@ static void gpencil_vfx_wave(WaveShaderFxData *fx, Object *ob, gpIterVfxData *it copy_v2_v2(wave_ofs, wave_dir); SWAP(float, wave_ofs[0], wave_ofs[1]); wave_ofs[1] *= -1.0f; - /* Keep world space scalling and aspect ratio. */ + /* Keep world space scaling and aspect ratio. */ mul_v2_fl(wave_dir, 1.0f / (max_ff(1e-8f, fx->period) * distance_factor)); mul_v2_v2(wave_dir, vp_size); mul_v2_fl(wave_ofs, fx->amplitude * distance_factor); @@ -647,7 +647,7 @@ void gpencil_vfx_cache_populate(GPENCIL_Data *vedata, Object *ob, GPENCIL_tObjec DRW_shgroup_uniform_int_copy(grp, "isFirstPass", true); DRW_shgroup_call_procedural_triangles(grp, NULL, 1); - /* We cannot do custom blending on MultiTarget framebuffers. + /* We cannot do custom blending on multi-target frame-buffers. * Workaround by doing 2 passes. */ grp = DRW_shgroup_create_sub(grp); DRW_shgroup_state_disable(grp, DRW_STATE_BLEND_MUL); diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 189ed91cbb4..3065d553dce 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -393,7 +393,7 @@ void stroke_vertex() is_squares = false; } - /* Enpoints, we discard the vertices. */ + /* Endpoints, we discard the vertices. */ if (ma1.x == -1 || (!is_dot && ma2.x == -1)) { discard_vert(); return; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl index 503248558ad..aedc8668387 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_vfx_frag.glsl @@ -274,7 +274,7 @@ uniform bool isFirstPass; vec2 compute_uvs(float x) { vec2 uv = uvcoordsvar.xy; - /* Tranform UV (loc, rot, scale) */ + /* Transform UV (loc, rot, scale) */ uv = uv.x * uvRotX + uv.y * uvRotY + uvOffset; uv += blurDir * x; /* Wave deform. */ diff --git a/source/blender/draw/engines/image/image_shader.c b/source/blender/draw/engines/image/image_shader.c index 7dc428de2ee..691c0d7029a 100644 --- a/source/blender/draw/engines/image/image_shader.c +++ b/source/blender/draw/engines/image/image_shader.c @@ -49,7 +49,7 @@ void IMAGE_shader_library_ensure(void) { if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); - /* NOTE: Theses needs to be ordered by dependencies. */ + /* NOTE: These need to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_view_lib); diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c index 229f9c5a88f..b263254696c 100644 --- a/source/blender/draw/engines/overlay/overlay_antialiasing.c +++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c @@ -80,7 +80,7 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) bool need_wire_expansion = (G_draw.block.sizePixel > 1.0f); pd->antialiasing.enabled = need_wire_expansion || - ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0); + ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0); GPUTexture *color_tex = NULL; GPUTexture *line_tex = NULL; @@ -93,7 +93,7 @@ void OVERLAY_antialiasing_init(OVERLAY_Data *vedata) line_tex = txl->overlay_line_tx; } else { - /* Just a copy of the defaults framebuffers. */ + /* Just a copy of the defaults frame-buffers. */ color_tex = dtxl->color_overlay; } @@ -127,7 +127,7 @@ void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata) if (pd->antialiasing.enabled) { /* `antialiasing.enabled` is also enabled for wire expansion. Check here if * anti aliasing is needed. */ - const bool do_smooth_lines = (U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0; + const bool do_smooth_lines = (U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0; DRW_PASS_CREATE(psl->antialiasing_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL); diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index cbd2589f20f..7042d095b56 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -1691,13 +1691,13 @@ static void draw_bone_degrees_of_freedom(ArmatureDrawContext *ctx, bPoseChannel unit_m4(posetrans); translate_m4(posetrans, pchan->pose_mat[3][0], pchan->pose_mat[3][1], pchan->pose_mat[3][2]); - /* in parent-bone pose space... */ + /* In parent-bone pose space... */ if (pchan->parent) { copy_m4_m4(tmp, pchan->parent->pose_mat); zero_v3(tmp[3]); mul_m4_m4m4(posetrans, posetrans, tmp); } - /* ... but own restspace */ + /* ... but own rest-space. */ mul_m4_m4m3(posetrans, posetrans, pchan->bone->bone_mat); float scale = pchan->bone->length * pchan->size[1]; diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index 38e171cb5e2..40a9dbe01c0 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -344,7 +344,7 @@ void OVERLAY_edit_mesh_draw(OVERLAY_Data *vedata) if (pd->edit_mesh.do_zbufclip) { DRW_draw_pass(psl->edit_mesh_depth_ps[IN_FRONT]); - /* render facefill */ + /* Render face-fill. */ DRW_view_set_active(pd->view_edit_faces); DRW_draw_pass(psl->edit_mesh_faces_ps[NOT_IN_FRONT]); diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c index 22433905b75..97dcf934c11 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.c +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -161,7 +161,7 @@ void OVERLAY_edit_uv_init(OVERLAY_Data *vedata) pd->edit_uv.do_tiled_image_border_overlay = is_image_type && is_tiled_image; pd->edit_uv.dash_length = 4.0f * UI_DPI_FAC; pd->edit_uv.line_style = edit_uv_line_style_from_space_image(sima); - pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) > 0); + pd->edit_uv.do_smooth_wire = ((U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0); pd->edit_uv.do_stencil_overlay = show_overlays && do_stencil_overlay; pd->edit_uv.draw_type = sima->dt_uvstretch; diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index 39f17581e0d..00429a19cf4 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -642,10 +642,10 @@ void OVERLAY_light_cache_populate(OVERLAY_Data *vedata, Object *ob) } instdata; copy_m4_m4(instdata.mat, ob->obmat); - /* FIXME / TODO: clipend has no meaning nowadays. - * In EEVEE, Only clipsta is used shadowmaping. + /* FIXME / TODO: clip_end has no meaning nowadays. + * In EEVEE, Only clip_sta is used shadow-mapping. * Clip end is computed automatically based on light power. - * For now, always use the custom distance as clipend. */ + * For now, always use the custom distance as clip_end. */ instdata.clip_end = la->att_dist; instdata.clip_sta = la->clipsta; @@ -1176,7 +1176,7 @@ void OVERLAY_camera_cache_populate(OVERLAY_Data *vedata, Object *ob) invert_v3(scale); for (int i = 0; i < 4; i++) { mul_v3_v3(vec[i], scale); - /* Project to z=-1 plane. Makes positionning / scaling easier. (see shader) */ + /* Project to z=-1 plane. Makes positioning / scaling easier. (see shader) */ mul_v2_fl(vec[i], 1.0f / fabsf(vec[i][2])); } diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c index 7f9290a6c3a..19af3ae7e5d 100644 --- a/source/blender/draw/engines/overlay/overlay_gpencil.c +++ b/source/blender/draw/engines/overlay/overlay_gpencil.c @@ -258,6 +258,16 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) copy_m4_m4(mat, ob->obmat); + /* Rotate and scale except align to cursor. */ + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + if (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR) { + float matrot[3][3]; + copy_m3_m4(matrot, gpl->layer_mat); + mul_m4_m4m3(mat, mat, matrot); + } + } + float viewinv[4][4]; /* Set the grid in the selected axis */ switch (ts->gp_sculpt.lock_axis) { @@ -294,6 +304,11 @@ void OVERLAY_gpencil_cache_init(OVERLAY_Data *vedata) mul_v2_v2fl(size, gpd->grid.scale, 2.0f * ED_scene_grid_scale(scene, &grid_unit)); rescale_m4(mat, (float[3]){size[0], size[1], 0.0f}); + /* Apply layer loc transform, except cursor mode. */ + if ((gpl != NULL) && (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + add_v3_v3(mat[3], gpl->layer_mat[3]); + } + const int gridlines = (gpd->grid.lines <= 0) ? 1 : gpd->grid.lines; int line_ct = gridlines * 4 + 2; diff --git a/source/blender/draw/engines/overlay/overlay_metaball.c b/source/blender/draw/engines/overlay/overlay_metaball.c index f973c1eda8a..46076a7c88b 100644 --- a/source/blender/draw/engines/overlay/overlay_metaball.c +++ b/source/blender/draw/engines/overlay/overlay_metaball.c @@ -63,7 +63,7 @@ static void metaball_instance_data_set( mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f); mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f); mul_v3_m4v3(data->mat[3], ob->obmat, pos); - /* WATCH: Reminder, alpha is wiresize. */ + /* WATCH: Reminder, alpha is wire-size. */ OVERLAY_bone_instance_data_set_color(data, color); } diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c index fa95bad4d86..71064e7ff47 100644 --- a/source/blender/draw/engines/overlay/overlay_particle.c +++ b/source/blender/draw/engines/overlay/overlay_particle.c @@ -185,7 +185,7 @@ void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob) /* TODO(fclem): Here would be a good place for preemptive culling. */ - /* fclem: Is color even usefull in our modern context? */ + /* NOTE(fclem): Is color even useful in our modern context? */ Material *ma = BKE_object_material_get(ob, part->omat); float color[4] = {0.6f, 0.6f, 0.6f, part->draw_size}; if (ma != NULL) { diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c index 88f4e28c039..6b07547bf96 100644 --- a/source/blender/draw/engines/overlay/overlay_shader.c +++ b/source/blender/draw/engines/overlay/overlay_shader.c @@ -238,7 +238,7 @@ void OVERLAY_shader_library_ensure(void) { if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); - /* NOTE: Theses needs to be ordered by dependencies. */ + /* NOTE: These need to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_globals_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_overlay_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_colormanagement_lib); diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl index 2989e07691f..f24aee56bb2 100644 --- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl +++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl @@ -146,7 +146,7 @@ void main() vec4 lines = vec4(neightbor_line0.z, neightbor_line1.z, neightbor_line2.z, neightbor_line3.z); /* Count number of line neighbors. */ float blend = dot(vec4(0.25), step(0.001, lines)); - /* Only do blend if there is more than 2 neighbor. This avoid loosing too much AA. */ + /* Only do blend if there are more than 2 neighbors. This avoids losing too much AA. */ blend = clamp(blend * 2.0 - 1.0, 0.0, 1.0); fragColor = mix(fragColor, fragColor / fragColor.a, blend); } diff --git a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl index 89bc0bcf522..74854dc0f8d 100644 --- a/source/blender/draw/engines/overlay/shaders/extra_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/extra_vert.glsl @@ -222,7 +222,7 @@ void main() edgePos = edgeStart = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy; #ifdef SELECT_EDGES - /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the + /* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the * wire to at least create one fragment that will pass the occlusion query. */ /* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */ gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0); diff --git a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl index 8a80441b5d9..91f45329018 100644 --- a/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/extra_wire_vert.glsl @@ -18,7 +18,7 @@ void main() gl_Position = point_world_to_ndc(world_pos); #ifdef SELECT_EDGES - /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the + /* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the * wire to at least create one fragment that will pass the occlusion query. */ /* TODO(fclem): Limit this workaround to selection. It's not very noticeable but still... */ gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0); diff --git a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl index c80d8f99628..c083fdacbbe 100644 --- a/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl @@ -169,7 +169,7 @@ void main() } #ifdef SELECT_EDGES - /* HACK: to avoid loosing sub pixel object in selections, we add a bit of randomness to the + /* HACK: to avoid losing sub-pixel object in selections, we add a bit of randomness to the * wire to at least create one fragment that will pass the occlusion query. */ gl_Position.xy += sizeViewportInv.xy * gl_Position.w * ((gl_VertexID % 2 == 0) ? -1.0 : 1.0); #endif diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index eaa553a10de..9bd49bb84f8 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -288,7 +288,7 @@ void main() ls_ray_dir -= ls_ray_ori; - /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ + /* TODO: Align rays to volume center so that it mimics old behavior of slicing the volume. */ float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir); if (dist > 0.0) { diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c index 20c30d9ce68..feb48b2623d 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c +++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c @@ -75,7 +75,7 @@ static void workbench_taa_jitter_init_order(float (*table)[2], int num) swap_v2_v2(table[0], table[closest_index]); } - /* sort list based on furtest distance with previous */ + /* Sort list based on farthest distance with previous. */ for (int i = 0; i < num - 2; i++) { float f_squared_dist = 0.0; int f_index = i; diff --git a/source/blender/draw/engines/workbench/workbench_effect_dof.c b/source/blender/draw/engines/workbench/workbench_effect_dof.c index 73cd501190f..a00453fe125 100644 --- a/source/blender/draw/engines/workbench/workbench_effect_dof.c +++ b/source/blender/draw/engines/workbench/workbench_effect_dof.c @@ -104,7 +104,7 @@ static void workbench_dof_setup_samples(struct GPUUniformBuf **ubo, square_to_circle(x, y, &r, &T); samp[2] = r; - /* Bokeh shape parametrisation */ + /* Bokeh shape parameterization. */ if (bokeh_sides > 1.0f) { float denom = T - (2.0 * M_PI / bokeh_sides) * floorf((bokeh_sides * T + M_PI) / (2.0 * M_PI)); diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 6aa794bda51..6e9118bfe46 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -76,7 +76,7 @@ void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd, alpha *= mat->a; copy_v3_v3(data->base_color, &mat->r); metallic = mat->metallic; - roughness = sqrtf(mat->roughness); /* Remap to disney roughness. */ + roughness = sqrtf(mat->roughness); /* Remap to Disney roughness. */ } else { copy_v3_fl(data->base_color, 0.8f); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index d157c260fbd..522aae7f542 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -225,7 +225,7 @@ BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_Material, 16) typedef struct WORKBENCH_Prepass { /** Hash storing shading group for each Material or GPUTexture to reduce state changes. */ struct GHash *material_hash; - /** First common (non-vcol and non-image colored) shading group to created subgroups. */ + /** First common (non-vertex-color and non-image-colored) shading group to created subgroups. */ struct DRWShadingGroup *common_shgrp; /** First Vertex Color shading group to created subgroups. */ struct DRWShadingGroup *vcol_shgrp; @@ -384,7 +384,7 @@ typedef struct WORKBENCH_ViewLayerData { struct GPUUniformBuf *cavity_sample_ubo; /** Blue noise texture used to randomize the sampling of some effects.*/ struct GPUTexture *cavity_jitter_tx; - /** Materials ubos allocated in a memblock for easy bookeeping. */ + /** Materials UBO's allocated in a memblock for easy bookkeeping. */ struct BLI_memblock *material_ubo; struct BLI_memblock *material_ubo_data; /** Number of samples for which cavity_sample_ubo is valid. */ diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c index 1c612404c95..ad610a6a885 100644 --- a/source/blender/draw/engines/workbench/workbench_shader.c +++ b/source/blender/draw/engines/workbench/workbench_shader.c @@ -120,7 +120,7 @@ void workbench_shader_library_ensure(void) { if (e_data.lib == NULL) { e_data.lib = DRW_shader_library_create(); - /* NOTE: Theses needs to be ordered by dependencies. */ + /* NOTE: These need to be ordered by dependencies. */ DRW_SHADER_LIB_ADD(e_data.lib, common_math_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_math_geom_lib); DRW_SHADER_LIB_ADD(e_data.lib, common_hair_lib); diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c index 881c186e3e5..99d945c311e 100644 --- a/source/blender/draw/engines/workbench/workbench_shadow.c +++ b/source/blender/draw/engines/workbench/workbench_shadow.c @@ -157,7 +157,7 @@ void workbench_shadow_cache_init(WORKBENCH_Data *data) DRWState state = DRW_STATE_DEPTH_LESS | DRW_STATE_STENCIL_ALWAYS; #endif - /* TODO(fclem): Merge into one pass with subpasses. */ + /* TODO(fclem): Merge into one pass with sub-passes. */ DRW_PASS_CREATE(psl->shadow_ps[0], state | depth_pass_state); DRW_PASS_CREATE(psl->shadow_ps[1], state | depth_fail_state); diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h index 4a43107c612..2545cfa65dc 100644 --- a/source/blender/draw/intern/DRW_render.h +++ b/source/blender/draw/intern/DRW_render.h @@ -93,7 +93,7 @@ typedef char DRWViewportEmptyList; #define DRW_VIEWPORT_LIST_SIZE(list) \ (sizeof(list) == sizeof(DRWViewportEmptyList) ? 0 : ((sizeof(list)) / sizeof(void *))) -/* Unused members must be either pass list or 'char *' when not usd. */ +/* Unused members must be either pass list or 'char *' when not used. */ #define DRW_VIEWPORT_DATA_SIZE(ty) \ { \ DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->fbl)), DRW_VIEWPORT_LIST_SIZE(*(((ty *)NULL)->txl)), \ @@ -327,14 +327,14 @@ typedef enum { /** Culling test */ DRW_STATE_CULL_BACK = (1 << 7), DRW_STATE_CULL_FRONT = (1 << 8), - /** Stencil test . These options are mutal exclusive and packed into 2 bits*/ + /** Stencil test . These options are mutually exclusive and packed into 2 bits. */ DRW_STATE_STENCIL_ALWAYS = (1 << 9), DRW_STATE_STENCIL_EQUAL = (2 << 9), DRW_STATE_STENCIL_NEQUAL = (3 << 9), /** Blend state. These options are mutual exclusive and packed into 4 bits */ DRW_STATE_BLEND_ADD = (1 << 11), - /** Same as additive but let alpha accumulate without premult. */ + /** Same as additive but let alpha accumulate without pre-multiply. */ DRW_STATE_BLEND_ADD_FULL = (2 << 11), /** Standard alpha blending. */ DRW_STATE_BLEND_ALPHA = (3 << 11), diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 5333f59bf38..fcd626eb92b 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -1325,7 +1325,7 @@ GPUBatch *DRW_cache_field_vortex_get(void) #undef SPIRAL_RESOL } -/* Screenaligned circle. */ +/* Screen-aligned circle. */ GPUBatch *DRW_cache_field_curve_get(void) { #define CIRCLE_RESOL 32 @@ -1414,7 +1414,7 @@ GPUBatch *DRW_cache_field_cone_limit_get(void) #undef CIRCLE_RESOL } -/* Screenaligned dashed circle */ +/* Screen-aligned dashed circle */ GPUBatch *DRW_cache_field_sphere_limit_get(void) { #define CIRCLE_RESOL 32 @@ -3385,7 +3385,7 @@ GPUBatch *DRW_cache_particles_get_prim(int type) int v = 0; int flag = VCLASS_EMPTY_AXES; - /* Set minimum to 0.001f so we can easilly normalize to get the color. */ + /* Set minimum to 0.001f so we can easily normalize to get the color. */ GPU_vertbuf_vert_set(vbo, v++, &(Vert){{0.0f, 0.0001f, 0.0f}, flag}); GPU_vertbuf_vert_set(vbo, v++, &(Vert){{0.0f, 2.0f, 0.0f}, flag}); GPU_vertbuf_vert_set(vbo, v++, &(Vert){{0.0001f, 0.0f, 0.0f}, flag}); diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 9fd7ffd4692..c15c246992d 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -239,7 +239,7 @@ typedef struct DRWVolumeGrid { float texture_to_object[4][4]; float object_to_texture[4][4]; - /* Transfrom from bounds to texture space. */ + /* Transform from bounds to texture space. */ float object_to_bounds[4][4]; float bounds_to_texture[4][4]; } DRWVolumeGrid; diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 9e2ac26f9f0..d9fbb01789f 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -907,7 +907,7 @@ static void extract_tris_finish(const MeshRenderData *mr, if (mr->use_final_mesh && cache->final.tris_per_mat) { MeshBufferCache *mbc = &cache->final; for (int i = 0; i < mr->mat_len; i++) { - /* Theses IBOs have not been queried yet but we create them just in case they are needed + /* These IBOs have not been queried yet but we create them just in case they are needed * later since they are not tracked by mesh_buffer_cache_create_requested(). */ if (mbc->tris_per_mat[i] == NULL) { mbc->tris_per_mat[i] = GPU_indexbuf_calloc(); @@ -1380,7 +1380,7 @@ static void extract_lines_paint_mask_iter_poly_mesh(const MeshRenderData *mr, } } else { - /* Set theses unselected loop only if this edge has no other selected loop. */ + /* Set these unselected loop only if this edge has no other selected loop. */ if (!BLI_BITMAP_TEST(data->select_map, e_index)) { GPU_indexbuf_set_line_verts(&data->elb, e_index, ml_index, ml_index_other); } @@ -5230,7 +5230,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, } } - /* It's really unlikely that all verts will be roots. Resize to avoid loosing VRAM. */ + /* It's really unlikely that all verts will be roots. Resize to avoid losing VRAM. */ GPU_vertbuf_data_len_set(vbo, root_len); return NULL; diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 72f3e7b0fa8..d606f70db9e 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -774,7 +774,7 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb, } } -/* Edge detection/adjecency */ +/* Edge detection/adjacency. */ #define NO_EDGE INT_MAX static void set_edge_adjacency_lines_indices( EdgeHash *eh, GPUIndexBufBuilder *elb, bool *r_is_manifold, uint v1, uint v2, uint v3) diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index e1523db36c7..8feacf8b026 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -800,20 +800,20 @@ static void gpencil_edit_curve_stroke_iter_cb(bGPDlayer *gpl, }; /* First segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[0]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[0]); vert_ptr->data = vflag[0]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; /* Second segment. */ - copy_v3_v3(vert_ptr->pos, bezt->vec[1]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[1]); vert_ptr->data = vflag[1]; vert_ptr++; - copy_v3_v3(vert_ptr->pos, bezt->vec[2]); + mul_v3_m4v3(vert_ptr->pos, gpl->layer_mat, bezt->vec[2]); vert_ptr->data = vflag[2]; vert_ptr++; } diff --git a/source/blender/draw/intern/draw_cache_impl_hair.c b/source/blender/draw/intern/draw_cache_impl_hair.c index 327a92a997e..fd28ac00186 100644 --- a/source/blender/draw/intern/draw_cache_impl_hair.c +++ b/source/blender/draw/intern/draw_cache_impl_hair.c @@ -318,7 +318,7 @@ bool hair_ensure_procedural_data(Object *object, HairBatchCache *cache = hair_batch_cache_get(hair); *r_hair_cache = &cache->hair; - const int steps = 2; /* TODO: don't hardcode? */ + const int steps = 2; /* TODO: don't hard-code? */ (*r_hair_cache)->final[subdiv].strands_res = 1 << (steps + subdiv); /* Refreshed on combing and simulation. */ diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 3f014a01680..1a1caa2943a 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -405,7 +405,7 @@ static void drw_mesh_weight_state_extract(Object *ob, &wstate->defgroup_sel_count); } } - /* With only one selected bone Multipaint reverts to regular mode. */ + /* With only one selected bone Multi-paint reverts to regular mode. */ else { wstate->defgroup_sel_count = 0; MEM_SAFE_FREE(wstate->defgroup_sel); diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 5029e71cac8..fef8ba4b606 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -161,7 +161,7 @@ void DRW_globals_update(void) /* Grid */ UI_GetThemeColorShade4fv(TH_GRID, 10, gb->colorGrid); - /* emphasise division lines lighter instead of darker, if background is darker than grid */ + /* Emphasize division lines lighter instead of darker, if background is darker than grid. */ UI_GetThemeColorShade4fv( TH_GRID, (gb->colorGrid[0] + gb->colorGrid[1] + gb->colorGrid[2] + 0.12f > @@ -333,7 +333,7 @@ int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color theme_id = TH_EMPTY; break; case OB_LIGHTPROBE: - /* TODO add lightprobe color */ + /* TODO: add light-probe color. */ theme_id = TH_EMPTY; break; default: diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c index 86f1b0e0ebb..bca227a24e2 100644 --- a/source/blender/draw/intern/draw_hair.c +++ b/source/blender/draw/intern/draw_hair.c @@ -320,7 +320,7 @@ void DRW_hair_update(void) max_size = max_ii(max_size, pr_call->vert_len); } - /* Create target Texture / Framebuffer */ + /* Create target Texture / Frame-buffer */ /* Don't use max size as it can be really heavy and fail. * Do chunks of maximum 2048 * 2048 hair points. */ int width = 2048; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index bc41eab9e22..fd31a11b0a8 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1570,13 +1570,13 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, drw_engines_enable(view_layer, engine_type, gpencil_engine_needed); drw_engines_data_validate(); - /* Update ubos */ + /* Update UBO's */ DRW_globals_update(); drw_debug_init(); DRW_hair_init(); - /* No framebuffer allowed before drawing. */ + /* No frame-buffer allowed before drawing. */ BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); /* Init engines */ @@ -1642,7 +1642,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, DRW_draw_callbacks_post_scene(); if (WM_draw_region_get_bound_viewport(region)) { - /* Don't unbind the framebuffer yet in this case and let + /* Don't unbind the frame-buffer yet in this case and let * GPU_viewport_unbind do it, so that we can still do further * drawing of action zones on top. */ } @@ -1706,7 +1706,7 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, if (draw_background) { /* HACK(fclem): In this case we need to make sure the final alpha is 1. * We use the blend mode to ensure that. A better way to fix that would - * be to do that in the colormanagmeent shader. */ + * be to do that in the color-management shader. */ GPU_offscreen_bind(ofs, false); GPU_clear_color(0.0f, 0.0f, 0.0f, 1.0f); /* Premult Alpha over black background. */ @@ -2088,12 +2088,12 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, drw_engines_enable_editors(); drw_engines_data_validate(); - /* Update ubos */ + /* Update UBO's */ DRW_globals_update(); drw_debug_init(); - /* No framebuffer allowed before drawing. */ + /* No frame-buffer allowed before drawing. */ BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); GPU_framebuffer_bind(DST.default_framebuffer); GPU_framebuffer_clear_depth_stencil(DST.default_framebuffer, 1.0f, 0xFF); @@ -2191,7 +2191,7 @@ void DRW_draw_render_loop_2d_ex(struct Depsgraph *depsgraph, GPU_depth_test(GPU_DEPTH_LESS_EQUAL); if (WM_draw_region_get_bound_viewport(region)) { - /* Don't unbind the framebuffer yet in this case and let + /* Don't unbind the frame-buffer yet in this case and let * GPU_viewport_unbind do it, so that we can still do further * drawing of action zones on top. */ } @@ -2373,7 +2373,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, drw_context_state_init(); drw_viewport_var_init(); - /* Update ubos */ + /* Update UBO's */ DRW_globals_update(); /* Init engines */ @@ -2445,7 +2445,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, DRW_render_instance_buffer_finish(); } - /* Setup framebuffer */ + /* Setup frame-buffer. */ draw_select_framebuffer_depth_only_setup(viewport_size); GPU_framebuffer_bind(g_select_buffer.framebuffer_depth_only); GPU_framebuffer_clear_depth(g_select_buffer.framebuffer_depth_only, 1.0f); @@ -2489,11 +2489,11 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, /** * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). */ -static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, - ARegion *region, - View3D *v3d, - GPUViewport *viewport, - const bool use_opengl_context) +static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, + ARegion *region, + View3D *v3d, + GPUViewport *viewport, + const bool use_opengl_context) { Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); @@ -2521,7 +2521,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, drw_task_graph_init(); drw_engines_data_validate(); - /* Setup framebuffer */ + /* Setup frame-buffer. */ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get( DST.viewport); GPU_framebuffer_bind(fbl->depth_only_fb); @@ -2531,7 +2531,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, drw_context_state_init(); drw_viewport_var_init(); - /* Update ubos */ + /* Update UBO's */ DRW_globals_update(); /* Init engines */ @@ -2587,7 +2587,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph, drw_state_ensure_not_reused(&DST); #endif - /* Changin context */ + /* Changing context. */ if (use_opengl_context) { DRW_opengl_context_disable(); } @@ -2616,7 +2616,7 @@ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, } } - drw_draw_depth_loop_imp(depsgraph, region, v3d, viewport, use_opengl_context); + drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, use_opengl_context); } /** @@ -2632,7 +2632,7 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, use_drw_engine(&draw_engine_gpencil_type); - drw_draw_depth_loop_imp(depsgraph, region, v3d, viewport, true); + drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, true); } void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, const rcti *rect) @@ -2671,7 +2671,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons DST.viewport = viewport; drw_viewport_var_init(); - /* Update ubos */ + /* Update UBO's */ DRW_globals_update(); /* Init Select Engine */ @@ -2728,7 +2728,7 @@ void DRW_draw_depth_object( GPU_matrix_set(rv3d->viewmat); GPU_matrix_mul(object->obmat); - /* Setup framebuffer */ + /* Setup frame-buffer. */ DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); GPU_framebuffer_bind(fbl->depth_only_fb); diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 3ab60bc3c96..f540ff09032 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -266,14 +266,14 @@ typedef union DRWCommand { DRWCommandClear clear; } DRWCommand; -/* Used for agregating calls into GPUVertBufs. */ +/** Used for aggregating calls into #GPUVertBuf's. */ struct DRWCallBuffer { GPUVertBuf *buf; GPUVertBuf *buf_select; int count; }; -/* Used by DRWUniform.type */ +/** Used by #DRWUniform.type */ typedef enum { DRW_UNIFORM_INT = 0, DRW_UNIFORM_INT_COPY, @@ -324,8 +324,8 @@ struct DRWUniform { /* DRW_UNIFORM_BLOCK_OBATTRS */ struct GPUUniformAttrList *uniform_attrs; }; - int location; /* Uniform location or binding point for textures and ubos. */ - uint8_t type; /* DRWUniformType */ + int location; /* Uniform location or binding point for textures and UBO's. */ + uint8_t type; /* #DRWUniformType */ uint8_t length; /* Length of vector types. */ uint8_t arraysize; /* Array size of scalar/vector types. */ }; diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 57b3373932e..6bdc5305fed 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -978,7 +978,7 @@ static void drw_sculpt_get_frustum_planes(Object *ob, float planes[6][4]) static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd) { - /* PBVH should always exist for non-empty meshes, created by depsgrah eval. */ + /* PBVH should always exist for non-empty meshes, created by depsgraph eval. */ PBVH *pbvh = (scd->ob->sculpt) ? scd->ob->sculpt->pbvh : NULL; if (!pbvh) { return; @@ -1601,10 +1601,10 @@ static void draw_frustum_bound_sphere_calc(const BoundBox *bbox, /* Detect which of the corner of the far clipping plane is the farthest to the origin */ float nfar[4]; /* most extreme far point in NDC space */ - float farxy[2]; /* farpoint projection onto the near plane */ + float farxy[2]; /* far-point projection onto the near plane */ float farpoint[3] = {0.0f}; /* most extreme far point in camera coordinate */ float nearpoint[3]; /* most extreme near point in camera coordinate */ - float farcenter[3] = {0.0f}; /* center of far cliping plane in camera coordinate */ + float farcenter[3] = {0.0f}; /* center of far clipping plane in camera coordinate */ float F = -1.0f, N; /* square distance of far and near point to origin */ float f, n; /* distance of far and near point to z axis. f is always > 0 but n can be < 0 */ float e, s; /* far and near clipping distance (<0) */ diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 5f7aa28c3c9..4c8fcb0e016 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -272,7 +272,7 @@ static void drw_stencil_state_set(uint write_mask, uint reference, uint compare_ GPU_stencil_compare_mask_set(compare_mask); } -/* Reset state to not interfer with other UI drawcall */ +/* Reset state to not interfere with other UI draw-call. */ void DRW_state_reset_ex(DRWState state) { DST.state = ~state; @@ -344,7 +344,7 @@ void DRW_state_reset(void) /* Should stay constant during the whole rendering. */ GPU_point_size(5); GPU_line_smooth(false); - /* Bypass U.pixelsize factor by using a factor of 0.0f. Will be clamped to 1.0f. */ + /* Bypass #U.pixelsize factor by using a factor of 0.0f. Will be clamped to 1.0f. */ GPU_line_width(0.0f); } @@ -855,7 +855,7 @@ static void draw_call_batching_do(DRWShadingGroup *shgroup, DRWCommandsState *state, DRWCommandDraw *call) { - /* If any condition requires to interupt the merging. */ + /* If any condition requires to interrupt the merging. */ bool neg_scale = DRW_handle_negative_scale_get(&call->handle); int chunk = DRW_handle_chunk_get(&call->handle); int id = DRW_handle_id_get(&call->handle); diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c index 8b948e62cf3..e9432f370b8 100644 --- a/source/blender/draw/intern/draw_manager_texture.c +++ b/source/blender/draw/intern/draw_manager_texture.c @@ -26,7 +26,7 @@ /* Maybe gpu_texture.c is a better place for this. */ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format) { - /* Some formats do not work with framebuffers. */ + /* Some formats do not work with frame-buffers. */ switch (format) { /* Only add formats that are COMPATIBLE with FB. * Generally they are multiple of 16bit. */ diff --git a/source/blender/draw/intern/shaders/common_fxaa_lib.glsl b/source/blender/draw/intern/shaders/common_fxaa_lib.glsl index a87b4558227..0ecfc397e95 100644 --- a/source/blender/draw/intern/shaders/common_fxaa_lib.glsl +++ b/source/blender/draw/intern/shaders/common_fxaa_lib.glsl @@ -1,7 +1,7 @@ /* --------------------------------------------------------------------------------- * File: es3-kepler\FXAA/FXAA3_11.h * SDK Version: v3.00 - * Email: gameworks@nvidia.com + * Email: <gameworks@nvidia.com> * Site: http://developer.nvidia.com/ * * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. diff --git a/source/blender/draw/intern/shaders/common_smaa_lib.glsl b/source/blender/draw/intern/shaders/common_smaa_lib.glsl index 78a62c6ae7d..36ffb4d8b32 100644 --- a/source/blender/draw/intern/shaders/common_smaa_lib.glsl +++ b/source/blender/draw/intern/shaders/common_smaa_lib.glsl @@ -118,7 +118,7 @@ * half-rate linear filtering on GCN. * * If SMAA is applied to 64-bit color buffers, switching to point filtering - * when accesing them will increase the performance. Search for + * when accessing them will increase the performance. Search for * 'SMAASamplePoint' to see which textures may benefit from point * filtering, and where (which is basically the color input in the edge * detection and resolve passes). diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 05cbb3ef48f..24bb58535a5 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -133,7 +133,16 @@ static void acf_generic_root_backdrop(bAnimContext *ac, UI_draw_roundbox_corner_set((expanded) ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* get backdrop color for data expanders under top-level Scene/Object */ @@ -421,7 +430,7 @@ static bool acf_generic_dataexpand_setting_valid(bAnimContext *ac, case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); - /* select is ok for most "ds*" channels (e.g. dsmat) */ + /* Select is ok for most `ds*` channels (e.g. `dsmat`) */ case ACHANNEL_SETTING_SELECT: return true; @@ -464,7 +473,16 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi */ UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); UI_draw_roundbox_3fv_alpha( - true, 0, yminc - 2, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = 0, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc - 2, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* name for summary entries */ @@ -875,7 +893,16 @@ static void acf_group_backdrop(bAnimContext *ac, bAnimListElem *ale, float yminc /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 8, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 8, + color, + 1.0f); } /* name for group entries */ @@ -1149,7 +1176,16 @@ static void acf_nla_controls_backdrop(bAnimContext *ac, /* rounded corners on LHS only - top only when expanded, but bottom too when collapsed */ UI_draw_roundbox_corner_set(expanded ? UI_CNR_TOP_LEFT : (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT)); UI_draw_roundbox_3fv_alpha( - true, offset, yminc, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymaxc, 5, color, 1.0f); + &(const rctf){ + .xmin = offset, + .xmax = v2d->cur.xmax + EXTRA_SCROLL_PAD, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 5, + color, + 1.0f); } /* name for nla controls expander entries */ @@ -3936,13 +3972,16 @@ static void acf_nlaaction_backdrop(bAnimContext *ac, bAnimListElem *ale, float y /* draw slightly shifted up vertically to look like it has more separation from other channels, * but we then need to slightly shorten it so that it doesn't look like it overlaps */ - UI_draw_roundbox_4fv(true, - offset, - yminc + NLACHANNEL_SKIP, - (float)v2d->cur.xmax, - ymaxc + NLACHANNEL_SKIP - 1, - 8, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = offset, + .xmax = (float)v2d->cur.xmax, + .ymin = yminc + NLACHANNEL_SKIP, + .ymax = ymaxc + NLACHANNEL_SKIP - 1, + }, + true, + 8, + color); } /* name for nla action entries */ @@ -4710,7 +4749,7 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, adt, &anim_eval_context, false); + &nla_cache, &id_ptr, adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP); @@ -4766,7 +4805,7 @@ static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, voi const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph, (float)CFRA); NlaKeyframingContext *nla_context = BKE_animsys_get_nla_keyframing_context( - &nla_cache, &id_ptr, key->adt, &anim_eval_context, false); + &nla_cache, &id_ptr, key->adt, &anim_eval_context); /* get current frame and apply NLA-mapping to it (if applicable) */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index a6e96a4d919..109cf79c786 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -393,7 +393,11 @@ static void anim_channels_select_set(bAnimContext *ac, FCurve *fcu = (FCurve *)ale->data; ACHANNEL_SET_FLAG(fcu, sel, FCURVE_SELECTED); - fcu->flag &= ~FCURVE_ACTIVE; + if ((fcu->flag & FCURVE_SELECTED) == 0) { + /* Only erase the ACTIVE flag when deselecting. This ensures that "select all curves" + * retains the currently active curve. */ + fcu->flag &= ~FCURVE_ACTIVE; + } break; } case ANIMTYPE_SHAPEKEY: { @@ -1197,7 +1201,7 @@ static void rearrange_nla_channels(bAnimContext *ac, AnimData *adt, eRearrangeAn rearrange_animchannel_islands( &adt->nla_tracks, rearrange_func, mode, ANIMTYPE_NLATRACK, &anim_data_visible); - /* Add back non-local NLA tracks at the begining of the animation data's list. */ + /* Add back non-local NLA tracks at the beginning of the animation data's list. */ if (!BLI_listbase_is_empty(&extracted_nonlocal_nla_tracks)) { BLI_assert(is_liboverride); ((NlaTrack *)extracted_nonlocal_nla_tracks.last)->next = adt->nla_tracks.first; @@ -1732,7 +1736,7 @@ static int animchannels_group_exec(bContext *C, wmOperator *op) /* free temp data */ ANIM_animdata_freelist(&anim_data); - /* updatss */ + /* Updates. */ WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); } diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index f2022194ed5..a03f19d0111 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2403,6 +2403,13 @@ static void animfilter_modifier_idpoin_cb(void *afm_ptr, } break; } + case ID_NT: { + bNodeTree *node_tree = (bNodeTree *)id; + if (!(afm->ads->filterflag & ADS_FILTER_NONTREE)) { + afm->items += animdata_filter_ds_nodetree( + afm->ac, &afm->tmp_data, afm->ads, owner_id, node_tree, afm->filter_mode); + } + } /* TODO: images? */ default: diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 088ac9dbcba..aac2465d43a 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -331,7 +331,7 @@ static void motionpath_calculate_update_range(MPathTarget *mpt, int fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, current_frame); int fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, current_frame); - /* Extend range furher, since accelleration compensation propagates even further away. */ + /* Extend range further, since acceleration compensation propagates even further away. */ if (fcu->auto_smoothing != FCURVE_SMOOTH_NONE) { fcu_sfra = motionpath_get_prev_prev_keyframe(mpt, &fcu_keys, fcu_sfra); fcu_efra = motionpath_get_next_next_keyframe(mpt, &fcu_keys, fcu_efra); diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index a5514f6517e..72d9bff545a 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -29,12 +29,10 @@ #include "BLI_math_base.h" #include "BLI_utildefines.h" -#include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -50,10 +48,8 @@ #include "ED_screen.h" #include "ED_sequencer.h" #include "ED_time_scrub_ui.h" -#include "ED_util.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "SEQ_sequencer.h" #include "SEQ_time.h" diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index b2a9d6ac9b7..43d5efe9ea9 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -33,7 +33,6 @@ #include "DNA_anim_types.h" #include "DNA_object_types.h" -#include "DNA_space_types.h" #include "DNA_texture_types.h" #include "BKE_anim_data.h" diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c index 542a6d45db7..b9ef69cf8bd 100644 --- a/source/blender/editors/animation/keyframes_draw.c +++ b/source/blender/editors/animation/keyframes_draw.c @@ -258,6 +258,10 @@ static DLRBT_Node *nalloc_ak_gpframe(void *data) /* count keyframes in this column */ ak->totkey = 1; + /* Set as visible block. */ + ak->totblock = 1; + ak->block.sel = ak->sel; + ak->block.flag |= ACTKEYBLOCK_FLAG_GPENCIL; return (DLRBT_Node *)ak; } @@ -689,6 +693,7 @@ static void draw_keylist(View2D *v2d, { const float icon_sz = U.widget_unit * 0.5f * yscale_fac; const float half_icon_sz = 0.5f * icon_sz; + const float quarter_icon_sz = 0.25f * icon_sz; const float smaller_sz = 0.35f * icon_sz; const float ipo_sz = 0.1f * icon_sz; @@ -724,6 +729,7 @@ static void draw_keylist(View2D *v2d, ipo_color_mix[3] *= 0.5f; uint block_len = 0; + uint gpencil_len = 0; LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { if (actkeyblock_get_valid_hold(ab)) { block_len++; @@ -731,50 +737,72 @@ static void draw_keylist(View2D *v2d, if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { block_len++; } + if ((ab->next != NULL) && (ab->block.flag & ACTKEYBLOCK_FLAG_GPENCIL)) { + gpencil_len++; + } } - if (block_len > 0) { + if ((block_len > 0) || (gpencil_len > 0)) { GPUVertFormat *format = immVertexFormat(); uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); - immBegin(GPU_PRIM_TRIS, 6 * block_len); - LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { - int valid_hold = actkeyblock_get_valid_hold(ab); - if (valid_hold != 0) { - if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { - /* draw "moving hold" long-keyframe block - slightly smaller */ - immRectf_fast_with_color(pos_id, - color_id, - ab->cfra, - ypos - smaller_sz, - ab->next->cfra, - ypos + smaller_sz, - (ab->block.sel) ? sel_mhcol : unsel_mhcol); + /* Normal Dopesheet. */ + if (block_len > 0) { + immBegin(GPU_PRIM_TRIS, 6 * block_len); + LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { + int valid_hold = actkeyblock_get_valid_hold(ab); + if (valid_hold != 0) { + if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) { + /* draw "moving hold" long-keyframe block - slightly smaller */ + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - smaller_sz, + ab->next->cfra, + ypos + smaller_sz, + (ab->block.sel) ? sel_mhcol : unsel_mhcol); + } + else { + /* draw standard long-keyframe block */ + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - half_icon_sz, + ab->next->cfra, + ypos + half_icon_sz, + (ab->block.sel) ? sel_color : unsel_color); + } } - else { - /* draw standard long-keyframe block */ - immRectf_fast_with_color(pos_id, - color_id, - ab->cfra, - ypos - half_icon_sz, - ab->next->cfra, - ypos + half_icon_sz, - (ab->block.sel) ? sel_color : unsel_color); + if (show_ipo && actkeyblock_is_valid(ab) && + (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { + /* draw an interpolation line */ + immRectf_fast_with_color( + pos_id, + color_id, + ab->cfra, + ypos - ipo_sz, + ab->next->cfra, + ypos + ipo_sz, + (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color); } } - if (show_ipo && actkeyblock_is_valid(ab) && - (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) { - /* draw an interpolation line */ - immRectf_fast_with_color( - pos_id, - color_id, - ab->cfra, - ypos - ipo_sz, - ab->next->cfra, - ypos + ipo_sz, - (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color); + } + /* Grease Pencil Dopesheet. */ + else { + immBegin(GPU_PRIM_TRIS, 6 * gpencil_len); + LISTBASE_FOREACH (ActKeyColumn *, ab, keys) { + if (ab->next == NULL) { + continue; + } + immRectf_fast_with_color(pos_id, + color_id, + ab->cfra, + ypos - quarter_icon_sz, + ab->next->cfra, + ypos + quarter_icon_sz, + (ab->block.sel) ? sel_mhcol : unsel_mhcol); } } immEnd(); diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c index 6ed9803dbd3..72e65272f13 100644 --- a/source/blender/editors/animation/keyframes_general.c +++ b/source/blender/editors/animation/keyframes_general.c @@ -39,13 +39,11 @@ #include "BKE_action.h" #include "BKE_curve.h" -#include "BKE_deform.h" #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_report.h" #include "RNA_access.h" -#include "RNA_enum_types.h" #include "ED_anim_api.h" #include "ED_keyframes_edit.h" diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index e8146ca960a..0d1633ab3a2 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -614,7 +614,7 @@ int insert_vert_fcurve( return -1; } - /* set handletype and interpolation */ + /* Set handle-type and interpolation. */ if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) { BezTriple *bezt = (fcu->bezt + a); @@ -1384,7 +1384,7 @@ static AnimationEvalContext nla_time_remap(const AnimationEvalContext *anim_eval if (adt && adt->action == act) { /* Get NLA context for value remapping. */ *r_nla_context = BKE_animsys_get_nla_keyframing_context( - nla_cache, id_ptr, adt, anim_eval_context, false); + nla_cache, id_ptr, adt, anim_eval_context); /* Apply NLA-mapping to frame. */ const float remapped_frame = BKE_nla_tweakedit_remap( diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 98b4d93fbf1..034378399b9 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -124,23 +124,22 @@ static void draw_current_frame(const Scene *scene, UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_3fv_alpha(true, - frame_x - box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymin + box_padding, - frame_x + box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymax - box_padding, - 4 * UI_DPI_FAC, - bg_color, - 1.0f); - - UI_GetThemeColorShade4fv(TH_CFRAME, 5, bg_color); - UI_draw_roundbox_aa(false, - frame_x - box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymin + box_padding, - frame_x + box_width / 2 + U.pixelsize / 2, - scrub_region_rect->ymax - box_padding, - 4 * UI_DPI_FAC, - bg_color); + float outline_color[4]; + UI_GetThemeColorShade4fv(TH_CFRAME, 5, outline_color); + + UI_draw_roundbox_4fv_ex( + &(const rctf){ + .xmin = frame_x - box_width / 2 + U.pixelsize / 2, + .xmax = frame_x + box_width / 2 + U.pixelsize / 2, + .ymin = scrub_region_rect->ymin + box_padding, + .ymax = scrub_region_rect->ymax - box_padding, + }, + bg_color, + NULL, + 1.0f, + outline_color, + U.pixelsize, + 4 * UI_DPI_FAC); uchar text_color[4]; UI_GetThemeColor4ubv(TH_HEADER_TEXT_HI, text_color); diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index a0b8bf862d7..68fff1091af 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -122,9 +122,6 @@ EditBone *ED_armature_ebone_add_primitive(Object *obedit_arm, float length, bool return bone; } -/* previously addvert_armature */ -/* the ctrl-click method */ - /** * Note this is already ported to multi-objects as it is. * Since only the active bone is extruded even for single objects, @@ -306,8 +303,7 @@ static EditBone *get_named_editbone(ListBase *edbo, const char *name) return NULL; } -/* Call this before doing any duplications - * */ +/* Call this before doing any duplications. */ void preEditBoneDuplicate(ListBase *editbones) { /* clear temp */ diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index da1b29307b1..a0face26bae 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -28,8 +28,6 @@ #include "ED_armature.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "armature_intern.h" diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 6951ed6f305..f86ec545712 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_string_utils.h" @@ -50,8 +49,6 @@ #include "ED_armature.h" #include "ED_mesh.h" -#include "eigen_capi.h" - #include "armature_intern.h" #include "meshlaplacian.h" diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index fba88e78162..3d1d8d0d1f1 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -699,11 +699,11 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) BKE_armature_bonelist_free(&arm->bonebase, true); arm->act_bone = NULL; - /* remove zero sized bones, this gives unstable restposes */ + /* Remove zero sized bones, this gives unstable rest-poses. */ for (eBone = arm->edbo->first; eBone; eBone = neBone) { float len_sq = len_squared_v3v3(eBone->head, eBone->tail); neBone = eBone->next; - /* TODO(sergey): How to ensure this is a constexpr? */ + /* TODO(sergey): How to ensure this is a `constexpr`? */ if (len_sq <= square_f(0.000001f)) { /* FLT_EPSILON is too large? */ EditBone *fBone; diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c index c6d7d2eb869..337d1138b23 100644 --- a/source/blender/editors/armature/editarmature_undo.c +++ b/source/blender/editors/armature/editarmature_undo.c @@ -178,8 +178,11 @@ static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain, return true; } -static void armature_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void armature_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { ArmatureUndoStep *us = (ArmatureUndoStep *)us_p; diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 3c0b6dacbf6..e362a2e2f40 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -422,7 +422,7 @@ static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTr } } -/* Raytracing for vertex to bone/vertex visibility */ +/* Ray-tracing for vertex to bone/vertex visibility. */ static void heat_ray_tree_create(LaplacianSystem *sys) { const MLoopTri *looptri = sys->heat.mlooptri; @@ -497,7 +497,7 @@ static float heat_source_distance(LaplacianSystem *sys, int vertex, int source) { float closest[3], d[3], dist, cosine; - /* compute euclidian distance */ + /* compute Euclidean distance */ closest_to_line_segment_v3( closest, sys->heat.verts[vertex], sys->heat.root[source], sys->heat.tip[source]); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 91893af003f..78bce8679bb 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -149,7 +149,7 @@ bool ED_object_posemode_exit(bContext *C, Object *ob) return ok; } -/* if a selected or active bone is protected, throw error (oonly if warn == 1) and return 1 */ +/* if a selected or active bone is protected, throw error (only if warn == 1) and return 1 */ /* only_selected == 1: the active bone is allowed to be protected */ #if 0 /* UNUSED 2.5 */ static bool pose_has_protected_selected(Object *ob, short warn) diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 55c9877e55f..38d15d8b880 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -423,7 +423,7 @@ static int group_sort_exec(bContext *C, wmOperator *UNUSED(op)) BLI_addtail(&pose->agroups, agrp_array[i].agrp); } - /* fix changed bone group indizes in bones */ + /* Fix changed bone group indices in bones. */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { for (i = 0; i < agrp_count; i++) { if (pchan->agrp_index == agrp_array[i].index) { diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 947e2dbf5aa..45f623f3a9d 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -1106,7 +1106,7 @@ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData if (pchan) { if (!any_bone_selected || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { if (autokey) { - /* add datasource override for the PoseChannel, to be used later */ + /* Add data-source override for the PoseChannel, to be used later. */ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); /* clear any unkeyed tags */ @@ -1142,7 +1142,7 @@ static void poselib_preview_apply(bContext *C, wmOperator *op) /* only recalc pose (and its dependencies) if pose has changed */ if (pld->redraw == PL_PREVIEW_REDRAWALL) { - /* don't clear pose if firsttime */ + /* Don't clear pose if first time. */ if ((pld->flag & PL_PREVIEW_FIRSTTIME) == 0) { poselib_backup_restore(pld); } diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index 4b646bb26e2..d636f0d68af 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -689,7 +689,7 @@ static void pose_slide_rest_pose_apply(bContext *C, tPoseSlideOp *pso) /* Not strictly a transform, but custom properties contribute * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ /* TODO Not implemented */ - // pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */ + // pose_slide_apply_props(pso, pfl, "[\""); } } @@ -702,7 +702,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) { tPChanFCurveLink *pfl; - /* sanitise the frame ranges */ + /* Sanitize the frame ranges. */ if (pso->prevFrame == pso->nextFrame) { /* move out one step either side */ pso->prevFrame--; @@ -765,7 +765,7 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso) if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) { /* Not strictly a transform, but custom properties contribute * to the pose produced in many rigs (e.g. the facial rigs used in Sintel). */ - pose_slide_apply_props(pso, pfl, "[\""); /* dummy " for texteditor bugs */ + pose_slide_apply_props(pso, pfl, "[\""); } } @@ -1125,7 +1125,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->val == KM_PRESS) { switch (event->type) { /* Transform Channel Limits */ - /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */ + /* XXX: Replace these hard-coded hotkeys with a modal-map that can be customized. */ case EVT_GKEY: /* Location */ { pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC); @@ -1183,7 +1183,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else { - /* unhandled event - maybe it was some view manip? */ + /* unhandled event - maybe it was some view manipulation? */ /* allow to pass through */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } @@ -1246,15 +1246,15 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) { PropertyRNA *prop; - prop = RNA_def_float_percentage(ot->srna, - "percentage", - 0.5f, - 0.0f, - 1.0f, - "Percentage", - "Weighting factor for which keyframe is favored more", - 0.0, - 1.0); + prop = RNA_def_float_factor(ot->srna, + "factor", + 0.5f, + 0.0f, + 1.0f, + "Factor", + "Weighting factor for which keyframe is favored more", + 0.0, + 1.0); RNA_def_property_flag(prop, PROP_SKIP_SAVE); prop = RNA_def_int(ot->srna, diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 3505aea3f40..722865cc942 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -225,7 +225,7 @@ static void applyarmature_process_selected_recursive(bArmature *arm, ApplyArmature_ParentState new_pstate = {.bone = bone}; if (BLI_findptr(selected, pchan, offsetof(CollectionPointerLink, ptr.data))) { - /* SELECTED BONE: Snap to final pose transform minus unapplied parent effects. + /* SELECTED BONE: Snap to final pose transform minus un-applied parent effects. * * I.e. bone position with accumulated parent effects but no local * transformation will match the original final pose_mat. diff --git a/source/blender/editors/armature/pose_utils.c b/source/blender/editors/armature/pose_utils.c index 2a6dc9f406b..c75e9c9ef69 100644 --- a/source/blender/editors/armature/pose_utils.c +++ b/source/blender/editors/armature/pose_utils.c @@ -33,7 +33,6 @@ #include "BKE_action.h" #include "BKE_anim_data.h" -#include "BKE_armature.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_object.h" @@ -312,7 +311,7 @@ void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, continue; } - /* add datasource override for the PoseChannel, to be used later */ + /* Add data-source override for the PoseChannel, to be used later. */ ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan); /* clear any unkeyed tags */ diff --git a/source/blender/editors/asset/CMakeLists.txt b/source/blender/editors/asset/CMakeLists.txt index 6cd94783251..8c5f91561b7 100644 --- a/source/blender/editors/asset/CMakeLists.txt +++ b/source/blender/editors/asset/CMakeLists.txt @@ -29,8 +29,8 @@ set(INC_SYS ) set(SRC - asset_edit.c - asset_ops.c + asset_edit.cc + asset_ops.cc ) set(LIB diff --git a/source/blender/editors/asset/asset_edit.c b/source/blender/editors/asset/asset_edit.cc index 3dca87d3a03..d20de4141cb 100644 --- a/source/blender/editors/asset/asset_edit.c +++ b/source/blender/editors/asset/asset_edit.cc @@ -20,11 +20,9 @@ #include "BKE_asset.h" #include "BKE_context.h" -#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "DNA_ID.h" -#include "DNA_asset_types.h" #include "UI_interface_icons.h" @@ -45,7 +43,7 @@ bool ED_asset_mark_id(const bContext *C, ID *id) id->asset_data = BKE_asset_metadata_create(); - UI_icon_render_id(C, NULL, id, ICON_SIZE_PREVIEW, true); + UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); return true; } @@ -65,5 +63,5 @@ bool ED_asset_clear_id(ID *id) bool ED_asset_can_make_single_from_context(const bContext *C) { /* Context needs a "id" pointer to be set for #ASSET_OT_mark()/#ASSET_OT_clear() to use. */ - return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != NULL; + return CTX_data_pointer_get_type_silent(C, "id", &RNA_ID).data != nullptr; } diff --git a/source/blender/editors/asset/asset_ops.c b/source/blender/editors/asset/asset_ops.c deleted file mode 100644 index 29c3174f051..00000000000 --- a/source/blender/editors/asset/asset_ops.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** \file - * \ingroup edasset - */ - -#include <string.h> - -#include "BKE_asset.h" -#include "BKE_context.h" -#include "BKE_report.h" - -#include "BLI_listbase.h" -#include "BLI_string_utils.h" -#include "BLI_utildefines.h" - -#include "DNA_asset_types.h" -#include "DNA_userdef_types.h" - -#include "ED_asset.h" - -#include "MEM_guardedalloc.h" - -#include "RNA_access.h" -#include "RNA_define.h" - -#include "WM_api.h" -#include "WM_types.h" - -/* -------------------------------------------------------------------- */ - -struct AssetMarkResultStats { - int tot_created; - int tot_already_asset; - ID *last_id; -}; - -static bool asset_ops_poll(bContext *UNUSED(C)) -{ - return U.experimental.use_asset_browser; -} - -/** - * Return the IDs to operate on as list of #CollectionPointerLink links. Needs freeing. - */ -static ListBase /* CollectionPointerLink */ asset_operation_get_ids_from_context(const bContext *C) -{ - ListBase list = {0}; - - PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); - - if (idptr.data) { - CollectionPointerLink *ctx_link = MEM_callocN(sizeof(*ctx_link), __func__); - ctx_link->ptr = idptr; - BLI_addtail(&list, ctx_link); - } - else { - CTX_data_selected_ids(C, &list); - } - - return list; -} - -static void asset_mark_for_idptr_list(const bContext *C, - const ListBase /* CollectionPointerLink */ *ids, - struct AssetMarkResultStats *r_stats) -{ - memset(r_stats, 0, sizeof(*r_stats)); - - LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { - BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); - - ID *id = ctx_id->ptr.data; - if (id->asset_data) { - r_stats->tot_already_asset++; - continue; - } - - if (ED_asset_mark_id(C, id)) { - r_stats->last_id = id; - r_stats->tot_created++; - } - } -} - -static bool asset_mark_results_report(const struct AssetMarkResultStats *stats, - ReportList *reports) -{ - /* User feedback on failure. */ - if ((stats->tot_created < 1) && (stats->tot_already_asset > 0)) { - BKE_report(reports, - RPT_ERROR, - "Selected data-blocks are already assets (or do not support use as assets)"); - return false; - } - if (stats->tot_created < 1) { - BKE_report(reports, - RPT_ERROR, - "No data-blocks to create assets for found (or do not support use as assets)"); - return false; - } - - /* User feedback on success. */ - if (stats->tot_created == 1) { - /* If only one data-block: Give more useful message by printing asset name. */ - BKE_reportf(reports, RPT_INFO, "Data-block '%s' is now an asset", stats->last_id->name + 2); - } - else { - BKE_reportf(reports, RPT_INFO, "%i data-blocks are now assets", stats->tot_created); - } - - return true; -} - -static int asset_mark_exec(bContext *C, wmOperator *op) -{ - ListBase ids = asset_operation_get_ids_from_context(C); - - struct AssetMarkResultStats stats; - asset_mark_for_idptr_list(C, &ids, &stats); - BLI_freelistN(&ids); - - if (!asset_mark_results_report(&stats, op->reports)) { - return OPERATOR_CANCELLED; - } - - WM_main_add_notifier(NC_ID | NA_EDITED, NULL); - WM_main_add_notifier(NC_ASSET | NA_ADDED, NULL); - - return OPERATOR_FINISHED; -} - -static void ASSET_OT_mark(wmOperatorType *ot) -{ - ot->name = "Mark Asset"; - ot->description = - "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of " - "customizable metadata (like previews, descriptions and tags)"; - ot->idname = "ASSET_OT_mark"; - - ot->exec = asset_mark_exec; - ot->poll = asset_ops_poll; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* -------------------------------------------------------------------- */ - -struct AssetClearResultStats { - int tot_removed; - ID *last_id; -}; - -static void asset_clear_from_idptr_list(const ListBase /* CollectionPointerLink */ *ids, - struct AssetClearResultStats *r_stats) -{ - memset(r_stats, 0, sizeof(*r_stats)); - - LISTBASE_FOREACH (CollectionPointerLink *, ctx_id, ids) { - BLI_assert(RNA_struct_is_ID(ctx_id->ptr.type)); - - ID *id = ctx_id->ptr.data; - if (!id->asset_data) { - continue; - } - - if (ED_asset_clear_id(id)) { - r_stats->tot_removed++; - r_stats->last_id = id; - } - } -} - -static bool asset_clear_result_report(const struct AssetClearResultStats *stats, - ReportList *reports) - -{ - if (stats->tot_removed < 1) { - BKE_report(reports, RPT_ERROR, "No asset data-blocks selected/focused"); - return false; - } - - if (stats->tot_removed == 1) { - /* If only one data-block: Give more useful message by printing asset name. */ - BKE_reportf( - reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats->last_id->name + 2); - } - else { - BKE_reportf(reports, RPT_INFO, "%i data-blocks are no assets anymore", stats->tot_removed); - } - - return true; -} - -static int asset_clear_exec(bContext *C, wmOperator *op) -{ - ListBase ids = asset_operation_get_ids_from_context(C); - - struct AssetClearResultStats stats; - asset_clear_from_idptr_list(&ids, &stats); - BLI_freelistN(&ids); - - if (!asset_clear_result_report(&stats, op->reports)) { - return OPERATOR_CANCELLED; - } - - WM_main_add_notifier(NC_ID | NA_EDITED, NULL); - WM_main_add_notifier(NC_ASSET | NA_REMOVED, NULL); - - return OPERATOR_FINISHED; -} - -static void ASSET_OT_clear(wmOperatorType *ot) -{ - ot->name = "Clear Asset"; - ot->description = - "Delete all asset metadata and turn the selected asset data-blocks back into normal " - "data-blocks"; - ot->idname = "ASSET_OT_clear"; - - ot->exec = asset_clear_exec; - ot->poll = asset_ops_poll; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* -------------------------------------------------------------------- */ - -void ED_operatortypes_asset(void) -{ - WM_operatortype_append(ASSET_OT_mark); - WM_operatortype_append(ASSET_OT_clear); -} diff --git a/source/blender/editors/asset/asset_ops.cc b/source/blender/editors/asset/asset_ops.cc new file mode 100644 index 00000000000..8ca1b488a1d --- /dev/null +++ b/source/blender/editors/asset/asset_ops.cc @@ -0,0 +1,259 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup edasset + */ + +#include "BKE_context.h" +#include "BKE_report.h" + +#include "BLI_vector.hh" + +#include "ED_asset.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* -------------------------------------------------------------------- */ + +using PointerRNAVec = blender::Vector<PointerRNA>; + +static bool asset_operation_poll(bContext * /*C*/) +{ + return U.experimental.use_asset_browser; +} + +/** + * Return the IDs to operate on as PointerRNA vector. Either a single one ("id" context member) or + * multiple ones ("selected_ids" context member). + */ +static PointerRNAVec asset_operation_get_ids_from_context(const bContext *C) +{ + PointerRNAVec ids; + + PointerRNA idptr = CTX_data_pointer_get_type(C, "id", &RNA_ID); + if (idptr.data) { + /* Single ID. */ + ids.append(idptr); + } + else { + ListBase list; + CTX_data_selected_ids(C, &list); + LISTBASE_FOREACH (CollectionPointerLink *, link, &list) { + ids.append(link->ptr); + } + BLI_freelistN(&list); + } + + return ids; +} + +/* -------------------------------------------------------------------- */ + +class AssetMarkHelper { + public: + void operator()(const bContext &C, PointerRNAVec &ids); + + void reportResults(ReportList &reports) const; + bool wasSuccessful() const; + + private: + struct Stats { + int tot_created = 0; + int tot_already_asset = 0; + ID *last_id = nullptr; + }; + + Stats stats; +}; + +void AssetMarkHelper::operator()(const bContext &C, PointerRNAVec &ids) +{ + for (PointerRNA &ptr : ids) { + BLI_assert(RNA_struct_is_ID(ptr.type)); + + ID *id = static_cast<ID *>(ptr.data); + if (id->asset_data) { + stats.tot_already_asset++; + continue; + } + + if (ED_asset_mark_id(&C, id)) { + stats.last_id = id; + stats.tot_created++; + } + } +} + +bool AssetMarkHelper::wasSuccessful() const +{ + return stats.tot_created > 0; +} + +void AssetMarkHelper::reportResults(ReportList &reports) const +{ + /* User feedback on failure. */ + if (!wasSuccessful()) { + if ((stats.tot_already_asset > 0)) { + BKE_report(&reports, + RPT_ERROR, + "Selected data-blocks are already assets (or do not support use as assets)"); + } + else { + BKE_report(&reports, + RPT_ERROR, + "No data-blocks to create assets for found (or do not support use as assets)"); + } + } + /* User feedback on success. */ + else if (stats.tot_created == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf(&reports, RPT_INFO, "Data-block '%s' is now an asset", stats.last_id->name + 2); + } + else { + BKE_reportf(&reports, RPT_INFO, "%i data-blocks are now assets", stats.tot_created); + } +} + +static int asset_mark_exec(bContext *C, wmOperator *op) +{ + PointerRNAVec ids = asset_operation_get_ids_from_context(C); + + AssetMarkHelper mark_helper; + mark_helper(*C, ids); + mark_helper.reportResults(*op->reports); + + if (!mark_helper.wasSuccessful()) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, nullptr); + WM_main_add_notifier(NC_ASSET | NA_ADDED, nullptr); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_mark(wmOperatorType *ot) +{ + ot->name = "Mark Asset"; + ot->description = + "Enable easier reuse of selected data-blocks through the Asset Browser, with the help of " + "customizable metadata (like previews, descriptions and tags)"; + ot->idname = "ASSET_OT_mark"; + + ot->exec = asset_mark_exec; + ot->poll = asset_operation_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +class AssetClearHelper { + public: + void operator()(PointerRNAVec &ids); + + void reportResults(ReportList &reports) const; + bool wasSuccessful() const; + + private: + struct Stats { + int tot_cleared = 0; + ID *last_id = nullptr; + }; + + Stats stats; +}; + +void AssetClearHelper::operator()(PointerRNAVec &ids) +{ + for (PointerRNA &ptr : ids) { + BLI_assert(RNA_struct_is_ID(ptr.type)); + + ID *id = static_cast<ID *>(ptr.data); + if (!id->asset_data) { + continue; + } + + if (ED_asset_clear_id(id)) { + stats.tot_cleared++; + stats.last_id = id; + } + } +} + +void AssetClearHelper::reportResults(ReportList &reports) const +{ + if (!wasSuccessful()) { + BKE_report(&reports, RPT_ERROR, "No asset data-blocks selected/focused"); + } + else if (stats.tot_cleared == 1) { + /* If only one data-block: Give more useful message by printing asset name. */ + BKE_reportf( + &reports, RPT_INFO, "Data-block '%s' is no asset anymore", stats.last_id->name + 2); + } + else { + BKE_reportf(&reports, RPT_INFO, "%i data-blocks are no assets anymore", stats.tot_cleared); + } +} + +bool AssetClearHelper::wasSuccessful() const +{ + return stats.tot_cleared > 0; +} + +static int asset_clear_exec(bContext *C, wmOperator *op) +{ + PointerRNAVec ids = asset_operation_get_ids_from_context(C); + + AssetClearHelper clear_helper; + clear_helper(ids); + clear_helper.reportResults(*op->reports); + + if (!clear_helper.wasSuccessful()) { + return OPERATOR_CANCELLED; + } + + WM_main_add_notifier(NC_ID | NA_EDITED, nullptr); + WM_main_add_notifier(NC_ASSET | NA_REMOVED, nullptr); + + return OPERATOR_FINISHED; +} + +static void ASSET_OT_clear(wmOperatorType *ot) +{ + ot->name = "Clear Asset"; + ot->description = + "Delete all asset metadata and turn the selected asset data-blocks back into normal " + "data-blocks"; + ot->idname = "ASSET_OT_clear"; + + ot->exec = asset_clear_exec; + ot->poll = asset_operation_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* -------------------------------------------------------------------- */ + +void ED_operatortypes_asset(void) +{ + WM_operatortype_append(ASSET_OT_mark); + WM_operatortype_append(ASSET_OT_clear); +} diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index e9ceedf7ce2..8ebc2077619 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2419,7 +2419,7 @@ static void adduplicateflagNurb( memcpy(newnu->bp, &nu->bp[a], newu * newv * sizeof(BPoint)); memcpy(&newnu->bp[newu * newv], nu->bp, newu * cyclicv * sizeof(BPoint)); - /* check for actvert in cylicv selection */ + /* check for actvert in cyclicv selection */ if (cu->actnu == i) { calc_duplicate_actvert( editnurb, newnurb, cu, cu->actvert, a, (newu * newv) + cu->actvert); @@ -6102,7 +6102,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bezt1 = nu->bezt; bezt2 = &nu->bezt[1]; @@ -6232,7 +6232,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bp1 = nu->bp; bp2 = &nu->bp[1]; @@ -6352,7 +6352,7 @@ static bool curve_delete_segments(Object *obedit, View3D *v3d, const bool split) } if (!split && cut != -1 && nu->pntsv > 2 && !(nu->flagv & CU_NURB_CYCLIC)) { - /* start and points copied if connecting segment was deleted and not cylic spline */ + /* start and points copied if connecting segment was deleted and not cyclic spline */ bp1 = nu->bp; bp2 = &nu->bp[nu->pntsu]; diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index 4097275a2b9..82f7b456284 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -1242,7 +1242,7 @@ static void curve_select_random(ListBase *editnurb, float randfac, int seed, boo static int curve_select_random_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c index 534d29c0cc7..681f387e83e 100644 --- a/source/blender/editors/curve/editcurve_undo.c +++ b/source/blender/editors/curve/editcurve_undo.c @@ -238,8 +238,11 @@ static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, Un return true; } -static void curve_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void curve_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { CurveUndoStep *us = (CurveUndoStep *)us_p; diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c index 8559234b62f..07f062e7a53 100644 --- a/source/blender/editors/curve/editfont_undo.c +++ b/source/blender/editors/curve/editfont_undo.c @@ -356,8 +356,11 @@ static bool font_undosys_step_encode(struct bContext *C, struct Main *bmain, Und return true; } -static void font_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void font_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { /* TODO(campbell): undo_system: use low-level API to set mode. */ ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL); diff --git a/source/blender/editors/geometry/geometry_attributes.c b/source/blender/editors/geometry/geometry_attributes.c index 4106c03f17d..2807e7c4392 100644 --- a/source/blender/editors/geometry/geometry_attributes.c +++ b/source/blender/editors/geometry/geometry_attributes.c @@ -23,7 +23,6 @@ #include "BKE_attribute.h" #include "BKE_context.h" -#include "BKE_report.h" #include "RNA_access.h" #include "RNA_define.h" @@ -34,7 +33,6 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_geometry.h" #include "ED_object.h" #include "geometry_intern.h" diff --git a/source/blender/editors/gizmo_library/gizmo_library_presets.c b/source/blender/editors/gizmo_library/gizmo_library_presets.c index 9039851da01..4e56ceb9fd4 100644 --- a/source/blender/editors/gizmo_library/gizmo_library_presets.c +++ b/source/blender/editors/gizmo_library/gizmo_library_presets.c @@ -22,12 +22,9 @@ * \brief Preset shapes that can be drawn from any gizmo type. */ -#include "MEM_guardedalloc.h" - #include "BLI_math.h" #include "DNA_object_types.h" -#include "DNA_view3d_types.h" #include "BKE_context.h" @@ -36,12 +33,8 @@ #include "DEG_depsgraph.h" -#include "RNA_access.h" - -#include "WM_api.h" #include "WM_types.h" -#include "ED_screen.h" #include "ED_view3d.h" /* own includes */ diff --git a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c index 5617b6e125e..1b1f1151053 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/blank3d_gizmo.c @@ -28,14 +28,11 @@ #include "BKE_context.h" #include "ED_gizmo_library.h" -#include "ED_view3d.h" #include "WM_api.h" #include "WM_types.h" /* own includes */ -#include "../gizmo_geometry.h" -#include "../gizmo_library_intern.h" static void gizmo_blank_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz)) { diff --git a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c index eb40500d011..cbca230da7e 100644 --- a/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c +++ b/source/blender/editors/gizmo_library/gizmo_types/button2d_gizmo.c @@ -320,6 +320,16 @@ static int gizmo_button2d_cursor_get(wmGizmo *gz) return WM_CURSOR_DEFAULT; } +static void gizmo_button2d_bounds(bContext *C, wmGizmo *gz, rcti *r_bounding_box) +{ + ScrArea *area = CTX_wm_area(C); + float rad = CIRCLE_RESOLUTION * U.dpi_fac / 2.0f; + r_bounding_box->xmin = gz->matrix_basis[3][0] + area->totrct.xmin - rad; + r_bounding_box->ymin = gz->matrix_basis[3][1] + area->totrct.ymin - rad; + r_bounding_box->xmax = r_bounding_box->xmin + rad; + r_bounding_box->ymax = r_bounding_box->ymin + rad; +} + static void gizmo_button2d_free(wmGizmo *gz) { ButtonGizmo2D *shape = (ButtonGizmo2D *)gz; @@ -346,6 +356,7 @@ static void GIZMO_GT_button_2d(wmGizmoType *gzt) gzt->draw_select = gizmo_button2d_draw_select; gzt->test_select = gizmo_button2d_test_select; gzt->cursor_get = gizmo_button2d_cursor_get; + gzt->screen_bounds_get = gizmo_button2d_bounds; gzt->free = gizmo_button2d_free; gzt->struct_size = sizeof(ButtonGizmo2D); diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 4e2951c3571..751f8333aaa 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -171,7 +171,8 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, int totpoints = tgpw->gps->totpoints; const float viewport[2] = {(float)tgpw->winx, (float)tgpw->winy}; - float curpressure = points[0].pressure; + const float min_thickness = 0.05f; + float fpt[3]; /* if cyclic needs more vertex */ @@ -205,7 +206,6 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, immUniform1i("fill_stroke", (int)tgpw->is_fill_stroke); /* draw stroke curve */ - GPU_line_width(max_ff(curpressure * thickness, 1.0f)); immBeginAtMost(GPU_PRIM_LINE_STRIP_ADJ, totpoints + cyclic_add + 2); const bGPDspoint *pt = points; @@ -215,18 +215,19 @@ static void gpencil_draw_stroke_3d(tGPDdraw *tgpw, gpencil_set_point_varying_color(points, ink, attr_id.color, (bool)tgpw->is_fill_stroke); if ((cyclic) && (totpoints > 2)) { - immAttr1f(attr_id.thickness, max_ff((points + totpoints - 1)->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, + max_ff((points + totpoints - 1)->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + totpoints - 1)->x); } else { - immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, max_ff((points + 1)->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &(points + 1)->x); } immVertex3fv(attr_id.pos, fpt); } /* set point */ gpencil_set_point_varying_color(pt, ink, attr_id.color, (bool)tgpw->is_fill_stroke); - immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, 1.0f)); + immAttr1f(attr_id.thickness, max_ff(pt->pressure * thickness, min_thickness)); mul_v3_m4v3(fpt, tgpw->diff_mat, &pt->x); immVertex3fv(attr_id.pos, fpt); } diff --git a/source/blender/editors/gpencil/editaction_gpencil.c b/source/blender/editors/gpencil/editaction_gpencil.c index aae31b11025..166111c582c 100644 --- a/source/blender/editors/gpencil/editaction_gpencil.c +++ b/source/blender/editors/gpencil/editaction_gpencil.c @@ -276,7 +276,7 @@ void ED_gpencil_layer_frames_duplicate(bGPDlayer *gpl) bGPDframe *gpfd; /* duplicate frame, and deselect self */ - gpfd = BKE_gpencil_frame_duplicate(gpf); + gpfd = BKE_gpencil_frame_duplicate(gpf, true); gpf->flag &= ~GP_FRAME_SELECT; BLI_insertlinkafter(&gpl->frames, gpf, gpfd); @@ -361,7 +361,7 @@ bool ED_gpencil_anim_copybuf_copy(bAnimContext *ac) /* if frame is selected, make duplicate it and its strokes */ if (gpf->flag & GP_FRAME_SELECT) { /* make a copy of this frame */ - bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf); + bGPDframe *new_frame = BKE_gpencil_frame_duplicate(gpf, true); BLI_addtail(&copied_frames, new_frame); /* extend extents for keyframes encountered */ diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c index 65141442237..d86bad7ef3c 100644 --- a/source/blender/editors/gpencil/gpencil_add_monkey.c +++ b/source/blender/editors/gpencil/gpencil_add_monkey.c @@ -29,16 +29,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_gpencil.h" diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c index 0c8cc621a3b..1e1a70f9c1d 100644 --- a/source/blender/editors/gpencil/gpencil_add_stroke.c +++ b/source/blender/editors/gpencil/gpencil_add_stroke.c @@ -29,16 +29,13 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_gpencil.h" diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index 5cc5e7ecdcd..3271096c433 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -31,12 +31,9 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "DNA_armature_types.h" #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index 09b57029350..ac75ae44c8a 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -178,7 +178,7 @@ static void gpencil_strokepoint_convertcoords(bContext *C, /* apply parent transform */ float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); mul_v3_m4v3(fpt, diff_mat, &source_pt->x); copy_v3_v3(&pt->x, fpt); @@ -370,7 +370,7 @@ static int gpencil_find_end_of_stroke_idx(tGpTimingData *gtd, static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, RNG *rng, int *nbr_gaps, - float *tot_gaps_time) + float *r_tot_gaps_time) { float delta_time = 0.0f; @@ -387,10 +387,10 @@ static void gpencil_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, } gtd->tot_time -= delta_time; - *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; - gtd->tot_time += *tot_gaps_time; + *r_tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *r_tot_gaps_time; if (G.debug & G_DEBUG) { - printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *r_tot_gaps_time, *nbr_gaps); } if (gtd->gap_randomness > 0.0f) { BLI_rng_srandom(rng, gtd->seed); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index ad9b72b713e..3be913f342d 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -449,21 +449,32 @@ void GPENCIL_OT_layer_annotation_move(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", slot_move, 0, "Type", ""); } /* ********************* Duplicate Layer ************************** */ +enum { + GP_LAYER_DUPLICATE_ALL = 0, + GP_LAYER_DUPLICATE_EMPTY = 1, +}; -static int gpencil_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) +static int gpencil_layer_copy_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); bGPDlayer *new_layer; - + const int mode = RNA_enum_get(op->ptr, "mode"); + const bool dup_strokes = (bool)(mode == GP_LAYER_DUPLICATE_ALL); /* sanity checks */ if (ELEM(NULL, gpd, gpl)) { return OPERATOR_CANCELLED; } - /* make copy of layer, and add it immediately after the existing layer */ - new_layer = BKE_gpencil_layer_duplicate(gpl); - BLI_insertlinkafter(&gpd->layers, gpl, new_layer); + /* Make copy of layer, and add it immediately after or before the existing layer. */ + new_layer = BKE_gpencil_layer_duplicate(gpl, true, dup_strokes); + if (dup_strokes) { + BLI_insertlinkafter(&gpd->layers, gpl, new_layer); + } + else { + /* For empty strokes is better add below. */ + BLI_insertlinkbefore(&gpd->layers, gpl, new_layer); + } /* ensure new layer has a unique name, and is now the active layer */ BLI_uniquename(&gpd->layers, @@ -484,6 +495,12 @@ static int gpencil_layer_copy_exec(bContext *C, wmOperator *UNUSED(op)) void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) { + static const EnumPropertyItem copy_mode[] = { + {GP_LAYER_DUPLICATE_ALL, "ALL", 0, "All Data", ""}, + {GP_LAYER_DUPLICATE_EMPTY, "EMPTY", 0, "Empty Keyframes", ""}, + {0, NULL, 0, NULL, NULL}, + }; + /* identifiers */ ot->name = "Duplicate Layer"; ot->idname = "GPENCIL_OT_layer_duplicate"; @@ -495,6 +512,8 @@ void GPENCIL_OT_layer_duplicate(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "mode", copy_mode, GP_LAYER_DUPLICATE_ALL, "Mode", ""); } /* ********************* Duplicate Layer in a new object ************************** */ @@ -1560,7 +1579,7 @@ static int gpencil_stroke_arrange_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* some stroke is already at front*/ @@ -1725,7 +1744,7 @@ static int gpencil_stroke_change_color_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2849,12 +2868,12 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, imat, offset_global); LISTBASE_FOREACH (bGPDlayer *, gpl_src, &gpd_src->layers) { - bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src); + bGPDlayer *gpl_new = BKE_gpencil_layer_duplicate(gpl_src, true, true); float diff_mat[4][4]; float inverse_diff_mat[4][4]; /* recalculate all stroke points */ - BKE_gpencil_parent_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob_iter, gpl_src, diff_mat); invert_m4_m4_safe_ortho(inverse_diff_mat, diff_mat); Material *ma_src = NULL; @@ -3388,7 +3407,7 @@ static int gpencil_material_select_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index d1c8eca1be0..aeff2acb04d 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1867,7 +1867,7 @@ static int gpencil_move_to_layer_exec(bContext *C, wmOperator *op) } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2610,7 +2610,7 @@ static int gpencil_delete_selected_points(bContext *C) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -2800,7 +2800,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) float diff_mat[4][4]; /* calculate difference matrix object */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -2808,7 +2808,7 @@ static int gpencil_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -2935,7 +2935,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -2946,7 +2946,7 @@ static int gpencil_snap_to_cursor(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3039,7 +3039,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, float diff_mat[4][4]; /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { bGPDspoint *pt; @@ -3050,7 +3050,7 @@ static bool gpencil_stroke_points_centroid(Depsgraph *depsgraph, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* only continue if this stroke is selected (editable doesn't guarantee this)... */ @@ -3565,7 +3565,7 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } elem = &strokes_list[tot_strokes]; @@ -3697,7 +3697,7 @@ static int gpencil_stroke_flip_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } @@ -4516,7 +4516,7 @@ static int gpencil_stroke_separate_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Separate selected strokes. */ @@ -4717,7 +4717,7 @@ static int gpencil_stroke_split_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Split selected strokes. */ @@ -4948,11 +4948,14 @@ static int gpencil_cutter_lasso_select(bContext *C, GPencilTestFn is_inside_fn, void *user_data) { + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Object *obact = CTX_data_active_object(C); bGPdata *gpd = ED_gpencil_data_get_active(C); ScrArea *area = CTX_wm_area(C); ToolSettings *ts = CTX_data_tool_settings(C); const float scale = ts->gp_sculpt.isect_threshold; const bool flat_caps = RNA_boolean_get(op->ptr, "flat_caps"); + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); bGPDspoint *pt; GP_SpaceConversion gsc = {NULL}; @@ -4979,57 +4982,87 @@ static int gpencil_cutter_lasso_select(bContext *C, } CTX_DATA_END; - /* select points */ - GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) { - int tot_inside = 0; - const int oldtot = gps->totpoints; - for (int i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) { - continue; - } - /* convert point coords to screen-space */ - const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data); - if (is_inside) { - tot_inside++; - changed = true; - pt->flag |= GP_SPOINT_SELECT; - gps->flag |= GP_STROKE_SELECT; - float r_hita[3], r_hitb[3]; - if (gps->totpoints > 1) { - ED_gpencil_select_stroke_segment(gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb); + /* Select points */ + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if ((gpl->flag & GP_LAYER_LOCKED) || ((gpl->flag & GP_LAYER_HIDE))) { + continue; + } + + float diff_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + if (ED_gpencil_stroke_can_use(C, gps) == false) { + continue; + } /* check if the color is editable */ + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { + continue; + } + int tot_inside = 0; + const int oldtot = gps->totpoints; + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) { + continue; + } + /* convert point coords to screen-space */ + const bool is_inside = is_inside_fn(gps, pt, &gsc, diff_mat, user_data); + if (is_inside) { + tot_inside++; + changed = true; + pt->flag |= GP_SPOINT_SELECT; + gps->flag |= GP_STROKE_SELECT; + float r_hita[3], r_hitb[3]; + if (gps->totpoints > 1) { + ED_gpencil_select_stroke_segment( + gpd, gpl, gps, pt, true, true, scale, r_hita, r_hitb); + } + /* avoid infinite loops */ + if (gps->totpoints > oldtot) { + break; + } + } + } + /* if mark all points inside lasso set to remove all stroke */ + if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) { + for (int i = 0; i < gps->totpoints; i++) { + pt = &gps->points[i]; + pt->flag |= GP_SPOINT_SELECT; + } + } } - /* avoid infinite loops */ - if (gps->totpoints > oldtot) { + /* if not multiedit, exit loop. */ + if (!is_multiedit) { break; } } } - /* if mark all points inside lasso set to remove all stroke */ - if ((tot_inside == oldtot) || ((tot_inside == 1) && (oldtot == 2))) { - for (int i = 0; i < gps->totpoints; i++) { - pt = &gps->points[i]; - pt->flag |= GP_SPOINT_SELECT; - } - } } - GP_EDITABLE_STROKES_END(gpstroke_iter); - /* dissolve selected points */ + /* Dissolve selected points. */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - if (gpl->flag & GP_LAYER_LOCKED) { - continue; - } - - bGPDframe *gpf = gpl->actframe; - if (gpf == NULL) { - continue; - } - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - if (gps->flag & GP_STROKE_SELECT) { - gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps); + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + bGPDframe *gpf_act = gpl->actframe; + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + gpl->actframe = gpf; + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + if (gps->flag & GP_STROKE_SELECT) { + gpencil_cutter_dissolve(gpd, gpl, gps, flat_caps); + } + } + /* if not multiedit, exit loop. */ + if (!is_multiedit) { + break; } } + gpl->actframe = gpf_act; } /* updates */ diff --git a/source/blender/editors/gpencil/gpencil_edit_curve.c b/source/blender/editors/gpencil/gpencil_edit_curve.c index 60d1d2169b4..031bbd61173 100644 --- a/source/blender/editors/gpencil/gpencil_edit_curve.c +++ b/source/blender/editors/gpencil/gpencil_edit_curve.c @@ -28,13 +28,10 @@ #include <stdlib.h> #include <string.h> -#include "MEM_guardedalloc.h" - #include "DNA_gpencil_types.h" #include "DNA_view3d_types.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_gpencil.h" #include "BKE_gpencil_curve.h" #include "BKE_gpencil_geom.h" diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index 8bd0b2f86de..832191c8321 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_stack.h" #include "BLI_utildefines.h" @@ -81,8 +82,18 @@ #define LEAK_HORZ 0 #define LEAK_VERT 1 +#define MIN_WINDOW_SIZE 128 -/* Temporary fill operation data (op->customdata) */ +/* Set to 1 to debug filling internal image. By default, the value must be 0. */ +#define FILL_DEBUG 0 + +/* Duplicated: etempFlags */ +enum { + GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */ + GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */ +}; + +/* Temporary fill operation data `op->customdata`. */ typedef struct tGPDfill { bContext *C; struct Main *bmain; @@ -101,7 +112,7 @@ typedef struct tGPDfill { struct View3D *v3d; /** region where painting originated */ struct ARegion *region; - /** current GP datablock */ + /** Current GP data-block. */ struct bGPdata *gpd; /** current material */ struct Material *mat; @@ -111,6 +122,8 @@ typedef struct tGPDfill { struct bGPDlayer *gpl; /** frame */ struct bGPDframe *gpf; + /** Temp mouse position stroke. */ + struct bGPDstroke *gps_mouse; /** flags */ short flag; @@ -118,9 +131,12 @@ typedef struct tGPDfill { short oldkey; /** send to back stroke */ bool on_back; - + /** Flag for render mode */ + bool is_render; + /** Flag to check something was done. */ + bool done; /** mouse fill center position */ - int center[2]; + int mouse[2]; /** windows width */ int sizex; /** window height */ @@ -137,7 +153,7 @@ typedef struct tGPDfill { /** boundary limits drawing mode */ int fill_draw_mode; /* scaling factor */ - short fill_factor; + float fill_factor; /* Frame to use. */ int active_cfra; @@ -156,14 +172,184 @@ typedef struct tGPDfill { /** handle for drawing strokes while operator is running 3d stuff */ void *draw_handle_3d; - /* tmp size x */ + /* Temporary size x. */ int bwinx; - /* tmp size y */ + /* Temporary size y. */ int bwiny; rcti brect; + /* Space Conversion Data */ + GP_SpaceConversion gsc; + + /** Zoom factor. */ + float zoom; + + /** Factor of extension. */ + float fill_extend_fac; + } tGPDfill; +bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index); +static void gpencil_draw_boundary_lines(const struct bContext *UNUSED(C), struct tGPDfill *tgpf); + +/* Delete any temporary stroke. */ +static void gpencil_delete_temp_stroke_extension(tGPDfill *tgpf, const bool all_frames) +{ + LISTBASE_FOREACH (bGPDlayer *, gpl, &tgpf->gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + bGPDframe *init_gpf = (all_frames) ? gpl->frames.first : + BKE_gpencil_layer_frame_get( + gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (init_gpf == NULL) { + continue; + } + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* free stroke */ + if ((gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG)) { + BLI_remlink(&gpf->strokes, gps); + BKE_gpencil_free_stroke(gps); + } + } + if (!all_frames) { + break; + } + } + } +} + +static void extrapolate_points_by_length(bGPDspoint *a, + bGPDspoint *b, + float length, + float r_point[3]) +{ + float ab[3]; + sub_v3_v3v3(ab, &b->x, &a->x); + normalize_v3(ab); + mul_v3_fl(ab, length); + add_v3_v3v3(r_point, &b->x, ab); +} + +/* Loop all layers create stroke extensions. */ +static void gpencil_create_extensions(tGPDfill *tgpf) +{ + Object *ob = tgpf->ob; + bGPdata *gpd = tgpf->gpd; + Brush *brush = tgpf->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + + bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); + BLI_assert(gpl_active != NULL); + + const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); + BLI_assert(gpl_active_index >= 0); + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + + /* Decide if the strokes of layers are included or not depending on the layer mode. */ + const int gpl_index = BLI_findindex(&gpd->layers, gpl); + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); + if (skip) { + continue; + } + + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* Check if stroke can be drawn. */ + if ((gps->points == NULL) || (gps->totpoints < 2)) { + continue; + } + if (gps->flag & (GP_STROKE_NOFILL | GP_STROKE_TAG)) { + continue; + } + /* Check if the color is visible. */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) { + continue; + } + + /* Extend start. */ + bGPDspoint *pt0 = &gps->points[1]; + bGPDspoint *pt1 = &gps->points[0]; + bGPDstroke *gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + bGPDspoint *pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); + + /* Extend end. */ + pt0 = &gps->points[gps->totpoints - 2]; + pt1 = &gps->points[gps->totpoints - 1]; + gps_new = BKE_gpencil_stroke_new(gps->mat_nr, 2, gps->thickness); + gps_new->flag |= GP_STROKE_NOFILL | GP_STROKE_TAG; + BLI_addtail(&gpf->strokes, gps_new); + + pt = &gps_new->points[0]; + copy_v3_v3(&pt->x, &pt1->x); + pt->strength = 1.0f; + pt->pressure = 1.0f; + + pt = &gps_new->points[1]; + pt->strength = 1.0f; + pt->pressure = 1.0f; + extrapolate_points_by_length(pt0, pt1, tgpf->fill_extend_fac * 0.1f, &pt->x); + } + } +} + +static void gpencil_update_extend(tGPDfill *tgpf) +{ + gpencil_delete_temp_stroke_extension(tgpf, false); + + if (tgpf->fill_extend_fac > 0.0f) { + gpencil_create_extensions(tgpf); + } + WM_event_add_notifier(tgpf->C, NC_GPENCIL | NA_EDITED, NULL); +} + +static bool gpencil_stroke_is_drawable(tGPDfill *tgpf, bGPDstroke *gps) +{ + if (tgpf->is_render) { + return true; + } + + const bool show_help = (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) != 0; + const bool show_extend = (tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) != 0; + const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); + + if ((!show_help) && (show_extend)) { + if (!is_extend) { + return false; + } + } + + if ((show_help) && (!show_extend)) { + if (is_extend) { + return false; + } + } + + return true; +} + /* draw a given stroke using same thickness and color for all points */ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, bGPDstroke *gps, @@ -171,7 +357,8 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, const bool cyclic, const float ink[4], const int flag, - const float thershold) + const float thershold, + const float thickness) { bGPDspoint *points = gps->points; @@ -181,9 +368,19 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, int totpoints = gps->totpoints; float fpt[3]; float col[4]; + const float extend_col[4] = {0.0f, 1.0f, 1.0f, 1.0f}; + const bool is_extend = (gps->flag & GP_STROKE_NOFILL) && (gps->flag & GP_STROKE_TAG); - copy_v4_v4(col, ink); + if (!gpencil_stroke_is_drawable(tgpf, gps)) { + return; + } + if ((is_extend) && (!tgpf->is_render)) { + copy_v4_v4(col, extend_col); + } + else { + copy_v4_v4(col, ink); + } /* if cyclic needs more vertex */ int cyclic_add = (cyclic) ? 1 : 0; @@ -194,7 +391,7 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); /* draw stroke curve */ - GPU_line_width(1.0f); + GPU_line_width((!is_extend) ? thickness : thickness * 2.0f); immBeginAtMost(GPU_PRIM_LINE_STRIP, totpoints + cyclic_add); const bGPDspoint *pt = points; @@ -225,15 +422,77 @@ static void gpencil_draw_basic_stroke(tGPDfill *tgpf, immUnbindProgram(); } -/* loop all layers */ -static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) +static void draw_mouse_position(tGPDfill *tgpf) { - /* duplicated: etempFlags */ - enum { - GP_DRAWFILLS_NOSTATUS = (1 << 0), /* don't draw status info */ - GP_DRAWFILLS_ONLY3D = (1 << 1), /* only draw 3d-strokes */ - }; + if (tgpf->gps_mouse == NULL) { + return; + } + uchar mouse_color[4] = {0, 0, 255, 255}; + bGPDspoint *pt = &tgpf->gps_mouse->points[0]; + float point_size = (tgpf->zoom == 1.0f) ? 4.0f * tgpf->fill_factor : + (0.5f * tgpf->zoom) + tgpf->fill_factor; + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint col = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); + + /* Draw mouse click position in Blue. */ + immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR); + GPU_point_size(point_size); + immBegin(GPU_PRIM_POINTS, 1); + immAttr4ubv(col, mouse_color); + immVertex3fv(pos, &pt->x); + immEnd(); + immUnbindProgram(); +} + +/* Helper: Check if must skip the layer */ +bool skip_layer_check(short fill_layer_mode, int gpl_active_index, int gpl_index) +{ + bool skip = false; + + switch (fill_layer_mode) { + case GP_FILL_GPLMODE_ACTIVE: { + if (gpl_index != gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ABOVE: { + if (gpl_index != gpl_active_index + 1) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_BELOW: { + if (gpl_index != gpl_active_index - 1) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ALL_ABOVE: { + if (gpl_index <= gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_ALL_BELOW: { + if (gpl_index >= gpl_active_index) { + skip = true; + } + break; + } + case GP_FILL_GPLMODE_VISIBLE: + default: + break; + } + + return skip; +} + +/* Loop all layers to draw strokes. */ +static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) +{ Object *ob = tgpf->ob; bGPdata *gpd = tgpf->gpd; Brush *brush = tgpf->brush; @@ -247,8 +506,8 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) tgpw.gpd = gpd; tgpw.offsx = 0; tgpw.offsy = 0; - tgpw.winx = tgpf->region->winx; - tgpw.winy = tgpf->region->winy; + tgpw.winx = tgpf->sizex; + tgpw.winy = tgpf->sizey; tgpw.dflag = 0; tgpw.disable_fill = 1; tgpw.dflag |= (GP_DRAWFILLS_ONLY3D | GP_DRAWFILLS_NOSTATUS); @@ -261,54 +520,22 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); BLI_assert(gpl_active_index >= 0); - LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { - /* calculate parent position */ - BKE_gpencil_parent_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Draw blue point where click with mouse. */ + draw_mouse_position(tgpf); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* do not draw layer if hidden */ if (gpl->flag & GP_LAYER_HIDE) { continue; } + /* calculate parent position */ + BKE_gpencil_layer_transform_matrix_get(tgpw.depsgraph, ob, gpl, tgpw.diff_mat); + /* Decide if the strokes of layers are included or not depending on the layer mode. * Cannot skip the layer because it can use boundary strokes and must be used. */ - bool skip = false; const int gpl_index = BLI_findindex(&gpd->layers, gpl); - switch (brush_settings->fill_layer_mode) { - case GP_FILL_GPLMODE_ACTIVE: { - if (gpl_index != gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ABOVE: { - if (gpl_index != gpl_active_index + 1) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_BELOW: { - if (gpl_index != gpl_active_index - 1) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ALL_ABOVE: { - if (gpl_index <= gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_ALL_BELOW: { - if (gpl_index >= gpl_active_index) { - skip = true; - } - break; - } - case GP_FILL_GPLMODE_VISIBLE: - default: - break; - } + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); /* if active layer and no keyframe, create a new one */ if (gpl == tgpf->gpl) { @@ -351,17 +578,19 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) tgpw.gpf = gpf; tgpw.t_gpf = gpf; - /* reduce thickness to avoid gaps */ tgpw.is_fill_stroke = (tgpf->fill_draw_mode == GP_FILL_DMODE_CONTROL) ? false : true; + /* Reduce thickness to avoid gaps. */ tgpw.lthick = gpl->line_change; tgpw.opacity = 1.0; copy_v4_v4(tgpw.tintcolor, ink); tgpw.onion = true; tgpw.custonion = true; - /* normal strokes */ + /* Normal strokes. */ if (ELEM(tgpf->fill_draw_mode, GP_FILL_DMODE_STROKE, GP_FILL_DMODE_BOTH)) { - ED_gpencil_draw_fill(&tgpw); + if (gpencil_stroke_is_drawable(tgpf, gps) && ((gps->flag & GP_STROKE_TAG) == 0)) { + ED_gpencil_draw_fill(&tgpw); + } } /* 3D Lines with basic shapes and invisible lines */ @@ -372,7 +601,8 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) gps->flag & GP_STROKE_CYCLIC, ink, tgpf->flag, - tgpf->fill_threshold); + tgpf->fill_threshold, + 1.0f); } } } @@ -380,7 +610,7 @@ static void gpencil_draw_datablock(tGPDfill *tgpf, const float ink[4]) GPU_blend(GPU_BLEND_NONE); } -/* draw strokes in offscreen buffer */ +/* Draw strokes in off-screen buffer. */ static bool gpencil_render_offscreen(tGPDfill *tgpf) { bool is_ortho = false; @@ -391,15 +621,15 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } /* set temporary new size */ - tgpf->bwinx = tgpf->region->winx; - tgpf->bwiny = tgpf->region->winy; + tgpf->bwinx = tgpf->region->sizex; + tgpf->bwiny = tgpf->region->sizey; tgpf->brect = tgpf->region->winrct; /* resize region */ tgpf->region->winrct.xmin = 0; tgpf->region->winrct.ymin = 0; - tgpf->region->winrct.xmax = (int)tgpf->region->winx * tgpf->fill_factor; - tgpf->region->winrct.ymax = (int)tgpf->region->winy * tgpf->fill_factor; + tgpf->region->winrct.xmax = max_ii((int)tgpf->region->winx * tgpf->fill_factor, MIN_WINDOW_SIZE); + tgpf->region->winrct.ymax = max_ii((int)tgpf->region->winy * tgpf->fill_factor, MIN_WINDOW_SIZE); tgpf->region->winx = (short)abs(tgpf->region->winrct.xmax - tgpf->region->winrct.xmin); tgpf->region->winy = (short)abs(tgpf->region->winrct.ymax - tgpf->region->winrct.ymin); @@ -407,12 +637,6 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) tgpf->sizex = (int)tgpf->region->winx; tgpf->sizey = (int)tgpf->region->winy; - /* adjust center */ - float center[2]; - center[0] = (float)tgpf->center[0] * ((float)tgpf->region->winx / (float)tgpf->bwinx); - center[1] = (float)tgpf->center[1] * ((float)tgpf->region->winy / (float)tgpf->bwiny); - round_v2i_v2fl(tgpf->center, center); - char err_out[256] = "unknown"; GPUOffScreen *offscreen = GPU_offscreen_create(tgpf->sizex, tgpf->sizey, true, false, err_out); if (offscreen == NULL) { @@ -421,7 +645,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } GPU_offscreen_bind(offscreen, true); - uint flag = IB_rect | IB_rectfloat; + uint flag = IB_rectfloat; ImBuf *ibuf = IMB_allocImBuf(tgpf->sizex, tgpf->sizey, 32, flag); rctf viewplane; @@ -436,6 +660,21 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) &clip_start, &clip_end, NULL); + + /* Rescale `viewplane` to fit all strokes. */ + float width = viewplane.xmax - viewplane.xmin; + float height = viewplane.ymax - viewplane.ymin; + + float width_new = width * tgpf->zoom; + float height_new = height * tgpf->zoom; + float scale_x = (width_new - width) / 2.0f; + float scale_y = (height_new - height) / 2.0f; + + viewplane.xmin -= scale_x; + viewplane.xmax += scale_x; + viewplane.ymin -= scale_y; + viewplane.ymax += scale_y; + if (is_ortho) { orthographic_m4(winmat, viewplane.xmin, @@ -456,7 +695,7 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) } GPU_matrix_push_projection(); - GPU_matrix_identity_set(); + GPU_matrix_identity_projection_set(); GPU_matrix_push(); GPU_matrix_identity_set(); @@ -495,45 +734,33 @@ static bool gpencil_render_offscreen(tGPDfill *tgpf) BKE_image_release_ibuf(tgpf->ima, ibuf, NULL); - /* switch back to window-system-provided framebuffer */ + /* Switch back to window-system-provided frame-buffer. */ GPU_offscreen_unbind(offscreen, true); GPU_offscreen_free(offscreen); return true; } -/* return pixel data (rgba) at index */ +/* Return pixel data (RGBA) at index. */ static void get_pixel(const ImBuf *ibuf, const int idx, float r_col[4]) { - if (ibuf->rect_float) { - const float *frgba = &ibuf->rect_float[idx * 4]; - copy_v4_v4(r_col, frgba); - } - else { - /* XXX: This case probably doesn't happen, as we only write to the float buffer, - * but we get compiler warnings about uninitialized vars otherwise - */ - BLI_assert(!"gpencil_fill.c - get_pixel() non-float case is used!"); - zero_v4(r_col); - } + BLI_assert(ibuf->rect_float != NULL); + memcpy(r_col, &ibuf->rect_float[idx * 4], sizeof(float[4])); } -/* set pixel data (rgba) at index */ +/* Set pixel data (RGBA) at index. */ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) { - // BLI_assert(idx <= ibuf->x * ibuf->y); - if (ibuf->rect) { - uint *rrect = &ibuf->rect[idx]; - uchar ccol[4]; - - rgba_float_to_uchar(ccol, col); - *rrect = *((uint *)ccol); - } + BLI_assert(ibuf->rect_float != NULL); + float *rrectf = &ibuf->rect_float[idx * 4]; + copy_v4_v4(rrectf, col); +} - if (ibuf->rect_float) { - float *rrectf = &ibuf->rect_float[idx * 4]; - copy_v4_v4(rrectf, col); - } +/* Helper: Check if one image row is empty. */ +static bool is_row_filled(const ImBuf *ibuf, const int row_index) +{ + float *row = &ibuf->rect_float[ibuf->x * 4 * row_index]; + return (row[0] == 0.0f && memcmp(row, row + 1, ((ibuf->x * 4) - 1) * sizeof(float)) != 0); } /** @@ -541,6 +768,9 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) * this is used for strokes with small gaps between them to get a full fill * and do not get a full screen fill. * + * This function assumes that if the furthest pixel is occupied, + * the other pixels are occupied. + * * \param ibuf: Image pixel data. * \param maxpixel: Maximum index. * \param limit: Limit of pixels to analyze. @@ -550,10 +780,10 @@ static void set_pixel(ImBuf *ibuf, int idx, const float col[4]) static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index, int type) { float rgba[4]; - int i; int pt; bool t_a = false; bool t_b = false; + const int extreme = limit - 1; /* Horizontal leak (check vertical pixels) * X @@ -564,37 +794,29 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index */ if (type == LEAK_HORZ) { /* pixels on top */ - for (i = 1; i <= limit; i++) { - pt = index + (ibuf->x * i); - if (pt <= maxpixel) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_a = true; - break; - } - } - else { - /* edge of image*/ + pt = index + (ibuf->x * extreme); + if (pt <= maxpixel) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { t_a = true; - break; } } + else { + /* edge of image*/ + t_a = true; + } /* pixels on bottom */ - for (i = 1; i <= limit; i++) { - pt = index - (ibuf->x * i); - if (pt >= 0) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_b = true; - break; - } - } - else { - /* edge of image*/ + pt = index - (ibuf->x * extreme); + if (pt >= 0) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { t_b = true; - break; } } + else { + /* edge of image*/ + t_b = true; + } } /* Vertical leak (check horizontal pixels) @@ -608,35 +830,27 @@ static bool is_leak_narrow(ImBuf *ibuf, const int maxpixel, int limit, int index int higpix = lowpix + ibuf->x - 1; /* pixels to right */ - for (i = 0; i < limit; i++) { - pt = index - (limit - i); - if (pt >= lowpix) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_a = true; - break; - } - } - else { - t_a = true; /* edge of image*/ - break; + pt = index - extreme; + if (pt >= lowpix) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { + t_a = true; } } + else { + t_a = true; /* edge of image*/ + } /* pixels to left */ - for (i = 0; i < limit; i++) { - pt = index + (limit - i); - if (pt <= higpix) { - get_pixel(ibuf, pt, rgba); - if (rgba[0] == 1.0f) { - t_b = true; - break; - } - } - else { - t_b = true; /* edge of image */ - break; + pt = index + extreme; + if (pt <= higpix) { + get_pixel(ibuf, pt, rgba); + if (rgba[0] == 1.0f) { + t_b = true; } } + else { + t_b = true; /* edge of image */ + } } return (bool)(t_a && t_b); } @@ -659,23 +873,37 @@ static void gpencil_boundaryfill_area(tGPDfill *tgpf) BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__); - /* calculate index of the seed point using the position of the mouse */ - int index = (tgpf->sizex * tgpf->center[1]) + tgpf->center[0]; + /* Calculate index of the seed point using the position of the mouse looking + * for a blue pixel. */ + int index = -1; + for (int i = 0; i < maxpixel; i++) { + get_pixel(ibuf, i, rgba); + if (rgba[2] == 1.0f) { + index = i; + break; + } + } + if ((index >= 0) && (index <= maxpixel)) { - BLI_stack_push(stack, &index); + if (!FILL_DEBUG) { + BLI_stack_push(stack, &index); + } } - /* the fill use a stack to save the pixel list instead of the common recursive + /** + * The fill use a stack to save the pixel list instead of the common recursive * 4-contact point method. * The problem with recursive calls is that for big fill areas, we can get max limit * of recursive calls and STACK_OVERFLOW error. * * The 4-contact point analyze the pixels to the left, right, bottom and top - * ----------- - * | X | - * | XoX | - * | X | - * ----------- + * <pre> + * ----------- + * | X | + * | XoX | + * | X | + * ----------- + * </pre> */ while (!BLI_stack_is_empty(stack)) { int v; @@ -763,7 +991,7 @@ static void gpencil_set_borders(tGPDfill *tgpf, const bool transparent) tgpf->ima->id.tag |= LIB_TAG_DOIT; } -/* Invert image to paint invese area. */ +/* Invert image to paint inverse area. */ static void gpencil_invert_image(tGPDfill *tgpf) { ImBuf *ibuf; @@ -773,18 +1001,24 @@ static void gpencil_invert_image(tGPDfill *tgpf) ibuf = BKE_image_acquire_ibuf(tgpf->ima, NULL, &lock); const int maxpixel = (ibuf->x * ibuf->y) - 1; + const int center = ibuf->x / 2; for (int v = maxpixel; v != 0; v--) { float color[4]; get_pixel(ibuf, v, color); - /* Green. */ + /* Green->Red. */ if (color[1] == 1.0f) { set_pixel(ibuf, v, fill_col[0]); } + /* Red->Green */ else if (color[0] == 1.0f) { set_pixel(ibuf, v, fill_col[1]); + /* Add thickness of 2 pixels to avoid too thin lines. */ + int offset = (v % ibuf->x < center) ? 1 : -1; + set_pixel(ibuf, v + offset, fill_col[1]); } else { + /* Set to Transparent. */ set_pixel(ibuf, v, fill_col[2]); } } @@ -821,21 +1055,37 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) float rgba[4]; for (int idy = 0; idy < ibuf->y; idy++) { - bool clear = false; + int init = -1; + int end = -1; for (int idx = 0; idx < ibuf->x; idx++) { int image_idx = ibuf->x * idy + idx; get_pixel(ibuf, image_idx, rgba); /* Blue. */ if (rgba[2] == 1.0f) { - clear = true; + if (init < 0) { + init = image_idx; + } + else { + end = image_idx; + } } /* Red. */ else if (rgba[0] == 1.0f) { - clear = false; + if (init > -1) { + for (int i = init; i <= max_ii(init, end); i++) { + set_pixel(ibuf, i, clear_col); + } + init = -1; + end = -1; + } } - if (clear) { - set_pixel(ibuf, image_idx, clear_col); + } + /* Check last segment. */ + if (init > -1) { + for (int i = init; i <= max_ii(init, end); i++) { + set_pixel(ibuf, i, clear_col); } + set_pixel(ibuf, init, clear_col); } } @@ -845,98 +1095,112 @@ static void gpencil_erase_processed_area(tGPDfill *tgpf) tgpf->ima->id.tag |= LIB_TAG_DOIT; } -/* Naive dilate +/** + * Naive dilate * * Expand green areas into enclosing red areas. * Using stack prevents creep when replacing colors directly. + * <pre> * ----------- * XXXXXXX * XoooooX * XXooXXX * XXXX * ----------- + * </pre> */ -static void dilate_shape(ImBuf *ibuf) +static bool dilate_shape(ImBuf *ibuf) { + bool done = false; + BLI_Stack *stack = BLI_stack_new(sizeof(int), __func__); const float green[4] = {0.0f, 1.0f, 0.0f, 1.0f}; - const int maxpixel = (ibuf->x * ibuf->y) - 1; + // const int maxpixel = (ibuf->x * ibuf->y) - 1; /* detect pixels and expand into red areas */ - for (int v = maxpixel; v != 0; v--) { - float color[4]; - int index; - int tp = 0; - int bm = 0; - int lt = 0; - int rt = 0; - get_pixel(ibuf, v, color); - if (color[1] == 1.0f) { - /* pixel left */ - if (v - 1 >= 0) { - index = v - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - lt = index; + for (int row = 0; row < ibuf->y; row++) { + if (!is_row_filled(ibuf, row)) { + continue; + } + int maxpixel = (ibuf->x * (row + 1)) - 1; + int minpixel = ibuf->x * row; + + for (int v = maxpixel; v != minpixel; v--) { + float color[4]; + int index; + get_pixel(ibuf, v, color); + if (color[1] == 1.0f) { + int tp = 0; + int bm = 0; + int lt = 0; + int rt = 0; + + /* pixel left */ + if (v - 1 >= 0) { + index = v - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + lt = index; + } } - } - /* pixel right */ - if (v + 1 <= maxpixel) { - index = v + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - rt = index; + /* pixel right */ + if (v + 1 <= maxpixel) { + index = v + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + rt = index; + } } - } - /* pixel top */ - if (v + ibuf->x <= maxpixel) { - index = v + ibuf->x; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - tp = index; + /* pixel top */ + if (v + (ibuf->x * 1) <= maxpixel) { + index = v + (ibuf->x * 1); + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + tp = index; + } } - } - /* pixel bottom */ - if (v - ibuf->x >= 0) { - index = v - ibuf->x; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); - bm = index; + /* pixel bottom */ + if (v - (ibuf->x * 1) >= 0) { + index = v - (ibuf->x * 1); + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + bm = index; + } } - } - /* pixel top-left */ - if (tp && lt) { - index = tp - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel top-left */ + if (tp && lt) { + index = tp - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel top-right */ - if (tp && rt) { - index = tp + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel top-right */ + if (tp && rt) { + index = tp + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel bottom-left */ - if (bm && lt) { - index = bm - 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel bottom-left */ + if (bm && lt) { + index = bm - 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } - } - /* pixel bottom-right */ - if (bm && rt) { - index = bm + 1; - get_pixel(ibuf, index, color); - if (color[0] == 1.0f) { - BLI_stack_push(stack, &index); + /* pixel bottom-right */ + if (bm && rt) { + index = bm + 1; + get_pixel(ibuf, index, color); + if (color[0] == 1.0f) { + BLI_stack_push(stack, &index); + } } } } @@ -946,8 +1210,11 @@ static void dilate_shape(ImBuf *ibuf) int v; BLI_stack_pop(stack, &v); set_pixel(ibuf, v, green); + done = true; } BLI_stack_free(stack); + + return done; } /* Get the outline points of a shape using Moore Neighborhood algorithm @@ -963,11 +1230,12 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) int v[2]; int boundary_co[2]; int start_co[2]; + int first_co[2] = {-1, -1}; int backtracked_co[2]; int current_check_co[2]; int prev_check_co[2]; int backtracked_offset[1][2] = {{0, 0}}; - // bool boundary_found = false; + bool first_pixel = false; bool start_found = false; const int NEIGHBOR_COUNT = 8; @@ -992,7 +1260,6 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) dilate_shape(ibuf); } - /* find the initial point to start outline analysis */ for (int idx = imagesize - 1; idx != 0; idx--) { get_pixel(ibuf, idx, rgba); if (rgba[1] == 1.0f) { @@ -1015,7 +1282,7 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) int cur_back_offset = -1; for (int i = 0; i < NEIGHBOR_COUNT; i++) { if (backtracked_offset[0][0] == offset[i][0] && backtracked_offset[0][1] == offset[i][1]) { - /* Finding the bracktracked pixel offset index */ + /* Finding the back-tracked pixel offset index */ cur_back_offset = i; break; } @@ -1045,19 +1312,24 @@ static void gpencil_get_outline_points(tGPDfill *tgpf, const bool dilate) cur_back_offset++; loop++; } - /* current pixel is equal to starting pixel */ - if (boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) { + /* Current pixel is equal to starting or first pixel. */ + if ((boundary_co[0] == start_co[0] && boundary_co[1] == start_co[1]) || + (boundary_co[0] == first_co[0] && boundary_co[1] == first_co[1])) { BLI_stack_pop(tgpf->stack, &v); - // boundary_found = true; break; } + + if (!first_pixel) { + first_pixel = true; + copy_v2_v2_int(first_co, boundary_co); + } } /* release ibuf */ BKE_image_release_ibuf(tgpf->ima, ibuf, lock); } -/* get z-depth array to reproject on surface */ +/* Get z-depth array to reproject on surface. */ static void gpencil_get_depth_array(tGPDfill *tgpf) { tGPspoint *ptc; @@ -1108,7 +1380,7 @@ static void gpencil_get_depth_array(tGPDfill *tgpf) } if (found_depth == false) { - /* eeh... not much we can do.. :/, ignore depth in this case */ + /* Sigh! not much we can do here. Ignore depth in this case. */ for (i = totpoints - 1; i >= 0; i--) { tgpf->depth_arr[i] = 0.9999f; } @@ -1171,6 +1443,9 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) return; } + /* Set as done. */ + tgpf->done = true; + /* Get frame or create a new one. */ tgpf->gpf = BKE_gpencil_layer_frame_get(tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); @@ -1275,7 +1550,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) float origin[3]; ED_gpencil_drawing_reference_get(tgpf->scene, tgpf->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpf->scene, tgpf->ob, tgpf->rv3d, gps, origin, tgpf->lock_axis - 1); + tgpf->scene, tgpf->ob, tgpf->rv3d, tgpf->gpl, gps, origin, tgpf->lock_axis - 1); } /* if parented change position relative to parent object */ @@ -1326,7 +1601,6 @@ static void gpencil_fill_draw_3d(const bContext *C, ARegion *UNUSED(region), voi if (region != tgpf->region) { return; } - gpencil_draw_boundary_lines(C, tgpf); } @@ -1377,6 +1651,10 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->win = CTX_wm_window(C); tgpf->active_cfra = CFRA; + /* Setup space conversions. */ + gpencil_point_conversion_init(C, &tgpf->gsc); + tgpf->zoom = 1.0f; + /* set GP datablock */ tgpf->gpd = gpd; tgpf->gpl = BKE_gpencil_layer_active_get(gpd); @@ -1387,6 +1665,7 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) tgpf->lock_axis = ts->gp_sculpt.lock_axis; tgpf->oldkey = -1; + tgpf->is_render = false; tgpf->sbuffer_used = 0; tgpf->sbuffer = NULL; tgpf->depth_arr = NULL; @@ -1395,11 +1674,13 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) Brush *brush = BKE_paint_brush(&ts->gp_paint->paint); tgpf->brush = brush; tgpf->flag = brush->gpencil_settings->flag; - tgpf->fill_leak = brush->gpencil_settings->fill_leak; tgpf->fill_threshold = brush->gpencil_settings->fill_threshold; tgpf->fill_simplylvl = brush->gpencil_settings->fill_simplylvl; tgpf->fill_draw_mode = brush->gpencil_settings->fill_draw_mode; - tgpf->fill_factor = (short)max_ii(1, min_ii((int)brush->gpencil_settings->fill_factor, 8)); + tgpf->fill_extend_fac = brush->gpencil_settings->fill_extend_fac; + tgpf->fill_factor = max_ff(GPENCIL_MIN_FILL_FAC, + min_ff(brush->gpencil_settings->fill_factor, GPENCIL_MAX_FILL_FAC)); + tgpf->fill_leak = (int)ceil((float)brush->gpencil_settings->fill_leak * tgpf->fill_factor); int totcol = tgpf->ob->totcol; @@ -1424,7 +1705,6 @@ static tGPDfill *gpencil_session_init_fill(bContext *C, wmOperator *UNUSED(op)) /* end operator */ static void gpencil_fill_exit(bContext *C, wmOperator *op) { - Main *bmain = CTX_data_main(C); Object *ob = CTX_data_active_object(C); /* clear undo stack */ @@ -1443,16 +1723,14 @@ static void gpencil_fill_exit(bContext *C, wmOperator *op) MEM_SAFE_FREE(tgpf->sbuffer); MEM_SAFE_FREE(tgpf->depth_arr); + /* Remove any temp stroke. */ + gpencil_delete_temp_stroke_extension(tgpf, true); + /* remove drawing handler */ if (tgpf->draw_handle_3d) { ED_region_draw_cb_exit(tgpf->region->type, tgpf->draw_handle_3d); } - /* Delete temp image. */ - if (tgpf->ima) { - BKE_id_free(bmain, tgpf->ima); - } - /* finally, free memory used by temp data */ MEM_freeN(tgpf); } @@ -1536,7 +1814,11 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE tgpf = op->customdata; /* Enable custom drawing handlers to show help lines */ - if (tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) { + const bool do_extend = (tgpf->fill_extend_fac > 0.0f); + const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || + ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + + if (help_lines) { tgpf->draw_handle_3d = ED_region_draw_cb_activate( tgpf->region->type, gpencil_fill_draw_3d, tgpf, REGION_DRAW_POST_VIEW); } @@ -1554,17 +1836,210 @@ static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE return OPERATOR_RUNNING_MODAL; } +/* Helper: Calc the maximum bounding box size of strokes to get the zoom level of the viewport. + * For each stroke, the 2D projected bounding box is calculated and using this data, the total + * object bounding box (all strokes) is calculated. */ +static void gpencil_zoom_level_set(tGPDfill *tgpf) +{ + Brush *brush = tgpf->brush; + if (brush->gpencil_settings->flag & GP_BRUSH_FILL_FIT_DISABLE) { + tgpf->zoom = 1.0f; + return; + } + + Object *ob = tgpf->ob; + bGPdata *gpd = tgpf->gpd; + BrushGpencilSettings *brush_settings = tgpf->brush->gpencil_settings; + bGPDlayer *gpl_active = BKE_gpencil_layer_active_get(gpd); + BLI_assert(gpl_active != NULL); + + const int gpl_active_index = BLI_findindex(&gpd->layers, gpl_active); + BLI_assert(gpl_active_index >= 0); + + /* Init maximum boundbox size. */ + rctf rect_max; + const float winx_half = tgpf->region->winx / 2.0f; + const float winy_half = tgpf->region->winy / 2.0f; + BLI_rctf_init(&rect_max, + 0.0f - winx_half, + tgpf->region->winx + winx_half, + 0.0f - winy_half, + tgpf->region->winy + winy_half); + + float objectbox_min[2], objectbox_max[2]; + INIT_MINMAX2(objectbox_min, objectbox_max); + rctf rect_bound; + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + if (gpl->flag & GP_LAYER_HIDE) { + continue; + } + float diff_mat[4][4]; + /* calculate parent matrix */ + BKE_gpencil_layer_transform_matrix_get(tgpf->depsgraph, ob, gpl, diff_mat); + + /* Decide if the strokes of layers are included or not depending on the layer mode. + * Cannot skip the layer because it can use boundary strokes and must be used. */ + const int gpl_index = BLI_findindex(&gpd->layers, gpl); + bool skip = skip_layer_check(brush_settings->fill_layer_mode, gpl_active_index, gpl_index); + + /* Get frame to check. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, tgpf->active_cfra, GP_GETFRAME_USE_PREV); + if (gpf == NULL) { + continue; + } + + /* Read all strokes. */ + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + /* check if stroke can be drawn */ + if ((gps->points == NULL) || (gps->totpoints < 2)) { + continue; + } + /* check if the color is visible */ + MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); + if ((gp_style == NULL) || (gp_style->flag & GP_MATERIAL_HIDE)) { + continue; + } + + /* If the layer must be skipped, but the stroke is not boundary, skip stroke. */ + if ((skip) && ((gps->flag & GP_STROKE_NOFILL) == 0)) { + continue; + } + + float boundbox_min[2]; + float boundbox_max[2]; + ED_gpencil_projected_2d_bound_box(&tgpf->gsc, gps, diff_mat, boundbox_min, boundbox_max); + minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_min); + minmax_v2v2_v2(objectbox_min, objectbox_max, boundbox_max); + } + } + /* Clamp max bound box. */ + BLI_rctf_init( + &rect_bound, objectbox_min[0], objectbox_max[0], objectbox_min[1], objectbox_max[1]); + float r_xy[2]; + BLI_rctf_clamp(&rect_bound, &rect_max, r_xy); + + /* Calculate total width used. */ + float width = tgpf->region->winx; + if (rect_bound.xmin < 0.0f) { + width -= rect_bound.xmin; + } + if (rect_bound.xmax > tgpf->region->winx) { + width += rect_bound.xmax - tgpf->region->winx; + } + /* Calculate total height used. */ + float height = tgpf->region->winy; + if (rect_bound.ymin < 0.0f) { + height -= rect_bound.ymin; + } + if (rect_bound.ymax > tgpf->region->winy) { + height += rect_bound.ymax - tgpf->region->winy; + } + + width = ceilf(width); + height = ceilf(height); + + float zoomx = (width > tgpf->region->winx) ? width / (float)tgpf->region->winx : 1.0f; + float zoomy = (height > tgpf->region->winy) ? height / (float)tgpf->region->winy : 1.0f; + if ((zoomx != 1.0f) || (zoomy != 1.0f)) { + tgpf->zoom = min_ff(max_ff(zoomx, zoomy) * 1.5f, 5.0f); + } +} + +static bool gpencil_do_frame_fill(tGPDfill *tgpf, const bool is_inverted) +{ + wmWindow *win = CTX_wm_window(tgpf->C); + + /* render screen to temp image */ + int totpoints = 1; + if (gpencil_render_offscreen(tgpf)) { + + /* Set red borders to create a external limit. */ + gpencil_set_borders(tgpf, true); + + /* apply boundary fill */ + gpencil_boundaryfill_area(tgpf); + + /* Invert direction if press Ctrl. */ + if (is_inverted) { + gpencil_invert_image(tgpf); + } + + /* Clean borders to avoid infinite loops. */ + gpencil_set_borders(tgpf, false); + WM_cursor_time(win, 50); + int totpoints_prv = 0; + int loop_limit = 0; + while (totpoints > 0) { + /* analyze outline */ + gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false); + + /* create array of points from stack */ + totpoints = gpencil_points_from_stack(tgpf); + + /* create z-depth array for reproject */ + gpencil_get_depth_array(tgpf); + + /* create stroke and reproject */ + gpencil_stroke_from_buffer(tgpf); + + if (is_inverted) { + gpencil_erase_processed_area(tgpf); + } + else { + /* Exit of the loop. */ + totpoints = 0; + } + + /* free temp stack data */ + if (tgpf->stack) { + BLI_stack_free(tgpf->stack); + } + WM_cursor_time(win, 100); + + /* Free memory. */ + MEM_SAFE_FREE(tgpf->sbuffer); + MEM_SAFE_FREE(tgpf->depth_arr); + + /* Limit very small areas. */ + if (totpoints < 3) { + break; + } + /* Limit infinite loops is some corner cases. */ + if (totpoints_prv == totpoints) { + loop_limit++; + if (loop_limit > 3) { + break; + } + } + totpoints_prv = totpoints; + } + + /* Delete temp image. */ + if ((tgpf->ima) && (!FILL_DEBUG)) { + BKE_id_free(tgpf->bmain, tgpf->ima); + } + + return true; + } + + return false; +} + /* events handling during interactive part of operator */ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGPDfill *tgpf = op->customdata; - Scene *scene = tgpf->scene; Brush *brush = tgpf->brush; BrushGpencilSettings *brush_settings = brush->gpencil_settings; + tgpf->on_back = RNA_boolean_get(op->ptr, "on_back"); + const bool is_brush_inv = brush_settings->fill_direction == BRUSH_DIR_IN; const bool is_inverted = (is_brush_inv && !event->ctrl) || (!is_brush_inv && event->ctrl); - - int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through */ + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(tgpf->gpd); + const bool do_extend = (tgpf->fill_extend_fac > 0.0f); + const bool help_lines = ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) || + ((tgpf->flag & GP_BRUSH_FILL_SHOW_EXTENDLINES) && (do_extend))); + int estate = OPERATOR_RUNNING_MODAL; switch (event->type) { case EVT_ESCKEY: @@ -1572,82 +2047,104 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; break; case LEFTMOUSE: - tgpf->on_back = RNA_boolean_get(op->ptr, "on_back"); /* first time the event is not enabled to show help lines. */ - if ((tgpf->oldkey != -1) || ((tgpf->flag & GP_BRUSH_FILL_SHOW_HELPLINES) == 0)) { + if ((tgpf->oldkey != -1) || (!help_lines)) { ARegion *region = BKE_area_find_region_xy( CTX_wm_area(C), RGN_TYPE_ANY, event->x, event->y); if (region) { bool in_bounds = false; - /* Perform bounds check */ in_bounds = BLI_rcti_isect_pt(®ion->winrct, event->x, event->y); if ((in_bounds) && (region->regiontype == RGN_TYPE_WINDOW)) { - tgpf->center[0] = event->mval[0]; - tgpf->center[1] = event->mval[1]; - - /* Set active frame as current for filling. */ - tgpf->active_cfra = CFRA; + tgpf->mouse[0] = event->mval[0]; + tgpf->mouse[1] = event->mval[1]; + tgpf->is_render = true; + /* Define Zoom level. */ + gpencil_zoom_level_set(tgpf); + + /* Create Temp stroke. */ + tgpf->gps_mouse = BKE_gpencil_stroke_new(0, 1, 10.0f); + tGPspoint point2D; + bGPDspoint *pt = &tgpf->gps_mouse->points[0]; + copy_v2fl_v2i(&point2D.x, tgpf->mouse); + gpencil_stroke_convertcoords_tpoint( + tgpf->scene, tgpf->region, tgpf->ob, &point2D, NULL, &pt->x); + + /* If not multiframe and there is no frame in CFRA for the active layer, create + * a new frame before to make the hash function can find something. */ + if (!is_multiedit) { + tgpf->gpf = BKE_gpencil_layer_frame_get( + tgpf->gpl, tgpf->active_cfra, GP_GETFRAME_ADD_NEW); + tgpf->gpf->flag |= GP_FRAME_SELECT; + } - /* render screen to temp image */ - int totpoints = 1; - if (gpencil_render_offscreen(tgpf)) { + /* Hash of selected frames.*/ + GHash *frame_list = BLI_ghash_int_new_ex(__func__, 64); + BKE_gpencil_frame_selected_hash(tgpf->gpd, frame_list); - /* Set red borders to create a external limit. */ - gpencil_set_borders(tgpf, true); + /* Loop all frames. */ + wmWindow *win = CTX_wm_window(C); - /* apply boundary fill */ - gpencil_boundaryfill_area(tgpf); + GHashIterator gh_iter; + int total = BLI_ghash_len(frame_list); + int i = 1; + GHASH_ITER (gh_iter, frame_list) { + /* Set active frame as current for filling. */ + tgpf->active_cfra = POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter)); + int step = ((float)i / (float)total) * 100.0f; + WM_cursor_time(win, step); - /* Invert direction if press Ctrl. */ - if (is_inverted) { - gpencil_invert_image(tgpf); + if (do_extend) { + gpencil_update_extend(tgpf); } - /* Clean borders to avoid infinite loops. */ - gpencil_set_borders(tgpf, false); - - while (totpoints > 0) { - /* analyze outline */ - gpencil_get_outline_points(tgpf, (totpoints == 1) ? true : false); - - /* create array of points from stack */ - totpoints = gpencil_points_from_stack(tgpf); - - /* create z-depth array for reproject */ - gpencil_get_depth_array(tgpf); - - /* create stroke and reproject */ - gpencil_stroke_from_buffer(tgpf); - - if (is_inverted) { - gpencil_erase_processed_area(tgpf); - } - else { - /* Exit of the loop. */ - totpoints = 0; - } - - /* free temp stack data */ - if (tgpf->stack) { - BLI_stack_free(tgpf->stack); + /* Repeat loop until get something. */ + tgpf->done = false; + int loop_limit = 0; + while ((!tgpf->done) && (loop_limit < 2)) { + WM_cursor_time(win, loop_limit + 1); + /* Render screen to temp image and do fill. */ + gpencil_do_frame_fill(tgpf, is_inverted); + + /* restore size */ + tgpf->region->winx = (short)tgpf->bwinx; + tgpf->region->winy = (short)tgpf->bwiny; + tgpf->region->winrct = tgpf->brect; + if (!tgpf->done) { + /* If the zoom was not set before, avoid a loop. */ + if (tgpf->zoom == 1.0f) { + loop_limit++; + } + else { + tgpf->zoom = 1.0f; + tgpf->fill_factor = max_ff( + GPENCIL_MIN_FILL_FAC, + min_ff(brush->gpencil_settings->fill_factor, GPENCIL_MAX_FILL_FAC)); + } } + loop_limit++; + } - /* Free memory. */ - MEM_SAFE_FREE(tgpf->sbuffer); - MEM_SAFE_FREE(tgpf->depth_arr); + if (do_extend) { + gpencil_delete_temp_stroke_extension(tgpf, true); } + + i++; } + WM_cursor_modal_restore(win); + /* Free hash table. */ + BLI_ghash_free(frame_list, NULL, NULL); - /* restore size */ - tgpf->region->winx = (short)tgpf->bwinx; - tgpf->region->winy = (short)tgpf->bwiny; - tgpf->region->winrct = tgpf->brect; + /* Free temp stroke. */ + BKE_gpencil_free_stroke(tgpf->gps_mouse); /* push undo data */ gpencil_undo_push(tgpf->gpd); + /* Save extend value for next operation. */ + brush_settings->fill_extend_fac = tgpf->fill_extend_fac; + estate = OPERATOR_FINISHED; } else { @@ -1658,8 +2155,29 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) estate = OPERATOR_CANCELLED; } } + else if (do_extend) { + gpencil_update_extend(tgpf); + } tgpf->oldkey = event->type; break; + case EVT_PAGEUPKEY: + case WHEELUPMOUSE: + if (tgpf->oldkey == 1) { + tgpf->fill_extend_fac -= (event->shift) ? 0.01f : 0.1f; + CLAMP_MIN(tgpf->fill_extend_fac, 0.0f); + gpencil_update_extend(tgpf); + } + break; + case EVT_PAGEDOWNKEY: + case WHEELDOWNMOUSE: + if (tgpf->oldkey == 1) { + tgpf->fill_extend_fac += (event->shift) ? 0.01f : 0.1f; + CLAMP_MAX(tgpf->fill_extend_fac, 100.0f); + gpencil_update_extend(tgpf); + } + break; + default: + break; } /* process last operations before exiting */ switch (estate) { @@ -1672,7 +2190,7 @@ static int gpencil_fill_modal(bContext *C, wmOperator *op, const wmEvent *event) gpencil_fill_exit(C, op); break; - case OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH: + default: break; } diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 4a908eff92e..5fea46626d5 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -667,7 +667,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -678,7 +679,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ @@ -718,7 +719,8 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ /* loop over strokes */ \ bGPDstroke *gpsn_; \ @@ -767,8 +769,10 @@ struct GP_EditableStrokes_Iter { bGPDframe *init_gpf_ = (is_multiedit_) ? gpl->frames.first : gpl->actframe; \ for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \ if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \ - BKE_gpencil_parent_matrix_get(depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ - invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \ + BKE_gpencil_layer_transform_matrix_get( \ + depsgraph_, obact_, gpl, gpstroke_iter.diff_mat); \ + /* Undo layer transform. */ \ + mul_m4_m4m4(gpstroke_iter.diff_mat, gpstroke_iter.diff_mat, gpl->layer_invmat); \ /* loop over strokes */ \ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf_->strokes) { \ /* skip strokes that are invalid for current view */ \ @@ -776,7 +780,7 @@ struct GP_EditableStrokes_Iter { continue; \ } \ /* check if the color is editable */ \ - if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) { \ + if (ED_gpencil_stroke_material_editable(obact_, gpl, gps) == false) { \ continue; \ } \ /* ... Do Stuff With Strokes ... */ diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index c666fcb67b7..ecd243ed595 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -48,31 +48,22 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_report.h" #include "UI_interface.h" -#include "UI_resources.h" #include "WM_api.h" #include "WM_types.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "UI_view2d.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_space_api.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" @@ -229,7 +220,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } @@ -283,8 +274,8 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) tgpil = MEM_callocN(sizeof(tGPDinterpolate_layer), "GPencil Interpolate Layer"); tgpil->gpl = gpl; - tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); - tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); + tgpil->prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe, true); + tgpil->nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next, true); BLI_addtail(&tgpi->ilayers, tgpil); @@ -315,7 +306,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi) } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, tgpil->gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, tgpil->gpl, gps_from) == false) { valid = false; } @@ -734,7 +725,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING; /* properties */ - RNA_def_float_percentage( + RNA_def_float_factor( ot->srna, "shift", 0.0f, @@ -1008,8 +999,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) } /* store extremes */ - prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe); - nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next); + prevFrame = BKE_gpencil_frame_duplicate(gpl->actframe, true); + nextFrame = BKE_gpencil_frame_duplicate(gpl->actframe->next, true); /* Loop over intermediary frames and create the interpolation */ for (cframe = prevFrame->framenum + step; cframe < nextFrame->framenum; cframe += step) { @@ -1048,7 +1039,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps_from) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps_from) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c index 272dff56291..435bff34998 100644 --- a/source/blender/editors/gpencil/gpencil_merge.c +++ b/source/blender/editors/gpencil/gpencil_merge.c @@ -48,12 +48,9 @@ #include "RNA_define.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_mesh.c b/source/blender/editors/gpencil/gpencil_mesh.c index 53beaeaa6a0..ffe676f0520 100644 --- a/source/blender/editors/gpencil/gpencil_mesh.c +++ b/source/blender/editors/gpencil/gpencil_mesh.c @@ -36,8 +36,6 @@ #include "BKE_anim_data.h" #include "BKE_context.h" #include "BKE_duplilist.h" -#include "BKE_global.h" -#include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_layer.h" #include "BKE_main.h" diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 0a29b83bc4f..1a6cb5670c4 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -27,9 +27,7 @@ #include "BLI_sys_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_gpencil.h" #include "BKE_paint.h" #include "DNA_brush_types.h" @@ -45,9 +43,6 @@ #include "RNA_access.h" #include "ED_gpencil.h" -#include "ED_object.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "gpencil_intern.h" diff --git a/source/blender/editors/gpencil/gpencil_ops_versioning.c b/source/blender/editors/gpencil/gpencil_ops_versioning.c index 815bbbaa254..45842c28dff 100644 --- a/source/blender/editors/gpencil/gpencil_ops_versioning.c +++ b/source/blender/editors/gpencil/gpencil_ops_versioning.c @@ -34,16 +34,12 @@ #include "DNA_gpencil_types.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "WM_api.h" @@ -53,7 +49,6 @@ #include "RNA_define.h" #include "ED_gpencil.h" -#include "ED_object.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index ed56f004ca4..b833125cf34 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -426,7 +426,7 @@ static void gpencil_reproject_toplane(tGPsdata *p, bGPDstroke *gps) /* get drawing origin */ gpencil_get_3d_reference(p, origin); - ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, gps, origin, p->lock_axis - 1); + ED_gpencil_project_stroke_to_plane(p->scene, obact, rv3d, p->gpl, gps, origin, p->lock_axis - 1); } /* convert screen-coordinates to buffer-coordinates */ @@ -887,11 +887,13 @@ static short gpencil_stroke_addpoint(tGPsdata *p, gpencil_get_3d_reference(p, origin); /* reproject current */ ED_gpencil_tpoint_to_point(p->region, origin, pt, &spt); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(p->region, origin, ptb, &spt2); - ED_gpencil_project_point_to_plane(p->scene, obact, rv3d, origin, p->lock_axis - 1, &spt2); + ED_gpencil_project_point_to_plane( + p->scene, obact, p->gpl, rv3d, origin, p->lock_axis - 1, &spt2); p->totpixlen += len_v3v3(&spt.x, &spt2.x); pt->uv_fac = p->totpixlen; } @@ -1304,6 +1306,12 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gpd, gps); + /* In Multiframe mode, duplicate the stroke in other frames. */ + if (GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd)) { + const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK); + BKE_gpencil_stroke_copy_to_keyframes(gpd, gpl, p->gpf, gps, tail); + } + gpencil_stroke_added_enable(p); } @@ -1321,10 +1329,8 @@ static float view3d_point_depth(const RegionView3D *rv3d, const float co[3]) } /* only erase stroke points that are visible */ -static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, - const bGPDspoint *pt, - const int x, - const int y) +static bool gpencil_stroke_eraser_is_occluded( + tGPsdata *p, bGPDlayer *gpl, const bGPDspoint *pt, const int x, const int y) { Object *obact = (Object *)p->ownerPtr.data; Brush *brush = p->brush; @@ -1341,7 +1347,6 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, if ((gp_settings != NULL) && (p->area->spacetype == SPACE_VIEW3D) && (gp_settings->flag & GP_BRUSH_OCCLUDE_ERASER)) { RegionView3D *rv3d = p->region->regiondata; - bGPDlayer *gpl = p->gpl; const int mval_i[2] = {x, y}; float mval_3d[3]; @@ -1349,7 +1354,7 @@ static bool gpencil_stroke_eraser_is_occluded(tGPsdata *p, float diff_mat[4][4]; /* calculate difference matrix if parent object */ - BKE_gpencil_parent_matrix_get(p->depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, obact, gpl, diff_mat); if (ED_view3d_autodist_simple(p->region, mval_i, mval_3d, 0, NULL)) { const float depth_mval = view3d_point_depth(rv3d, mval_3d); @@ -1452,6 +1457,7 @@ static void gpencil_stroke_soft_refine(bGPDstroke *gps) /* eraser tool - evaluation per stroke */ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, + bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const float mval[2], @@ -1577,9 +1583,9 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, * - this assumes that linewidth is irrelevant */ if (gpencil_stroke_inside_circle(mval, radius, pc0[0], pc0[1], pc2[0], pc2[1])) { - if ((gpencil_stroke_eraser_is_occluded(p, pt0, pc0[0], pc0[1]) == false) || - (gpencil_stroke_eraser_is_occluded(p, pt1, pc1[0], pc1[1]) == false) || - (gpencil_stroke_eraser_is_occluded(p, pt2, pc2[0], pc2[1]) == false)) { + if ((gpencil_stroke_eraser_is_occluded(p, gpl, pt0, pc0[0], pc0[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, gpl, pt1, pc1[0], pc1[1]) == false) || + (gpencil_stroke_eraser_is_occluded(p, gpl, pt2, pc2[0], pc2[1]) == false)) { /* Point is affected: */ /* Adjust thickness * - Influence of eraser falls off with distance from the middle of the eraser @@ -1681,6 +1687,8 @@ static void gpencil_stroke_eraser_dostroke(tGPsdata *p, /* erase strokes which fall under the eraser strokes */ static void gpencil_stroke_doeraser(tGPsdata *p) { + const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(p->gpd); + rcti rect; Brush *brush = p->brush; Brush *eraser = p->eraser; @@ -1721,40 +1729,53 @@ static void gpencil_stroke_doeraser(tGPsdata *p) * on multiple layers... */ LISTBASE_FOREACH (bGPDlayer *, gpl, &p->gpd->layers) { - bGPDframe *gpf = gpl->actframe; - /* only affect layer if it's editable (and visible) */ if (BKE_gpencil_layer_is_editable(gpl) == false) { continue; } - if (gpf == NULL) { + + bGPDframe *init_gpf = (is_multiedit) ? gpl->frames.first : gpl->actframe; + if (init_gpf == NULL) { continue; } - /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); - /* loop over strokes, checking segments for intersections */ - LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { - /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(p->ob, gpl, gps) == false) { - continue; - } + for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) { + if ((gpf == gpl->actframe) || ((gpf->flag & GP_FRAME_SELECT) && (is_multiedit))) { + if (gpf == NULL) { + continue; + } + /* calculate difference matrix */ + BKE_gpencil_layer_transform_matrix_get(p->depsgraph, p->ob, gpl, p->diff_mat); + + /* loop over strokes, checking segments for intersections */ + LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) { + /* check if the color is editable */ + if (ED_gpencil_stroke_material_editable(p->ob, gpl, gps) == false) { + continue; + } - /* Check if the stroke collide with mouse. */ - if (!ED_gpencil_stroke_check_collision(&p->gsc, gps, p->mval, calc_radius, p->diff_mat)) { - continue; - } + /* Check if the stroke collide with mouse. */ + if (!ED_gpencil_stroke_check_collision( + &p->gsc, gps, p->mval, calc_radius, p->diff_mat)) { + continue; + } - /* Not all strokes in the datablock may be valid in the current editor/context - * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) - */ - if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { - gpencil_stroke_eraser_dostroke(p, gpf, gps, p->mval, calc_radius, &rect); + /* Not all strokes in the datablock may be valid in the current editor/context + * (e.g. 2D space strokes in the 3D view, if the same datablock is shared) + */ + if (ED_gpencil_stroke_can_use_direct(p->area, gps)) { + gpencil_stroke_eraser_dostroke(p, gpl, gpf, gps, p->mval, calc_radius, &rect); + } + } + + /* if not multiedit, exit loop*/ + if (!is_multiedit) { + break; + } } } } } - /* ******************************************* */ /* Sketching Operator */ @@ -2103,6 +2124,11 @@ static void gpencil_paint_initstroke(tGPsdata *p, copy_v3_v3(p->gpl->color, p->custom_color); } } + + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(p->gpl->layer_mat, p->gpl->location, p->gpl->rotation, p->gpl->scale); + invert_m4_m4(p->gpl->layer_invmat, p->gpl->layer_mat); + if ((paintmode != GP_PAINTMODE_ERASER) && (p->gpl->flag & GP_LAYER_LOCKED)) { p->status = GP_STATUS_ERROR; if (G.debug & G_DEBUG) { diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 53e0043df37..bcdde49b93d 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -317,6 +317,10 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) } tgpi->gpl = gpl; + /* Recalculate layer transform matrix to avoid problems if props are animated. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* create a new temporary frame */ tgpi->gpf = MEM_callocN(sizeof(bGPDframe), "Temp bGPDframe"); tgpi->gpf->framenum = tgpi->cframe = cfra; @@ -1004,12 +1008,12 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* reproject current */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tpt, &spt); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt); /* reproject previous */ ED_gpencil_tpoint_to_point(tgpi->region, origin, tptb, &spt2); ED_gpencil_project_point_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); + tgpi->scene, tgpi->ob, tgpi->gpl, tgpi->rv3d, origin, tgpi->lock_axis - 1, &spt2); tgpi->totpixlen += len_v3v3(&spt.x, &spt2.x); tpt->uv_fac = tgpi->totpixlen; } @@ -1068,7 +1072,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) float origin[3]; ED_gpencil_drawing_reference_get(tgpi->scene, tgpi->ob, ts->gpencil_v3d_align, origin); ED_gpencil_project_stroke_to_plane( - tgpi->scene, tgpi->ob, tgpi->rv3d, gps, origin, ts->gp_sculpt.lock_axis - 1); + tgpi->scene, tgpi->ob, tgpi->rv3d, tgpi->gpl, gps, origin, ts->gp_sculpt.lock_axis - 1); } /* if parented change position relative to parent object */ @@ -1373,6 +1377,12 @@ static void gpencil_primitive_interaction_end(bContext *C, BKE_gpencil_stroke_geometry_update(tgpi->gpd, gps); } + /* In Multiframe mode, duplicate the stroke in other frames. */ + if (GPENCIL_MULTIEDIT_SESSIONS_ON(tgpi->gpd)) { + const bool tail = (ts->gpencil_flags & GP_TOOL_FLAG_PAINT_ONBACK); + BKE_gpencil_stroke_copy_to_keyframes(tgpi->gpd, tgpi->gpl, gpf, gps, tail); + } + DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_COPY_ON_WRITE); DEG_id_tag_update(&tgpi->gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c index bb9dd8cac5d..0d3ab9011d6 100644 --- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c +++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c @@ -1441,11 +1441,6 @@ static bool gpencil_sculpt_brush_do_stroke(tGP_BrushEditData *gso, bool changed = false; float rot_eval = 0.0f; - /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { - return false; - } - if (gps->totpoints == 1) { bGPDspoint pt_temp; pt = &gps->points[0]; @@ -1577,6 +1572,13 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, Object *ob = gso->object; bGPdata *gpd = ob->data; char tool = gso->brush->gpencil_sculpt_tool; + GP_SpaceConversion *gsc = &gso->gsc; + Brush *brush = gso->brush; + const int radius = (brush->flag & GP_BRUSH_USE_PRESSURE) ? gso->brush->size * gso->pressure : + gso->brush->size; + /* Calc bound box matrix. */ + float bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(gso->depsgraph, gso->object, gpl, bound_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* skip strokes that are invalid for current view */ @@ -1584,7 +1586,12 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { + continue; + } + + /* Check if the stroke collide with brush. */ + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { continue; } @@ -1742,7 +1749,8 @@ static bool gpencil_sculpt_brush_apply_standard(bContext *C, tGP_BrushEditData * /* calculate difference matrix */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index 281ab8c5adc..a00d21bf88a 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -2473,7 +2473,7 @@ static void gpencil_selected_hue_table(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } if ((gps->flag & GP_STROKE_SELECT) == 0) { diff --git a/source/blender/editors/gpencil/gpencil_trace_ops.c b/source/blender/editors/gpencil/gpencil_trace_ops.c index 0be9d74278e..0f344909692 100644 --- a/source/blender/editors/gpencil/gpencil_trace_ops.c +++ b/source/blender/editors/gpencil/gpencil_trace_ops.c @@ -23,7 +23,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -31,34 +30,26 @@ #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" -#include "DNA_space_types.h" #include "BKE_context.h" -#include "BKE_duplilist.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_image.h" #include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "BKE_report.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" -#include "UI_interface.h" -#include "UI_resources.h" - #include "WM_api.h" #include "WM_types.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" -#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "ED_gpencil.h" @@ -66,7 +57,6 @@ #include "gpencil_intern.h" #include "gpencil_trace.h" -#include "potracelib.h" typedef struct TraceJob { /* from wmJob */ @@ -87,6 +77,7 @@ typedef struct TraceJob { bGPDlayer *gpl; bool was_ob_created; + bool use_current_frame; int32_t frame_target; float threshold; @@ -228,15 +219,17 @@ static void trace_start_job(void *customdata, short *stop, short *do_update, flo trace_job->do_update = do_update; trace_job->progress = progress; trace_job->was_canceled = false; + const int init_frame = max_ii((trace_job->use_current_frame) ? trace_job->frame_target : 0, 0); G.is_break = false; /* Single Image. */ - if ((trace_job->image->source == IMA_SRC_FILE) || (trace_job->mode == GPENCIL_TRACE_MODE_SINGLE)) { void *lock; - ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, NULL, &lock); + ImageUser *iuser = trace_job->ob_active->iuser; + iuser->framenr = init_frame; + ImBuf *ibuf = BKE_image_acquire_ibuf(trace_job->image, iuser, &lock); if (ibuf) { /* Create frame. */ bGPDframe *gpf = BKE_gpencil_layer_frame_get( @@ -249,7 +242,7 @@ static void trace_start_job(void *customdata, short *stop, short *do_update, flo /* Image sequence. */ else if (trace_job->image->type == IMA_TYPE_IMAGE) { ImageUser *iuser = trace_job->ob_active->iuser; - for (int i = 0; i < iuser->frames; i++) { + for (int i = init_frame; i < iuser->frames; i++) { if (G.is_break) { trace_job->was_canceled = true; break; @@ -320,6 +313,7 @@ static int gpencil_trace_image_exec(bContext *C, wmOperator *op) job->ob_active = job->base_active->object; job->image = (Image *)job->ob_active->data; job->frame_target = CFRA; + job->use_current_frame = RNA_boolean_get(op->ptr, "use_current_frame"); /* Create a new grease pencil object or reuse selected. */ eGP_TargetObjectMode target = RNA_enum_get(op->ptr, "target"); @@ -493,4 +487,9 @@ void GPENCIL_OT_trace_image(wmOperatorType *ot) GPENCIL_TRACE_MODE_SINGLE, "Mode", "Determines if trace simple image or full sequence"); + RNA_def_boolean(ot->srna, + "use_current_frame", + true, + "Start At Current Frame", + "Trace Image starting in current image frame"); } diff --git a/source/blender/editors/gpencil/gpencil_undo.c b/source/blender/editors/gpencil/gpencil_undo.c index c2504ce329e..4e172104ce7 100644 --- a/source/blender/editors/gpencil/gpencil_undo.c +++ b/source/blender/editors/gpencil/gpencil_undo.c @@ -36,6 +36,7 @@ #include "BKE_blender_undo.h" #include "BKE_context.h" #include "BKE_gpencil.h" +#include "BKE_undo_system.h" #include "ED_gpencil.h" @@ -61,28 +62,22 @@ int ED_gpencil_session_active(void) return (BLI_listbase_is_empty(&undo_nodes) == false); } -int ED_undo_gpencil_step(bContext *C, int step, const char *name) +int ED_undo_gpencil_step(bContext *C, const eUndoStepDir step) { bGPdata **gpd_ptr = NULL, *new_gpd = NULL; gpd_ptr = ED_gpencil_data_get_pointers(C, NULL); - if (step == 1) { /* undo */ - // printf("\t\tGP - undo step\n"); + if (step == STEP_UNDO) { if (cur_node->prev) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->prev; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->prev; + new_gpd = cur_node->gpd; } } - else if (step == -1) { - // printf("\t\tGP - redo step\n"); + else if (step == STEP_REDO) { if (cur_node->next) { - if (!name || STREQ(cur_node->name, name)) { - cur_node = cur_node->next; - new_gpd = cur_node->gpd; - } + cur_node = cur_node->next; + new_gpd = cur_node->gpd; } } @@ -99,7 +94,7 @@ int ED_undo_gpencil_step(bContext *C, int step, const char *name) LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* make a copy of source layer and its data */ - gpld = BKE_gpencil_layer_duplicate(gpl); + gpld = BKE_gpencil_layer_duplicate(gpl, true, true); BLI_addtail(&gpd->layers, gpld); } } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 7c796f7b7a1..9b12772bc9b 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -579,7 +579,7 @@ bool ED_gpencil_stroke_can_use(const bContext *C, const bGPDstroke *gps) } /* Check whether given stroke can be edited for the current color */ -bool ED_gpencil_stroke_color_use(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) +bool ED_gpencil_stroke_material_editable(Object *ob, const bGPDlayer *gpl, const bGPDstroke *gps) { /* check if the color is editable */ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -674,7 +674,7 @@ void gpencil_apply_parent(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, b float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); for (i = 0; i < gps->totpoints; i++) { @@ -697,10 +697,11 @@ void gpencil_apply_parent_point(Depsgraph *depsgraph, float inverse_diff_mat[4][4]; float fpt[3]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); mul_v3_m4v3(fpt, inverse_diff_mat, &pt->x); + copy_v3_v3(&pt->x, fpt); } @@ -997,6 +998,12 @@ void ED_gpencil_drawing_reference_get(const Scene *scene, else { /* use object location */ copy_v3_v3(r_vec, ob->obmat[3]); + /* Apply layer offset. */ + bGPdata *gpd = ob->data; + bGPDlayer *gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl != NULL) { + add_v3_v3(r_vec, gpl->layer_mat[3]); + } } } } @@ -1021,7 +1028,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * /* init space conversion stuff */ gpencil_point_conversion_init(C, &gsc); - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); /* Adjust each point */ @@ -1046,6 +1053,7 @@ void ED_gpencil_project_stroke_to_view(bContext *C, bGPDlayer *gpl, bGPDstroke * void ED_gpencil_project_stroke_to_plane(const Scene *scene, const Object *ob, const RegionView3D *rv3d, + bGPDlayer *gpl, bGPDstroke *gps, const float origin[3], const int axis) @@ -1058,6 +1066,10 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, float ray[3]; float rpoint[3]; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + /* normal vector for a plane locked to axis */ zero_v3(plane_normal); if (axis < 0) { @@ -1074,24 +1086,27 @@ void ED_gpencil_project_stroke_to_plane(const Scene *scene, copy_m4_m4(mat, ob->obmat); /* move origin to cursor */ + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { copy_v3_v3(mat[3], cursor->location); } mul_mat3_m4_v3(mat, plane_normal); } + + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } else { const float scale[3] = {1.0f, 1.0f, 1.0f}; plane_normal[2] = 1.0f; float mat[4][4]; loc_eul_size_to_mat4(mat, cursor->location, cursor->rotation_euler, scale); - - /* move origin to object */ - if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { - copy_v3_v3(mat[3], ob->obmat[3]); - } - mul_mat3_m4_v3(mat, plane_normal); } @@ -1127,8 +1142,12 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, ARegion *region = gsc->region; RegionView3D *rv3d = region->regiondata; + /* Recalculate layer transform matrix. */ + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + float diff_mat[4][4], inverse_diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, gsc->ob, gpl, diff_mat); invert_m4_m4(inverse_diff_mat, diff_mat); float origin[3]; @@ -1194,7 +1213,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, } } - ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2); + ED_gpencil_project_point_to_plane(gsc->scene, gsc->ob, gpl, rv3d, origin, axis, &pt2); copy_v3_v3(&pt->x, &pt2.x); @@ -1250,6 +1269,7 @@ void ED_gpencil_stroke_reproject(Depsgraph *depsgraph, */ void ED_gpencil_project_point_to_plane(const Scene *scene, const Object *ob, + bGPDlayer *gpl, const RegionView3D *rv3d, const float origin[3], const int axis, @@ -1277,6 +1297,11 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, if (ob && (ob->type == OB_GPENCIL)) { float mat[4][4]; copy_m4_m4(mat, ob->obmat); + if ((ts->gpencil_v3d_align & GP_PROJECT_CURSOR) == 0) { + if (gpl != NULL) { + add_v3_v3(mat[3], gpl->location); + } + } /* move origin to cursor */ if (ts->gpencil_v3d_align & GP_PROJECT_CURSOR) { @@ -1284,6 +1309,10 @@ void ED_gpencil_project_point_to_plane(const Scene *scene, } mul_mat3_m4_v3(mat, plane_normal); + /* Apply layer rotation (local transform). */ + if ((gpl != NULL) && (ts->gp_sculpt.lock_axis != GP_LOCKAXIS_CURSOR)) { + mul_mat3_m4_v3(gpl->layer_mat, plane_normal); + } } } else { @@ -1449,7 +1478,7 @@ void ED_gpencil_reset_layers_parent(Depsgraph *depsgraph, Object *obact, bGPdata /* only redo if any change */ if (!equals_m4m4(gpl->inverse, cur_mat)) { /* first apply current transformation to all strokes */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo local object */ sub_v3_v3(diff_mat[3], gpl_loc); @@ -2144,7 +2173,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat) LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { /* check if it is editable */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } gps_ma = BKE_gpencil_material(ob, gps->mat_nr + 1); @@ -3003,12 +3032,12 @@ void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, } } -/* Helper to get the bigger 2D bound box points. */ -static void gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, - bGPDstroke *gps, - const float diff_mat[4][4], - float r_min[2], - float r_max[2]) +/* Get the bigger 2D bound box points. */ +void ED_gpencil_projected_2d_bound_box(GP_SpaceConversion *gsc, + bGPDstroke *gps, + const float diff_mat[4][4], + float r_min[2], + float r_max[2]) { float bounds[8][2]; BoundBox bb; @@ -3053,7 +3082,7 @@ bool ED_gpencil_stroke_check_collision(GP_SpaceConversion *gsc, BKE_gpencil_stroke_boundingbox_calc(gps); } - gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max); + ED_gpencil_projected_2d_bound_box(gsc, gps, diff_mat, boundbox_min, boundbox_max); rcti rect_stroke = {boundbox_min[0], boundbox_max[0], boundbox_min[1], boundbox_max[1]}; @@ -3126,7 +3155,7 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, /* calculate difference matrix object */ float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); /* Calculate the extremes of the stroke in 2D. */ bGPDspoint pt_parent; @@ -3144,15 +3173,13 @@ bGPDstroke *ED_gpencil_stroke_nearest_to_ends(bContext *C, float dist_min = FLT_MAX; LISTBASE_FOREACH (bGPDstroke *, gps_target, &gpf->strokes) { /* Check if the color is editable. */ - if ((gps_target == gps) || (ED_gpencil_stroke_color_use(ob, gpl, gps) == false)) { + if ((gps_target == gps) || (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false)) { continue; } /* Check if one of the ends is inside target stroke bounding box. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_start, radius, diff_mat)) { - continue; - } - if (!ED_gpencil_stroke_check_collision(gsc, gps, pt2d_end, radius, diff_mat)) { + if ((!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_start, radius, diff_mat)) && + (!ED_gpencil_stroke_check_collision(gsc, gps_target, pt2d_end, radius, diff_mat))) { continue; } /* Check the distance of the ends with the ends of target stroke to avoid middle contact. diff --git a/source/blender/editors/gpencil/gpencil_uv.c b/source/blender/editors/gpencil/gpencil_uv.c index ec2ccabddfe..677451eaabc 100644 --- a/source/blender/editors/gpencil/gpencil_uv.c +++ b/source/blender/editors/gpencil/gpencil_uv.c @@ -31,7 +31,6 @@ #include "BKE_context.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_unit.h" #include "RNA_access.h" #include "RNA_define.h" diff --git a/source/blender/editors/gpencil/gpencil_vertex_ops.c b/source/blender/editors/gpencil/gpencil_vertex_ops.c index b212872b607..bf46fa2544f 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_ops.c +++ b/source/blender/editors/gpencil/gpencil_vertex_ops.c @@ -28,16 +28,11 @@ #include "BLI_ghash.h" #include "BLI_math.h" -#include "BLT_translation.h" - #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" #include "DNA_material_types.h" -#include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_gpencil.h" -#include "BKE_gpencil_modifier.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_paint.h" @@ -48,16 +43,11 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "UI_view2d.h" #include "ED_gpencil.h" #include "ED_screen.h" -#include "ED_view3d.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "gpencil_intern.h" @@ -674,7 +664,7 @@ static bool gpencil_extract_palette_from_vertex(bContext *C, if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1); @@ -859,7 +849,7 @@ static int gpencil_material_to_vertex_exec(bContext *C, wmOperator *op) if (ED_gpencil_stroke_can_use(C, gps) == false) { continue; } - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/gpencil/gpencil_vertex_paint.c b/source/blender/editors/gpencil/gpencil_vertex_paint.c index e2c81d53fba..a05cc3c4dbd 100644 --- a/source/blender/editors/gpencil/gpencil_vertex_paint.c +++ b/source/blender/editors/gpencil/gpencil_vertex_paint.c @@ -151,7 +151,7 @@ typedef struct tGP_BrushVertexpaintData { tGP_Grid *grid; /** Total number of rows/cols. */ int grid_size; - /** Total number of cells elments in the grid array. */ + /** Total number of cells elements in the grid array. */ int grid_len; /** Grid sample position (used to determine distance of falloff) */ int grid_sample[2]; @@ -825,7 +825,8 @@ static void gpencil_save_selected_point(tGP_BrushVertexpaintData *gso, static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, bGPDstroke *gps, const char tool, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -853,7 +854,7 @@ static bool gpencil_vertexpaint_select_stroke(tGP_BrushVertexpaintData *gso, } /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return false; } @@ -998,7 +999,8 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, tGP_BrushVertexpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); const char tool = ob->mode == OB_MODE_VERTEX_GPENCIL ? gso->brush->gpencil_vertex_tool : @@ -1020,12 +1022,12 @@ static bool gpencil_vertexpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat); + bool hit = gpencil_vertexpaint_select_stroke(gso, gps, tool, diff_mat, bound_mat); /* If stroke was hit and has an editcurve the curve needs an update. */ bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps; @@ -1130,9 +1132,11 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -1159,7 +1163,7 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert } /* affect strokes in this frame */ - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -1167,7 +1171,8 @@ static bool gpencil_vertexpaint_brush_apply_to_layers(bContext *C, tGP_BrushVert /* Apply to active frame's strokes */ if (gpl->actframe != NULL) { gso->mf_falloff = 1.0f; - changed |= gpencil_vertexpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_vertexpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/gpencil/gpencil_weight_paint.c b/source/blender/editors/gpencil/gpencil_weight_paint.c index 7fa71fcce3c..a3e5ece5862 100644 --- a/source/blender/editors/gpencil/gpencil_weight_paint.c +++ b/source/blender/editors/gpencil/gpencil_weight_paint.c @@ -383,7 +383,8 @@ static void gpencil_save_selected_point(tGP_BrushWeightpaintData *gso, /* Select points in this stroke and add to an array to be used later. */ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bGPDstroke *gps, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { GP_SpaceConversion *gsc = &gso->gsc; rcti *rect = &gso->brush_rect; @@ -402,7 +403,7 @@ static void gpencil_weightpaint_select_stroke(tGP_BrushWeightpaintData *gso, bool include_last = false; /* Check if the stroke collide with brush. */ - if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, diff_mat)) { + if (!ED_gpencil_stroke_check_collision(gsc, gps, gso->mval, radius, bound_mat)) { return; } @@ -505,7 +506,8 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, tGP_BrushWeightpaintData *gso, bGPDlayer *gpl, bGPDframe *gpf, - const float diff_mat[4][4]) + const float diff_mat[4][4], + const float bound_mat[4][4]) { Object *ob = CTX_data_active_object(C); char tool = gso->brush->gpencil_weight_tool; @@ -526,12 +528,12 @@ static bool gpencil_weightpaint_brush_do_frame(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(ob, gpl, gps) == false) { continue; } /* Check points below the brush. */ - gpencil_weightpaint_select_stroke(gso, gps, diff_mat); + gpencil_weightpaint_select_stroke(gso, gps, diff_mat, bound_mat); } /*--------------------------------------------------------------------- @@ -578,9 +580,11 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig continue; } - /* calculate difference matrix */ - float diff_mat[4][4]; - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + /* Calculate transform matrix. */ + float diff_mat[4][4], bound_mat[4][4]; + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); + copy_m4_m4(bound_mat, diff_mat); + mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_invmat); /* Active Frame or MultiFrame? */ if (gso->is_multiframe) { @@ -608,7 +612,7 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig } /* affect strokes in this frame */ - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpf, diff_mat, bound_mat); } } } @@ -616,7 +620,8 @@ static bool gpencil_weightpaint_brush_apply_to_layers(bContext *C, tGP_BrushWeig if (gpl->actframe != NULL) { /* Apply to active frame's strokes */ gso->mf_falloff = 1.0f; - changed |= gpencil_weightpaint_brush_do_frame(C, gso, gpl, gpl->actframe, diff_mat); + changed |= gpencil_weightpaint_brush_do_frame( + C, gso, gpl, gpl->actframe, diff_mat, bound_mat); } } } diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 0a66c439f79..56494f87bfe 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -99,6 +99,30 @@ void ED_space_clip_set_clip(struct bContext *C, struct Mask *ED_space_clip_get_mask(struct SpaceClip *sc); void ED_space_clip_set_mask(struct bContext *C, struct SpaceClip *sc, struct Mask *mask); +/* Locked state is used to preserve current clip editor viewport upon changes. Example usage: + * + * ... + * + * ClipViewLockState lock_state; + * ED_clip_view_lock_state_store(C, &lock_state); + * + * <change selection> + * + * ED_clip_view_lock_state_restore_no_jump(C, &lock_state); + * + * These function are to be used from space clip editor context only. Otherwise debug builds will + * assert, release builds will crash. */ + +typedef struct ClipViewLockState { + float offset_x, offset_y; + float lock_offset_x, lock_offset_y; + float zoom; +} ClipViewLockState; + +void ED_clip_view_lock_state_store(const struct bContext *C, ClipViewLockState *state); +void ED_clip_view_lock_state_restore_no_jump(const struct bContext *C, + const ClipViewLockState *state); + /* ** clip_ops.c ** */ void ED_operatormacros_clip(void); diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index d12882f0e29..7538dac1354 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -194,7 +194,7 @@ typedef enum FSMenuInsert { FS_INSERT_SAVE = (1 << 1), /** moves the item to the front of the list when its not already there */ FS_INSERT_FIRST = (1 << 2), - /** just append to preseve delivered order */ + /** just append to preserve delivered order */ FS_INSERT_LAST = (1 << 3), } FSMenuInsert; diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1b7caf27ecf..12aef6e9464 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -62,6 +62,8 @@ struct bAnimContext; struct wmKeyConfig; struct wmOperator; +enum eUndoStepDir; + #define GPENCIL_MINIMUM_JOIN_DIST 20.0f /* Reproject stroke modes. */ @@ -147,9 +149,9 @@ bool ED_gpencil_has_keyframe_v3d(struct Scene *scene, struct Object *ob, int cfr bool ED_gpencil_stroke_can_use_direct(const struct ScrArea *area, const struct bGPDstroke *gps); bool ED_gpencil_stroke_can_use(const struct bContext *C, const struct bGPDstroke *gps); -bool ED_gpencil_stroke_color_use(struct Object *ob, - const struct bGPDlayer *gpl, - const struct bGPDstroke *gps); +bool ED_gpencil_stroke_material_editable(struct Object *ob, + const struct bGPDlayer *gpl, + const struct bGPDstroke *gps); /* ----------- Grease Pencil Operators ----------------- */ @@ -213,7 +215,7 @@ bool ED_gpencil_anim_copybuf_paste(struct bAnimContext *ac, const short copy_mod /* ------------ Grease-Pencil Undo System ------------------ */ int ED_gpencil_session_active(void); -int ED_undo_gpencil_step(struct bContext *C, int step, const char *name); +int ED_undo_gpencil_step(struct bContext *C, const enum eUndoStepDir step); /* ------------ Grease-Pencil Armature ------------------ */ bool ED_gpencil_add_armature(const struct bContext *C, @@ -263,11 +265,13 @@ bool ED_object_gpencil_exit(struct Main *bmain, struct Object *ob); void ED_gpencil_project_stroke_to_plane(const struct Scene *scene, const struct Object *ob, const struct RegionView3D *rv3d, + struct bGPDlayer *gpl, struct bGPDstroke *gps, const float origin[3], const int axis); void ED_gpencil_project_point_to_plane(const struct Scene *scene, const struct Object *ob, + struct bGPDlayer *gpl, const struct RegionView3D *rv3d, const float origin[3], const int axis, @@ -366,6 +370,11 @@ bool ED_gpencil_stroke_point_is_inside(struct bGPDstroke *gps, struct GP_SpaceConversion *gsc, int mouse[2], const float diff_mat[4][4]); +void ED_gpencil_projected_2d_bound_box(struct GP_SpaceConversion *gsc, + struct bGPDstroke *gps, + const float diff_mat[4][4], + float r_min[2], + float r_max[2]); struct bGPDstroke *ED_gpencil_stroke_nearest_to_ends(struct bContext *C, struct GP_SpaceConversion *gsc, diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h index 3cc77887b1a..2f8faf1b2bd 100644 --- a/source/blender/editors/include/ED_keyframes_draw.h +++ b/source/blender/editors/include/ED_keyframes_draw.h @@ -95,6 +95,8 @@ typedef enum eActKeyBlock_Hold { ACTKEYBLOCK_FLAG_ANY_HOLD = (1 << 2), /* The curve segment uses non-bezier interpolation */ ACTKEYBLOCK_FLAG_NON_BEZIER = (1 << 3), + /* The block is grease pencil */ + ACTKEYBLOCK_FLAG_GPENCIL = (1 << 4), } eActKeyBlock_Flag; /* *********************** Keyframe Drawing ****************************** */ diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index b08ab57545f..63f124798aa 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -118,7 +118,7 @@ typedef struct KeyframeEdit_CircleData { } KeyframeEdit_CircleData; /* ************************************************ */ -/* Non-Destuctive Editing API (keyframes_edit.c) */ +/* Non-Destructive Editing API (keyframes_edit.c) */ /* --- Defines for 'OK' polls + KeyframeEditData Flags --------- */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index bcf52da3f69..247911bdc55 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -63,7 +63,10 @@ void ED_mask_point_pos__reverse( struct ScrArea *area, struct ARegion *region, float x, float y, float *xr, float *yr); void ED_mask_cursor_location_get(struct ScrArea *area, float cursor[2]); -bool ED_mask_selected_minmax(const struct bContext *C, float min[2], float max[2]); +bool ED_mask_selected_minmax(const struct bContext *C, + float min[2], + float max[2], + bool handles_as_control_point); /* mask_draw.c */ void ED_mask_draw(const struct bContext *C, const char draw_flag, const char draw_type); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 417cae800ea..78f354a300d 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -51,6 +51,10 @@ typedef enum { #define NODE_GRID_STEPS 5 /* space_node.c */ + +void ED_node_cursor_location_get(const struct SpaceNode *snode, float value[2]); +void ED_node_cursor_location_set(struct SpaceNode *snode, const float value[2]); + int ED_node_tree_path_length(struct SpaceNode *snode); void ED_node_tree_path_get(struct SpaceNode *snode, char *value); void ED_node_tree_path_get_fixedbuf(struct SpaceNode *snode, char *value, int max_length); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index bd1a4a0c63f..73326a2d5f2 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -159,7 +159,7 @@ extern struct EnumPropertyItem prop_clear_parent_types[]; extern struct EnumPropertyItem prop_make_parent_types[]; #endif -/* Set the object's parent, return true iff successful. */ +/* Set the object's parent, return true if successful. */ bool ED_object_parent_set(struct ReportList *reports, const struct bContext *C, struct Scene *scene, diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 20417634020..deb6b7502c7 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -57,15 +57,14 @@ struct wmMsgSubscribeKey; struct wmMsgSubscribeValue; struct wmNotifier; struct wmOperatorType; +struct wmRegionListenerParams; +struct wmRegionMessageSubscribeParams; +struct wmSpaceTypeListenerParams; struct wmWindow; struct wmWindowManager; /* regions */ -void ED_region_do_listen(struct wmWindow *win, - struct ScrArea *area, - struct ARegion *region, - struct wmNotifier *note, - const Scene *scene); +void ED_region_do_listen(struct wmRegionListenerParams *params); void ED_region_do_layout(struct bContext *C, struct ARegion *region); void ED_region_do_draw(struct bContext *C, struct ARegion *region); void ED_region_exit(struct bContext *C, struct ARegion *region); @@ -144,29 +143,11 @@ void ED_area_do_msg_notify_tag_refresh(struct bContext *C, struct wmMsgSubscribeKey *msg_key, struct wmMsgSubscribeValue *msg_val); -void ED_area_do_mgs_subscribe_for_tool_header(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); -void ED_area_do_mgs_subscribe_for_tool_ui(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_area_do_mgs_subscribe_for_tool_header(const struct wmRegionMessageSubscribeParams *params); +void ED_area_do_mgs_subscribe_for_tool_ui(const struct wmRegionMessageSubscribeParams *params); /* message bus */ -void ED_region_message_subscribe(struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_message_subscribe(struct wmRegionMessageSubscribeParams *params); /* spaces */ void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); @@ -178,7 +159,7 @@ void ED_area_exit(struct bContext *C, struct ScrArea *area); int ED_screen_area_active(const struct bContext *C); void ED_screen_global_areas_refresh(struct wmWindow *win); void ED_screen_global_areas_sync(struct wmWindow *win); -void ED_area_do_listen(struct wmWindow *win, ScrArea *area, struct wmNotifier *note, Scene *scene); +void ED_area_do_listen(struct wmSpaceTypeListenerParams *params); void ED_area_tag_redraw(ScrArea *area); void ED_area_tag_redraw_no_rebuild(ScrArea *area); void ED_area_tag_redraw_regiontype(ScrArea *area, int type); @@ -427,13 +408,8 @@ void ED_region_cache_draw_cached_segments(struct ARegion *region, const int efra); /* area_utils.c */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus); +void ED_region_generic_tools_region_message_subscribe( + const struct wmRegionMessageSubscribeParams *params); int ED_region_generic_tools_region_snap_size(const struct ARegion *region, int size, int axis); /* area_query.c */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index ca3e351a052..8f1be847e2b 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -40,7 +40,7 @@ void transform_operatortypes(void); /* ******************** Macros & Prototypes *********************** */ /* MODE AND NUMINPUT FLAGS */ -enum TfmMode { +typedef enum { TFM_INIT = -1, TFM_DUMMY, TFM_TRANSLATION, @@ -77,29 +77,11 @@ enum TfmMode { TFM_BONE_ENVELOPE_DIST, TFM_NORMAL_ROTATION, TFM_GPENCIL_OPACITY, -}; - -/* TRANSFORM CONTEXTS */ -#define CTX_NONE 0 -#define CTX_TEXTURE (1 << 0) -#define CTX_EDGE (1 << 1) -#define CTX_NO_PET (1 << 2) -#define CTX_NO_MIRROR (1 << 3) -#define CTX_AUTOCONFIRM (1 << 4) -#define CTX_MOVIECLIP (1 << 6) -#define CTX_MASK (1 << 7) -#define CTX_PAINT_CURVE (1 << 8) -#define CTX_GPENCIL_STROKES (1 << 9) -#define CTX_CURSOR (1 << 10) -/** When transforming object's, adjust the object data so it stays in the same place. */ -#define CTX_OBMODE_XFORM_OBDATA (1 << 11) -/** Transform object parents without moving their children. */ -#define CTX_OBMODE_XFORM_SKIP_CHILDREN (1 << 12) +} eTfmMode; /* Standalone call to get the transformation center corresponding to the current situation * returns 1 if successful, 0 otherwise (usually means there's no selection) - * (if 0 is returns, *vec is unmodified) - * */ + * (if false is returns, `cent3d` is unmodified). */ bool calculateTransformCenter(struct bContext *C, int centerMode, float cent3d[3], diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 7bbb7225f14..066d262cc44 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -56,6 +56,7 @@ struct bNode; struct bNodeSocket; struct bNodeTree; struct bScreen; +struct rctf; struct rcti; struct uiButSearch; struct uiFontStyle; @@ -414,57 +415,38 @@ void UI_draw_anti_tria( void UI_draw_anti_fan(float tri_array[][2], unsigned int length, const float color[4]); void UI_draw_roundbox_corner_set(int type); -void UI_draw_roundbox_aa( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]); -void UI_draw_roundbox_4fv( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]); -void UI_draw_roundbox_3ub_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, +void UI_draw_roundbox_aa(const struct rctf *rect, bool filled, float rad, const float color[4]); +void UI_draw_roundbox_4fv(const struct rctf *rect, bool filled, float rad, const float col[4]); +void UI_draw_roundbox_3ub_alpha(const struct rctf *rect, + bool filled, float rad, const unsigned char col[3], unsigned char alpha); -void UI_draw_roundbox_3fv_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const float col[3], - float alpha); -void UI_draw_roundbox_shade_x(bool filled, - float minx, - float miny, - float maxx, - float maxy, +void UI_draw_roundbox_3fv_alpha( + const struct rctf *rect, bool filled, float rad, const float col[3], float alpha); +void UI_draw_roundbox_shade_x(const struct rctf *rect, + bool filled, float rad, float shadetop, float shadedown, const float col[4]); +void UI_draw_roundbox_4fv_ex(const struct rctf *rect, + const float inner1[4], + const float inner2[4], + float shade_dir, + const float outline[4], + float outline_width, + float rad); #if 0 /* unused */ int UI_draw_roundbox_corner_get(void); -void UI_draw_roundbox_shade_y(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadeleft, - float shaderight, - const float col[4]); #endif -void UI_draw_box_shadow(unsigned char alpha, float minx, float miny, float maxx, float maxy); +void UI_draw_box_shadow(const struct rctf *rect, unsigned char alpha); void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]); void UI_draw_safe_areas(uint pos, - float x1, - float x2, - float y1, - float y2, + const struct rctf *rect, const float title_aspect[2], const float action_aspect[2]); @@ -526,6 +508,7 @@ typedef bool (*uiButSearchContextMenuFn)(struct bContext *C, const struct wmEvent *event); typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, struct ARegion *region, + const struct rcti *item_rect, void *arg, void *active); @@ -664,8 +647,7 @@ bool UI_popup_block_name_exists(const struct bScreen *screen, const char *name); * Begin/Define Buttons/End/Draw is the typical order in which these * function should be called, though for popup blocks Draw is left out. * Freeing blocks is done by the screen/ module automatically. - * - * */ + */ uiBlock *UI_block_begin(const struct bContext *C, struct ARegion *region, @@ -1431,6 +1413,8 @@ enum { int UI_icon_from_id(struct ID *id); int UI_icon_from_report_type(int type); +int UI_icon_colorid_from_report_type(int type); +int UI_text_colorid_from_report_type(int type); int UI_icon_from_event_type(short event_type, short event_value); int UI_icon_from_keymap_item(const struct wmKeyMapItem *kmi, int r_icon_mod[4]); @@ -2499,11 +2483,12 @@ void UI_context_active_but_prop_get_templateID(struct bContext *C, struct PropertyRNA **r_prop); struct ID *UI_context_active_but_get_tab_ID(struct bContext *C); -uiBut *UI_region_active_but_get(struct ARegion *region); +uiBut *UI_region_active_but_get(const struct ARegion *region); uiBut *UI_region_but_find_rect_over(const struct ARegion *region, const struct rcti *rect_px); uiBlock *UI_region_block_find_mouse_over(const struct ARegion *region, const int xy[2], bool only_clip); +struct ARegion *UI_region_searchbox_region_get(const struct ARegion *button_region); /* uiFontStyle.align */ typedef enum eFontStyle_Align { @@ -2583,6 +2568,21 @@ struct ARegion *UI_tooltip_create_from_button(struct bContext *C, struct ARegion *UI_tooltip_create_from_gizmo(struct bContext *C, struct wmGizmo *gz); void UI_tooltip_free(struct bContext *C, struct bScreen *screen, struct ARegion *region); +typedef struct { + /** A description for the item, e.g. what happens when selecting it. */ + char description[UI_MAX_DRAW_STR]; + /* The full name of the item, without prefixes or suffixes (e.g. hint with UI_SEP_CHARP). */ + const char *name; + /** Additional info about the item (e.g. library name of a linked data-block). */ + char hint[UI_MAX_DRAW_STR]; +} uiSearchItemTooltipData; + +struct ARegion *UI_tooltip_create_from_search_item_generic( + struct bContext *C, + const struct ARegion *searchbox_region, + const struct rcti *item_rect, + const uiSearchItemTooltipData *item_tooltip_data); + /* How long before a tool-tip shows. */ #define UI_TOOLTIP_DELAY 0.5 #define UI_TOOLTIP_DELAY_LABEL 0.2 diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index d77a87e7200..266a538b6c3 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -23,6 +23,9 @@ #pragma once +/* Required for #eIconSizes which can't be forward declared if this file is included in C++. */ +#include "DNA_ID_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,8 +37,6 @@ struct PreviewImage; struct Scene; struct bContext; -enum eIconSizes; - typedef struct IconFile { struct IconFile *next, *prev; char filename[256]; /* FILE_MAXFILE size */ diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index c09bf41e152..1820c2f133c 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -433,7 +433,7 @@ void UI_GetColorPtrBlendShade3ubv(const unsigned char cp1[3], * (for anything fancy use UI_GetThemeColor[Fancy] then BLF_color) */ void UI_FontThemeColor(int fontid, int colorid); -/* clear the framebuffer using the input colorid */ +/* Clear the frame-buffer using the input colorid. */ void UI_ThemeClearColor(int colorid); /* internal (blender) usage only, for init and set active */ diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index 8df29e5b520..64f881052a1 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -231,7 +231,7 @@ struct View2D *UI_view2d_fromcontext(const struct bContext *C); struct View2D *UI_view2d_fromcontext_rwin(const struct bContext *C); void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_y); -void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_scale_get(const struct View2D *v2d, float *r_x, float *r_y); float UI_view2d_scale_get_x(const struct View2D *v2d); float UI_view2d_scale_get_y(const struct View2D *v2d); void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 319ae385ffc..10cbc2dc5fa 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1284,12 +1284,10 @@ static bool ui_but_event_property_operator_string(const bContext *C, char *buf, const size_t buf_len) { - /* context toggle operator names to check... */ + /* Context toggle operator names to check. */ /* This function could use a refactor to generalize button type to operator relationship - * as well as which operators use properties. - * - Campbell - * */ + * as well as which operators use properties. - Campbell */ const char *ctx_toggle_opnames[] = { "WM_OT_context_toggle", "WM_OT_context_toggle_enum", @@ -1424,10 +1422,10 @@ static bool ui_but_event_property_operator_string(const bContext *C, // printf("prop shortcut: '%s' (%s)\n", RNA_property_identifier(prop), data_path); } - /* we have a datapath! */ + /* We have a data-path! */ bool found = false; if (data_path || (prop_enum_value_ok && prop_enum_value_id)) { - /* create a property to host the "datapath" property we're sending to the operators */ + /* Create a property to host the "data_path" property we're sending to the operators. */ IDProperty *prop_path; const IDPropertyTemplate val = {0}; @@ -1947,7 +1945,7 @@ void ui_fontscale(short *points, float aspect) } } -/* project button or block (but==NULL) to pixels in regionspace */ +/* Project button or block (but==NULL) to pixels in region-space. */ static void ui_but_to_pixelrect(rcti *rect, const ARegion *region, uiBlock *block, uiBut *but) { rctf rectf; @@ -4026,7 +4024,7 @@ static uiBut *ui_def_but(uiBlock *block, but->emboss = block->emboss; but->pie_dir = UI_RADIAL_NONE; - but->block = block; /* pointer back, used for frontbuffer status, and picker */ + but->block = block; /* pointer back, used for front-buffer status, and picker. */ if ((block->flag & UI_BUT_ALIGN) && ui_but_can_align(but)) { but->alignnr = block->alignnr; @@ -4749,7 +4747,7 @@ static int findBitIndex(uint x) return idx; } -/* autocomplete helper functions */ +/* Auto-complete helper functions. */ struct AutoComplete { size_t maxlen; int matches; diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 85730d138ac..53a04ec9db5 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -953,7 +953,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) } } - /* If the button reprents an id, it can set the "id" context pointer. */ + /* If the button represents an id, it can set the "id" context pointer. */ if (U.experimental.use_asset_browser && ED_asset_can_make_single_from_context(C)) { ID *id = CTX_data_pointer_get_type(C, "id", &RNA_ID).data; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 5bb6b0f21e7..d10cdc207c2 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -81,544 +81,116 @@ int UI_draw_roundbox_corner_get(void) } #endif -void UI_draw_roundbox_3ub_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const uchar col[3], - uchar alpha) +void UI_draw_roundbox_4fv_ex(const rctf *rect, + const float inner1[4], + const float inner2[4], + float shade_dir, + const float outline[4], + float outline_width, + float rad) { - float colv[4]; - colv[0] = ((float)col[0]) / 255; - colv[1] = ((float)col[1]) / 255; - colv[2] = ((float)col[2]) / 255; - colv[3] = ((float)alpha) / 255; - UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); -} - -void UI_draw_roundbox_3fv_alpha(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - const float col[3], - float alpha) -{ - float colv[4]; - colv[0] = col[0]; - colv[1] = col[1]; - colv[2] = col[2]; - colv[3] = alpha; - UI_draw_roundbox_4fv(filled, minx, miny, maxx, maxy, rad, colv); -} - -void UI_draw_roundbox_aa( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float color[4]) -{ - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, - .radi = rad, - .rad = rad, - .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, - .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, - .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, - .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = filled ? color[0] : 0.0f, - .color_inner1[1] = filled ? color[1] : 0.0f, - .color_inner1[2] = filled ? color[2] : 0.0f, - .color_inner1[3] = filled ? color[3] : 0.0f, - .color_inner2[0] = filled ? color[0] : 0.0f, - .color_inner2[1] = filled ? color[1] : 0.0f, - .color_inner2[2] = filled ? color[2] : 0.0f, - .color_inner2[3] = filled ? color[3] : 0.0f, - .color_outline[0] = color[0], - .color_outline[1] = color[1], - .color_outline[2] = color[2], - .color_outline[3] = color[3], - .alpha_discard = 1.0f, - }; - - /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect - * of the previous AA method. Better fix the callers. */ - if (filled) { - widget_params.color_inner1[3] *= 0.65f; - widget_params.color_inner2[3] *= 0.65f; - widget_params.color_outline[3] *= 0.65f; - } - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. * If it has been scaled, then it's no longer valid. */ - - GPUBatch *batch = ui_batch_roundbox_widget_get(); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - - GPU_blend(GPU_BLEND_ALPHA); - - GPU_batch_draw(batch); - - GPU_blend(GPU_BLEND_NONE); -} - -void UI_draw_roundbox_4fv( - bool filled, float minx, float miny, float maxx, float maxy, float rad, const float col[4]) -{ -#if 0 - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - int a; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - uint vert_len = 0; - vert_len += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_len += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4fv(col); - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_len); - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - immVertex2f(pos, maxx - rad, miny); - for (a = 0; a < 7; a++) { - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - immVertex2f(pos, maxx, miny + rad); - } - else { - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - immVertex2f(pos, maxx, maxy - rad); - for (a = 0; a < 7; a++) { - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - immVertex2f(pos, maxx - rad, maxy); - } - else { - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - immVertex2f(pos, minx + rad, maxy); - for (a = 0; a < 7; a++) { - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - immVertex2f(pos, minx, maxy - rad); - } - else { - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - immVertex2f(pos, minx, miny + rad); - for (a = 0; a < 7; a++) { - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } - immVertex2f(pos, minx + rad, miny); - } - else { - immVertex2f(pos, minx, miny); - } - - immEnd(); - immUnbindProgram(); -#endif uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, + .recti.xmin = rect->xmin + outline_width, + .recti.ymin = rect->ymin + outline_width, + .recti.xmax = rect->xmax - outline_width, + .recti.ymax = rect->ymax - outline_width, + .rect = *rect, .radi = rad, .rad = rad, .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = filled ? col[0] : 0.0f, - .color_inner1[1] = filled ? col[1] : 0.0f, - .color_inner1[2] = filled ? col[2] : 0.0f, - .color_inner1[3] = filled ? col[3] : 0.0f, - .color_inner2[0] = filled ? col[0] : 0.0f, - .color_inner2[1] = filled ? col[1] : 0.0f, - .color_inner2[2] = filled ? col[2] : 0.0f, - .color_inner2[3] = filled ? col[3] : 0.0f, - .color_outline[0] = col[0], - .color_outline[1] = col[1], - .color_outline[2] = col[2], - .color_outline[3] = col[3], + .color_inner1[0] = inner1 ? inner1[0] : 0.0f, + .color_inner1[1] = inner1 ? inner1[1] : 0.0f, + .color_inner1[2] = inner1 ? inner1[2] : 0.0f, + .color_inner1[3] = inner1 ? inner1[3] : 0.0f, + .color_inner2[0] = inner2 ? inner2[0] : inner1 ? inner1[0] : 0.0f, + .color_inner2[1] = inner2 ? inner2[1] : inner1 ? inner1[1] : 0.0f, + .color_inner2[2] = inner2 ? inner2[2] : inner1 ? inner1[2] : 0.0f, + .color_inner2[3] = inner2 ? inner2[3] : inner1 ? inner1[3] : 0.0f, + .color_outline[0] = outline ? outline[0] : inner1 ? inner1[0] : 0.0f, + .color_outline[1] = outline ? outline[1] : inner1 ? inner1[1] : 0.0f, + .color_outline[2] = outline ? outline[2] : inner1 ? inner1[2] : 0.0f, + .color_outline[3] = outline ? outline[3] : inner1 ? inner1[3] : 0.0f, + .shade_dir = shade_dir, .alpha_discard = 1.0f, }; - /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */ - - /* WATCH: This is assuming the ModelViewProjectionMatrix is area pixel space. - * If it has been scaled, then it's no longer valid. */ - GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - GPU_blend(GPU_BLEND_ALPHA); - GPU_batch_draw(batch); - GPU_blend(GPU_BLEND_NONE); } -#if 0 -static void round_box_shade_col(uint attr, - const float col1[3], - float const col2[3], - const float fac) +void UI_draw_roundbox_3ub_alpha( + const rctf *rect, bool filled, float rad, const uchar col[3], uchar alpha) { - float col[4] = { - fac * col1[0] + (1.0f - fac) * col2[0], - fac * col1[1] + (1.0f - fac) * col2[1], - fac * col1[2] + (1.0f - fac) * col2[2], - 1.0f, + float colv[4] = { + ((float)col[0]) / 255, + ((float)col[1]) / 255, + ((float)col[2]) / 255, + ((float)alpha) / 255, }; - immAttr4fv(attr, col); + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); } -#endif -/* linear horizontal shade within button or in outline */ -/* view2d scrollers use it */ -void UI_draw_roundbox_shade_x(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadetop, - float shadedown, - const float col[4]) +void UI_draw_roundbox_3fv_alpha( + const rctf *rect, bool filled, float rad, const float col[3], float alpha) { -#if 0 - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - const float div = maxy - miny; - const float idiv = 1.0f / div; - float coltop[3], coldown[3]; - int vert_count = 0; - int a; - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - /* 'shade' defines strength of shading */ - coltop[0] = min_ff(1.0f, col[0] + shadetop); - coltop[1] = min_ff(1.0f, col[1] + shadetop); - coltop[2] = min_ff(1.0f, col[2] + shadetop); - coldown[0] = max_ff(0.0f, col[0] + shadedown); - coldown[1] = max_ff(0.0f, col[1] + shadedown); - coldown[2] = max_ff(0.0f, col[2] + shadedown); - - vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count); - - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, maxx - rad, miny); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, vec[a][1] * idiv); - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - - round_box_shade_col(color, coltop, coldown, rad * idiv); - immVertex2f(pos, maxx, miny + rad); - } - else { - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - - round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); - immVertex2f(pos, maxx, maxy - rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (div - rad + vec[a][1]) * idiv); - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, maxx - rad, maxy); - } - else { - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, minx + rad, maxy); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (div - vec[a][1]) * idiv); - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - - round_box_shade_col(color, coltop, coldown, (div - rad) * idiv); - immVertex2f(pos, minx, maxy - rad); - } - else { - round_box_shade_col(color, coltop, coldown, 1.0); - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - - round_box_shade_col(color, coltop, coldown, rad * idiv); - immVertex2f(pos, minx, miny + rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, coltop, coldown, (rad - vec[a][1]) * idiv); - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } + float colv[4] = {col[0], col[1], col[2], alpha}; + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); +} - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, minx + rad, miny); - } - else { - round_box_shade_col(color, coltop, coldown, 0.0); - immVertex2f(pos, minx, miny); +void UI_draw_roundbox_aa(const rctf *rect, bool filled, float rad, const float color[4]) +{ + /* XXX this is to emulate previous behavior of semitransparent fills but that's was a side effect + * of the previous AA method. Better fix the callers. */ + float colv[4] = {color[0], color[1], color[2], color[3]}; + if (filled) { + colv[3] *= 0.65f; } - immEnd(); - immUnbindProgram(); -#endif - uiWidgetBaseParameters widget_params = { - .recti.xmin = minx + U.pixelsize, - .recti.ymin = miny + U.pixelsize, - .recti.xmax = maxx - U.pixelsize, - .recti.ymax = maxy - U.pixelsize, - .rect.xmin = minx, - .rect.ymin = miny, - .rect.xmax = maxx, - .rect.ymax = maxy, - .radi = rad, - .rad = rad, - .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, - .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, - .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, - .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, - .color_inner1[0] = !filled ? 0.0f : min_ff(1.0f, col[0] + shadetop), - .color_inner1[1] = !filled ? 0.0f : min_ff(1.0f, col[1] + shadetop), - .color_inner1[2] = !filled ? 0.0f : min_ff(1.0f, col[2] + shadetop), - .color_inner1[3] = !filled ? 0.0f : 1.0f, - .color_inner2[0] = !filled ? 0.0f : max_ff(0.0f, col[0] + shadedown), - .color_inner2[1] = !filled ? 0.0f : max_ff(0.0f, col[1] + shadedown), - .color_inner2[2] = !filled ? 0.0f : max_ff(0.0f, col[2] + shadedown), - .color_inner2[3] = !filled ? 0.0f : 1.0f, - /* TODO: non-filled box don't have gradients. Just use middle color. */ - .color_outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f), - .color_outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f), - .shade_dir = 1.0f, - .alpha_discard = 1.0f, - }; - - GPU_blend(GPU_BLEND_ALPHA); - - GPUBatch *batch = ui_batch_roundbox_widget_get(); - GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); - GPU_batch_uniform_4fv_array(batch, "parameters", 11, (float(*)[4]) & widget_params); - GPU_batch_draw(batch); + UI_draw_roundbox_4fv_ex(rect, (filled) ? colv : NULL, NULL, 1.0f, colv, U.pixelsize, rad); +} - GPU_blend(GPU_BLEND_NONE); +void UI_draw_roundbox_4fv(const rctf *rect, bool filled, float rad, const float col[4]) +{ + /* Exactly the same as UI_draw_roundbox_aa but does not do the legacy transparency. */ + UI_draw_roundbox_4fv_ex(rect, (filled) ? col : NULL, NULL, 1.0f, col, U.pixelsize, rad); } -#if 0 /* unused */ -/* linear vertical shade within button or in outline */ +/* linear horizontal shade within button or in outline */ /* view2d scrollers use it */ -void UI_draw_roundbox_shade_y(bool filled, - float minx, - float miny, - float maxx, - float maxy, - float rad, - float shadeleft, - float shaderight, - const float col[4]) +void UI_draw_roundbox_shade_x( + const rctf *rect, bool filled, float rad, float shadetop, float shadedown, const float col[4]) { - float vec[7][2] = { - {0.195, 0.02}, - {0.383, 0.067}, - {0.55, 0.169}, - {0.707, 0.293}, - {0.831, 0.45}, - {0.924, 0.617}, - {0.98, 0.805}, - }; - const float div = maxx - minx; - const float idiv = 1.0f / div; - float colLeft[3], colRight[3]; - int vert_count = 0; - int a; - - /* mult */ - for (a = 0; a < 7; a++) { - mul_v2_fl(vec[a], rad); - } - - GPUVertFormat *format = immVertexFormat(); - uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); - - immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR); - - /* 'shade' defines strength of shading */ - colLeft[0] = min_ff(1.0f, col[0] + shadeleft); - colLeft[1] = min_ff(1.0f, col[1] + shadeleft); - colLeft[2] = min_ff(1.0f, col[2] + shadeleft); - colRight[0] = max_ff(0.0f, col[0] + shaderight); - colRight[1] = max_ff(0.0f, col[1] + shaderight); - colRight[2] = max_ff(0.0f, col[2] + shaderight); - - vert_count += (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_RIGHT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_TOP_LEFT) ? 9 : 1; - vert_count += (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 9 : 1; - - immBegin(filled ? GPU_PRIM_TRI_FAN : GPU_PRIM_LINE_LOOP, vert_count); + float inner1[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float inner2[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float outline[4]; - /* start with corner right-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_RIGHT) { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx - rad, miny); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, vec[a][0] * idiv); - immVertex2f(pos, maxx - rad + vec[a][0], miny + vec[a][1]); - } - - round_box_shade_col(color, colLeft, colRight, rad * idiv); - immVertex2f(pos, maxx, miny + rad); - } - else { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, miny); - } - - /* corner right-top */ - if (roundboxtype & UI_CNR_TOP_RIGHT) { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, maxy - rad); - - for (a = 0; a < 7; a++) { - - round_box_shade_col(color, colLeft, colRight, (div - rad - vec[a][0]) * idiv); - immVertex2f(pos, maxx - vec[a][1], maxy - rad + vec[a][0]); - } - round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); - immVertex2f(pos, maxx - rad, maxy); - } - else { - round_box_shade_col(color, colLeft, colRight, 0.0); - immVertex2f(pos, maxx, maxy); - } - - /* corner left-top */ - if (roundboxtype & UI_CNR_TOP_LEFT) { - round_box_shade_col(color, colLeft, colRight, (div - rad) * idiv); - immVertex2f(pos, minx + rad, maxy); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, (div - rad + vec[a][0]) * idiv); - immVertex2f(pos, minx + rad - vec[a][0], maxy - vec[a][1]); - } - - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, maxy - rad); - } - else { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, maxy); - } - - /* corner left-bottom */ - if (roundboxtype & UI_CNR_BOTTOM_LEFT) { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, miny + rad); - - for (a = 0; a < 7; a++) { - round_box_shade_col(color, colLeft, colRight, (vec[a][0]) * idiv); - immVertex2f(pos, minx + vec[a][1], miny + rad - vec[a][0]); - } - - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx + rad, miny); - } - else { - round_box_shade_col(color, colLeft, colRight, 1.0); - immVertex2f(pos, minx, miny); - } - - immEnd(); - immUnbindProgram(); + if (filled) { + inner1[0] = min_ff(1.0f, col[0] + shadetop); + inner1[1] = min_ff(1.0f, col[1] + shadetop); + inner1[2] = min_ff(1.0f, col[2] + shadetop); + inner1[3] = 1.0f; + inner2[0] = max_ff(0.0f, col[0] + shadedown); + inner2[1] = max_ff(0.0f, col[1] + shadedown); + inner2[2] = max_ff(0.0f, col[2] + shadedown); + inner2[3] = 1.0f; + } + + /* TODO: non-filled box don't have gradients. Just use middle color. */ + outline[0] = clamp_f(col[0] + shadetop + shadedown, 0.0f, 1.0f); + outline[1] = clamp_f(col[1] + shadetop + shadedown, 0.0f, 1.0f); + outline[2] = clamp_f(col[2] + shadetop + shadedown, 0.0f, 1.0f); + outline[3] = clamp_f(col[3] + shadetop + shadedown, 0.0f, 1.0f); + + UI_draw_roundbox_4fv_ex(rect, inner1, inner2, 1.0f, outline, U.pixelsize, rad); } -#endif /* unused */ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const float color[4]) { @@ -783,7 +355,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), GPU_blend(GPU_BLEND_NONE); # if 0 - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); # endif @@ -799,15 +371,12 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(region), * \param x1, x2, y1, y2: The offsets for the view, not the zones. */ void UI_draw_safe_areas(uint pos, - float x1, - float x2, - float y1, - float y2, + const rctf *rect, const float title_aspect[2], const float action_aspect[2]) { - const float size_x_half = (x2 - x1) * 0.5f; - const float size_y_half = (y2 - y1) * 0.5f; + const float size_x_half = (rect->xmax - rect->xmin) * 0.5f; + const float size_y_half = (rect->ymax - rect->ymin) * 0.5f; const float *safe_areas[] = {title_aspect, action_aspect}; const int safe_len = ARRAY_SIZE(safe_areas); @@ -817,10 +386,10 @@ void UI_draw_safe_areas(uint pos, const float margin_x = safe_areas[i][0] * size_x_half; const float margin_y = safe_areas[i][1] * size_y_half; - const float minx = x1 + margin_x; - const float miny = y1 + margin_y; - const float maxx = x2 - margin_x; - const float maxy = y2 - margin_y; + const float minx = rect->xmin + margin_x; + const float miny = rect->ymin + margin_y; + const float maxx = rect->xmax - margin_x; + const float maxy = rect->ymax - margin_y; imm_draw_box_wire_2d(pos, minx, miny, maxx, maxy); } @@ -835,7 +404,15 @@ static void draw_scope_end(const rctf *rect) UI_draw_roundbox_corner_set(UI_CNR_ALL); const float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; UI_draw_roundbox_4fv( - false, rect->xmin - 1, rect->ymin, rect->xmax + 1, rect->ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect->xmin - 1, + .xmax = rect->xmax + 1, + .ymin = rect->ymin, + .ymax = rect->ymax + 1, + }, + false, + 3.0f, + color); } static void histogram_draw_one(float r, @@ -928,7 +505,15 @@ void ui_draw_but_HISTOGRAM(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, histogram can draw outside of boundary */ int scissor[4]; @@ -1070,7 +655,15 @@ void ui_draw_but_WAVEFORM(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, waveform can draw outside of boundary */ GPU_scissor_get(scissor); @@ -1399,7 +992,15 @@ void ui_draw_but_VECTORSCOPE(ARegion *UNUSED(region), UI_GetThemeColor4fv(TH_PREVIEW_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin - 1, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin - 1, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); /* need scissor test, hvectorscope can draw outside of boundary */ int scissor[4]; @@ -1774,7 +1375,16 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec /* backdrop */ UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_3ub_alpha( - true, rect->xmin, rect->ymin, rect->xmax, rect->ymax, 5.0f, wcol->inner, 255); + &(const rctf){ + .xmin = rect->xmin, + .xmax = rect->xmax, + .ymin = rect->ymin, + .ymax = rect->ymax, + }, + true, + 5.0f, + wcol->inner, + 255); GPU_face_culling(GPU_CULL_BACK); @@ -1800,7 +1410,7 @@ void ui_draw_but_UNITVEC(uiBut *but, const uiWidgetColors *wcol, const rcti *rec GPU_batch_uniform_3fv(sphere, "light", light); GPU_batch_draw(sphere); - /* restore */ + /* Restore. */ GPU_face_culling(GPU_CULL_NONE); /* AA circle */ @@ -2130,7 +1740,7 @@ void ui_draw_but_CURVE(ARegion *region, uiBut *but, const uiWidgetColors *wcol, immEnd(); immUnbindProgram(); - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* outline */ @@ -2420,7 +2030,7 @@ void ui_draw_but_CURVEPROFILE(ARegion *region, } immUnbindProgram(); - /* restore scissortest */ + /* Restore scissor-test. */ GPU_scissor(scissor[0], scissor[1], scissor[2], scissor[3]); /* Outline */ @@ -2465,7 +2075,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.7f, 0.3f, 0.3f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); ok = true; } @@ -2514,7 +2132,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); @@ -2577,7 +2203,15 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), const float color[4] = {0.0f, 0.0f, 0.0f, 0.3f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_4fv( - true, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color); + &(const rctf){ + .xmin = rect.xmin - 1, + .xmax = rect.xmax + 1, + .ymin = rect.ymin, + .ymax = rect.ymax + 1, + }, + true, + 3.0f, + color); } /* Restore scissor test. */ @@ -2594,14 +2228,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *UNUSED(region), * would replace / modify the following 3 functions - merwin */ -static void ui_shadowbox(uint pos, - uint color, - float minx, - float miny, - float maxx, - float maxy, - float shadsize, - uchar alpha) +static void ui_shadowbox(const rctf *rect, uint pos, uint color, float shadsize, uchar alpha) { /** * <pre> @@ -2616,16 +2243,16 @@ static void ui_shadowbox(uint pos, * v8______v6_- * </pre> */ - const float v1[2] = {maxx, maxy - 0.3f * shadsize}; - const float v2[2] = {maxx + shadsize, maxy - 0.75f * shadsize}; - const float v3[2] = {maxx, miny}; - const float v4[2] = {maxx + shadsize, miny}; + const float v1[2] = {rect->xmax, rect->ymax - 0.3f * shadsize}; + const float v2[2] = {rect->xmax + shadsize, rect->ymax - 0.75f * shadsize}; + const float v3[2] = {rect->xmax, rect->ymin}; + const float v4[2] = {rect->xmax + shadsize, rect->ymin}; - const float v5[2] = {maxx + 0.7f * shadsize, miny - 0.7f * shadsize}; + const float v5[2] = {rect->xmax + 0.7f * shadsize, rect->ymin - 0.7f * shadsize}; - const float v6[2] = {maxx, miny - shadsize}; - const float v7[2] = {minx + 0.3f * shadsize, miny}; - const float v8[2] = {minx + 0.5f * shadsize, miny - shadsize}; + const float v6[2] = {rect->xmax, rect->ymin - shadsize}; + const float v7[2] = {rect->xmin + 0.3f * shadsize, rect->ymin}; + const float v8[2] = {rect->xmin + 0.5f * shadsize, rect->ymin - shadsize}; /* right quad */ immAttr4ub(color, 0, 0, 0, alpha); @@ -2664,7 +2291,7 @@ static void ui_shadowbox(uint pos, immVertex2fv(pos, v3); } -void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float maxy) +void UI_draw_box_shadow(const rctf *rect, uchar alpha) { GPU_blend(GPU_BLEND_ALPHA); @@ -2678,9 +2305,9 @@ void UI_draw_box_shadow(uchar alpha, float minx, float miny, float maxx, float m immBegin(GPU_PRIM_TRIS, 54); /* accumulated outline boxes to make shade not linear, is more pleasant */ - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 11.0, (20 * alpha) >> 8); - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 7.0, (40 * alpha) >> 8); - ui_shadowbox(pos, color, minx, miny, maxx, maxy, 5.0, (80 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 11.0, (20 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 7.0, (40 * alpha) >> 8); + ui_shadowbox(rect, pos, color, 5.0, (80 * alpha) >> 8); immEnd(); @@ -2755,13 +2382,16 @@ void ui_draw_dropshadow( /* outline emphasis */ const float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; - UI_draw_roundbox_4fv(false, - rct->xmin - 0.5f, - rct->ymin - 0.5f, - rct->xmax + 0.5f, - rct->ymax + 0.5f, - radius + 0.5f, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin - 0.5f, + .xmax = rct->xmax + 0.5f, + .ymin = rct->ymin - 0.5f, + .ymax = rct->ymax + 0.5f, + }, + false, + radius + 0.5f, + color); GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c index 4d0e1584156..de39484bc1e 100644 --- a/source/blender/editors/interface/interface_eyedropper.c +++ b/source/blender/editors/interface/interface_eyedropper.c @@ -24,8 +24,6 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "BLI_blenlib.h" - #include "BKE_context.h" #include "BKE_screen.h" diff --git a/source/blender/editors/interface/interface_eyedropper_depth.c b/source/blender/editors/interface/interface_eyedropper_depth.c index ead65a62226..a4adbef0b94 100644 --- a/source/blender/editors/interface/interface_eyedropper_depth.c +++ b/source/blender/editors/interface/interface_eyedropper_depth.c @@ -41,8 +41,6 @@ #include "BKE_screen.h" #include "BKE_unit.h" -#include "DEG_depsgraph.h" - #include "RNA_access.h" #include "UI_interface.h" @@ -66,9 +64,9 @@ typedef struct DepthDropper { bool is_undo; bool is_set; - float init_depth; /* for resetting on cancel */ + float init_depth; /* For resetting on cancel. */ - bool accum_start; /* has mouse been presed */ + bool accum_start; /* Has mouse been pressed. */ float accum_depth; int accum_tot; diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 97d9b225d3c..1bfd84a7046 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -349,7 +349,7 @@ typedef struct uiHandleButtonData { #endif ColorBand *coba; - /* tooltip */ + /* Tool-tip. */ uint tooltip_force : 1; /* auto open */ @@ -1617,7 +1617,7 @@ static int ui_handler_region_drag_toggle(bContext *C, const wmEvent *event, void static bool ui_but_is_drag_toggle(const uiBut *but) { return ((ui_drag_toggle_but_is_supported(but) == true) && - /* menu check is importnt so the button dragged over isn't removed instantly */ + /* Menu check is important so the button dragged over isn't removed instantly. */ (ui_block_is_menu(but->block) == false)); } @@ -3710,9 +3710,9 @@ static void ui_do_but_textedit( case EVT_AKEY: - /* Ctrl + A: Select all */ + /* Ctrl-A: Select all. */ #if defined(__APPLE__) - /* OSX uses cmd-a systemwide, so add it */ + /* OSX uses Command-A system-wide, so add it. */ if ((event->oskey && !IS_EVENT_MOD(event, shift, alt, ctrl)) || (event->ctrl && !IS_EVENT_MOD(event, shift, alt, oskey))) #else @@ -3726,7 +3726,7 @@ static void ui_do_but_textedit( break; case EVT_TABKEY: - /* there is a key conflict here, we can't tab with autocomplete */ + /* There is a key conflict here, we can't tab with auto-complete. */ if (but->autocomplete_func || data->searchbox) { const int autocomplete = ui_textedit_autocomplete(C, but, data); changed = autocomplete != AUTOCOMPLETE_NO_MATCH; @@ -3735,13 +3735,14 @@ static void ui_do_but_textedit( button_activate_state(C, but, BUTTON_STATE_EXIT); } } - /* the hotkey here is not well defined, was G.qual so we check all */ - else if (IS_EVENT_MOD(event, shift, ctrl, alt, oskey)) { - ui_textedit_prev_but(block, but, data); - button_activate_state(C, but, BUTTON_STATE_EXIT); - } - else { - ui_textedit_next_but(block, but, data); + else if (!IS_EVENT_MOD(event, ctrl, alt, oskey)) { + /* Use standard keys for cycling through buttons Tab, Shift-Tab to reverse. */ + if (event->shift) { + ui_textedit_prev_but(block, but, data); + } + else { + ui_textedit_next_but(block, but, data); + } button_activate_state(C, but, BUTTON_STATE_EXIT); } retval = WM_UI_HANDLER_BREAK; @@ -4575,7 +4576,7 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_BREAK; } if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) { - /* Support ctrl-wheel to cycle values on expanded enum rows. */ + /* Support Ctrl-Wheel to cycle values on expanded enum rows. */ if (but->type == UI_BTYPE_ROW) { int type = event->type; int val = event->val; @@ -5086,7 +5087,7 @@ static int ui_do_but_NUM( else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM - /* if we started multibutton but didn't drag, then edit */ + /* If we started multi-button but didn't drag, then edit. */ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) { click = 1; } @@ -5408,7 +5409,7 @@ static int ui_do_but_SLI( else if (event->type == LEFTMOUSE && event->val == KM_RELEASE) { if (data->dragchange) { #ifdef USE_DRAG_MULTINUM - /* if we started multibutton but didn't drag, then edit */ + /* If we started multi-button but didn't drag, then edit. */ if (data->multi_data.init == BUTTON_MULTI_INIT_SETUP) { click = 1; } @@ -6836,7 +6837,7 @@ static bool ui_numedit_but_CURVE(uiBlock *block, #ifdef USE_CONT_MOUSE_CORRECT /* note: using 'cmp_last' is weak since there may be multiple points selected, - * but in practice this isnt really an issue */ + * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ data->ungrab_mval[0] = but->rect.xmin + ((cmp_last->x - cumap->curr.xmin) * zoomx); @@ -7107,7 +7108,7 @@ static bool ui_numedit_but_CURVEPROFILE(uiBlock *block, changed = true; #ifdef USE_CONT_MOUSE_CORRECT /* note: using 'cmp_last' is weak since there may be multiple points selected, - * but in practice this isnt really an issue */ + * but in practice this isn't really an issue */ if (ui_but_is_cursor_warp(but)) { /* OK but can go outside bounds */ data->ungrab_mval[0] = but->rect.xmin + ((last_x - profile->view_rect.xmin) * zoomx); @@ -7822,7 +7823,7 @@ static void ui_blocks_set_tooltips(ARegion *region, const bool enable) } /** - * Recreate tooltip (use to update dynamic tips) + * Recreate tool-tip (use to update dynamic tips) */ void UI_but_tooltip_refresh(bContext *C, uiBut *but) { @@ -7921,7 +7922,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s return; } - /* highlight has timers for tooltips and auto open */ + /* Highlight has timers for tool-tips and auto open. */ if (state == BUTTON_STATE_HIGHLIGHT) { but->flag &= ~UI_SELECT; @@ -8261,7 +8262,7 @@ static void button_activate_exit( } } - /* disable tooltips until mousemove + last active flag */ + /* Disable tool-tips until mouse-move + last active flag. */ LISTBASE_FOREACH (uiBlock *, block_iter, &data->region->uiblocks) { LISTBASE_FOREACH (uiBut *, bt, &block_iter->buttons) { bt->flag &= ~UI_BUT_LAST_ACTIVE; @@ -8325,7 +8326,7 @@ void ui_but_active_free(const bContext *C, uiBut *but) } /* returns the active button with an optional checking function */ -static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiBut *)) +static uiBut *ui_context_button_active(const ARegion *region, bool (*but_check_cb)(const uiBut *)) { uiBut *but_found = NULL; @@ -8349,7 +8350,7 @@ static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiB but_found = activebut; - /* recurse into opened menu, like colorpicker case */ + /* Recurse into opened menu, like color-picker case. */ if (data && data->menu && (region != data->menu->region)) { region = data->menu->region; } @@ -8366,7 +8367,7 @@ static uiBut *ui_context_button_active(ARegion *region, bool (*but_check_cb)(uiB return but_found; } -static bool ui_context_rna_button_active_test(uiBut *but) +static bool ui_context_rna_button_active_test(const uiBut *but) { return (but->rnapoin.data != NULL); } @@ -8391,7 +8392,7 @@ uiBut *UI_context_active_but_get_respect_menu(const bContext *C) return ui_context_button_active(region_menu ? region_menu : CTX_wm_region(C), NULL); } -uiBut *UI_region_active_but_get(ARegion *region) +uiBut *UI_region_active_but_get(const ARegion *region) { return ui_context_button_active(region, NULL); } @@ -8489,6 +8490,15 @@ wmOperator *UI_context_active_operator_get(const struct bContext *C) return NULL; } +/** + * Try to find a search-box region opened from a button in \a button_region. + */ +ARegion *UI_region_searchbox_region_get(const ARegion *button_region) +{ + uiBut *but = UI_region_active_but_get(button_region); + return (but != NULL) ? but->active->searchbox : NULL; +} + /* helper function for insert keyframe, reset to default, etc operators */ void UI_context_update_anim_flag(const bContext *C) { @@ -8522,7 +8532,7 @@ void UI_context_update_anim_flag(const bContext *C) } if (activebut) { - /* always recurse into opened menu, so all buttons update (like colorpicker) */ + /* Always recurse into opened menu, so all buttons update (like color-picker). */ uiHandleButtonData *data = activebut->active; if (data && data->menu) { region = data->menu->region; @@ -8564,7 +8574,8 @@ static int ui_handle_button_over(bContext *C, const wmEvent *event, ARegion *reg button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); if (event->alt && but->active) { - /* display tooltips if holding alt on mouseover when tooltips are off in prefs */ + /* Display tool-tips if holding Alt on mouse-over when tool-tips are disabled in the + * preferences. */ but->active->tooltip_force = true; } } @@ -8606,7 +8617,7 @@ void ui_but_activate_event(bContext *C, ARegion *region, uiBut *but) * Simulate moving the mouse over a button (or navigating to it with arrow keys). * * exported so menus can start with a highlighted button, - * even if the mouse isnt over it + * even if the mouse isn't over it */ void ui_but_activate_over(bContext *C, ARegion *region, uiBut *but) { @@ -8786,7 +8797,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->x != event->prevx || event->y != event->prevy) { - /* re-enable tooltip on mouse move */ + /* Re-enable tool-tip on mouse move. */ ui_blocks_set_tooltips(region, true); button_tooltip_timer_reset(C, but); } @@ -8810,7 +8821,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) break; } /* XXX hardcoded keymap check... but anyway, - * while view changes, tooltips should be removed */ + * while view changes, tool-tips should be removed */ case WHEELUPMOUSE: case WHEELDOWNMOUSE: case MIDDLEMOUSE: @@ -9513,7 +9524,7 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock /* pass, skip for dialogs */ } else if (!ui_region_contains_point_px(but->active->region, event->x, event->y)) { - /* pass, needed to click-exit outside of non-flaoting menus */ + /* Pass, needed to click-exit outside of non-floating menus. */ ui_region_auto_open_clear(but->active->region); } else if ((!ELEM(event->type, MOUSEMOVE, WHEELUPMOUSE, WHEELDOWNMOUSE, MOUSEPAN)) && @@ -10135,7 +10146,7 @@ static int ui_handle_menu_event(bContext *C, ui_mouse_motion_towards_check(block, menu, &event->x, is_parent_inside == false); - /* check for all parent rects, enables arrowkeys to be used */ + /* Check for all parent rects, enables arrow-keys to be used. */ for (saferct = block->saferct.first; saferct; saferct = saferct->next) { /* for mouse move we only check our own rect, for other * events we check all preceding block rects too to make @@ -10409,7 +10420,7 @@ static int ui_pie_handler(bContext *C, const wmEvent *event, uiPopupBlockHandle } } - /* check pie velociy here if gesture has ended */ + /* Check pie velocity here if gesture has ended. */ if (block->pie_data.flags & UI_PIE_GESTURE_END_WAIT) { float len_sq = 10; @@ -10735,7 +10746,7 @@ static int ui_region_handler(bContext *C, const wmEvent *event, void *UNUSED(use } } - /* re-enable tooltips */ + /* Re-enable tool-tips. */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(region, true); } @@ -10832,7 +10843,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE } } - /* re-enable tooltips */ + /* Re-enable tool-tips. */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(region, true); } @@ -10926,7 +10937,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) WM_event_add_mousemove(win); } else { - /* re-enable tooltips */ + /* Re-enable tool-tips */ if (event->type == MOUSEMOVE && (event->x != event->prevx || event->y != event->prevy)) { ui_blocks_set_tooltips(menu->region, true); } @@ -10936,7 +10947,7 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) ui_apply_but_funcs_after(C); if (reset_pie) { - /* reaqcuire window in case pie invalidates it somehow */ + /* Reacquire window in case pie invalidates it somehow. */ wmWindow *win = CTX_wm_window(C); if (win) { diff --git a/source/blender/editors/interface/interface_icons_event.c b/source/blender/editors/interface/interface_icons_event.c index 223fcbfd45b..3962ff6a702 100644 --- a/source/blender/editors/interface/interface_icons_event.c +++ b/source/blender/editors/interface/interface_icons_event.c @@ -118,7 +118,15 @@ void icon_draw_rect_input(float x, UI_GetThemeColor4fv(TH_TEXT, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_aa( - false, (int)x - U.pixelsize, (int)y, (int)(x + w), (int)(y + h), 3.0f * U.pixelsize, color); + &(const rctf){ + .xmin = (int)x - U.pixelsize, + .xmax = (int)(x + w), + .ymin = (int)y, + .ymax = (int)(y + h), + }, + false, + 3.0f * U.pixelsize, + color); const enum { UNIX, diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index f4e68ca3909..6a921f3f541 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -525,7 +525,7 @@ struct uiBlock { /** for doing delayed */ int bounds, minbounds; - /** pulldowns, to detect outside, can differ per case how it is created */ + /** pull-downs, to detect outside, can differ per case how it is created. */ rctf safety; /** uiSafetyRct list */ ListBase saferct; @@ -659,7 +659,7 @@ void ui_block_cm_to_display_space_v3(uiBlock *block, float pixel[3]); /* interface_regions.c */ struct uiKeyNavLock { - /* set when we're using keyinput */ + /* Set when we're using key-input. */ bool is_keynav; /* only used to check if we've moved the cursor */ int event_xy[2]; @@ -756,7 +756,7 @@ uiBlock *ui_block_func_COLOR(struct bContext *C, uiPopupBlockHandle *handle, voi ColorPicker *ui_block_colorpicker_create(struct uiBlock *block); /* interface_region_search.c */ -/* Searchbox for string button */ +/* Search-box for string button. */ struct ARegion *ui_searchbox_create_generic(struct bContext *C, struct ARegion *butregion, uiButSearch *search_but); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3281b8de920..fef243d7193 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2642,7 +2642,7 @@ void uiItemsEnumR(uiLayout *layout, struct PointerRNA *ptr, const char *propname static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRNA **r_prop) { /* look for collection property in Main */ - /* Note: using global Main is OK-ish here, UI shall not access other Mains anyay... */ + /* NOTE: using global Main is OK-ish here, UI shall not access other Mains anyway. */ RNA_main_pointer_create(G_MAIN, r_ptr); *r_prop = NULL; @@ -2821,7 +2821,7 @@ void ui_item_menutype_func(bContext *C, uiLayout *layout, void *arg_mt) UI_menutype_draw(C, mt, layout); - /* menus are created flipped (from event handling pov) */ + /* Menus are created flipped (from event handling point of view). */ layout->root->block->flag ^= UI_BLOCK_IS_FLIP; } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e5aa0665a16..05a2a6ef29b 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -901,7 +901,7 @@ bool UI_context_copy_to_selected_list(bContext *C, MEM_freeN(link); } else { - /* avoid prepending 'data' to the path */ + /* Avoid prepending 'data' to the path. */ RNA_id_pointer_create(id_data, &link->ptr); } diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index bf140eb1692..7343417137a 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -926,9 +926,9 @@ bool UI_panel_matches_search_filter(const Panel *panel) /** * Set the flag telling the panel to use its search result status for its expansion. */ -static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, - Panel *panel, - const bool use_search_closed) +static void panel_set_expansion_from_search_filter_recursive(const bContext *C, + Panel *panel, + const bool use_search_closed) { /* This has to run on inactive panels that may not have a type, * but we can prevent running on header-less panels in some cases. */ @@ -939,21 +939,21 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C, LISTBASE_FOREACH (Panel *, child_panel, &panel->children) { /* Don't check if the sub-panel is active, otherwise the * expansion won't be reset when the parent is closed. */ - panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_search_closed); + panel_set_expansion_from_search_filter_recursive(C, child_panel, use_search_closed); } } /** * Set the flag telling every panel to override its expansion with its search result status. */ -static void region_panels_set_expansion_from_seach_filter(const bContext *C, - ARegion *region, - const bool use_search_closed) +static void region_panels_set_expansion_from_search_filter(const bContext *C, + ARegion *region, + const bool use_search_closed) { LISTBASE_FOREACH (Panel *, panel, ®ion->panels) { /* Don't check if the panel is active, otherwise the expansion won't * be correct when switching back to tab after exiting search. */ - panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed); + panel_set_expansion_from_search_filter_recursive(C, panel, use_search_closed); } set_panels_list_data_expand_flag(C, region); } @@ -1121,13 +1121,16 @@ static void panel_draw_highlight_border(const Panel *panel, float color[4]; UI_GetThemeColor4fv(TH_SELECT_ACTIVE, color); - UI_draw_roundbox_4fv(false, - rect->xmin, - UI_panel_is_closed(panel) ? header_rect->ymin : rect->ymin, - rect->xmax, - header_rect->ymax, - radius, - color); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rect->xmin, + .xmax = rect->xmax, + .ymin = UI_panel_is_closed(panel) ? header_rect->ymin : rect->ymin, + .ymax = header_rect->ymax, + }, + false, + radius, + color); } static void panel_draw_aligned_widgets(const uiStyle *style, @@ -1253,13 +1256,16 @@ static void panel_draw_aligned_backdrop(const Panel *panel, float color[4]; UI_GetThemeColor4fv(TH_PANEL_SUB_BACK, color); /* Change the width a little bit to line up with sides. */ - UI_draw_roundbox_aa(true, - rect->xmin + U.pixelsize, - rect->ymin + U.pixelsize, - rect->xmax - U.pixelsize, - rect->ymax, - box_wcol->roundness * U.widget_unit, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = rect->xmin + U.pixelsize, + .xmax = rect->xmax - U.pixelsize, + .ymin = rect->ymin + U.pixelsize, + .ymax = rect->ymax, + }, + true, + box_wcol->roundness * U.widget_unit, + color); } else { immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); @@ -1333,7 +1339,7 @@ void ui_draw_aligned_panel(const uiStyle *style, { const Panel *panel = block->panel; - /* Add 0.001f to prevent flicker frpm float inaccuracy. */ + /* Add 0.001f to prevent flicker from float inaccuracy. */ const rcti header_rect = { rect->xmin, rect->xmax, @@ -1544,20 +1550,26 @@ void UI_panel_category_draw_all(ARegion *region, const char *category_id_active) { /* Draw filled rectangle and outline for tab. */ UI_draw_roundbox_corner_set(roundboxtype); - UI_draw_roundbox_4fv(true, - rct->xmin, - rct->ymin, - rct->xmax, - rct->ymax, - tab_curve_radius, - is_active ? theme_col_tab_active : theme_col_tab_inactive); - UI_draw_roundbox_4fv(false, - rct->xmin, - rct->ymin, - rct->xmax, - rct->ymax, - tab_curve_radius, - theme_col_tab_outline); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + true, + tab_curve_radius, + is_active ? theme_col_tab_active : theme_col_tab_inactive); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + false, + tab_curve_radius, + theme_col_tab_outline); /* Disguise the outline on one side to join the tab to the panel. */ pos = GPU_vertformat_attr_add( @@ -1911,10 +1923,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y) const bool region_search_filter_active = region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE; if (properties_space_needs_realign(area, region)) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); + region_panels_set_expansion_from_search_filter(C, region, region_search_filter_active); } else if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) { - region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active); + region_panels_set_expansion_from_search_filter(C, region, region_search_filter_active); } if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) { @@ -2354,7 +2366,7 @@ static int ui_handle_panel_category_cycling(const wmEvent *event, PanelCategoryDyn *pc_dyn = UI_panel_category_find(region, category); if (LIKELY(pc_dyn)) { if (is_mousewheel) { - /* We can probably get rid of this and only allow ctrl-tabbing. */ + /* We can probably get rid of this and only allow Ctrl-Tabbing. */ pc_dyn = (event->type == WHEELDOWNMOUSE) ? pc_dyn->next : pc_dyn->prev; } else { diff --git a/source/blender/editors/interface/interface_region_menu_pie.c b/source/blender/editors/interface/interface_region_menu_pie.c index d047d5421d7..81c627816b9 100644 --- a/source/blender/editors/interface/interface_region_menu_pie.c +++ b/source/blender/editors/interface/interface_region_menu_pie.c @@ -392,7 +392,7 @@ void ui_pie_menu_level_create(uiBlock *block, EnumPropertyItem *remaining = MEM_mallocN(array_size + sizeof(EnumPropertyItem), "pie_level_item_array"); memcpy(remaining, items + totitem_parent, array_size); - /* a NULL terminating sentinal element is required */ + /* A NULL terminating sentinel element is required. */ memset(&remaining[totitem_remain], 0, sizeof(EnumPropertyItem)); /* yuk, static... issue is we can't reliably free this without doing dangerous changes */ diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c index 93e3dbb2cc8..3228e9741bb 100644 --- a/source/blender/editors/interface/interface_region_popup.c +++ b/source/blender/editors/interface/interface_region_popup.c @@ -413,12 +413,11 @@ static void ui_block_region_draw(const bContext *C, ARegion *region) /** * Use to refresh centered popups on screen resizing (for splash). */ -static void ui_block_region_popup_window_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void ui_block_region_popup_window_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + switch (wmn->category) { case NC_WINDOW: { switch (wmn->action) { @@ -540,7 +539,7 @@ static void ui_popup_block_remove(bContext *C, uiPopupBlockHandle *handle) CTX_wm_window_set(C, win); ui_region_temp_remove(C, screen, handle->region); - /* Reset context (area and region were NULL'ed when chaning context window). */ + /* Reset context (area and region were NULL'ed when changing context window). */ CTX_wm_window_set(C, ctx_win); CTX_wm_area_set(C, ctx_area); CTX_wm_region_set(C, ctx_region); diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index 816162e9aa2..d1d4290bd11 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -289,7 +289,7 @@ int ui_searchbox_find_index(ARegion *region, const char *name) return UI_search_items_find_index(&data->items, name); } -/* x and y in screencoords */ +/* x and y in screen-coords. */ bool ui_searchbox_inside(ARegion *region, int x, int y) { uiSearchboxData *data = region->regiondata; @@ -347,9 +347,20 @@ static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C, } uiButSearch *search_but = (uiButSearch *)but; - if (search_but->item_tooltip_fn) { - return search_but->item_tooltip_fn(C, region, search_but->arg, search_but->item_active); + if (!search_but->item_tooltip_fn) { + continue; } + + ARegion *searchbox_region = UI_region_searchbox_region_get(region); + uiSearchboxData *data = searchbox_region->regiondata; + + BLI_assert(data->items.pointers[data->active] == search_but->item_active); + + rcti rect; + ui_searchbox_butrect(&rect, data, data->active); + + return search_but->item_tooltip_fn( + C, region, &rect, search_but->arg, search_but->item_active); } } return NULL; @@ -452,8 +463,11 @@ static void ui_searchbox_update_fn(bContext *C, const char *str, uiSearchItems *items) { - wmWindow *win = CTX_wm_window(C); - WM_tooltip_clear(C, win); + /* While the button is in text editing mode (searchbox open), remove tooltips on every update. */ + if (search_but->but.editstr) { + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + } search_but->items_update_fn(C, search_but->arg, str, items); } @@ -1046,7 +1060,7 @@ void ui_but_search_refresh(uiButSearch *search_but) ui_searchbox_update_fn(but->block->evil_C, search_but, but->drawstr, items); - /* only redalert when we are sure of it, this can miss cases when >10 matches */ + /* Only red-alert when we are sure of it, this can miss cases when >10 matches. */ if (items->totitem == 0) { UI_but_flag_enable(but, UI_BUT_REDALERT); } diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c index 2bf63955855..050a14cf574 100644 --- a/source/blender/editors/interface/interface_region_tooltip.c +++ b/source/blender/editors/interface/interface_region_tooltip.c @@ -1456,15 +1456,91 @@ ARegion *UI_tooltip_create_from_gizmo(bContext *C, wmGizmo *gz) { wmWindow *win = CTX_wm_window(C); const float aspect = 1.0f; - float init_position[2]; + float init_position[2] = {win->eventstate->x, win->eventstate->y}; uiTooltipData *data = ui_tooltip_data_from_gizmo(C, gz); if (data == NULL) { return NULL; } + /* TODO(harley): + * Julian preferred that the gizmo callback return the 3D bounding box + * which we then project to 2D here. Would make a nice improvement. + */ + if (gz->type->screen_bounds_get) { + rcti bounds; + gz->type->screen_bounds_get(C, gz, &bounds); + init_position[0] = bounds.xmin; + init_position[1] = bounds.ymin; + } + + return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect); +} + +static uiTooltipData *ui_tooltip_data_from_search_item_tooltip_data( + const uiSearchItemTooltipData *item_tooltip_data) +{ + uiTooltipData *data = MEM_callocN(sizeof(uiTooltipData), "uiTooltipData"); + + if (item_tooltip_data->description[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_HEADER, + .color_id = UI_TIP_LC_NORMAL, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->description); + } + + if (item_tooltip_data->name && item_tooltip_data->name[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_VALUE, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->name); + } + if (item_tooltip_data->hint[0]) { + uiTooltipField *field = text_field_add(data, + &(uiTooltipFormat){ + .style = UI_TIP_STYLE_NORMAL, + .color_id = UI_TIP_LC_NORMAL, + .is_pad = true, + }); + field->text = BLI_strdup(item_tooltip_data->hint); + } + + if (data->fields_len == 0) { + MEM_freeN(data); + return NULL; + } + return data; +} + +/** + * Create a tooltip from search-item tooltip data \a item_tooltip data. + * To be called from a callback set with #UI_but_func_search_set_tooltip(). + * + * \param item_rect: Rectangle of the search item in search region space (#ui_searchbox_butrect()) + * which is passed to the tooltip callback. + */ +ARegion *UI_tooltip_create_from_search_item_generic( + bContext *C, + const ARegion *searchbox_region, + const rcti *item_rect, + const uiSearchItemTooltipData *item_tooltip_data) +{ + uiTooltipData *data = ui_tooltip_data_from_search_item_tooltip_data(item_tooltip_data); + if (data == NULL) { + return NULL; + } + + const float aspect = 1.0f; + const wmWindow *win = CTX_wm_window(C); + float init_position[2]; init_position[0] = win->eventstate->x; - init_position[1] = win->eventstate->y; + init_position[1] = item_rect->ymin + searchbox_region->winrct.ymin - (UI_POPUP_MARGIN / 2); return ui_tooltip_create_with_data(C, data, init_position, NULL, aspect); } diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index a37fb0dfde1..eaefc2c3736 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -341,13 +341,16 @@ void UI_fontstyle_draw_simple_backdrop(const uiFontStyle *fs, const float color[4] = {col_bg[0], col_bg[1], col_bg[2], 0.5f}; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - x - margin, - (y + decent) - margin, - x + width + margin, - (y + decent) + height + margin, - margin, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = x - margin, + .xmax = x + width + margin, + .ymin = (y + decent) - margin, + .ymax = (y + decent) + height + margin, + }, + true, + margin, + color); } BLF_position(fs->uifont_id, x, y, 0.0f); diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 9f4cd32588d..25cf2e12377 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -1069,6 +1069,7 @@ static bool ui_search_menu_create_context_menu(struct bContext *C, static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C, struct ARegion *region, + const rcti *UNUSED(item_rect), void *arg, void *active) { diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c index 21529a97c01..ff0f9a2e5cd 100644 --- a/source/blender/editors/interface/interface_template_search_operator.c +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -23,11 +23,8 @@ #include <string.h> -#include "DNA_gpencil_modifier_types.h" -#include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_shader_fx_types.h" #include "DNA_texture_types.h" #include "BLI_alloca.h" diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 003bb110baf..dad8253d101 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -208,6 +208,7 @@ static uiBlock *template_common_search_menu(const bContext *C, void *search_arg, uiButHandleFunc search_exec_fn, void *active_item, + uiButSearchTooltipFn item_tooltip_fn, const int preview_rows, const int preview_cols, float scale) @@ -284,6 +285,7 @@ static uiBlock *template_common_search_menu(const bContext *C, NULL, search_exec_fn, active_item); + UI_but_func_search_set_tooltip(but, item_tooltip_fn); UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); UI_block_direction_set(block, UI_DIR_DOWN); @@ -347,7 +349,7 @@ static bool id_search_allows_id(TemplateID *template_ui, const int flag, ID *id, } } - /* Hide dot-datablocks, but only if filter does not force them visible. */ + /* Hide dot prefixed data-blocks, but only if filter does not force them visible. */ if (U.uiflag & USER_HIDE_DOT) { if ((id->name[2] == '.') && (query[0] != '.')) { return false; @@ -485,6 +487,31 @@ static void id_search_cb_objects_from_scene(const bContext *C, id_search_cb_tagged(C, arg_template, str, items); } +static ARegion *template_ID_search_menu_item_tooltip( + bContext *C, ARegion *region, const rcti *item_rect, void *arg, void *active) +{ + TemplateID *template_ui = arg; + ID *active_id = active; + StructRNA *type = RNA_property_pointer_type(&template_ui->ptr, template_ui->prop); + + uiSearchItemTooltipData tooltip_data = {0}; + + tooltip_data.name = active_id->name + 2; + BLI_snprintf(tooltip_data.description, + sizeof(tooltip_data.description), + TIP_("Choose %s data-block to be assigned to this user"), + RNA_struct_ui_name(type)); + if (ID_IS_LINKED(active_id)) { + BLI_snprintf(tooltip_data.hint, + sizeof(tooltip_data.hint), + TIP_("Source library: %s\n%s"), + active_id->lib->id.name + 2, + active_id->lib->filepath); + } + + return UI_tooltip_create_from_search_item_generic(C, region, item_rect, &tooltip_data); +} + /* ID Search browse menu, open */ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) { @@ -512,6 +539,7 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) &template_ui, template_ID_set_property_exec_fn, active_item_ptr.data, + template_ID_search_menu_item_tooltip, template_ui.prv_rows, template_ui.prv_cols, template_ui.scale); @@ -895,7 +923,7 @@ static void template_ID(const bContext *C, idfrom = template_ui->ptr.owner_id; // lb = template_ui->idlb; - /* Allow opertators to take the ID from context. */ + /* Allow operators to take the ID from context. */ uiLayoutSetContextPointer(layout, "id", &idptr); block = uiLayoutGetBlock(layout); @@ -906,7 +934,7 @@ static void template_ID(const bContext *C, } if (text) { - /* Add label resepecting the separated layout property split state. */ + /* Add label respecting the separated layout property split state. */ uiItemL_respect_property_split(layout, text, ICON_NONE); } @@ -1632,6 +1660,7 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem &template_search, template_search_exec_fn, active_ptr.data, + NULL, template_search.preview_rows, template_search.preview_cols, 1.0f); @@ -6802,20 +6831,16 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) width = min_ii((int)(rti->widthfac * width), width); width = max_ii(width, 10 * UI_DPI_FAC); - /* make a box around the report to make it stand out */ UI_block_align_begin(block); - but = uiDefBut( - block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */ - rgba_float_to_uchar(but->col, rti->col); + /* Background for icon. */ but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", - UI_UNIT_X + 5, 0, - UI_UNIT_X + width, + 0, + UI_UNIT_X + (6 * UI_DPI_FAC), UI_UNIT_Y, NULL, 0.0f, @@ -6823,46 +6848,57 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) 0, 0, ""); - rgba_float_to_uchar(but->col, rti->col); + /* UI_BTYPE_ROUNDBOX's bg color is set in but->col. */ + UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col); - UI_block_align_end(block); + /* Background for the rest of the message. */ + but = uiDefBut(block, + UI_BTYPE_ROUNDBOX, + 0, + "", + UI_UNIT_X + (6 * UI_DPI_FAC), + 0, + UI_UNIT_X + width, + UI_UNIT_Y, + NULL, + 0.0f, + 0.0f, + 0, + 0, + ""); - /* icon and report message on top */ - const int icon = UI_icon_from_report_type(report->type); + /* Use icon background at low opacity to highlight, but still contrasting with area TH_TEXT. */ + UI_GetThemeColorType4ubv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, but->col); + but->col[3] = 64; - /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report - * to be shown instead of icon when appropriate... - */ + UI_block_align_end(block); UI_block_emboss_set(block, UI_EMBOSS_NONE); - if (reports->list.first != reports->list.last) { - uiDefIconButO(block, - UI_BTYPE_BUT, - "SCREEN_OT_info_log_show", - WM_OP_INVOKE_REGION_WIN, - icon, - 2, - 0, - UI_UNIT_X, - UI_UNIT_Y, - TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); - } - else { - uiDefIconBut( - block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - } + /* The report icon itself. */ + but = uiDefIconButO(block, + UI_BTYPE_BUT, + "SCREEN_OT_info_log_show", + WM_OP_INVOKE_REGION_WIN, + UI_icon_from_report_type(report->type), + (3 * UI_DPI_FAC), + 0, + UI_UNIT_X, + UI_UNIT_Y, + TIP_("Click to see the remaining reports in text block: 'Recent Reports'")); + UI_GetThemeColorType4ubv(UI_text_colorid_from_report_type(report->type), SPACE_INFO, but->col); + but->col[3] = 255; /* This theme color is RBG only, so have to set alpha here. */ + /* The report message. */ but = uiDefButO(block, UI_BTYPE_BUT, "SCREEN_OT_info_log_show", WM_OP_INVOKE_REGION_WIN, report->message, - UI_UNIT_X + 5, + UI_UNIT_X, 0, - UI_UNIT_X + width, + width + UI_UNIT_X, UI_UNIT_Y, "Show in Info Log"); - rgba_float_to_uchar(but->col, rti->col); } void uiTemplateInputStatus(uiLayout *layout, struct bContext *C) diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 958a0bc03cd..f9eba9eeb6f 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -544,15 +544,74 @@ int UI_icon_from_id(ID *id) int UI_icon_from_report_type(int type) { if (type & RPT_ERROR_ALL) { - return ICON_ERROR; + return ICON_CANCEL; } - if (type & RPT_WARNING_ALL) { + else if (type & RPT_WARNING_ALL) { return ICON_ERROR; } - if (type & RPT_INFO_ALL) { + else if (type & RPT_INFO_ALL) { return ICON_INFO; } - return ICON_NONE; + else if (type & RPT_DEBUG_ALL) { + return ICON_SYSTEM; + } + else if (type & RPT_PROPERTY) { + return ICON_OPTIONS; + } + else if (type & RPT_OPERATOR) { + return ICON_CHECKMARK; + } + return ICON_INFO; +} + +int UI_icon_colorid_from_report_type(int type) +{ + if (type & RPT_ERROR_ALL) { + return TH_INFO_ERROR; + } + else if (type & RPT_WARNING_ALL) { + return TH_INFO_WARNING; + } + else if (type & RPT_INFO_ALL) { + return TH_INFO_INFO; + } + else if (type & RPT_DEBUG_ALL) { + return TH_INFO_DEBUG; + } + else if (type & RPT_PROPERTY) { + return TH_INFO_PROPERTY; + } + else if (type & RPT_OPERATOR) { + return TH_INFO_OPERATOR; + } + else { + return TH_INFO_WARNING; + } +} + +int UI_text_colorid_from_report_type(int type) +{ + if (type & RPT_ERROR_ALL) { + return TH_INFO_ERROR_TEXT; + } + else if (type & RPT_WARNING_ALL) { + return TH_INFO_WARNING_TEXT; + } + else if (type & RPT_INFO_ALL) { + return TH_INFO_INFO_TEXT; + } + else if (type & RPT_DEBUG_ALL) { + return TH_INFO_DEBUG_TEXT; + } + else if (type & RPT_PROPERTY) { + return TH_INFO_PROPERTY_TEXT; + } + else if (type & RPT_OPERATOR) { + return TH_INFO_OPERATOR_TEXT; + } + else { + return TH_INFO_WARNING_TEXT; + } } /********************************** Misc **************************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 868f62c89c9..5c59d0edeb5 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1311,7 +1311,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, tria_col[3] = wcol->item[3]; } - /* Draw everything in one drawcall */ + /* Draw everything in one draw-call. */ if (inner_col1[3] || inner_col2[3] || outline_col[3] || emboss_col[3] || tria_col[3] || show_alpha_checkers) { widgetbase_set_uniform_colors_ubv( @@ -1533,25 +1533,22 @@ static void ui_text_clip_right_ex(const uiFontStyle *fstyle, { BLI_assert(str[0]); - /* If the trailing ellipsis takes more than 20% of all available width, just cut the string - * (as using the ellipsis would remove even more useful chars, and we cannot show much - * already!). - */ - if (sep_strwidth / okwidth > 0.2f) { - float tmp; - const int l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, &tmp); - str[l_end] = '\0'; + /* How many BYTES (not characters) of this utf-8 string can fit, along with appended ellipsis. */ + int l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, NULL); + + if (l_end > 0) { + /* At least one character, so clip and add the ellipsis. */ + memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */ if (r_final_len) { - *r_final_len = (size_t)l_end; + *r_final_len = (size_t)(l_end) + sep_len; } } else { - float tmp; - const int l_end = BLF_width_to_strlen( - fstyle->uifont_id, str, max_len, okwidth - sep_strwidth, &tmp); - memcpy(str + l_end, sep, sep_len + 1); /* +1 for trailing '\0'. */ + /* Otherwise fit as much as we can without adding an ellipsis. */ + l_end = BLF_width_to_strlen(fstyle->uifont_id, str, max_len, okwidth, NULL); + str[l_end] = '\0'; if (r_final_len) { - *r_final_len = (size_t)(l_end) + sep_len; + *r_final_len = (size_t)l_end; } } } @@ -2352,7 +2349,7 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, int icon_size = BLI_rcti_size_y(rect); int text_size = 0; - /* This is a bit britle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ + /* This is a bit brittle, but avoids adding an 'UI_BUT_HAS_LABEL' flag to but... */ if (icon_size > BLI_rcti_size_x(rect)) { /* button is not square, it has extra height for label */ text_size = UI_UNIT_Y; @@ -2413,7 +2410,9 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, rect->xmin += 0.2f * U.widget_unit; } - widget_draw_icon(but, icon, alpha, rect, wcol->text); + /* By default icon is the color of text, but can optionally override with but->col. */ + widget_draw_icon(but, icon, alpha, rect, (but->col[3] != 0) ? but->col : wcol->text); + if (show_menu_icon) { BLI_assert(but->block->content_hints & UI_BLOCK_CONTAINS_SUBMENU_BUT); widget_draw_submenu_tria(but, rect, wcol); @@ -3617,7 +3616,7 @@ static void widget_scroll( rect1.xmin = rect1.xmin + ceilf(fac * (value - but->softmin)); rect1.xmax = rect1.xmin + ceilf(fac * (but->a1 - but->softmin)); - /* ensure minimium size */ + /* Ensure minimum size. */ const float min = BLI_rcti_size_y(rect); if (BLI_rcti_size_x(&rect1) < min) { @@ -3634,7 +3633,7 @@ static void widget_scroll( rect1.ymax = rect1.ymax - ceilf(fac * (value - but->softmin)); rect1.ymin = rect1.ymax - ceilf(fac * (but->a1 - but->softmin)); - /* ensure minimium size */ + /* Ensure minimum size. */ const float min = BLI_rcti_size_x(rect); if (BLI_rcti_size_y(&rect1) < min) { @@ -3671,7 +3670,7 @@ static void widget_progressbar( const float offs = wcol->roundness * BLI_rcti_size_y(&rect_prog); float w = value * BLI_rcti_size_x(&rect_prog); - /* ensure minimium size */ + /* Ensure minimum size. */ w = MAX2(w, offs); rect_bar.xmax = rect_bar.xmin + w; @@ -5224,8 +5223,7 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl * * \param state: The state of the button, * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE. - * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned, - * use for displaying key shortcuts. + * \param separator_type: The kind of separator which controls if and how the string is clipped. * \param r_xmax: The right hand position of the text, this takes into the icon, * padding and text clipping when there is not enough room to display the full text. */ @@ -5273,7 +5271,7 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, rect->xmax -= BLF_width(fstyle->uifont_id, cpoin + 1, INT_MAX) + UI_DPI_ICON_SIZE; } else if (separator_type == UI_MENU_ITEM_SEPARATOR_HINT) { - /* Deterimine max-width for the hint string to leave the name string un-clipped (if there's + /* Determine max-width for the hint string to leave the name string un-clipped (if there's * enough space to display it). */ const int available_width = BLI_rcti_size_x(rect) - padding; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f115618c13b..59aee0fde29 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -1895,7 +1895,7 @@ void UI_view2d_scroller_size_get(const View2D *v2d, float *r_x, float *r_y) * * \param r_x, r_y: scale on each axis */ -void UI_view2d_scale_get(View2D *v2d, float *r_x, float *r_y) +void UI_view2d_scale_get(const View2D *v2d, float *r_x, float *r_y) { if (r_x) { *r_x = UI_view2d_scale_get_x(v2d); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 222f03ee1d8..e234ab5dcdc 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -46,7 +46,7 @@ #include "UI_interface.h" #include "UI_view2d.h" -#include "PIL_time.h" /* USER_ZOOM_CONT */ +#include "PIL_time.h" /* USER_ZOOM_CONTINUE */ /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -1106,14 +1106,9 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op) float dx = RNA_float_get(op->ptr, "deltax") / U.dpi_fac; float dy = RNA_float_get(op->ptr, "deltay") / U.dpi_fac; - if (U.uiflag & USER_ZOOM_INVERT) { - dx *= -1; - dy *= -1; - } - /* Check if the 'timer' is initialized, as zooming with the trackpad * never uses the "Continuous" zoom method, and the 'timer' is not initialized. */ - if ((U.viewzoom == USER_ZOOM_CONT) && vzd->timer) { /* XXX store this setting as RNA prop? */ + if ((U.viewzoom == USER_ZOOM_CONTINUE) && vzd->timer) { /* XXX store this setting as RNA prop? */ const double time = PIL_check_seconds_timer(); const float time_step = (float)(time - vzd->timer_lastdraw); @@ -1232,26 +1227,53 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even vzd->lastx = event->prevx; vzd->lasty = event->prevy; - /* As we have only 1D information (magnify value), feed both axes - * with magnify information that is stored in x axis - */ - float fac = 0.01f * (event->prevx - event->x); - float dx = fac * BLI_rctf_size_x(&v2d->cur) / 10.0f; + float facx, facy; + float zoomfac = 0.01f; + + /* Some view2d's (graph) don't have min/max zoom, or extreme ones. */ + if (v2d->maxzoom > 0.0f) { + zoomfac = clamp_f(0.001f * v2d->maxzoom, 0.001f, 0.01f); + } + if (event->type == MOUSEPAN) { - fac = 0.01f * (event->prevy - event->y); + facx = zoomfac * WM_event_absolute_delta_x(event); + facy = zoomfac * WM_event_absolute_delta_y(event); + + if (U.uiflag & USER_ZOOM_INVERT) { + facx *= -1.0f; + facy *= -1.0f; + } + } + else { /* MOUSEZOOM */ + facx = facy = zoomfac * WM_event_absolute_delta_x(event); + } + + /* Only respect user setting zoom axis if the view does not have any zoom restrictions + * any will be scaled uniformly. */ + if (((v2d->keepzoom & (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y)) == 0) && + (v2d->keepzoom & V2D_KEEPASPECT)) { + if (U.uiflag & USER_ZOOM_HORIZ) { + facy = 0.0f; + } + else { + facx = 0.0f; + } } - float dy = fac * BLI_rctf_size_y(&v2d->cur) / 10.0f; /* support trackpad zoom to always zoom entirely - the v2d code uses portrait or * landscape exceptions */ if (v2d->keepzoom & V2D_KEEPASPECT) { - if (fabsf(dx) > fabsf(dy)) { - dy = dx; + if (fabsf(facx) > fabsf(facy)) { + facy = facx; } else { - dx = dy; + facx = facy; } } + + const float dx = facx * BLI_rctf_size_x(&v2d->cur); + const float dy = facy * BLI_rctf_size_y(&v2d->cur); + RNA_float_set(op->ptr, "deltax", dx); RNA_float_set(op->ptr, "deltay", dy); @@ -1282,7 +1304,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even /* add temp handler */ WM_event_add_modal_handler(C, op); - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vzd->timer = WM_event_add_timer(CTX_wm_manager(C), window, TIMER, 0.01f); vzd->timer_lastdraw = PIL_check_seconds_timer(); @@ -1320,19 +1342,13 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event /* x-axis transform */ dist = BLI_rcti_size_x(&v2d->mask) / 2.0f; - len_old[0] = fabsf(vzd->lastx - vzd->region->winrct.xmin - dist); - len_new[0] = fabsf(event->x - vzd->region->winrct.xmin - dist); - - len_old[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur); - len_new[0] *= zoomfac * BLI_rctf_size_x(&v2d->cur); + len_old[0] = zoomfac * fabsf(vzd->lastx - vzd->region->winrct.xmin - dist); + len_new[0] = zoomfac * fabsf(event->x - vzd->region->winrct.xmin - dist); /* y-axis transform */ dist = BLI_rcti_size_y(&v2d->mask) / 2.0f; - len_old[1] = fabsf(vzd->lasty - vzd->region->winrct.ymin - dist); - len_new[1] = fabsf(event->y - vzd->region->winrct.ymin - dist); - - len_old[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur); - len_new[1] *= zoomfac * BLI_rctf_size_y(&v2d->cur); + len_old[1] = zoomfac * fabsf(vzd->lasty - vzd->region->winrct.ymin - dist); + len_new[1] = zoomfac * fabsf(event->y - vzd->region->winrct.ymin - dist); /* Calculate distance */ if (v2d->keepzoom & V2D_KEEPASPECT) { @@ -1343,40 +1359,44 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event dx = len_new[0] - len_old[0]; dy = len_new[1] - len_old[1]; } - } - else { - /* 'continuous' or 'dolly' */ - float fac; - /* x-axis transform */ - fac = zoomfac * (event->x - vzd->lastx); - dx = fac * BLI_rctf_size_x(&v2d->cur); - /* y-axis transform */ - fac = zoomfac * (event->y - vzd->lasty); - dy = fac * BLI_rctf_size_y(&v2d->cur); + dx *= BLI_rctf_size_x(&v2d->cur); + dy *= BLI_rctf_size_y(&v2d->cur); + } + else { /* USER_ZOOM_CONTINUE or USER_ZOOM_DOLLY */ + float facx = zoomfac * (event->x - vzd->lastx); + float facy = zoomfac * (event->y - vzd->lasty); /* Only respect user setting zoom axis if the view does not have any zoom restrictions * any will be scaled uniformly */ if ((v2d->keepzoom & V2D_LOCKZOOM_X) == 0 && (v2d->keepzoom & V2D_LOCKZOOM_Y) == 0 && (v2d->keepzoom & V2D_KEEPASPECT)) { if (U.uiflag & USER_ZOOM_HORIZ) { - dy = 0; + facy = 0.0f; } else { - dx = 0; + facx = 0.0f; } } - } - /* support zoom to always zoom entirely - the v2d code uses portrait or - * landscape exceptions */ - if (v2d->keepzoom & V2D_KEEPASPECT) { - if (fabsf(dx) > fabsf(dy)) { - dy = dx; - } - else { - dx = dy; + /* support zoom to always zoom entirely - the v2d code uses portrait or + * landscape exceptions */ + if (v2d->keepzoom & V2D_KEEPASPECT) { + if (fabsf(facx) > fabsf(facy)) { + facy = facx; + } + else { + facx = facy; + } } + + dx = facx * BLI_rctf_size_x(&v2d->cur); + dy = facy * BLI_rctf_size_y(&v2d->cur); + } + + if (U.uiflag & USER_ZOOM_INVERT) { + dx *= -1.0f; + dy *= -1.0f; } /* set transform amount, and add current deltas to stored total delta (for redo) */ @@ -1390,7 +1410,7 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event * - Continuous zoom only depends on distance of mouse * to starting point to determine rate of change. */ - if (U.viewzoom != USER_ZOOM_CONT) { /* XXX store this setting as RNA prop? */ + if (U.viewzoom != USER_ZOOM_CONTINUE) { /* XXX store this setting as RNA prop? */ vzd->lastx = event->x; vzd->lasty = event->y; } @@ -2204,7 +2224,7 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent * scroller_activate_init(C, op, event, in_scroller); v2dScrollerMove *vsm = (v2dScrollerMove *)op->customdata; - /* support for quick jump to location - gtk and qt do this on linux */ + /* Support for quick jump to location - GTK and QT do this on Linux. */ if (event->type == MIDDLEMOUSE) { switch (vsm->scroller) { case 'h': /* horizontal scroller - so only horizontal movement diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 636e6688971..a66f53ea839 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -35,19 +35,16 @@ # include "MEM_guardedalloc.h" -# include "DNA_mesh_types.h" # include "DNA_modifier_types.h" # include "DNA_object_types.h" # include "DNA_scene_types.h" # include "DNA_space_types.h" # include "BKE_context.h" -# include "BKE_global.h" # include "BKE_main.h" # include "BKE_report.h" # include "BLI_listbase.h" -# include "BLI_math_vector.h" # include "BLI_path_util.h" # include "BLI_string.h" # include "BLI_utildefines.h" diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index b73b8abccfe..1e66a86c8fd 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -26,7 +26,6 @@ #include "DNA_cachefile_types.h" #include "DNA_space_types.h" -#include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 200786ca99d..2bf975cc4f5 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -29,7 +29,6 @@ # include "BLI_utildefines.h" # include "BKE_context.h" -# include "BKE_global.h" # include "BKE_main.h" # include "BKE_object.h" # include "BKE_report.h" @@ -37,7 +36,6 @@ # include "DEG_depsgraph.h" # include "ED_object.h" -# include "ED_screen.h" # include "RNA_access.h" # include "RNA_define.h" diff --git a/source/blender/editors/lattice/editlattice_select.c b/source/blender/editors/lattice/editlattice_select.c index 4497ca1a379..cb3f9a89e62 100644 --- a/source/blender/editors/lattice/editlattice_select.c +++ b/source/blender/editors/lattice/editlattice_select.c @@ -108,7 +108,7 @@ bool ED_lattice_deselect_all_multi(struct bContext *C) static int lattice_select_random_exec(bContext *C, wmOperator *op) { - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c index 3a5734706f1..3ffbc3712fc 100644 --- a/source/blender/editors/lattice/editlattice_undo.c +++ b/source/blender/editors/lattice/editlattice_undo.c @@ -212,8 +212,11 @@ static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoSte return true; } -static void lattice_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void lattice_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { LatticeUndoStep *us = (LatticeUndoStep *)us_p; diff --git a/source/blender/editors/lattice/lattice_ops.c b/source/blender/editors/lattice/lattice_ops.c index d5505c00132..3f96b8a303b 100644 --- a/source/blender/editors/lattice/lattice_ops.c +++ b/source/blender/editors/lattice/lattice_ops.c @@ -23,15 +23,10 @@ #include "DNA_scene_types.h" -#include "RNA_access.h" - #include "WM_api.h" -#include "WM_types.h" #include "ED_lattice.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "lattice_intern.h" diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index d7b3d74bc7e..1226cc57359 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -507,6 +507,9 @@ static int add_vertex_handle_cyclic( static int add_vertex_exec(bContext *C, wmOperator *op) { + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + Mask *mask = CTX_data_edit_mask(C); if (mask == NULL) { /* if there's no active mask, create one */ @@ -548,6 +551,8 @@ static int add_vertex_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -690,6 +695,9 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) static int create_primitive_from_points( bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type) { + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ScrArea *area = CTX_wm_area(C); int size = RNA_float_get(op->ptr, "size"); @@ -752,6 +760,8 @@ static int create_primitive_from_points( DEG_id_tag_update(&mask->id, ID_RECALC_GEOMETRY); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index 89fd2fa9b62..d3fa0e93597 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -539,7 +539,7 @@ static void draw_spline_curve(const bContext *C, uint tot_feather_point; float(*feather_points)[2]; - diff_points = BKE_mask_spline_differentiate_with_resolution(spline, &tot_diff_point, resol); + diff_points = BKE_mask_spline_differentiate_with_resolution(spline, resol, &tot_diff_point); if (!diff_points) { return; @@ -550,7 +550,7 @@ static void draw_spline_curve(const bContext *C, } feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution( - spline, &tot_feather_point, resol, (is_fill != false)); + spline, resol, (is_fill != false), &tot_feather_point); /* draw feather */ mask_spline_feather_color_get(mask_layer, spline, is_spline_sel, rgb_tmp); diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 663ae0097ad..f1041d062a8 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -184,3 +184,39 @@ void ED_operatormacros_mask(void) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lock-to-selection viewport preservation + * \{ */ + +void ED_mask_view_lock_state_store(const bContext *C, MaskViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + if (space_clip != NULL) { + ED_clip_view_lock_state_store(C, &state->space_clip_state); + } +} + +void ED_mask_view_lock_state_restore_no_jump(const bContext *C, const MaskViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + if (space_clip != NULL) { + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + /* Early output if the editor is not locked to selection. + * Avoids forced dependency graph evaluation here. */ + return; + } + + /* Mask's lock-to-selection requires deformed splines to be evaluated to calculate bounds of + * points after animation has been evaluated. The restore-no-jump type of function does + * calculation of new offset for the view for an updated state of mask to cancel the offset out + * by modifying locked offset. In order to do such calculation mask needs to be evaluated after + * modification by an operator. */ + struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + (void)depsgraph; + + ED_clip_view_lock_state_restore_no_jump(C, &state->space_clip_state); + } +} + +/** \} */ diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index f6990583383..ee1784011ea 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -23,6 +23,8 @@ #pragma once +#include "ED_clip.h" + struct Mask; struct bContext; struct wmOperatorType; @@ -92,6 +94,19 @@ void ED_mask_select_flush_all(struct Mask *mask); bool ED_maskedit_poll(struct bContext *C); bool ED_maskedit_mask_poll(struct bContext *C); +/* Generalized solution for preserving editor viewport when making changes while lock-to-selection + * is enabled. + * Any mask operator can use this API, without worrying that some editors do not have an idea of + * lock-to-selection. */ + +typedef struct MaskViewLockState { + ClipViewLockState space_clip_state; +} MaskViewLockState; + +void ED_mask_view_lock_state_store(const struct bContext *C, MaskViewLockState *state); +void ED_mask_view_lock_state_restore_no_jump(const struct bContext *C, + const MaskViewLockState *state); + /* mask_query.c */ bool ED_mask_find_nearest_diff_point(const struct bContext *C, struct Mask *mask, diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 25cc39bf9a0..14f81520b9a 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -226,13 +226,19 @@ typedef struct SlidePointData { int width, height; float prev_mouse_coord[2]; + + /* Previous clip coordinate which was resolved from mouse position (0, 0). + * Is used to compensate for view offset moving in-between of mouse events when + * lock-to-selection is enabled. */ + float prev_zero_coord[2]; + float no[2]; bool is_curvature_only, is_accurate, is_initial_feather, is_overall_feather; bool is_sliding_new_point; - /* Data needed to restre the state. */ + /* Data needed to restore the state. */ float vec[3][3]; char old_h1, old_h2; @@ -431,6 +437,9 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * const float threshold = 19; eMaskWhichHandle which_handle; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_mouse_pos(area, region, event->mval, co); ED_mask_get_size(area, &width, &height); @@ -530,7 +539,15 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent * } customdata->which_handle = which_handle; + { + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + DEG_id_tag_update(&mask->id, 0); + + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + } + ED_mask_mouse_pos(area, region, event->mval, customdata->prev_mouse_coord); + ED_mask_mouse_pos(area, region, (int[2]){0, 0}, customdata->prev_zero_coord); } return customdata; @@ -655,10 +672,24 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_mask_mouse_pos(area, region, event->mval, co); sub_v2_v2v2(delta, co, data->prev_mouse_coord); + copy_v2_v2(data->prev_mouse_coord, co); + + /* Compensate for possibly moved view offset since the last event. + * The idea is to see how mapping of a fixed and known position did change. */ + { + float zero_coord[2]; + ED_mask_mouse_pos(area, region, (int[2]){0, 0}, zero_coord); + + float zero_delta[2]; + sub_v2_v2v2(zero_delta, zero_coord, data->prev_zero_coord); + sub_v2_v2(delta, zero_delta); + + copy_v2_v2(data->prev_zero_coord, zero_coord); + } + if (data->is_accurate) { mul_v2_fl(delta, 0.2f); } - copy_v2_v2(data->prev_mouse_coord, co); if (data->action == SLIDE_ACTION_HANDLE) { float new_handle[2]; @@ -832,7 +863,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) if (event->type == data->event_invoke_type && event->val == KM_RELEASE) { Scene *scene = CTX_data_scene(C); - /* dont key sliding feather uw's */ + /* Don't key sliding feather UW's. */ if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) { if (IS_AUTOKEY_ON(scene)) { ED_mask_layer_shape_auto_key(data->mask_layer, CFRA); @@ -966,6 +997,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, float u, co[2]; BezTriple *next_bezt; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, co); if (!ED_mask_find_nearest_diff_point(C, @@ -1019,7 +1053,7 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, slide_data->bezt_backup = *slide_data->adjust_bezt; slide_data->other_bezt_backup = *slide_data->other_bezt; - /* Let's dont touch other side of the point for now, so set handle to FREE. */ + /* Let's don't touch other side of the point for now, so set handle to FREE. */ if (u < 0.5f) { if (slide_data->adjust_bezt->h2 <= HD_VECT) { slide_data->adjust_bezt->h2 = HD_FREE; @@ -1047,6 +1081,9 @@ static SlideSplineCurvatureData *slide_spline_curvature_customdata(bContext *C, mask_layer->act_point = point; ED_mask_select_flush_all(mask); + DEG_id_tag_update(&mask->id, 0); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return slide_data; } @@ -1233,7 +1270,7 @@ static int slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEve case LEFTMOUSE: case RIGHTMOUSE: if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) { - /* dont key sliding feather uw's */ + /* Don't key sliding feather UW's. */ if (IS_AUTOKEY_ON(scene)) { ED_mask_layer_shape_auto_key(slide_data->mask_layer, CFRA); } diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c index cfd57ca3477..401b6eac4f2 100644 --- a/source/blender/editors/mask/mask_query.c +++ b/source/blender/editors/mask/mask_query.c @@ -604,22 +604,37 @@ void ED_mask_point_pos__reverse( *yr = co[1]; } -bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) +static void handle_position_for_minmax(const MaskSplinePoint *point, + eMaskWhichHandle which_handle, + bool handles_as_control_point, + float r_handle[2]) +{ + if (handles_as_control_point) { + copy_v2_v2(r_handle, point->bezt.vec[1]); + return; + } + BKE_mask_point_handle(point, which_handle, r_handle); +} + +bool ED_mask_selected_minmax(const bContext *C, + float min[2], + float max[2], + bool handles_as_control_point) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Mask *mask = CTX_data_edit_mask(C); - /* Use evaluated mask to take animation into account. - * The animation of splies is not "flushed" back to original, so need to explicitly - * sue evaluated datablock here. */ - Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask->id); - bool ok = false; if (mask == NULL) { return ok; } + /* Use evaluated mask to take animation into account. + * The animation of splies is not "flushed" back to original, so need to explicitly + * sue evaluated datablock here. */ + Mask *mask_eval = (Mask *)DEG_get_evaluated_id(depsgraph, &mask->id); + INIT_MINMAX2(min, max); for (MaskLayer *mask_layer = mask_eval->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { @@ -638,22 +653,29 @@ bool ED_mask_selected_minmax(const bContext *C, float min[2], float max[2]) } if (bezt->f2 & SELECT) { minmax_v2v2_v2(min, max, deform_point->bezt.vec[1]); + ok = true; } + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_STICK, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_STICK, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } else { if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_LEFT, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_LEFT, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { - BKE_mask_point_handle(deform_point, MASK_WHICH_HANDLE_RIGHT, handle); + handle_position_for_minmax( + deform_point, MASK_WHICH_HANDLE_RIGHT, handles_as_control_point, handle); minmax_v2v2_v2(min, max, handle); + ok = true; } } - ok = true; } } } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index cdc6ece1e84..5c369afc4cd 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -214,12 +214,17 @@ static int select_all_exec(bContext *C, wmOperator *op) Mask *mask = CTX_data_edit_mask(C); int action = RNA_enum_get(op->ptr, "action"); + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + ED_mask_select_toggle_all(mask, action); ED_mask_select_flush_all(mask); DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -261,6 +266,9 @@ static int select_exec(bContext *C, wmOperator *op) eMaskWhichHandle which_handle; const float threshold = 19; + MaskViewLockState lock_state; + ED_mask_view_lock_state_store(C, &lock_state); + RNA_float_get_array(op->ptr, "location", co); point = ED_mask_point_find_nearest( @@ -324,6 +332,8 @@ static int select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } @@ -364,12 +374,15 @@ static int select_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&mask->id, ID_RECALC_SELECT); WM_event_add_notifier(C, NC_MASK | ND_SELECT, mask); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); + return OPERATOR_FINISHED; } if (deselect_all) { /* For clip editor tracks, leave deselect all to clip editor. */ if (!ED_clip_can_select(C)) { ED_mask_deselect_all(C); + ED_mask_view_lock_state_restore_no_jump(C, &lock_state); return OPERATOR_FINISHED; } } diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index a5dd29c9d73..d60d83850a5 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -24,7 +24,6 @@ #include "BLI_math.h" #include "BLI_sys_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -42,7 +41,6 @@ #include "ED_mesh.h" #include "ED_object.h" #include "ED_screen.h" -#include "ED_uvedit.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/editmesh_automerge.c b/source/blender/editors/mesh/editmesh_automerge.c index f9910f01f47..2bd5b9b26ca 100644 --- a/source/blender/editors/mesh/editmesh_automerge.c +++ b/source/blender/editors/mesh/editmesh_automerge.c @@ -26,12 +26,9 @@ * - #EDBM_automerge_and_split */ -#include "MEM_guardedalloc.h" - #include "BKE_editmesh.h" #include "DNA_object_types.h" -#include "DNA_scene_types.h" #include "ED_mesh.h" diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 8ea3c883433..66a7b97b440 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -28,11 +28,9 @@ #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_curveprofile.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_layer.h" -#include "BKE_mesh.h" #include "BKE_unit.h" #include "DNA_curveprofile_types.h" @@ -575,7 +573,7 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event) opdata->shift_value[vmode] = -1.0f; } - /* clamp accordingto value mode, and store value back */ + /* Clamp according to value mode, and store value back. */ CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]); if (vmode == SEGMENTS_VALUE) { opdata->segments = value; diff --git a/source/blender/editors/mesh/editmesh_extrude_spin.c b/source/blender/editors/mesh/editmesh_extrude_spin.c index 7b3fabf07fc..187652ae00f 100644 --- a/source/blender/editors/mesh/editmesh_extrude_spin.c +++ b/source/blender/editors/mesh/editmesh_extrude_spin.c @@ -33,17 +33,13 @@ #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" -#include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" #include "ED_screen.h" #include "ED_view3d.h" -#include "UI_resources.h" - #include "MEM_guardedalloc.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index f45f48e0e32..1f894ec0f1d 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -210,7 +210,7 @@ typedef struct KnifeTool_OpData { /* run by the UI or not */ bool is_interactive; - /* operatpr options */ + /* Operator options. */ bool cut_through; /* preference, can be modified at runtime (that feature may go) */ bool only_select; /* set on initialization */ bool select_result; /* set on initialization */ @@ -2752,8 +2752,6 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) } } - view3d_operator_needs_opengl(C); - /* alloc new customdata */ kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__); @@ -2831,7 +2829,6 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) em_setup_viewcontext(C, &kcd->vc); kcd->region = kcd->vc.region; - view3d_operator_needs_opengl(C); ED_view3d_init_mats_rv3d(obedit, kcd->vc.rv3d); /* needed to initialize clipping */ if (kcd->mode == MODE_PANNING) { @@ -3067,8 +3064,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug { KnifeTool_OpData *kcd; - view3d_operator_needs_opengl(C); - /* init */ { const bool only_select = false; diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 3e0bee3c4b8..7d849c096e7 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -81,7 +81,7 @@ typedef struct GeometryExtactParams { /* For extracting Mask. */ float mask_threshold; - /* Common paramenters. */ + /* Common parameters. */ bool add_boundary_loop; int num_smooth_iterations; bool apply_shrinkwrap; @@ -106,7 +106,7 @@ static int geometry_extract_apply(bContext *C, BKE_sculpt_mask_layers_ensure(ob, NULL); - /* Ensures that deformation from sculpt mode is taken into accunt before duplicating the mesh to + /* Ensures that deformation from sculpt mode is taken into account before duplicating the mesh to * extract the geometry. */ CTX_data_ensure_evaluated_depsgraph(C); @@ -385,7 +385,7 @@ static int face_set_extract_modal(bContext *C, wmOperator *op, const wmEvent *ev ED_workspace_status_text(C, NULL); /* This modal operator uses and eyedropper to pick a Face Set from the mesh. This ensures - * that the mouse clicked in a viewport region and its coordinates can be used to raycast + * that the mouse clicked in a viewport region and its coordinates can be used to ray-cast * the PBVH and update the active Face Set ID. */ bScreen *screen = CTX_wm_screen(C); ARegion *region = BKE_screen_find_main_region_at_xy( diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index b5b4802aa78..c8449644dd0 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2205,7 +2205,7 @@ void EDBM_selectmode_set(BMEditMesh *em) } } else if (em->selectmode & SCE_SELECT_FACE) { - /* deselect eges, and select again based on face select */ + /* Deselect edges, and select again based on face select. */ BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) { BM_edge_select_set(em->bm, eed, false); } @@ -2247,7 +2247,7 @@ void EDBM_selectmode_convert(BMEditMesh *em, /* first tag-to-select, then select --- this avoids a feedback loop */ - /* have to find out what the selectionmode was previously */ + /* Have to find out what the selection-mode was previously. */ if (selectmode_old == SCE_SELECT_VERTEX) { if (bm->totvertsel == 0) { /* pass */ @@ -4573,7 +4573,7 @@ void MESH_OT_select_non_manifold(wmOperatorType *ot) static int edbm_select_random_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 84f4e35cb0c..de37ddec885 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3905,7 +3905,7 @@ static float bm_edge_seg_isect(const float sco_a[2], x12 = mouse_path[i][0]; y12 = mouse_path[i][1]; - /* Perp. Distance from point to line */ + /* Calculate the distance from point to line. */ if (m2 != MAXSLOPE) { /* sqrt(m2 * m2 + 1); Only looking for change in sign. Skip extra math .*/ dist = (y12 - m2 * x12 - b2); @@ -4010,7 +4010,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) short numcuts = 1; const short mode = RNA_int_get(op->ptr, "type"); - /* allocd vars */ + /* Allocated variables. */ float(*screen_vert_coords)[2], (*sco)[2], (*mouse_path)[2]; /* edit-object needed for matrix, and region->regiondata for projections to work */ diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 41bb3faa135..dd51d63961c 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -188,7 +188,7 @@ static void um_arraystore_cd_compact(struct CustomData *cdata, else { bcd_reference_current = NULL; - /* do a full lookup when un-alligned */ + /* Do a full lookup when unaligned. */ if (bcd_reference) { const BArrayCustomData *bcd_iter = bcd_reference; while (bcd_iter) { @@ -766,8 +766,11 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und return true; } -static void mesh_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void mesh_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { MeshUndoStep *us = (MeshUndoStep *)us_p; diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 2cf97b7235f..27d73497b49 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -21,7 +21,6 @@ * \ingroup edmesh */ -#include "DNA_modifier_types.h" #include "DNA_scene_types.h" #include "RNA_access.h" @@ -30,9 +29,7 @@ #include "WM_types.h" #include "ED_mesh.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "mesh_intern.h" /* own include */ diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 3b5897de0b0..3450d61337c 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -145,7 +145,7 @@ static void join_mesh_single(Depsgraph *depsgraph, if (ob_src != ob_dst) { float cmat[4][4]; - /* watch this: switch matmul order really goes wrong */ + /* Watch this: switch matrix multiplication order really goes wrong. */ mul_m4_m4m4(cmat, imat, ob_src->obmat); /* transform vertex coordinates into new space */ @@ -733,7 +733,7 @@ int ED_mesh_join_objects_exec(bContext *C, wmOperator *op) BKE_key_sort(key); } - /* Due to dependnecy cycle some other object might access old derived data. */ + /* Due to dependency cycle some other object might access old derived data. */ BKE_object_free_derived_caches(ob); DEG_relations_tag_update(bmain); /* removed objects, need to rebuild dag */ diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c index cbc60bcc031..b817bc3a718 100644 --- a/source/blender/editors/metaball/editmball_undo.c +++ b/source/blender/editors/metaball/editmball_undo.c @@ -187,8 +187,11 @@ static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, Un return true; } -static void mball_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final)) +static void mball_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir UNUSED(dir), + bool UNUSED(is_final)) { MBallUndoStep *us = (MBallUndoStep *)us_p; diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 094011ebef1..cf453bf0c32 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -483,7 +483,7 @@ void MBALL_OT_select_similar(wmOperatorType *ot) static int select_random_metaelems_exec(bContext *C, wmOperator *op) { const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); ViewLayer *view_layer = CTX_data_view_layer(C); diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c index 100ca4691ca..a54ec384d8e 100644 --- a/source/blender/editors/metaball/mball_ops.c +++ b/source/blender/editors/metaball/mball_ops.c @@ -29,9 +29,7 @@ #include "WM_types.h" #include "ED_mball.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "mball_intern.h" diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index c6d6b8b16b9..b6b6dcfaa59 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -516,7 +516,7 @@ bool ED_object_add_generic_get_opts(bContext *C, if (RNA_struct_property_is_set(op->ptr, "rotation")) { /* If rotation is set, always use it. Alignment (and corresponding user preference) * can be ignored since this is in world space anyways. - * To not confuse (e.g. on redo), dont set it to ALIGN_WORLD in the op UI though. */ + * To not confuse (e.g. on redo), don't set it to #ALIGN_WORLD in the op UI though. */ *is_view_aligned = false; RNA_float_get_array(op->ptr, "rotation", rot); } @@ -607,7 +607,6 @@ Object *ED_object_add_type_with_obdata(bContext *C, Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - /* For as long scene has editmode... */ { Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); if (obedit != NULL) { @@ -1712,9 +1711,8 @@ static int object_speaker_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type(C, OB_SPEAKER, NULL, loc, rot, false, local_view_bits); const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); - /* to make it easier to start using this immediately in NLA, a default sound clip is created - * ready to be moved around to retime the sound and/or make new sound clips - */ + /* To make it easier to start using this immediately in NLA, a default sound clip is created + * ready to be moved around to re-time the sound and/or make new sound clips. */ { /* create new data for NLA hierarchy */ AnimData *adt = BKE_animdata_add_id(&ob->id); @@ -3364,6 +3362,9 @@ static int object_add_named_exec(bContext *C, wmOperator *op) ED_view3d_cursor3d_position(C, mval, false, basen->object->loc); } + /* object_add_duplicate_internal() doesn't deselect other objects, unlike object_add_common() or + * BKE_view_layer_base_deselect_all(). */ + ED_object_base_deselect_all(view_layer, NULL, BA_DESELECT); ED_object_base_select(basen, BA_SELECT); ED_object_base_activate(C, basen); diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index db9e51a490d..b1ba856ff0f 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -1339,7 +1339,7 @@ static int bake(const BakeAPIRender *bkr, highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false); - /* lowpoly to highpoly transformation matrix */ + /* Low-poly to high-poly transformation matrix. */ copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat); invert_m4_m4(highpoly[i].imat, highpoly[i].obmat); diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 4cbb8858bf4..b251e617a4c 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -51,8 +51,6 @@ #include "ED_object.h" -#include "UI_interface.h" - #include "object_intern.h" /* All possible data to transfer. @@ -65,7 +63,7 @@ static const EnumPropertyItem DT_layer_items[] = { 0, "Vertex Group(s)", "Transfer active or all vertex groups"}, -#if 0 /* XXX For now, would like to finish/merge work from 2014 gsoc first. */ +#if 0 /* XXX For now, would like to finish/merge work from 2014 GSOC first. */ {DT_TYPE_SHAPEKEY, "SHAPEKEYS", 0, "Shapekey(s)", "Transfer active or all shape keys"}, #endif /* XXX When SkinModifier is enabled, diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 6350ffb9c77..7e0e52d3874 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -3024,7 +3024,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) i++; } - /* make a copy of ocean to use for baking - threadsafety */ + /* Make a copy of ocean to use for baking - thread-safety. */ struct Ocean *ocean = BKE_ocean_add(); BKE_ocean_init_from_modifier(ocean, omd, omd->resolution); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 964d9898ac0..2124d242ee2 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -25,23 +25,15 @@ #include <stdlib.h> #include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BLI_utildefines.h" #include "BKE_context.h" #include "RNA_access.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" #include "ED_object.h" -#include "ED_screen.h" -#include "ED_select_utils.h" - -#include "DEG_depsgraph.h" #include "object_intern.h" diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index acad1b43cbb..5a2ef1c6556 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1790,20 +1790,33 @@ void OBJECT_OT_make_links_scene(wmOperatorType *ot) void OBJECT_OT_make_links_data(wmOperatorType *ot) { static const EnumPropertyItem make_links_items[] = { - {MAKE_LINKS_OBDATA, "OBDATA", 0, "Object Data", ""}, - {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Materials", ""}, - {MAKE_LINKS_ANIMDATA, "ANIMATION", 0, "Animation Data", ""}, - {MAKE_LINKS_GROUP, "GROUPS", 0, "Collection", ""}, - {MAKE_LINKS_DUPLICOLLECTION, "DUPLICOLLECTION", 0, "Instance Collection", ""}, - {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Modifiers", ""}, - {MAKE_LINKS_FONTS, "FONTS", 0, "Fonts", ""}, - {MAKE_LINKS_SHADERFX, "EFFECTS", 0, "Effects", ""}, + {MAKE_LINKS_OBDATA, "OBDATA", 0, "Link Object Data", "Replace assigned Object Data"}, + {MAKE_LINKS_MATERIALS, "MATERIAL", 0, "Link Materials", "Replace assigned Materials"}, + {MAKE_LINKS_ANIMDATA, + "ANIMATION", + 0, + "Link Animation Data", + "Replace assigned Animation Data"}, + {MAKE_LINKS_GROUP, "GROUPS", 0, "Link Collections", "Replace assigned Collections"}, + {MAKE_LINKS_DUPLICOLLECTION, + "DUPLICOLLECTION", + 0, + "Link Instance Collection", + "Replace assigned Collection Instance"}, + {MAKE_LINKS_FONTS, "FONTS", 0, "Link Fonts to Text", "Replace Text object Fonts"}, + {0, "", 0, NULL, NULL}, + {MAKE_LINKS_MODIFIERS, "MODIFIERS", 0, "Copy Modifiers", "Replace Modifiers"}, + {MAKE_LINKS_SHADERFX, + "EFFECTS", + 0, + "Copy Grease Pencil Effects", + "Replace Grease Pencil Effects"}, {0, NULL, 0, NULL, NULL}, }; /* identifiers */ - ot->name = "Link Data"; - ot->description = "Apply active object links to other selected objects"; + ot->name = "Link/Transfer Data"; + ot->description = "Transfer data from active object to selected objects"; ot->idname = "OBJECT_OT_make_links_data"; /* api callbacks */ @@ -2328,7 +2341,7 @@ void OBJECT_OT_make_local(wmOperatorType *ot) static bool make_override_library_object_overridable_check(Main *bmain, Object *object) { - /* An object is actually overrideable only if it is in at least one local collections. + /* An object is actually overridable only if it is in at least one local collection. * Unfortunately 'direct link' flag is not enough here. */ LISTBASE_FOREACH (Collection *, collection, &bmain->collections) { if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, object)) { diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index d560d347217..f55ce88b426 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -327,7 +327,7 @@ static void voxel_size_edit_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), const float total_len = len_v3v3(cd->preview_plane[0], cd->preview_plane[1]); const int tot_lines = (int)(total_len / cd->voxel_size); - /* Smoothstep to reduce the alpha of the grid as the line number increases. */ + /* Smooth-step to reduce the alpha of the grid as the line number increases. */ const float a = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES * 0.1f; const float b = VOXEL_SIZE_EDIT_MAX_GRIDS_LINES; const float x = clamp_f((tot_lines - a) / (b - a), 0.0f, 1.0); @@ -738,7 +738,7 @@ static int quadriflow_break_job(void *customdata) return should_break; } -/* called by oceanbake, wmJob sends notifier */ +/** Called by ocean-bake, #wmJob sends notifier. */ static void quadriflow_update_job(void *customdata, float progress, int *cancel) { QuadriFlowJob *qj = customdata; @@ -982,7 +982,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) quadriflow_free_job(job); } else { - /* Non blocking call. For when the operator has been called from the gui */ + /* Non blocking call. For when the operator has been called from the GUI. */ job->is_nonblocking_job = true; wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index b36d89dc37a..1e6a7b9f14e 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -317,7 +317,7 @@ bool ED_object_jump_to_object(bContext *C, Object *ob, const bool UNUSED(reveal_ /** * Select and make the target object and bone active. * Switches to Pose mode if in Object mode so the selection is visible. - * Unhides the target bone and bone layer if necessary. + * Un-hides the target bone and bone layer if necessary. * * \returns false if object not in layer, bone not found, or other error */ @@ -1453,7 +1453,7 @@ void OBJECT_OT_select_less(wmOperatorType *ot) static int object_select_random_exec(bContext *C, wmOperator *op) { - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index 1bb0246deb5..fd649854d8f 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -36,7 +36,6 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -#include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" @@ -44,7 +43,6 @@ #include "DNA_object_types.h" #include "BKE_context.h" -#include "BKE_curve.h" #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_main.h" diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 0528d64dca9..13c0740bce6 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1394,7 +1394,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) * (all layers are considered without evaluating lock attributes) */ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* undo matrix */ invert_m4_m4(inverse_diff_mat, diff_mat); LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { diff --git a/source/blender/editors/object/object_volume.c b/source/blender/editors/object/object_volume.c index 6b46d43e5bf..fbdee00c29c 100644 --- a/source/blender/editors/object/object_volume.c +++ b/source/blender/editors/object/object_volume.c @@ -23,9 +23,6 @@ #include <string.h> -#include "MEM_guardedalloc.h" - -#include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_path_util.h" diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c index b36a8543d67..4b15385b537 100644 --- a/source/blender/editors/object/object_warp.c +++ b/source/blender/editors/object/object_warp.c @@ -36,7 +36,6 @@ #include "WM_types.h" #include "ED_transverts.h" -#include "ED_view3d.h" #include "object_intern.h" @@ -75,7 +74,7 @@ static void object_warp_transverts_minmax_x(TransVertStore *tvs, for (int i = 0; i < tvs->transverts_tot; i++, tv++) { float val; - /* convert objectspace->viewspace */ + /* Convert object-space to view-space. */ val = dot_m4_v3_row_x(mat_view, tv->loc); min = min_ff(min, val); @@ -123,7 +122,7 @@ static void object_warp_transverts(TransVertStore *tvs, float co[3], co_add[2]; float val, phi; - /* convert objectspace->viewspace */ + /* Convert object-space to view-space. */ mul_v3_m4v3(co, mat_view, tv->loc); sub_v2_v2(co, center_view); @@ -158,7 +157,7 @@ static void object_warp_transverts(TransVertStore *tvs, add_v2_v2(co, co_add); - /* convert viewspace->objectspace */ + /* Convert view-space to object-space. */ add_v2_v2(co, center_view); mul_v3_m4v3(tv->loc, imat_view, co); } @@ -187,7 +186,7 @@ static int object_warp_verts_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - /* get viewmatrix */ + /* Get view-matrix. */ { PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat"); if (RNA_property_is_set(op->ptr, prop_viewmat)) { diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 381bf317bee..a761701f60b 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -233,7 +233,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op) /* if type is already enabled, toggle it off */ if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { - int exists = dynamicPaint_outputLayerExists(surface, ob, output); + bool exists = dynamicPaint_outputLayerExists(surface, ob, output); const char *name; if (output == 0) { diff --git a/source/blender/editors/physics/particle_boids.c b/source/blender/editors/physics/particle_boids.c index 22cfa50aee9..9b8622e6eac 100644 --- a/source/blender/editors/physics/particle_boids.c +++ b/source/blender/editors/physics/particle_boids.c @@ -33,7 +33,6 @@ #include "BKE_boids.h" #include "BKE_context.h" #include "BKE_main.h" -#include "BKE_particle.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 8ab25fa74b8..d7e30f2b65c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -1999,7 +1999,7 @@ static int select_random_exec(bContext *C, wmOperator *op) int p; int k; - const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f; + const float randfac = RNA_float_get(op->ptr, "ratio"); const int seed = WM_operator_properties_select_random_seed_increment_get(op); const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT); RNG *rng; @@ -2905,7 +2905,7 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem } } -/************************ subdivide opertor *********************/ +/************************ subdivide operator *********************/ /* works like normal edit mode subdivide, inserts keys between neighboring selected keys */ static void subdivide_particle(PEData *data, int pa_index) @@ -3029,7 +3029,7 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/************************ remove doubles opertor *********************/ +/************************ remove doubles operator *********************/ static int remove_doubles_exec(bContext *C, wmOperator *op) { @@ -3750,8 +3750,7 @@ static void brush_puff(PEData *data, int point_index, float mouse_distance) } } else { - /* compute position as if hair was standing up straight. - * */ + /* Compute position as if hair was standing up straight. */ float length; copy_v3_v3(co_prev, co); copy_v3_v3(co, key->co); @@ -4566,7 +4565,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) mval[0] = mouse[0]; mval[1] = mouse[1]; - /* disable locking temporatily for disconnected hair */ + /* Disable locking temporarily for disconnected hair. */ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) { pset->flag &= ~PE_LOCK_FIRST; } @@ -5004,7 +5003,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } - /* disable locking temporatily for disconnected hair */ + /* Disable locking temporarily for disconnected hair. */ if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) { pset->flag &= ~PE_LOCK_FIRST; } diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c index 77b8d410d81..5d2e0e5b6ef 100644 --- a/source/blender/editors/physics/particle_edit_undo.c +++ b/source/blender/editors/physics/particle_edit_undo.c @@ -247,7 +247,7 @@ static bool particle_undosys_step_encode(struct bContext *C, static void particle_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, - int UNUSED(dir), + const eUndoStepDir UNUSED(dir), bool UNUSED(is_final)) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 32d2e39d6f6..a94a2b9b764 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -33,21 +33,17 @@ #include "DNA_object_types.h" #include "BLI_blenlib.h" -#include "BLI_math.h" #include "BLI_path_util.h" #include "BLI_utildefines.h" #include "BLT_translation.h" #include "BKE_context.h" -#include "BKE_customdata.h" #include "BKE_fluid.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_modifier.h" -#include "BKE_object.h" #include "BKE_report.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "DEG_depsgraph.h" @@ -59,11 +55,9 @@ #include "WM_api.h" #include "WM_types.h" -#include "manta_fluid_API.h" #include "physics_intern.h" /* own include */ #include "DNA_fluid_types.h" -#include "DNA_mesh_types.h" #include "DNA_scene_types.h" #define FLUID_JOB_BAKE_ALL "FLUID_OT_bake_all" diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index eb154b97eb0..f5b80679689 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -23,14 +23,9 @@ #include <stdlib.h> -#include "RNA_access.h" - #include "WM_api.h" -#include "WM_types.h" -#include "ED_object.h" #include "ED_physics.h" -#include "ED_select_utils.h" #include "physics_intern.h" /* own include */ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 1d5903bf417..ea8a4ce2a79 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -34,7 +34,6 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_layer.h" -#include "BKE_particle.h" #include "BKE_pointcache.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 4fd304ea71d..81a8b57776b 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -34,9 +34,7 @@ #include "BLT_translation.h" -#include "BKE_collection.h" #include "BKE_context.h" -#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_rigidbody.h" diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 10cf4131584..50ba5907703 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -43,14 +43,10 @@ #include "DNA_userdef_types.h" #include "DNA_view3d_types.h" -#include "BKE_blender_undo.h" -#include "BKE_blender_version.h" -#include "BKE_camera.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" -#include "BKE_layer.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" @@ -58,19 +54,15 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_undo_system.h" #include "DEG_depsgraph.h" #include "WM_api.h" #include "WM_types.h" -#include "ED_object.h" #include "ED_render.h" #include "ED_screen.h" -#include "ED_undo.h" #include "ED_util.h" -#include "ED_view3d.h" #include "BIF_glutil.h" @@ -85,8 +77,6 @@ #include "SEQ_relations.h" -#include "BLO_undofile.h" - #include "render_intern.h" /* Render Callbacks */ @@ -1098,7 +1088,7 @@ void RENDER_OT_render(wmOperatorType *ot) ot->cancel = screen_render_cancel; ot->exec = screen_render_exec; - /* this isn't needed, causes failer in background mode */ + /* This isn't needed, causes failure in background mode. */ #if 0 ot->poll = ED_operator_screenactive; #endif diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 4cb6994bc4b..71e4dca3ab1 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -363,7 +363,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R } } else { - /* shouldnt suddenly give errors mid-render but possible */ + /* shouldn't suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 6cf8515bdbb..4e766841c24 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -200,6 +200,11 @@ static bool check_engine_supports_preview(Scene *scene) return (type->flag & RE_USE_PREVIEW) != 0; } +static bool preview_method_is_render(int pr_method) +{ + return ELEM(pr_method, PR_ICON_RENDER, PR_BUTS_RENDER, PR_NODE_RENDER); +} + void ED_preview_free_dbase(void) { if (G_pr_main) { @@ -1179,7 +1184,7 @@ static void icon_copy_rect(ImBuf *ibuf, uint w, uint h, uint *rect) return; } - /* waste of cpu cyles... but the imbuf API has no other way to scale fast (ton) */ + /* Waste of cpu cycles... but the imbuf API has no other way to scale fast (ton). */ ima = IMB_dupImBuf(ibuf); if (!ima) { @@ -1352,13 +1357,12 @@ static void common_preview_startjob(void *customdata, */ static void other_id_types_preview_render(IconPreview *ip, IconPreviewSize *cur_size, - const bool is_deferred, + const int pr_method, short *stop, short *do_update, float *progress) { ShaderPreview *sp = MEM_callocN(sizeof(ShaderPreview), "Icon ShaderPreview"); - const bool is_render = !is_deferred; /* These types don't use the ShaderPreview mess, they have their own types and functions. */ BLI_assert(!ip->id || !ELEM(GS(ip->id->name), ID_OB)); @@ -1368,7 +1372,7 @@ static void other_id_types_preview_render(IconPreview *ip, sp->owner = ip->owner; sp->sizex = cur_size->sizex; sp->sizey = cur_size->sizey; - sp->pr_method = is_render ? PR_ICON_RENDER : PR_ICON_DEFERRED; + sp->pr_method = pr_method; sp->pr_rect = cur_size->rect; sp->id = ip->id; sp->id_copy = ip->id_copy; @@ -1376,7 +1380,7 @@ static void other_id_types_preview_render(IconPreview *ip, sp->own_id_copy = false; Material *ma = NULL; - if (is_render) { + if (sp->pr_method == PR_ICON_RENDER) { BLI_assert(ip->id); /* grease pencil use its own preview file */ @@ -1424,6 +1428,8 @@ static void icon_preview_startjob_all_sizes(void *customdata, for (cur_size = ip->sizes.first; cur_size; cur_size = cur_size->next) { PreviewImage *prv = ip->owner; + /* Is this a render job or a deferred loading job? */ + const int pr_method = (prv->tag & PRV_TAG_DEFFERED) ? PR_ICON_DEFERRED : PR_ICON_RENDER; if (*stop) { break; @@ -1434,7 +1440,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, continue; } - if (!check_engine_supports_preview(ip->scene)) { + if (preview_method_is_render(pr_method) && !check_engine_supports_preview(ip->scene)) { continue; } @@ -1450,8 +1456,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, object_preview_render(ip, cur_size); } else { - other_id_types_preview_render( - ip, cur_size, (prv->tag & PRV_TAG_DEFFERED), stop, do_update, progress); + other_id_types_preview_render(ip, cur_size, pr_method, stop, do_update, progress); } } } @@ -1634,7 +1639,7 @@ void ED_preview_shader_job(const bContext *C, /* Use workspace render only for buttons Window, * since the other previews are related to the datablock. */ - if (!check_engine_supports_preview(scene)) { + if (preview_method_is_render(method) && !check_engine_supports_preview(scene)) { return; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 499ffac6028..4ed1cbd60a5 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -25,7 +25,6 @@ #include "DNA_light_types.h" #include "DNA_material_types.h" -#include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -33,7 +32,6 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "DRW_engine.h" @@ -44,13 +42,11 @@ #include "BKE_context.h" #include "BKE_icons.h" -#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_scene.h" -#include "BKE_workspace.h" #include "RE_engine.h" #include "RE_pipeline.h" @@ -65,8 +61,6 @@ #include "WM_api.h" -#include "render_intern.h" /* own include */ - #include <stdio.h> /***************************** Render Engines ********************************/ diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 581169d823e..2c71345699f 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -141,13 +141,15 @@ void ED_region_pixelspace(ARegion *region) } /* only exported for WM */ -void ED_region_do_listen( - wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *note, const Scene *scene) +void ED_region_do_listen(wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *notifier = params->notifier; + /* generic notes first */ - switch (note->category) { + switch (notifier->category) { case NC_WM: - if (note->data == ND_FILEREAD) { + if (notifier->data == ND_FILEREAD) { ED_region_tag_redraw(region); } break; @@ -157,16 +159,16 @@ void ED_region_do_listen( } if (region->type && region->type->listener) { - region->type->listener(win, area, region, note, scene); + region->type->listener(params); } } /* only exported for WM */ -void ED_area_do_listen(wmWindow *win, ScrArea *area, wmNotifier *note, Scene *scene) +void ED_area_do_listen(wmSpaceTypeListenerParams *params) { /* no generic notes? */ - if (area->type && area->type->listener) { - area->type->listener(win, area, note, scene); + if (params->area->type && params->area->type->listener) { + params->area->type->listener(params); } } @@ -289,7 +291,15 @@ static void region_draw_azone_tab_arrow(ScrArea *area, ARegion *region, AZone *a float alpha = WM_region_use_viewport(area, region) ? 0.6f : 0.4f; const float color[4] = {0.05f, 0.05f, 0.05f, alpha}; UI_draw_roundbox_aa( - true, (float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, 4.0f, color); + &(const rctf){ + .xmin = (float)az->x1, + .xmax = (float)az->x2, + .ymin = (float)az->y1, + .ymax = (float)az->y2, + }, + true, + 4.0f, + color); draw_azone_arrow((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y2, az->edge); } @@ -373,7 +383,16 @@ static void region_draw_status_text(ScrArea *area, ARegion *region) float color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; UI_GetThemeColor3fv(TH_BACK, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, x1, y1, x2, y2, 4.0f, color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + true, + 4.0f, + color); UI_FontThemeColor(fontid, TH_TEXT); } @@ -418,16 +437,13 @@ void ED_area_do_msg_notify_tag_refresh( ED_area_tag_refresh(area); } -void ED_area_do_mgs_subscribe_for_tool_header( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +/* Follow ARegionType.message_subscribe */ +void ED_area_do_mgs_subscribe_for_tool_header(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_TOOL_HEADER); wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, @@ -438,16 +454,12 @@ void ED_area_do_mgs_subscribe_for_tool_header( mbus, &workspace->id, workspace, WorkSpace, tools, &msg_sub_value_region_tag_redraw); } -void ED_area_do_mgs_subscribe_for_tool_ui( - /* Follow ARegionType.message_subscribe */ - const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_area_do_mgs_subscribe_for_tool_ui(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + BLI_assert(region->regiontype == RGN_TYPE_UI); const char *panel_category_tool = "Tool"; const char *category = UI_panel_category_active_get(region, false); @@ -634,7 +646,16 @@ void ED_region_do_draw(bContext *C, ARegion *region) WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_region_tag_redraw, __func__); } - ED_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + wmRegionMessageSubscribeParams message_subscribe_params = { + .context = C, + .message_bus = mbus, + .workspace = workspace, + .scene = scene, + .screen = screen, + .area = area, + .region = region, + }; + ED_region_message_subscribe(&message_subscribe_params); } } @@ -4027,14 +4048,12 @@ void ED_region_cache_draw_cached_segments( /** * Generate subscriptions for this region. */ -void ED_region_message_subscribe(bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_message_subscribe(wmRegionMessageSubscribeParams *params) { + ARegion *region = params->region; + const bContext *C = params->context; + struct wmMsgBus *mbus = params->message_bus; + if (region->gizmo_map != NULL) { WM_gizmomap_message_subscribe(C, region->gizmo_map, region, mbus); } @@ -4044,7 +4063,7 @@ void ED_region_message_subscribe(bContext *C, } if (region->type->message_subscribe != NULL) { - region->type->message_subscribe(C, workspace, scene, screen, area, region, mbus); + region->type->message_subscribe(params); } } diff --git a/source/blender/editors/screen/area_utils.c b/source/blender/editors/screen/area_utils.c index 075759f1120..30553bb7f07 100644 --- a/source/blender/editors/screen/area_utils.c +++ b/source/blender/editors/screen/area_utils.c @@ -22,6 +22,8 @@ #include "DNA_userdef_types.h" +#include "BKE_screen.h" + #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -32,7 +34,6 @@ #include "ED_screen.h" -#include "UI_interface.h" #include "UI_interface_icons.h" /* -------------------------------------------------------------------- */ @@ -42,14 +43,11 @@ /** * Callback for #ARegionType.message_subscribe */ -void ED_region_generic_tools_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +void ED_region_generic_tools_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 33b918e6d4d..a88afecd064 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -57,11 +57,12 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state) vert_format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); } -/* To be used before calling immDrawPixelsTex - * Default shader is GPU_SHADER_2D_IMAGE_COLOR - * You can still set uniforms with : - * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0); - * */ +/** + * To be used before calling #immDrawPixelsTex + * Default shader is #GPU_SHADER_2D_IMAGE_COLOR + * You can still set uniforms with: + * `GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);` + */ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) { IMMDrawPixelsTexState state; @@ -77,10 +78,11 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) return state; } -/* Use the currently bound shader. +/** + * Use the currently bound shader. * - * Use immDrawPixelsTexSetup to bind the shader you - * want before calling immDrawPixelsTex. + * Use #immDrawPixelsTexSetup to bind the shader you + * want before calling #immDrawPixelsTex. * * If using a special shader double check it uses the same * attributes "pos" "texCoord" and uniform "image". @@ -89,7 +91,7 @@ IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin) * * Be also aware that this function unbinds the shader when * it's finished. - * */ + */ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state, float x, float y, diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 1dfe606be78..627a67358f2 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -866,7 +866,7 @@ static eContextResult screen_ctx_editable_gpencil_strokes(const bContext *C, LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (ED_gpencil_stroke_can_use_direct(area, gps)) { /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c index 6432bdac1b1..1ea64c542f5 100644 --- a/source/blender/editors/screen/screen_draw.c +++ b/source/blender/editors/screen/screen_draw.c @@ -478,7 +478,7 @@ void ED_screen_draw_split_preview(ScrArea *area, const int dir, const float fac) uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - /* splitpoint */ + /* Split-point. */ GPU_blend(GPU_BLEND_ALPHA); immUniformColor4ub(255, 255, 255, 100); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index be52874ed0b..c25b572d200 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -871,6 +871,11 @@ static void screen_global_area_refresh(wmWindow *win, const short height_min, const short height_max) { + /* Full-screens shouldn't have global areas. Don't touch them. */ + if (screen->state == SCREENFULL) { + return; + } + ScrArea *area = NULL; LISTBASE_FOREACH (ScrArea *, area_iter, &win->global_areas.areabase) { if (area_iter->spacetype == space_type) { @@ -1019,7 +1024,7 @@ void screen_change_update(bContext *C, wmWindow *win, bScreen *screen) WM_event_add_notifier(C, NC_WINDOW, NULL); WM_event_add_notifier(C, NC_SCREEN | ND_LAYOUTSET, layout); - /* makes button hilites work */ + /* Makes button highlights work. */ WM_event_add_mousemove(win); } @@ -1216,7 +1221,7 @@ void ED_screen_full_restore(bContext *C, ScrArea *area) } /** - * \param toggle_area: If this is set, its space data will be swapped with the one of the new emtpy + * \param toggle_area: If this is set, its space data will be swapped with the one of the new empty * area, when toggling back it can be swapped back again. * \return The newly created screen with the non-normal area. */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index a03e65d8a9d..c51ff559786 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -29,10 +29,10 @@ struct bContextDataResult; /* internal exports only */ -#define AZONESPOTW UI_HEADER_OFFSET /* width of corner azone - max */ -#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner azone */ -#define AZONEFADEIN (5.0f * U.widget_unit) /* when azone is totally visible */ -#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the azone */ +#define AZONESPOTW UI_HEADER_OFFSET /* width of corner #AZone - max */ +#define AZONESPOTH (0.6f * U.widget_unit) /* height of corner #AZone */ +#define AZONEFADEIN (5.0f * U.widget_unit) /* when #AZone is totally visible */ +#define AZONEFADEOUT (6.5f * U.widget_unit) /* when we start seeing the #AZone */ #define AREAJOINTOLERANCE (1.0f * U.widget_unit) /* Edges must be close to allow joining. */ diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index ca1c75be0a1..244d8c10e4e 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1637,7 +1637,7 @@ static int area_snap_calc_location(const bScreen *screen, /* Thirds. */ 1.0f / 3.0f, 2.0f / 3.0f, - /* Quaters. */ + /* Quarters. */ 1.0f / 4.0f, 3.0f / 4.0f, /* Eighth. */ diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 550913fc8af..7eb08cbabac 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -1755,7 +1755,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont else if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_RADIAL && brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) { /* Display the simulation limits if sculpting outside them. */ - /* This does not makes much sense of plane falloff as the falloff is infinte or global. */ + /* This does not makes much sense of plane falloff as the falloff is infinite or global. */ if (len_v3v3(ss->cache->true_location, ss->cache->true_initial_location) > ss->cache->radius * (1.0f + brush->cloth_sim_limit)) { diff --git a/source/blender/editors/sculpt_paint/paint_curve_undo.c b/source/blender/editors/sculpt_paint/paint_curve_undo.c index a8e22f66734..dbe522bf304 100644 --- a/source/blender/editors/sculpt_paint/paint_curve_undo.c +++ b/source/blender/editors/sculpt_paint/paint_curve_undo.c @@ -126,7 +126,7 @@ static bool paintcurve_undosys_step_encode(struct bContext *C, static void paintcurve_undosys_step_decode(struct bContext *UNUSED(C), struct Main *UNUSED(bmain), UndoStep *us_p, - int UNUSED(dir), + const eUndoStepDir UNUSED(dir), bool UNUSED(is_final)) { PaintCurveUndoStep *us = (PaintCurveUndoStep *)us_p; diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 5c15fd05116..f7c0f7718bb 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -138,7 +138,7 @@ BLI_INLINE uchar f_to_char(const float val) #ifndef PROJ_DEBUG_NOSEAMBLEED /* projectFaceSeamFlags options */ -//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ +//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, back-facing or occluded. */ //#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ /* If this face has a seam on any of its edges. */ @@ -150,7 +150,7 @@ BLI_INLINE uchar f_to_char(const float val) # define PROJ_FACE_NOSEAM1 (1 << 5) # define PROJ_FACE_NOSEAM2 (1 << 6) -/* If the seam is completely initialized, including adjecent seams. */ +/* If the seam is completely initialized, including adjacent seams. */ # define PROJ_FACE_SEAM_INIT0 (1 << 8) # define PROJ_FACE_SEAM_INIT1 (1 << 9) # define PROJ_FACE_SEAM_INIT2 (1 << 10) @@ -294,7 +294,7 @@ typedef struct ProjPaintState { /** verts projected into floating point screen space. */ float (*screenCoords)[4]; - /** 2D bounds for mesh verts on the screen's plane (screenspace). */ + /** 2D bounds for mesh verts on the screen's plane (screen-space). */ float screenMin[2]; float screenMax[2]; /** Calculated from screenMin & screenMax. */ @@ -310,10 +310,10 @@ typedef struct ProjPaintState { bool do_stencil_brush; bool do_material_slots; - /** Use raytraced occlusion? - ortherwise will paint right through to the back. */ + /** Use ray-traced occlusion? - otherwise will paint right through to the back. */ bool do_occlude; /** ignore faces with normals pointing away, - * skips a lot of raycasts if your normals are correctly flipped. */ + * skips a lot of ray-casts if your normals are correctly flipped. */ bool do_backfacecull; /** mask out pixels based on their normals. */ bool do_mask_normal; @@ -579,7 +579,7 @@ static Image *project_paint_face_clone_image(const ProjPaintState *ps, int tri_i /* fast projection bucket array lookup, use the safe version for bound checking */ static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) { - /* If we were not dealing with screenspace 2D coords we could simple do... + /* If we were not dealing with screen-space 2D coords we could simple do... * ps->bucketRect[x + (y*ps->buckets_y)] */ /* please explain? @@ -887,8 +887,8 @@ static int project_paint_occlude_ptv_clip(const float pt[3], return -1; } -/* Check if a screenspace location is occluded by any other faces - * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison +/* Check if a screen-space location is occluded by any other faces + * check, pixelScreenCo must be in screen-space, its Z-Depth only needs to be used for comparison * and doesn't need to be correct in relation to X and Y coords * (this is the case in perspective view) */ static bool project_bucket_point_occluded(const ProjPaintState *ps, @@ -1514,10 +1514,10 @@ static void project_face_seams_init(const ProjPaintState *ps, } #endif // PROJ_DEBUG_NOSEAMBLEED -/* Converts a UV location to a 3D screenspace location +/* Converts a UV location to a 3D screen-space location * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo * - * This is used for finding a pixels location in screenspace for painting */ + * This is used for finding a pixels location in screen-space for painting */ static void screen_px_from_ortho(const float uv[2], const float v1co[3], const float v2co[3], @@ -1537,7 +1537,7 @@ static void screen_px_from_ortho(const float uv[2], static void screen_px_from_persp(const float uv[2], const float v1co[4], const float v2co[4], - const float v3co[4], /* screenspace coords */ + const float v3co[4], /* screen-space coords */ const float uv1co[2], const float uv2co[2], const float uv3co[2], @@ -1923,7 +1923,7 @@ static ProjPixel *project_paint_uvpixel_init(const ProjPaintState *ps, projPixel->newColor.uint = 0; } - /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ + /* Screen-space unclamped, we could keep its z and w values but don't need them at the moment. */ if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { copy_v3_v3(projPixel->worldCoSS, world_spaceCo); } @@ -2304,14 +2304,14 @@ static bool project_bucket_isect_circle(const float cent[2], return false; } -/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp() +/* Note for #rect_to_uvspace_ortho() and #rect_to_uvspace_persp() * in ortho view this function gives good results when bucket_bounds are outside the triangle * however in some cases, perspective view will mess up with faces - * that have minimal screenspace area (viewed from the side). + * that have minimal screen-space area (viewed from the side). * * for this reason its not reliable in this case so we'll use the Simple Barycentric' - * funcs that only account for points inside the triangle. - * however switching back to this for ortho is always an option */ + * functions that only account for points inside the triangle. + * however switching back to this for ortho is always an option. */ static void rect_to_uvspace_ortho(const rctf *bucket_bounds, const float *v1coSS, @@ -2415,9 +2415,10 @@ static bool IsectPT2Df_limit( (area_tri_v2(v1, v2, v3))) < limit; } -/* Clip the face by a bucket and set the uv-space bucket_bounds_uv +/** + * Clip the face by a bucket and set the uv-space bucket_bounds_uv * so we have the clipped UV's to do pixel intersection tests with - * */ + */ static int float_z_sort_flip(const void *p1, const void *p2) { return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1); @@ -2516,8 +2517,8 @@ static void project_bucket_clip_face(const bool is_ortho, flip = (((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != is_flip_object) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); - /* all screenspace points are inside the bucket bounding box, - * this means we don't need to clip and can simply return the UVs */ + /* All screen-space points are inside the bucket bounding box, + * this means we don't need to clip and can simply return the UVs. */ if (flip) { /* facing the back? */ copy_v2_v2(bucket_bounds_uv[0], uv3co); copy_v2_v2(bucket_bounds_uv[1], uv2co); @@ -2634,7 +2635,7 @@ static void project_bucket_clip_face(const bool is_ortho, (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); if (inside_face_flag == ISECT_ALL4) { - /* bucket is totally inside the screenspace face, we can safely use weights */ + /* Bucket is totally inside the screen-space face, we can safely use weights. */ if (is_ortho) { rect_to_uvspace_ortho( @@ -2655,7 +2656,7 @@ static void project_bucket_clip_face(const bool is_ortho, * The 2 cases above are where the face is inside the bucket * or the bucket is inside the face. * - * we need to make a convex polyline from the intersection between the screenspace face + * we need to make a convex poly-line from the intersection between the screen-space face * and the bucket bounds. * * There are a number of ways this could be done, currently it just collects all @@ -2996,7 +2997,7 @@ static void project_paint_face_init(const ProjPaintState *ps, /* vert co screen-space, these will be assigned to lt_vtri[0-2] */ const float *v1coSS, *v2coSS, *v3coSS; - /* vertex screenspace coords */ + /* Vertex screen-space coords. */ const float *vCo[3]; float w[3], wco[3]; @@ -3006,9 +3007,9 @@ static void project_paint_face_init(const ProjPaintState *ps, float pixelScreenCo[4]; bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; - /* ispace bounds */ + /* Image-space bounds. */ rcti bounds_px; - /* vars for getting uvspace bounds */ + /* Variables for getting UV-space bounds. */ /* bucket bounds in UV space so we can init pixels only for this face, */ float lt_uv_pxoffset[3][2]; @@ -3206,10 +3207,10 @@ static void project_paint_face_init(const ProjPaintState *ps, /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in perspective view */ float insetCos[3][3]; - /* vertex screenspace coords */ + /* Vertex screen-space coords. */ const float *vCoSS[3]; - /* Store the screenspace coords of the face, + /* Store the screen-space coords of the face, * clipped by the bucket's screen aligned rectangle. */ float bucket_clip_edges[2][2]; float edge_verts_inset_clip[2][3]; @@ -3418,7 +3419,7 @@ static void project_paint_face_init(const ProjPaintState *ps, } /** - * Takes floating point screenspace min/max and + * Takes floating point screen-space min/max and * returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */ static void project_paint_bucket_bounds(const ProjPaintState *ps, @@ -3887,7 +3888,7 @@ static void proj_paint_state_cavity_init(ProjPaintState *ps) float no[3]; mul_v3_fl(edges[a], 1.0f / counter[a]); normal_short_to_float_v3(no, mv->no); - /* augment the diffe*/ + /* Augment the difference. */ cavities[a] = saacos(10.0f * dot_v3v3(no, edges[a])) * (float)M_1_PI; } else { @@ -4307,7 +4308,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, slot_last = slot; } - /* don't allow using the same inage for painting and stencilling */ + /* Don't allow using the same image for painting and stenciling. */ if (slot->ima == ps->stencil_ima) { /* Delay continuing the loop until after loop_uvs and bleed faces are initialized. * While this shouldn't be used, face-winding reads all polys. @@ -4337,7 +4338,6 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps, continue; } - /* tfbase here should be non-null! */ BLI_assert(mloopuv_base != NULL); if (is_face_sel && tpage) { diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 8eb2ebd0f19..8fd5759d695 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -168,8 +168,11 @@ void PAINT_OT_weight_from_bones(wmOperatorType *ot) /** \name Sample Weight Operator * \{ */ -/* sets wp->weight to the closest weight value to vertex */ -/* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ +/** + * Sets wp->weight to the closest weight value to vertex. + * + * \note we can't sample front-buffer, weight colors are interpolated too unpredictable. + */ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); @@ -201,7 +204,7 @@ static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *even } else if (ED_mesh_pick_face( C, vc.obact, event->mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { - /* this relies on knowning the internal worksings of ED_mesh_pick_face_vert() */ + /* This relies on knowing the internal workings of #ED_mesh_pick_face_vert() */ BKE_report( op->reports, RPT_WARNING, "The modifier used does not support deformed locations"); } @@ -604,7 +607,7 @@ static void gradientVert_update(WPGradient_userData *grad_data, int index) Mesh *me = grad_data->me; WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index]; - /* Optionally restrict to assigned verices only. */ + /* Optionally restrict to assigned vertices only. */ if (grad_data->use_vgroup_restrict && ((vs->flag & VGRAD_STORE_DW_EXIST) == 0)) { return; } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index cb5d708908b..d1028e5f542 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -391,13 +391,14 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) == face_set) { - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } + if (abs(ss->face_sets[i]) != face_set) { + continue; + } + if (visible) { + ss->face_sets[i] = abs(ss->face_sets[i]); + } + else { + ss->face_sets[i] = -abs(ss->face_sets[i]); } } break; @@ -1057,12 +1058,13 @@ bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], char symm) { for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - float location[3]; - flip_v3_v3(location, br_co, (char)i); - if (len_squared_v3v3(location, vertex) < radius * radius) { - return true; - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + float location[3]; + flip_v3_v3(location, br_co, (char)i); + if (len_squared_v3v3(location, vertex) < radius * radius) { + return true; } } return false; @@ -1107,20 +1109,22 @@ void SCULPT_floodfill_add_initial_with_symmetry( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = index; - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = index; + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1131,20 +1135,22 @@ void SCULPT_floodfill_add_active( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = SCULPT_active_vertex_get(ss); - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = SCULPT_active_vertex_get(ss); + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1161,12 +1167,19 @@ void SCULPT_floodfill_execute( SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const int to_v = ni.index; - if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v) && SCULPT_vertex_visible_get(ss, to_v)) { - BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); - if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { - BLI_gsqueue_push(flood->queue, &to_v); - } + if (BLI_BITMAP_TEST(flood->visited_vertices, to_v)) { + continue; + } + + if (!SCULPT_vertex_visible_get(ss, to_v)) { + continue; + } + + BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); + + if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { + BLI_gsqueue_push(flood->queue, &to_v); } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -1466,40 +1479,42 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, unode = SCULPT_undo_get_node(data->nodes[n]); } - if (unode) { - PBVHVertexIter vd; - SculptOrigVertData orig_data; + if (!unode) { + return; + } - SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); + PBVHVertexIter vd; + SculptOrigVertData orig_data; - BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) - { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); - if (orig_data.unode->type == SCULPT_UNDO_COORDS) { - copy_v3_v3(vd.co, orig_data.co); - if (vd.no) { - copy_v3_v3_short(vd.no, orig_data.no); - } - else { - normal_short_to_float_v3(vd.fno, orig_data.no); - } - } - else if (orig_data.unode->type == SCULPT_UNDO_MASK) { - *vd.mask = orig_data.mask; - } - else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { - copy_v4_v4(vd.col, orig_data.col); - } + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + if (orig_data.unode->type == SCULPT_UNDO_COORDS) { + copy_v3_v3(vd.co, orig_data.co); + if (vd.no) { + copy_v3_v3_short(vd.no, orig_data.no); + } + else { + normal_short_to_float_v3(vd.fno, orig_data.no); } } - BKE_pbvh_vertex_iter_end; + else if (orig_data.unode->type == SCULPT_UNDO_MASK) { + *vd.mask = orig_data.mask; + } + else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { + copy_v4_v4(vd.col, orig_data.col); + } - BKE_pbvh_node_mark_update(data->nodes[n]); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } + BKE_pbvh_vertex_iter_end; + + BKE_pbvh_node_mark_update(data->nodes[n]); } static void paint_mesh_restore_co(Sculpt *sd, Object *ob) @@ -1545,11 +1560,15 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect) * mesh parts could disappear from screen (sergey). */ SculptSession *ss = ob->sculpt; - if (ss->cache) { - if (!BLI_rcti_is_empty(&ss->cache->previous_r)) { - BLI_rcti_union(rect, &ss->cache->previous_r); - } + if (!ss->cache) { + return; + } + + if (BLI_rcti_is_empty(&ss->cache->previous_r)) { + return; } + + BLI_rcti_union(rect, &ss->cache->previous_r); } /* Get a screen-space rectangle of the modified area. */ @@ -1651,28 +1670,30 @@ bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = sqrtf(distsq); - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = sqrtf(distsq); + return true; } bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + test->dist = distsq; + return true; } bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3]) @@ -1689,14 +1710,16 @@ bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3]) closest_to_plane_normalized_v3(co_proj, test->plane_view, co); float distsq = len_squared_v3v3(co_proj, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = distsq; + return true; } bool SCULPT_brush_test_cube(SculptBrushTest *test, @@ -1724,25 +1747,26 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test, const float constant_side = hardness * side; const float falloff_side = roundness * side; - if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) { + if (!(local_co[0] <= side && local_co[1] <= side && local_co[2] <= side)) { + /* Outside the square. */ + return false; + } + if (min_ff(local_co[0], local_co[1]) > constant_side) { /* Corner, distance to the center of the corner circle. */ - if (min_ff(local_co[0], local_co[1]) > constant_side) { - float r_point[3]; - copy_v3_fl(r_point, constant_side); - test->dist = len_v2v2(r_point, local_co) / falloff_side; - return true; - } + float r_point[3]; + copy_v3_fl(r_point, constant_side); + test->dist = len_v2v2(r_point, local_co) / falloff_side; + return true; + } + if (max_ff(local_co[0], local_co[1]) > constant_side) { /* Side, distance to the square XY axis. */ - if (max_ff(local_co[0], local_co[1]) > constant_side) { - test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; - return true; - } - /* Inside the square, constant distance. */ - test->dist = 0.0f; + test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; return true; } - /* Outside the square. */ - return false; + + /* Inside the square, constant distance. */ + test->dist = 0.0f; + return true; } SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, @@ -1777,21 +1801,21 @@ static float frontface(const Brush *br, const short no[3], const float fno[3]) { - if (br->flag & BRUSH_FRONTFACE) { - float dot; + if (!(br->flag & BRUSH_FRONTFACE)) { + return 1.0f; + } - if (no) { - float tmp[3]; + float dot; + if (no) { + float tmp[3]; - normal_short_to_float_v3(tmp, no); - dot = dot_v3v3(tmp, sculpt_normal); - } - else { - dot = dot_v3v3(fno, sculpt_normal); - } - return dot > 0.0f ? dot : 0.0f; + normal_short_to_float_v3(tmp, no); + dot = dot_v3v3(tmp, sculpt_normal); + } + else { + dot = dot_v3v3(fno, sculpt_normal); } - return 1.0f; + return dot > 0.0f ? dot : 0.0f; } #if 0 @@ -1871,25 +1895,25 @@ static float calc_radial_symmetry_feather(Sculpt *sd, static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) { - if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) { - float overlap; - const int symm = cache->symmetry; - - overlap = 0.0f; - for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - - overlap += calc_overlap(cache, i, 0, 0); + if (!(sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER)) { + return 1.0f; + } + float overlap; + const int symm = cache->symmetry; - overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); - } + overlap = 0.0f; + for (int i = 0; i <= symm; i++) { + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; } - return 1.0f / overlap; + overlap += calc_overlap(cache, i, 0, 0); + + overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); } - return 1.0f; + return 1.0f / overlap; } /* -------------------------------------------------------------------- */ @@ -1991,35 +2015,37 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } - normal_tri_v3(no, UNPACK3(co_tri)); + float no[3]; + int flip_index; - flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); - if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); - const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + normal_tri_v3(no, UNPACK3(co_tri)); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], co); + flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f); + if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - anctd->count_co[flip_index] += 1; - } - if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); - const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); + add_v3_v3(anctd->area_cos[flip_index], co); + + anctd->count_co[flip_index] += 1; + } + if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } } @@ -2051,49 +2077,51 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } + + float no[3]; + int flip_index; - data->any_vertex_sampled = true; + data->any_vertex_sampled = true; - if (use_original) { - normal_short_to_float_v3(no, no_s); + if (use_original) { + normal_short_to_float_v3(no, no_s); + } + else { + if (vd.no) { + normal_short_to_float_v3(no, vd.no); } else { - if (vd.no) { - normal_short_to_float_v3(no, vd.no); - } - else { - copy_v3_v3(no, vd.fno); - } + copy_v3_v3(no, vd.fno); } + } - flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= - 0.0f); + flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= + 0.0f); - if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); - const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + if (use_area_cos && area_test_r) { + /* Weight the coordinates towards the center. */ + float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); + const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], co); - anctd->count_co[flip_index] += 1; - } - if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); - const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + add_v3_v3(anctd->area_cos[flip_index], co); + anctd->count_co[flip_index] += 1; + } + if (use_area_nos && normal_test_r) { + /* Weight the normals towards the center. */ + float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); + const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } BKE_pbvh_vertex_iter_end; @@ -2150,10 +2178,12 @@ static void calc_area_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2249,10 +2279,12 @@ static void calc_area_normal_and_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2892,26 +2924,27 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = - bstrength * - SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * - ss->cache->pressure; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * + ss->cache->pressure; - float avg[3], val[3]; + float avg[3], val[3]; - SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); + SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); - sub_v3_v3v3(val, avg, vd.co); + sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); + madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); + SCULPT_clip(sd, ss, vd.co, val); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -2964,21 +2997,23 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (bstrength > 0.0f) { - (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); - } - else { - (*vd.mask) += fade * bstrength * (*vd.mask); - } - *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + const float fade = SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (bstrength > 0.0f) { + (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); + } + else { + (*vd.mask) += fade * bstrength * (*vd.mask); + } + *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } BKE_pbvh_vertex_iter_end; } @@ -3039,26 +3074,27 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - float limit_co[3]; - float disp[3]; - SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); - sub_v3_v3v3(disp, limit_co, vd.co); - mul_v3_v3fl(proxy[vd.i], disp, fade); + float limit_co[3]; + float disp[3]; + SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); + sub_v3_v3v3(disp, limit_co, vd.co); + mul_v3_v3fl(proxy[vd.i], disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3151,12 +3187,15 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata, ss->cache->limit_surface_co[vd.index]); const float *neighbor_limit_surface_disp = ss->cache->prev_displacement[ni.index]; normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float disp_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); - weights_accum += disp_interp; + + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } + + const float disp_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); + weights_accum += disp_interp; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -3246,23 +3285,24 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3325,23 +3365,24 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3407,52 +3448,53 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float current_disp[3]; - float current_disp_norm[3]; - float final_disp[3] = {0.0f, 0.0f, 0.0f}; + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float current_disp[3]; + float current_disp_norm[3]; + float final_disp[3] = {0.0f, 0.0f, 0.0f}; - switch (brush->slide_deform_type) { - case BRUSH_SLIDE_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SLIDE_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SLIDE_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } + switch (brush->slide_deform_type) { + case BRUSH_SLIDE_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SLIDE_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SLIDE_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { - madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); - } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { + madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - mul_v3_v3fl(proxy[vd.i], final_disp, fade); + mul_v3_v3fl(proxy[vd.i], final_disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3482,16 +3524,17 @@ void SCULPT_relax_vertex(SculptSession *ss, /* When the vertex to relax is boundary, use only connected boundary vertices for the average * position. */ if (is_boundary) { - if (SCULPT_vertex_is_boundary(ss, ni.index)) { - add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); - avg_count++; - - /* Calculate a normal for the constraint plane using the edges of the boundary. */ - float to_neighbor[3]; - sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); - normalize_v3(to_neighbor); - add_v3_v3(boundary_normal, to_neighbor); + if (!SCULPT_vertex_is_boundary(ss, ni.index)) { + continue; } + add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); + avg_count++; + + /* Calculate a normal for the constraint plane using the edges of the boundary. */ + float to_neighbor[3]; + sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); + normalize_v3(to_neighbor); + add_v3_v3(boundary_normal, to_neighbor); } else { add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); @@ -3563,21 +3606,22 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3728,38 +3772,39 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val1[3]; - float val2[3]; - - /* First we pinch. */ - sub_v3_v3v3(val1, test.location, vd.co); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val1[3]; + float val2[3]; + + /* First we pinch. */ + sub_v3_v3v3(val1, test.location, vd.co); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); + } - mul_v3_fl(val1, fade * flippedbstrength); + mul_v3_fl(val1, fade * flippedbstrength); - sculpt_project_v3(spvc, val1, val1); + sculpt_project_v3(spvc, val1, val1); - /* Then we draw. */ - mul_v3_v3fl(val2, offset, fade); + /* Then we draw. */ + mul_v3_v3fl(val2, offset, fade); - add_v3_v3v3(proxy[vd.i], val1, val2); + add_v3_v3v3(proxy[vd.i], val1, val2); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3845,40 +3890,41 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - /* Calculate displacement from the vertex to the brush center. */ - sub_v3_v3v3(disp_center, test.location, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + /* Calculate displacement from the vertex to the brush center. */ + sub_v3_v3v3(disp_center, test.location, vd.co); - /* Project the displacement into the X vector (aligned to the stroke). */ - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + /* Project the displacement into the X vector (aligned to the stroke). */ + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - /* Project the displacement into the Z vector (aligned to the surface normal). */ - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + /* Project the displacement into the Z vector (aligned to the surface normal). */ + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - /* Add the two projected vectors to calculate the final displacement. - * The Y component is removed. */ - add_v3_v3v3(disp_center, x_disp, z_disp); + /* Add the two projected vectors to calculate the final displacement. + * The Y component is removed. */ + add_v3_v3v3(disp_center, x_disp, z_disp); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); - } - mul_v3_v3fl(proxy[vd.i], disp_center, fade); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); + } + mul_v3_v3fl(proxy[vd.i], disp_center, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3961,33 +4007,34 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (grab_silhouette) { - float silhouette_test_dir[3]; - normalize_v3_v3(silhouette_test_dir, grab_delta); - if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { - mul_v3_fl(silhouette_test_dir, -1.0f); - } - float vno[3]; - normal_short_to_float_v3(vno, orig_data.no); - fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (grab_silhouette) { + float silhouette_test_dir[3]; + normalize_v3_v3(silhouette_test_dir, grab_delta); + if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { + mul_v3_fl(silhouette_test_dir, -1.0f); } + float vno[3]; + normal_short_to_float_v3(vno, orig_data.no); + fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4149,13 +4196,14 @@ void SCULPT_flip_v3_by_symm_area(float v[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_v3(v, symm_it); - } - if (pivot[i] < 0.0f) { - flip_v3(v, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_v3(v, symm_it); + } + if (pivot[i] < 0.0f) { + flip_v3(v, symm_it); } } } @@ -4167,13 +4215,14 @@ void SCULPT_flip_quat_by_symm_area(float quat[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_qt(quat, symm_it); - } - if (pivot[i] < 0.0f) { - flip_qt(quat, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_qt(quat, symm_it); + } + if (pivot[i] < 0.0f) { + flip_qt(quat, symm_it); } } } @@ -4289,22 +4338,23 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4368,75 +4418,76 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) { + if (!do_elastic && !sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - float fade; - if (do_elastic) { - fade = 1.0f; - } - else { - fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - } + float fade; + if (do_elastic) { + fade = 1.0f; + } + else { + fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - /* Negative pinch will inflate, helps maintain volume. */ - if (do_pinch) { - float delta_pinch_init[3], delta_pinch[3]; + /* Negative pinch will inflate, helps maintain volume. */ + if (do_pinch) { + float delta_pinch_init[3], delta_pinch[3]; - sub_v3_v3v3(delta_pinch, vd.co, test.location); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); - } + sub_v3_v3v3(delta_pinch, vd.co, test.location); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); + } - /* Important to calculate based on the grabbed location - * (intentionally ignore fade here). */ - add_v3_v3(delta_pinch, grab_delta); + /* Important to calculate based on the grabbed location + * (intentionally ignore fade here). */ + add_v3_v3(delta_pinch, grab_delta); - sculpt_project_v3(spvc, delta_pinch, delta_pinch); + sculpt_project_v3(spvc, delta_pinch, delta_pinch); - copy_v3_v3(delta_pinch_init, delta_pinch); + copy_v3_v3(delta_pinch_init, delta_pinch); - float pinch_fade = pinch * fade; - /* When reducing, scale reduction back by how close to the center we are, - * so we don't pinch into nothingness. */ - if (pinch > 0.0f) { - /* Square to have even less impact for close vertices. */ - pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); - } - mul_v3_fl(delta_pinch, 1.0f + pinch_fade); - sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); - add_v3_v3(proxy[vd.i], delta_pinch); + float pinch_fade = pinch * fade; + /* When reducing, scale reduction back by how close to the center we are, + * so we don't pinch into nothingness. */ + if (pinch > 0.0f) { + /* Square to have even less impact for close vertices. */ + pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); } + mul_v3_fl(delta_pinch, 1.0f + pinch_fade); + sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); + add_v3_v3(proxy[vd.i], delta_pinch); + } - if (do_rake_rotation) { - float delta_rotate[3]; - sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); - add_v3_v3(proxy[vd.i], delta_rotate); - } + if (do_rake_rotation) { + float delta_rotate[3]; + sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); + add_v3_v3(proxy[vd.i], delta_rotate); + } - if (do_elastic) { - float disp[3]; - BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); - mul_v3_fl(disp, bstrength * 20.0f); - if (vd.mask) { - mul_v3_fl(disp, 1.0f - *vd.mask); - } - mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); - copy_v3_v3(proxy[vd.i], disp); + if (do_elastic) { + float disp[3]; + BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); + mul_v3_fl(disp, bstrength * 20.0f); + if (vd.mask) { + mul_v3_fl(disp, 1.0f - *vd.mask); } + mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); + copy_v3_v3(proxy[vd.i], disp); + } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4507,22 +4558,23 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4580,27 +4632,28 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float vec[3], rot[3][3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float vec[3], rot[3][3]; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - sub_v3_v3v3(vec, orig_data.co, ss->cache->location); - axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); - mul_v3_m3v3(proxy[vd.i], rot, vec); - add_v3_v3(proxy[vd.i], ss->cache->location); - sub_v3_v3(proxy[vd.i], orig_data.co); + sub_v3_v3v3(vec, orig_data.co, ss->cache->location); + axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); + mul_v3_m3v3(proxy[vd.i], rot, vec); + add_v3_v3(proxy[vd.i], ss->cache->location); + sub_v3_v3(proxy[vd.i], orig_data.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4652,70 +4705,71 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - const int vi = vd.index; - float *disp_factor; - if (use_persistent_base) { - disp_factor = &ss->persistent_base[vi].disp; - } - else { - disp_factor = &ss->cache->layer_displacement_factor[vi]; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + const int vi = vd.index; + float *disp_factor; + if (use_persistent_base) { + disp_factor = &ss->persistent_base[vi].disp; + } + else { + disp_factor = &ss->cache->layer_displacement_factor[vi]; + } - /* When using persistent base, the layer brush (holding Control) invert mode resets the - * height of the layer to 0. This makes possible to clean edges of previously added layers - * on top of the base. */ - /* The main direction of the layers is inverted using the regular brush strength with the - * brush direction property. */ - if (use_persistent_base && ss->cache->invert) { - (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * - ((*disp_factor) > 0.0f ? -1.0f : 1.0f); - } - else { - (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); - } - if (vd.mask) { - const float clamp_mask = 1.0f - *vd.mask; - *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); - } - else { - *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); - } + /* When using persistent base, the layer brush (holding Control) invert mode resets the + * height of the layer to 0. This makes possible to clean edges of previously added layers + * on top of the base. */ + /* The main direction of the layers is inverted using the regular brush strength with the + * brush direction property. */ + if (use_persistent_base && ss->cache->invert) { + (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * + ((*disp_factor) > 0.0f ? -1.0f : 1.0f); + } + else { + (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); + } + if (vd.mask) { + const float clamp_mask = 1.0f - *vd.mask; + *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); + } + else { + *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); + } - float final_co[3]; - float normal[3]; + float final_co[3]; + float normal[3]; - if (use_persistent_base) { - SCULPT_vertex_persistent_normal_get(ss, vi, normal); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); - } - else { - normal_short_to_float_v3(normal, orig_data.no); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); - } + if (use_persistent_base) { + SCULPT_vertex_persistent_normal_get(ss, vi, normal); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); + } + else { + normal_short_to_float_v3(normal, orig_data.no); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); + } - float vdisp[3]; - sub_v3_v3v3(vdisp, final_co, vd.co); - mul_v3_fl(vdisp, fabsf(fade)); - add_v3_v3v3(final_co, vd.co, vdisp); + float vdisp[3]; + sub_v3_v3v3(vdisp, final_co, vd.co); + mul_v3_fl(vdisp, fabsf(fade)); + add_v3_v3v3(final_co, vd.co, vdisp); - SCULPT_clip(sd, ss, vd.co, final_co); + SCULPT_clip(sd, ss, vd.co, final_co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4764,31 +4818,32 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val[3]; - if (vd.fno) { - copy_v3_v3(val, vd.fno); - } - else { - normal_short_to_float_v3(val, vd.no); - } + if (vd.fno) { + copy_v3_v3(val, vd.fno); + } + else { + normal_short_to_float_v3(val, vd.no); + } - mul_v3_fl(val, fade * ss->cache->radius); - mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4869,30 +4924,31 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float intr[3]; + float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - sub_v3_v3v3(val, intr, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (SCULPT_plane_trim(ss->cache, brush, val)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } } @@ -4975,16 +5031,17 @@ static void calc_clay_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float plane_dist = dist_signed_to_plane_v3(vd.co, plane); - float plane_dist_abs = fabsf(plane_dist); - if (plane_dist > 0.0f) { - csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); - } - else { - csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); - } + float plane_dist = dist_signed_to_plane_v3(vd.co, plane); + float plane_dist_abs = fabsf(plane_dist); + if (plane_dist > 0.0f) { + csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); + } + else { + csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); } BKE_pbvh_vertex_iter_end; } @@ -5025,28 +5082,30 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + sub_v3_v3v3(val, intr, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5143,35 +5202,37 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { - if (plane_point_side_flip(vd.co, test.plane_tool, flip)) { - float intr[3]; - float val[3]; + if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { + continue; + } - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!plane_point_side_flip(vd.co, test.plane_tool, flip)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ - const float fade = bstrength * - SCULPT_brush_strength_factor(ss, - brush, - vd.co, - ss->cache->radius * test.dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + ss->cache->radius * test.dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5295,33 +5356,37 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5390,33 +5455,37 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5501,38 +5570,39 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - mul_v3_m4v3(local_co, mat, vd.co); - float intr[3], intr_tilt[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - - /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex - * coordinates. */ - /* We can also control the mix with a curve if it produces noticeable artifacts in the center - * of the brush. */ - const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; - interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); - sub_v3_v3v3(val, intr_tilt, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + mul_v3_m4v3(local_co, mat, vd.co); + float intr[3], intr_tilt[3]; + float val[3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex + * coordinates. */ + /* We can also control the mix with a curve if it produces noticeable artifacts in the center + * of the brush. */ + const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; + interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); + sub_v3_v3v3(val, intr_tilt, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5656,22 +5726,23 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5766,49 +5837,51 @@ static void sculpt_topology_update(Sculpt *sd, ob, sd, brush, use_original, radius_scale, &totnode); /* Only act if some verts are inside the brush area. */ - if (totnode) { - PBVHTopologyUpdateMode mode = 0; - float location[3]; + if (totnode == 0) { + return; + } - if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { - if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { - mode |= PBVH_Subdivide; - } + PBVHTopologyUpdateMode mode = 0; + float location[3]; - if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { - mode |= PBVH_Collapse; - } + if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { + if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { + mode |= PBVH_Subdivide; } - for (n = 0; n < totnode; n++) { - SCULPT_undo_push_node(ob, - nodes[n], - brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : - SCULPT_UNDO_COORDS); - BKE_pbvh_node_mark_update(nodes[n]); - - if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_node_mark_topology_update(nodes[n]); - BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); - } + if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { + mode |= PBVH_Collapse; } + } + + for (n = 0; n < totnode; n++) { + SCULPT_undo_push_node(ob, + nodes[n], + brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : + SCULPT_UNDO_COORDS); + BKE_pbvh_node_mark_update(nodes[n]); if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_bmesh_update_topology(ss->pbvh, - mode, - ss->cache->location, - ss->cache->view_normal, - ss->cache->radius, - (brush->flag & BRUSH_FRONTFACE) != 0, - (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); + BKE_pbvh_node_mark_topology_update(nodes[n]); + BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); } + } - MEM_SAFE_FREE(nodes); - - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_bmesh_update_topology(ss->pbvh, + mode, + ss->cache->location, + ss->cache->view_normal, + ss->cache->radius, + (brush->flag & BRUSH_FRONTFACE) != 0, + (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); } + + MEM_SAFE_FREE(nodes); + + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); } static void do_brush_action_task_cb(void *__restrict userdata, @@ -5914,202 +5987,199 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe } /* Only act if some verts are inside the brush area. */ - if (totnode) { - float location[3]; + if (totnode == 0) { + return; + } + float location[3]; - SculptThreadedTaskData task_data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); - if (sculpt_brush_needs_normal(ss, brush)) { - update_sculpt_normal(sd, ob, nodes, totnode); - } + if (sculpt_brush_needs_normal(ss, brush)) { + update_sculpt_normal(sd, ob, nodes, totnode); + } - if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { - update_brush_local_mat(sd, ob); - } + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { + update_brush_local_mat(sd, ob); + } - if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { - SCULPT_pose_brush_init(sd, ob, ss, brush); - } + if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { + SCULPT_pose_brush_init(sd, ob, ss, brush); + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (!ss->cache->cloth_sim) { - ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( - ss, 1.0f, 0.0f, 0.0f, false, true); - SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); - } - SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); - SCULPT_cloth_brush_ensure_nodes_constraints( - sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (!ss->cache->cloth_sim) { + ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( + ss, 1.0f, 0.0f, 0.0f, false, true); + SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); } + SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); + SCULPT_cloth_brush_ensure_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + } - bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; + bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; - /* Apply one type of brush action. */ - switch (brush->sculpt_tool) { - case SCULPT_TOOL_DRAW: - do_draw_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMOOTH: - if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { - SCULPT_do_smooth_brush(sd, ob, nodes, totnode); - } - else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { - SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_CREASE: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BLOB: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PINCH: - do_pinch_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_INFLATE: - do_inflate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_GRAB: - do_grab_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ROTATE: - do_rotate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SNAKE_HOOK: - do_snake_hook_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_NUDGE: - do_nudge_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_THUMB: - do_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_LAYER: - do_layer_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FLATTEN: - do_flatten_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY: - do_clay_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_STRIPS: - do_clay_strips_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_MULTIPLANE_SCRAPE: - SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_THUMB: - do_clay_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FILL: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_scrape_brush(sd, ob, nodes, totnode); - } - else { - do_fill_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_SCRAPE: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_fill_brush(sd, ob, nodes, totnode); - } - else { - do_scrape_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_MASK: - do_mask_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_POSE: - SCULPT_do_pose_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_SHARP: - do_draw_sharp_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ELASTIC_DEFORM: - do_elastic_deform_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SLIDE_RELAX: - do_slide_relax_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BOUNDARY: - SCULPT_do_boundary_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLOTH: - SCULPT_do_cloth_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_FACE_SETS: - SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_ERASER: - do_displacement_eraser_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_SMEAR: - do_displacement_smear_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PAINT: - SCULPT_do_paint_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMEAR: - SCULPT_do_smear_brush(sd, ob, nodes, totnode); - break; - } - - if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && - brush->autosmooth_factor > 0) { - if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { - SCULPT_smooth(sd, - ob, - nodes, - totnode, - brush->autosmooth_factor * (1.0f - ss->cache->pressure), - false); + /* Apply one type of brush action. */ + switch (brush->sculpt_tool) { + case SCULPT_TOOL_DRAW: + do_draw_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMOOTH: + if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { + SCULPT_do_smooth_brush(sd, ob, nodes, totnode); + } + else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { + SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_CREASE: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BLOB: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PINCH: + do_pinch_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_INFLATE: + do_inflate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_GRAB: + do_grab_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ROTATE: + do_rotate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SNAKE_HOOK: + do_snake_hook_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_NUDGE: + do_nudge_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_THUMB: + do_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_LAYER: + do_layer_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FLATTEN: + do_flatten_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY: + do_clay_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_STRIPS: + do_clay_strips_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_MULTIPLANE_SCRAPE: + SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_THUMB: + do_clay_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FILL: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_scrape_brush(sd, ob, nodes, totnode); } else { - SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); + do_fill_brush(sd, ob, nodes, totnode); } - } + break; + case SCULPT_TOOL_SCRAPE: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_fill_brush(sd, ob, nodes, totnode); + } + else { + do_scrape_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_MASK: + do_mask_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_POSE: + SCULPT_do_pose_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_SHARP: + do_draw_sharp_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ELASTIC_DEFORM: + do_elastic_deform_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SLIDE_RELAX: + do_slide_relax_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BOUNDARY: + SCULPT_do_boundary_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLOTH: + SCULPT_do_cloth_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_FACE_SETS: + SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_ERASER: + do_displacement_eraser_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + do_displacement_smear_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PAINT: + SCULPT_do_paint_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMEAR: + SCULPT_do_smear_brush(sd, ob, nodes, totnode); + break; + } - if (sculpt_brush_use_topology_rake(ss, brush)) { - bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && + brush->autosmooth_factor > 0) { + if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { + SCULPT_smooth( + sd, ob, nodes, totnode, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false); } - - /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ - if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_BOUNDARY)) { - do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + else { + SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); } + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { - SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); - SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); - } + if (sculpt_brush_use_topology_rake(ss, brush)) { + bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + } + + /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ + if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_BOUNDARY)) { + do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + } + + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { + SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); + SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); } + } - MEM_SAFE_FREE(nodes); + MEM_SAFE_FREE(nodes); - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); - add_v3_v3(ups->average_stroke_accum, location); - ups->average_stroke_counter++; - /* Update last stroke position. */ - ups->last_stroke_valid = true; - } + add_v3_v3(ups->average_stroke_accum, location); + ups->average_stroke_counter++; + /* Update last stroke position. */ + ups->last_stroke_valid = true; } /* Flush displacement from deformed PBVH vertex to original mesh. */ @@ -6199,22 +6269,22 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) PBVHNode **nodes; int totnode; - BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); - - /* First line is tools that don't support proxies. */ - if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { - SculptThreadedTaskData data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + if (!ss->cache->supports_gravity && sculpt_tool_is_proxy_used(brush->sculpt_tool)) { + /* First line is tools that don't support proxies. */ + return; } + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); MEM_SAFE_FREE(nodes); } @@ -6235,12 +6305,14 @@ static void sculpt_update_keyblock(Object *ob) vertCos = BKE_pbvh_vert_coords_alloc(ss->pbvh); } - if (vertCos) { - SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + if (!vertCos) { + return; + } - if (vertCos != ss->orig_cos) { - MEM_freeN(vertCos); - } + SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + + if (vertCos != ss->orig_cos) { + MEM_freeN(vertCos); } } @@ -6259,10 +6331,12 @@ static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata, { sculpt_flush_pbvhvert_deform(ob, &vd); - if (vertCos) { - int index = vd.vert_indices[vd.i]; - copy_v3_v3(vertCos[index], ss->orig_cos[index]); + if (!vertCos) { + continue; } + + int index = vd.vert_indices[vd.i]; + copy_v3_v3(vertCos[index], ss->orig_cos[index]); } BKE_pbvh_vertex_iter_end; } @@ -6490,17 +6564,18 @@ static void do_symmetrical_brush_actions(Sculpt *sd, /* `symm` is a bit combination of XYZ - * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - cache->mirror_symmetry_pass = i; - cache->radial_symmetry_pass = 0; + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + cache->mirror_symmetry_pass = i; + cache->radial_symmetry_pass = 0; - SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); - do_tiled(sd, ob, brush, ups, action); + SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); + do_tiled(sd, ob, brush, ups, action); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); - } + do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); } } @@ -6668,22 +6743,25 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) ModifierData *md; for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { - MirrorModifierData *mmd = (MirrorModifierData *)md; - - if (mmd->flag & MOD_MIR_CLIPPING) { - /* Check each axis for mirroring. */ - for (int i = 0; i < 3; i++) { - if (mmd->flag & (MOD_MIR_AXIS_X << i)) { - /* Enable sculpt clipping. */ - ss->cache->flag |= CLIP_X << i; - - /* Update the clip tolerance. */ - if (mmd->tolerance > ss->cache->clip_tolerance[i]) { - ss->cache->clip_tolerance[i] = mmd->tolerance; - } - } - } + if (!(md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime))) { + continue; + } + MirrorModifierData *mmd = (MirrorModifierData *)md; + + if (!(mmd->flag & MOD_MIR_CLIPPING)) { + continue; + } + /* Check each axis for mirroring. */ + for (int i = 0; i < 3; i++) { + if (!(mmd->flag & (MOD_MIR_AXIS_X << i))) { + continue; + } + /* Enable sculpt clipping. */ + ss->cache->flag |= CLIP_X << i; + + /* Update the clip tolerance. */ + if (mmd->tolerance > ss->cache->clip_tolerance[i]) { + ss->cache->clip_tolerance[i] = mmd->tolerance; } } } @@ -6926,150 +7004,151 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru }; int tool = brush->sculpt_tool; - if (ELEM(tool, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_NUDGE, - SCULPT_TOOL_CLAY_STRIPS, - SCULPT_TOOL_PINCH, - SCULPT_TOOL_MULTIPLANE_SCRAPE, - SCULPT_TOOL_CLAY_THUMB, - SCULPT_TOOL_SNAKE_HOOK, - SCULPT_TOOL_POSE, - SCULPT_TOOL_BOUNDARY, - SCULPT_TOOL_THUMB) || - sculpt_brush_use_topology_rake(ss, brush)) { - float grab_location[3], imat[4][4], delta[3], loc[3]; + if (!ELEM(tool, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_NUDGE, + SCULPT_TOOL_CLAY_STRIPS, + SCULPT_TOOL_PINCH, + SCULPT_TOOL_MULTIPLANE_SCRAPE, + SCULPT_TOOL_CLAY_THUMB, + SCULPT_TOOL_SNAKE_HOOK, + SCULPT_TOOL_POSE, + SCULPT_TOOL_BOUNDARY, + SCULPT_TOOL_THUMB) && + !sculpt_brush_use_topology_rake(ss, brush)) { + return; + } + float grab_location[3], imat[4][4], delta[3], loc[3]; - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->orig_grab_location, - SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); - } - else { - copy_v3_v3(cache->orig_grab_location, cache->true_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->orig_grab_location, + SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); } - else if (tool == SCULPT_TOOL_SNAKE_HOOK || - (tool == SCULPT_TOOL_CLOTH && - brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { - add_v3_v3(cache->true_location, cache->grab_delta); + else { + copy_v3_v3(cache->orig_grab_location, cache->true_location); } + } + else if (tool == SCULPT_TOOL_SNAKE_HOOK || + (tool == SCULPT_TOOL_CLOTH && + brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { + add_v3_v3(cache->true_location, cache->grab_delta); + } - /* Compute 3d coordinate at same z from original location + mouse. */ - mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); - ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); + /* Compute 3d coordinate at same z from original location + mouse. */ + mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); + ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); - /* Compute delta to move verts by. */ - if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (sculpt_needs_delta_from_anchored_origin(brush)) { - sub_v3_v3v3(delta, grab_location, cache->old_grab_location); - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, delta); - add_v3_v3(cache->grab_delta, delta); - } - else if (sculpt_needs_delta_for_tip_orientation(brush)) { - if (brush->flag & BRUSH_ANCHORED) { - float orig[3]; - mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); - sub_v3_v3v3(cache->grab_delta, grab_location, orig); - } - else { - sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); - } - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, cache->grab_delta); + /* Compute delta to move verts by. */ + if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (sculpt_needs_delta_from_anchored_origin(brush)) { + sub_v3_v3v3(delta, grab_location, cache->old_grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, delta); + add_v3_v3(cache->grab_delta, delta); + } + else if (sculpt_needs_delta_for_tip_orientation(brush)) { + if (brush->flag & BRUSH_ANCHORED) { + float orig[3]; + mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); + sub_v3_v3v3(cache->grab_delta, grab_location, orig); } else { - /* Use for 'Brush.topology_rake_factor'. */ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, cache->grab_delta); } else { - zero_v3(cache->grab_delta); + /* Use for 'Brush.topology_rake_factor'. */ + sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + } + else { + zero_v3(cache->grab_delta); + } - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); - } + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); + } - copy_v3_v3(cache->old_grab_location, grab_location); + copy_v3_v3(cache->old_grab_location, grab_location); - if (tool == SCULPT_TOOL_GRAB) { - if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } - else { - copy_v3_v3(cache->anchored_location, cache->true_location); - } + if (tool == SCULPT_TOOL_GRAB) { + if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); } - else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + else { copy_v3_v3(cache->anchored_location, cache->true_location); } - else if (tool == SCULPT_TOOL_THUMB) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } + } + else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + copy_v3_v3(cache->anchored_location, cache->true_location); + } + else if (tool == SCULPT_TOOL_THUMB) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); + } - if (sculpt_needs_delta_from_anchored_origin(brush)) { - /* Location stays the same for finding vertices in brush radius. */ - copy_v3_v3(cache->true_location, cache->orig_grab_location); + if (sculpt_needs_delta_from_anchored_origin(brush)) { + /* Location stays the same for finding vertices in brush radius. */ + copy_v3_v3(cache->true_location, cache->orig_grab_location); - ups->draw_anchored = true; - copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - ups->anchored_size = ups->pixel_radius; - } + ups->draw_anchored = true; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + ups->anchored_size = ups->pixel_radius; + } - /* Handle 'rake' */ - cache->is_rake_rotation_valid = false; + /* Handle 'rake' */ + cache->is_rake_rotation_valid = false; - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, grab_location); - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - copy_v3_v3(cache->rake_data.follow_co, grab_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + copy_v3_v3(cache->rake_data.follow_co, grab_location); + } - if (sculpt_brush_needs_rake_rotation(brush)) { - cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; + if (!sculpt_brush_needs_rake_rotation(brush)) { + return; + } + cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; - if (!is_zero_v3(cache->grab_delta)) { - const float eps = 0.00001f; + if (!is_zero_v3(cache->grab_delta)) { + const float eps = 0.00001f; - float v1[3], v2[3]; + float v1[3], v2[3]; - copy_v3_v3(v1, cache->rake_data.follow_co); - copy_v3_v3(v2, cache->rake_data.follow_co); - sub_v3_v3(v2, cache->grab_delta); + copy_v3_v3(v1, cache->rake_data.follow_co); + copy_v3_v3(v2, cache->rake_data.follow_co); + sub_v3_v3(v2, cache->grab_delta); - sub_v3_v3(v1, grab_location); - sub_v3_v3(v2, grab_location); + sub_v3_v3(v1, grab_location); + sub_v3_v3(v2, grab_location); - if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && - (len_squared_v3v3(v1, v2) > eps)) { - const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); - const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? - 1.0f : - sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; + if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && (len_squared_v3v3(v1, v2) > eps)) { + const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); + const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? + 1.0f : + sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; - float axis[3], angle; - float tquat[4]; + float axis[3], angle; + float tquat[4]; - rotation_between_vecs_to_quat(tquat, v1, v2); + rotation_between_vecs_to_quat(tquat, v1, v2); - /* Use axis-angle to scale rotation since the factor may be above 1. */ - quat_to_axis_angle(axis, &angle, tquat); - normalize_v3(axis); + /* Use axis-angle to scale rotation since the factor may be above 1. */ + quat_to_axis_angle(axis, &angle, tquat); + normalize_v3(axis); - angle *= brush->rake_factor * rake_fade; - axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); - cache->is_rake_rotation_valid = true; - } - } - sculpt_rake_data_update(&cache->rake_data, grab_location); + angle *= brush->rake_factor * rake_fade; + axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); + cache->is_rake_rotation_valid = true; } } + sculpt_rake_data_update(&cache->rake_data, grab_location); } static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush) @@ -7257,71 +7336,73 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptRaycastData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptRaycastData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_raycast(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->isect_precalc, - &srd->depth, - &srd->active_vertex_index, - &srd->active_face_grid_index, - srd->face_normal)) { - srd->hit = true; - *tmin = srd->depth; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_raycast(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->isect_precalc, + &srd->depth, + &srd->active_vertex_index, + &srd->active_face_grid_index, + srd->face_normal)) { + srd->hit = true; + *tmin = srd->depth; + } } static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptFindNearestToRayData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptFindNearestToRayData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->depth, - &srd->dist_sq_to_ray)) { - srd->hit = true; - *tmin = srd->dist_sq_to_ray; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->depth, + &srd->dist_sq_to_ray)) { + srd->hit = true; + *tmin = srd->dist_sq_to_ray; + } } float SCULPT_raycast_init(ViewContext *vc, @@ -7546,26 +7627,30 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2]) } } - if (!hit) { - if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { - SculptFindNearestToRayData srd = { - .original = original, - .ss = ob->sculpt, - .hit = false, - .ray_start = ray_start, - .ray_normal = ray_normal, - .depth = FLT_MAX, - .dist_sq_to_ray = FLT_MAX, - }; - BKE_pbvh_find_nearest_to_ray( - ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); - if (srd.hit) { - hit = true; - copy_v3_v3(out, ray_normal); - mul_v3_fl(out, srd.depth); - add_v3_v3(out, ray_start); - } - } + if (hit) { + return hit; + } + + if (!ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { + return hit; + } + + SculptFindNearestToRayData srd = { + .original = original, + .ss = ob->sculpt, + .hit = false, + .ray_start = ray_start, + .ray_normal = ray_normal, + .depth = FLT_MAX, + .dist_sq_to_ray = FLT_MAX, + }; + BKE_pbvh_find_nearest_to_ray( + ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); + if (srd.hit) { + hit = true; + copy_v3_v3(out, ray_normal); + mul_v3_fl(out, srd.depth); + add_v3_v3(out, ray_start); } return hit; @@ -7748,19 +7833,20 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up bScreen *screen = WM_window_get_active_screen(win); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { SpaceLink *sl = area->spacedata.first; - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - if (v3d != current_v3d) { - need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); - } + if (sl->spacetype != SPACE_VIEW3D) { + continue; + } + View3D *v3d = (View3D *)sl; + if (v3d != current_v3d) { + need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); + } - /* Tag all 3D viewports for redraw now that we are done. Others - * viewports did not get a full redraw, and anti-aliasing for the - * current viewport was deactivated. */ - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (region->regiontype == RGN_TYPE_WINDOW) { - ED_region_tag_redraw(region); - } + /* Tag all 3D viewports for redraw now that we are done. Others + * viewports did not get a full redraw, and anti-aliasing for the + * current viewport was deactivated. */ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + ED_region_tag_redraw(region); } } } @@ -7920,55 +8006,56 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str Sculpt *sd = CTX_data_tool_settings(C)->sculpt; /* Finished. */ - if (ss->cache) { - UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; - Brush *brush = BKE_paint_brush(&sd->paint); - BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ - ups->draw_inverted = false; + if (!ss->cache) { + sculpt_brush_exit_tex(sd); + return; + } + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; + Brush *brush = BKE_paint_brush(&sd->paint); + BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ + ups->draw_inverted = false; - SCULPT_stroke_modifiers_check(C, ob, brush); + SCULPT_stroke_modifiers_check(C, ob, brush); - /* Alt-Smooth. */ - if (ss->cache->alt_smooth) { - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - brush->mask_tool = ss->cache->saved_mask_brush_tool; - } - else if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_SLIDE_RELAX, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_SMEAR)) { - /* Do nothing. */ - } - else { - BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); - brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); - if (brush) { - BKE_paint_brush_set(&sd->paint, brush); - } - } + /* Alt-Smooth. */ + if (ss->cache->alt_smooth) { + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + brush->mask_tool = ss->cache->saved_mask_brush_tool; } - - if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - SCULPT_automasking_cache_free(ss->cache->automasking); + else if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_SLIDE_RELAX, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR)) { + /* Do nothing. */ } + else { + BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); + brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); + if (brush) { + BKE_paint_brush_set(&sd->paint, brush); + } + } + } - BKE_pbvh_node_color_buffer_free(ss->pbvh); - SCULPT_cache_free(ss->cache); - ss->cache = NULL; + if (SCULPT_is_automasking_enabled(sd, ss, brush)) { + SCULPT_automasking_cache_free(ss->cache->automasking); + } - SCULPT_undo_push_end(); + BKE_pbvh_node_color_buffer_free(ss->pbvh); + SCULPT_cache_free(ss->cache); + ss->cache = NULL; - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); - } - else { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); - } + SCULPT_undo_push_end(); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); + } + else { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); sculpt_brush_exit_tex(sd); } @@ -8090,21 +8177,22 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - if (ss) { - SCULPT_vertex_random_access_ensure(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); + if (!ss) { + return OPERATOR_FINISHED; + } + SCULPT_vertex_random_access_ensure(ss); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - MEM_SAFE_FREE(ss->persistent_base); + MEM_SAFE_FREE(ss->persistent_base); - const int totvert = SCULPT_vertex_count_get(ss); - ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, - "layer persistent base"); + const int totvert = SCULPT_vertex_count_get(ss); + ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, + "layer persistent base"); - for (int i = 0; i < totvert; i++) { - copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); - SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); - ss->persistent_base[i].disp = 0.0f; - } + for (int i = 0; i < totvert; i++) { + copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); + SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); + ss->persistent_base[i].disp = 0.0f; } return OPERATOR_FINISHED; @@ -8564,12 +8652,13 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float totpoints++; ss->preview_vert_index_list[totpoints] = to_v; totpoints++; - if (!BLI_BITMAP_TEST(visited_vertices, to_v)) { - BLI_BITMAP_ENABLE(visited_vertices, to_v); - const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); - if (len_squared_v3v3(brush_co, co) < radius * radius) { - BLI_gsqueue_push(not_visited_vertices, &to_v); - } + if (BLI_BITMAP_TEST(visited_vertices, to_v)) { + continue; + } + BLI_BITMAP_ENABLE(visited_vertices, to_v); + const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); + if (len_squared_v3v3(brush_co, co) < radius * radius) { + BLI_gsqueue_push(not_visited_vertices, &to_v); } } } @@ -8993,7 +9082,7 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist) for (int i = 0; i < totvert; i++) { const int from_v = i; - /* This vertex does not have a fake neighbor yet, seach one for it. */ + /* This vertex does not have a fake neighbor yet, search one for it. */ if (ss->fake_neighbors.fake_neighbor_index[from_v] == FAKE_NEIGHBOR_NONE) { const int to_v = SCULPT_fake_neighbor_search(sd, ob, from_v, max_dist); if (to_v != -1) { @@ -9099,11 +9188,12 @@ static void do_mask_by_color_contiguous_update_nodes_cb( const float current_mask = *vd.mask; const float new_mask = data->mask_by_color_floodfill[vd.index]; *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -9206,11 +9296,12 @@ static void do_mask_by_color_task_cb(void *__restrict userdata, const float new_mask = sculpt_mask_by_color_delta_get(active_color, vd.col, threshold, invert); *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index bb68ec56b25..5f5fb51d75f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -298,24 +298,26 @@ float *SCULPT_boundary_automasking_init(Object *ob, for (int propagation_it = 0; propagation_it < propagation_steps; propagation_it++) { for (int i = 0; i < totvert; i++) { - if (edge_distance[i] == EDGE_DISTANCE_INF) { - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { - if (edge_distance[ni.index] == propagation_it) { - edge_distance[i] = propagation_it + 1; - } + if (edge_distance[i] != EDGE_DISTANCE_INF) { + continue; + } + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { + if (edge_distance[ni.index] == propagation_it) { + edge_distance[i] = propagation_it + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } } for (int i = 0; i < totvert; i++) { - if (edge_distance[i] != EDGE_DISTANCE_INF) { - const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); - const float edge_boundary_automask = pow2f(p); - automask_factor[i] *= (1.0f - edge_boundary_automask); + if (edge_distance[i] == EDGE_DISTANCE_INF) { + continue; } + const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); + const float edge_boundary_automask = pow2f(p); + automask_factor[i] *= (1.0f - edge_boundary_automask); } MEM_SAFE_FREE(edge_distance); diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c index 0cfb6f17adb..fca19c04b98 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.c +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c @@ -227,19 +227,19 @@ static bool boundary_floodfill_cb( { BoundaryFloodFillData *data = userdata; SculptBoundary *boundary = data->boundary; - if (SCULPT_vertex_is_boundary(ss, to_v)) { - const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, to_v)); - const float distance_boundary_to_dst = boundary->distance ? - boundary->distance[from_v] + edge_len : - 0.0f; - sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); - if (!is_duplicate) { - sculpt_boundary_preview_edge_add(boundary, from_v, to_v); - } - return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); + if (!SCULPT_vertex_is_boundary(ss, to_v)) { + return false; + } + const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, to_v)); + const float distance_boundary_to_dst = boundary->distance ? + boundary->distance[from_v] + edge_len : + 0.0f; + sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); + if (!is_duplicate) { + sculpt_boundary_preview_edge_add(boundary, from_v, to_v); } - return false; + return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); } static void sculpt_boundary_indices_init(SculptSession *ss, @@ -360,49 +360,50 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const bool is_visible = SCULPT_vertex_visible_get(ss, ni.index); - if (is_visible && - boundary->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) { - boundary->edit_info[ni.index].original_vertex = - boundary->edit_info[from_v].original_vertex; + if (!is_visible || + boundary->edit_info[ni.index].num_propagation_steps != BOUNDARY_STEPS_NONE) { + continue; + } + boundary->edit_info[ni.index].original_vertex = + boundary->edit_info[from_v].original_vertex; - BLI_BITMAP_ENABLE(visited_vertices, ni.index); + BLI_BITMAP_ENABLE(visited_vertices, ni.index); - if (ni.is_duplicate) { - /* Grids duplicates handling. */ - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps; - } - else { - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - - BLI_gsqueue_push(next_iteration, &ni.index); - - /* When copying the data to the neighbor for the next iteration, it has to be copied to - * all its duplicates too. This is because it is not possible to know if the updated - * neighbor or one if its uninitialized duplicates is going to come first in order to - * copy the data in the from_v neighbor iterator. */ - if (has_duplicates) { - SculptVertexNeighborIter ni_duplis; - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { - if (ni_duplis.is_duplicate) { - boundary->edit_info[ni_duplis.index].original_vertex = - boundary->edit_info[from_v].original_vertex; - boundary->edit_info[ni_duplis.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - } + if (ni.is_duplicate) { + /* Grids duplicates handling. */ + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps; + } + else { + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; + + BLI_gsqueue_push(next_iteration, &ni.index); + + /* When copying the data to the neighbor for the next iteration, it has to be copied to + * all its duplicates too. This is because it is not possible to know if the updated + * neighbor or one if its uninitialized duplicates is going to come first in order to + * copy the data in the from_v neighbor iterator. */ + if (has_duplicates) { + SculptVertexNeighborIter ni_duplis; + SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { + if (ni_duplis.is_duplicate) { + boundary->edit_info[ni_duplis.index].original_vertex = + boundary->edit_info[from_v].original_vertex; + boundary->edit_info[ni_duplis.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); + } - /* Check the distance using the vertex that was propagated from the initial vertex that - * was used to initialize the boundary. */ - if (boundary->edit_info[from_v].original_vertex == initial_vertex) { - boundary->pivot_vertex = ni.index; - copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); - accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, ni.index)); - } + /* Check the distance using the vertex that was propagated from the initial vertex that + * was used to initialize the boundary. */ + if (boundary->edit_info[from_v].original_vertex == initial_vertex) { + boundary->pivot_vertex = ni.index; + copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); + accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, ni.index)); } } } @@ -552,28 +553,30 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo totvert, 3 * sizeof(float), "pivot positions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - float dir[3]; - float normal[3]; - SCULPT_vertex_normal_get(ss, i, normal); - sub_v3_v3v3(dir, - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - cross_v3_v3v3( - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); - normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, i)); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { + continue; } + float dir[3]; + float normal[3]; + SCULPT_vertex_normal_get(ss, i, normal); + sub_v3_v3v3(dir, + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + cross_v3_v3v3( + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); + normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, i)); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->bend.pivot_positions[i], - boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_rotation_axis[i], - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->bend.pivot_positions[i], + boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_rotation_axis[i], + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); } } @@ -583,19 +586,20 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b boundary->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { } + sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->slide.directions[i], - boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->slide.directions[i], + boundary->slide.directions[boundary->edit_info[i].original_vertex]); } } @@ -662,24 +666,27 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->bend.pivot_rotation_axis[vd.index], - angle * boundary->edit_info[vd.index].strength_factor * mask * automask); - add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->bend.pivot_rotation_axis[vd.index], + angle * boundary->edit_info[vd.index].strength_factor * mask * automask); + add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -708,22 +715,25 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - boundary->slide.directions[vd.index], - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + boundary->slide.directions[vd.index], + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -752,24 +762,27 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float normal[3]; - normal_short_to_float_v3(normal, orig_data.no); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - normal, - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float normal[3]; + normal_short_to_float_v3(normal, orig_data.no); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + normal, + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -796,21 +809,24 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - ss->cache->grab_delta_symmetry, - boundary->edit_info[vd.index].strength_factor * mask * automask * strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + ss->cache->grab_delta_symmetry, + boundary->edit_info[vd.index].strength_factor * mask * automask * strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -845,24 +861,27 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->twist.rotation_axis, - angle * mask * automask * boundary->edit_info[vd.index].strength_factor); - add_v3_v3(target_co, boundary->twist.pivot_position); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->twist.rotation_axis, + angle * mask * automask * boundary->edit_info[vd.index].strength_factor); + add_v3_v3(target_co, boundary->twist.pivot_position); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index c97f31fa682..16d10f6d6bb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -540,97 +540,98 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, vertex_gravity, vd.index); /* When using the plane falloff mode the falloff is not constrained by the brush radius. */ - if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) { - - float dist = sqrtf(test.dist); + if (!sculpt_brush_test_sq_fn(&test, current_vertex_location) && !use_falloff_plane) { + continue; + } - if (use_falloff_plane) { - dist = dist_to_plane_v3(current_vertex_location, deform_plane); - } + float dist = sqrtf(test.dist); - const float fade = sim_factor * bstrength * - SCULPT_brush_strength_factor(ss, - brush, - current_vertex_location, - dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float brush_disp[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } + if (use_falloff_plane) { + dist = dist_to_plane_v3(current_vertex_location, deform_plane); + } - switch (brush->cloth_deform_type) { - case BRUSH_CLOTH_DEFORM_DRAG: - sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PUSH: - /* Invert the fade to push inwards. */ - mul_v3_v3fl(force, offset, -fade); - break; - case BRUSH_CLOTH_DEFORM_GRAB: - madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], - cloth_sim->init_pos[vd.index], - ss->cache->grab_delta_symmetry, - fade); - if (use_falloff_plane) { - cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); - } - else { - cloth_sim->deformation_strength[vd.index] = 1.0f; - } - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: - copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); - madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); - cloth_sim->deformation_strength[vd.index] = fade; - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_PINCH_POINT: - if (use_falloff_plane) { - float distance = dist_signed_to_plane_v3(vd.co, deform_plane); - copy_v3_v3(brush_disp, plane_normal); - mul_v3_fl(brush_disp, -distance); - } - else { - sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); - } - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - sub_v3_v3v3(disp_center, ss->cache->location, vd.co); - normalize_v3(disp_center); - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - add_v3_v3v3(disp_center, x_disp, z_disp); - mul_v3_v3fl(force, disp_center, fade); - } break; - case BRUSH_CLOTH_DEFORM_INFLATE: - mul_v3_v3fl(force, normal, fade); - break; - case BRUSH_CLOTH_DEFORM_EXPAND: - cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; - zero_v3(force); - break; - } + const float fade = sim_factor * bstrength * + SCULPT_brush_strength_factor(ss, + brush, + current_vertex_location, + dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float brush_disp[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } - cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); + switch (brush->cloth_deform_type) { + case BRUSH_CLOTH_DEFORM_DRAG: + sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PUSH: + /* Invert the fade to push inwards. */ + mul_v3_v3fl(force, offset, -fade); + break; + case BRUSH_CLOTH_DEFORM_GRAB: + madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], + cloth_sim->init_pos[vd.index], + ss->cache->grab_delta_symmetry, + fade); + if (use_falloff_plane) { + cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); + } + else { + cloth_sim->deformation_strength[vd.index] = 1.0f; + } + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: + copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); + madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); + cloth_sim->deformation_strength[vd.index] = fade; + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_PINCH_POINT: + if (use_falloff_plane) { + float distance = dist_signed_to_plane_v3(vd.co, deform_plane); + copy_v3_v3(brush_disp, plane_normal); + mul_v3_fl(brush_disp, -distance); + } + else { + sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); + } + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + sub_v3_v3v3(disp_center, ss->cache->location, vd.co); + normalize_v3(disp_center); + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + add_v3_v3v3(disp_center, x_disp, z_disp); + mul_v3_v3fl(force, disp_center, fade); + } break; + case BRUSH_CLOTH_DEFORM_INFLATE: + mul_v3_v3fl(force, normal, fade); + break; + case BRUSH_CLOTH_DEFORM_EXPAND: + cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; + zero_v3(force); + break; } + + cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); } BKE_pbvh_vertex_iter_end; } @@ -644,17 +645,22 @@ static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph) DEG_ITER_OBJECT_FLAG_DUPLI) { CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Collision); - if (cmd && cmd->bvhtree) { - if (cache == NULL) { - cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); - } + if (!cmd) { + continue; + } - ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); - col->ob = ob; - col->collmd = cmd; - collision_move_object(cmd, 1.0, 0.0, true); - BLI_addtail(cache, col); + if (!cmd->bvhtree) { + continue; } + if (cache == NULL) { + cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + } + + ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); + col->ob = ob; + col->collmd = cmd; + collision_move_object(cmd, 1.0, 0.0, true); + BLI_addtail(cache, col); } DEG_OBJECT_ITER_END; return cache; @@ -734,26 +740,27 @@ static void cloth_brush_solve_collision(Object *object, &col, raycast_flag); - if (hit.index != -1) { - - float collision_disp[3]; - float movement_disp[3]; - mul_v3_v3fl(collision_disp, hit.no, 0.005f); - sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); - float friction_plane[4]; - float pos_on_friction_plane[3]; - plane_from_point_normal_v3(friction_plane, hit.co, hit.no); - closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); - sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); - - /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ - mul_v3_fl(movement_disp, 0.35f); - - copy_v3_v3(cloth_sim->pos[i], hit.co); - add_v3_v3(cloth_sim->pos[i], movement_disp); - add_v3_v3(cloth_sim->pos[i], collision_disp); - mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); + if (hit.index == -1) { + continue; } + + float collision_disp[3]; + float movement_disp[3]; + mul_v3_v3fl(collision_disp, hit.no, 0.005f); + sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); + float friction_plane[4]; + float pos_on_friction_plane[3]; + plane_from_point_normal_v3(friction_plane, hit.co, hit.no); + closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); + sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); + + /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ + mul_v3_fl(movement_disp, 0.35f); + + copy_v3_v3(cloth_sim->pos[i], hit.co); + add_v3_v3(cloth_sim->pos[i], movement_disp); + add_v3_v3(cloth_sim->pos[i], collision_disp); + mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); } } @@ -784,38 +791,40 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( ss->cache ? cloth_brush_simulation_falloff_get( brush, ss->cache->radius, sim_location, cloth_sim->init_pos[vd.index]) : 1.0f; - if (sim_factor > 0.0f) { - int i = vd.index; - float temp[3]; - copy_v3_v3(temp, cloth_sim->pos[i]); + if (sim_factor <= 0.0f) { + continue; + } - mul_v3_fl(cloth_sim->acceleration[i], time_step); + int i = vd.index; + float temp[3]; + copy_v3_v3(temp, cloth_sim->pos[i]); - float pos_diff[3]; - sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); - mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); + mul_v3_fl(cloth_sim->acceleration[i], time_step); - const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * - SCULPT_automasking_factor_get(automasking, ss, vd.index); + float pos_diff[3]; + sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); + mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); - madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); - madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); + const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * + SCULPT_automasking_factor_get(automasking, ss, vd.index); - if (cloth_sim->collider_list != NULL) { - cloth_brush_solve_collision(data->ob, cloth_sim, i); - } + madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); + madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + if (cloth_sim->collider_list != NULL) { + cloth_brush_solve_collision(data->ob, cloth_sim, i); + } - copy_v3_v3(cloth_sim->prev_pos[i], temp); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_fl(cloth_sim->acceleration[i], 0.0f); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + copy_v3_v3(cloth_sim->prev_pos[i], temp); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + copy_v3_fl(cloth_sim->acceleration[i], 0.0f); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index aa1d407dc24..ddf7ba1e412 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -24,46 +24,29 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BLI_hash.h" #include "BLI_math.h" -#include "BLI_task.h" #include "BLT_translation.h" #include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_mesh.h" -#include "BKE_mesh_mapping.h" -#include "BKE_object.h" #include "BKE_paint.h" #include "BKE_pbvh.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "DEG_depsgraph.h" #include "WM_api.h" -#include "WM_message.h" -#include "WM_toolsystem.h" #include "WM_types.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_sculpt.h" #include "ED_view3d.h" -#include "paint_intern.h" #include "sculpt_intern.h" #include "RNA_access.h" #include "RNA_define.h" -#include "UI_interface.h" - -#include "bmesh.h" - #include <math.h> #include <stdlib.h> diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 1fba958d695..df03d2adeaf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -148,40 +148,42 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, float poly_center[3]; BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center); - if (sculpt_brush_test_sq_fn(&test, poly_center)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, poly_center)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { + ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); } } } else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f) { - SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f) { + SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); } } } @@ -205,7 +207,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, ss, &test, data->brush->falloff_shape); const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0); - /* This operations needs a stregth tweak as the relax deformation is too weak by default. */ + /* This operations needs a strength tweak as the relax deformation is too weak by default. */ if (relax_face_sets) { bstrength *= 2.0f; } @@ -214,23 +216,26 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) { + continue; + } - SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -313,7 +318,7 @@ static int sculpt_face_set_create_exec(bContext *C, wmOperator *op) const int mode = RNA_enum_get(op->ptr, "mode"); - /* Dyntopo not suported. */ + /* Dyntopo not supported. */ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { return OPERATOR_CANCELLED; } @@ -582,44 +587,49 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, int next_face_set = 1; for (int i = 0; i < totfaces; i++) { - if (!BLI_BITMAP_TEST(visited_faces, i)) { - GSQueue *queue; - queue = BLI_gsqueue_new(sizeof(int)); - - face_sets[i] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, i); - BLI_gsqueue_push(queue, &i); - - while (!BLI_gsqueue_is_empty(queue)) { - int from_f; - BLI_gsqueue_pop(queue, &from_f); - - BMFace *f, *f_neighbor; - BMEdge *ed; - BMIter iter_a, iter_b; - - f = BM_face_at_index(bm, from_f); - - BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { - if (f_neighbor != f) { - int neighbor_face_index = BM_elem_index_get(f_neighbor); - if (!BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { - if (test(bm, f, ed, f_neighbor, threshold)) { - face_sets[neighbor_face_index] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); - BLI_gsqueue_push(queue, &neighbor_face_index); - } - } - } + if (BLI_BITMAP_TEST(visited_faces, i)) { + continue; + } + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(int)); + + face_sets[i] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, i); + BLI_gsqueue_push(queue, &i); + + while (!BLI_gsqueue_is_empty(queue)) { + int from_f; + BLI_gsqueue_pop(queue, &from_f); + + BMFace *f, *f_neighbor; + BMEdge *ed; + BMIter iter_a, iter_b; + + f = BM_face_at_index(bm, from_f); + + BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { + if (f_neighbor == f) { + continue; } + int neighbor_face_index = BM_elem_index_get(f_neighbor); + if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { + continue; + } + if (!test(bm, f, ed, f_neighbor, threshold)) { + continue; + } + + face_sets[neighbor_face_index] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); + BLI_gsqueue_push(queue, &neighbor_face_index); } } + } - next_face_set += 1; + next_face_set += 1; - BLI_gsqueue_free(queue); - } + BLI_gsqueue_free(queue); } MEM_SAFE_FREE(visited_faces); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index e11894a8c01..3cf6a8cc561 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -553,7 +553,7 @@ static void mesh_filter_sharpen_init(SculptSession *ss, filter_cache->sharpen_factor[i] = 1.0f - pow2f(1.0f - filter_cache->sharpen_factor[i]); } - /* Smooth the calculated factors and directions to remove high frecuency detail. */ + /* Smooth the calculated factors and directions to remove high frequency detail. */ for (int smooth_iterations = 0; smooth_iterations < filter_cache->sharpen_curvature_smooth_iterations; smooth_iterations++) { diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index d1e17c7e59b..f90cf366ed9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -511,7 +511,7 @@ void SCULPT_boundary_edges_preview_draw(const uint gpuattr, const float outline_alpha); void SCULPT_boundary_pivot_line_preview_draw(const uint gpuattr, struct SculptSession *ss); -/* Multiplane Scrape Brush. */ +/* Multi-plane Scrape Brush. */ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, Brush *brush, diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index e47a94dff90..cfc31e1dcdd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -88,38 +88,39 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } - mul_v3_m4v3(local_co, mat, vd.co); - /* Use the brush falloff to weight the sampled normals. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Sample the normal and area of the +X and -X axis individually. */ - if (local_co[0] > 0.0f) { - madd_v3_v3fl(mssd->area_nos[0], normal, fade); - add_v3_v3(mssd->area_cos[0], vd.co); - mssd->area_count[0]++; - } - else { - madd_v3_v3fl(mssd->area_nos[1], normal, fade); - add_v3_v3(mssd->area_cos[1], vd.co); - mssd->area_count[1]++; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } + mul_v3_m4v3(local_co, mat, vd.co); + /* Use the brush falloff to weight the sampled normals. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Sample the normal and area of the +X and -X axis individually. */ + if (local_co[0] > 0.0f) { + madd_v3_v3fl(mssd->area_nos[0], normal, fade); + add_v3_v3(mssd->area_cos[0], vd.co); + mssd->area_count[0]++; + } + else { + madd_v3_v3fl(mssd->area_nos[1], normal, fade); + add_v3_v3(mssd->area_cos[1], vd.co); + mssd->area_count[1]++; } BKE_pbvh_vertex_iter_end; } @@ -168,56 +169,61 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - bool deform = false; - - mul_v3_m4v3(local_co, mat, vd.co); - - if (local_co[0] > 0.0f) { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); - } - else { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); - } - - if (angle < 0.0f) { - deform = true; - } - - if (deform) { - float intr[3]; - float val[3]; - - if (local_co[0] > 0.0f) { - closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); - } - else { - closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); - } - - sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ - /* This produces a not round brush tip. */ - local_co[1] *= 2.0f; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - len_v3(local_co), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + float local_co[3]; + bool deform = false; + + mul_v3_m4v3(local_co, mat, vd.co); + + if (local_co[0] > 0.0f) { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); + } + else { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); + } + + if (angle < 0.0f) { + deform = true; + } + + if (!deform) { + continue; + } + + float intr[3]; + float val[3]; + + if (local_co[0] > 0.0f) { + closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); + } + else { + closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); + } + + sub_v3_v3v3(val, intr, vd.co); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ + /* This produces a not round brush tip. */ + local_co[1] *= 2.0f; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + len_v3(local_co), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index 39320f3f558..5fdf8415f28 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -87,24 +87,25 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float smooth_color[4]; - SCULPT_neighbor_color_average(ss, smooth_color, vd.index); - blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float smooth_color[4]; + SCULPT_neighbor_color_average(ss, smooth_color, vd.index); + blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -153,46 +154,49 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, distance_to_stroke_location = sqrtf(test.dist); } - if (affect_vertex) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - distance_to_stroke_location, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Density. */ - float noise = 1.0f; - const float density = ss->cache->paint_brush.density; - if (density < 1.0f) { - const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); - if (hash_noise > density) { - noise = density * hash_noise; - fade = fade * noise; - } + if (!affect_vertex) { + continue; + } + + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + distance_to_stroke_location, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Density. */ + float noise = 1.0f; + const float density = ss->cache->paint_brush.density; + if (density < 1.0f) { + const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); + if (hash_noise > density) { + noise = density * hash_noise; + fade = fade * noise; } + } - /* Brush paint color, brush test falloff and flow. */ - float paint_color[4]; - float wet_mix_color[4]; - float buffer_color[4]; + /* Brush paint color, brush test falloff and flow. */ + float paint_color[4]; + float wet_mix_color[4]; + float buffer_color[4]; - mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); - mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); - /* Interpolate with the wet_mix color for wet paint mixing. */ - blend_color_interpolate_float( - paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); - blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); + /* Interpolate with the wet_mix color for wet paint mixing. */ + blend_color_interpolate_float( + paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); + blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); - /* Final mix over the original color using brush alpha. */ - mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + /* Final mix over the original color using brush alpha. */ + mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + + IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - } CLAMP4(vd.col, 0.0f, 1.0f); if (vd.mvert) { @@ -225,10 +229,12 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - add_v4_v4(swptd->color, vd.col); - swptd->tot_samples++; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + + add_v4_v4(swptd->color, vd.col); + swptd->tot_samples++; } BKE_pbvh_vertex_iter_end; } @@ -380,59 +386,61 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float current_disp[3]; - float current_disp_norm[3]; - float interp_color[4]; - copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); - - switch (brush->smear_deform_type) { - case BRUSH_SMEAR_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SMEAR_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SMEAR_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - const float *neighbor_color = ss->cache->prev_colors[ni.index]; - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float color_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - float color_mix[4]; - copy_v4_v4(color_mix, neighbor_color); - mul_v4_fl(color_mix, color_interp * fade); - blend_color_mix_float(interp_color, interp_color, color_mix); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float current_disp[3]; + float current_disp_norm[3]; + float interp_color[4]; + copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); + + switch (brush->smear_deform_type) { + case BRUSH_SMEAR_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SMEAR_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SMEAR_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + const float *neighbor_color = ss->cache->prev_colors[ni.index]; + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + const float color_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + float color_mix[4]; + copy_v4_v4(color_mix, neighbor_color); + mul_v4_fl(color_mix, color_interp * fade); + blend_color_mix_float(interp_color, interp_color, color_mix); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); + blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index 1bf9ba60073..a85f805894b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -490,50 +490,52 @@ static bool pose_face_sets_floodfill_cb( is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set); } - if (is_vertex_valid) { - - if (!BLI_BITMAP_TEST(data->is_weighted, index)) { - data->pose_factor[index] = 1.0f; - BLI_BITMAP_ENABLE(data->is_weighted, index); - visit_next = true; - } - - /* Fallback origin accumulation. */ - if (symmetry_check) { - add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); - data->fallback_count++; - } - - if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) { + if (!is_vertex_valid) { + return visit_next; + } - /* We only add coordinates for calculating the origin when it is possible to go from this - * vertex to another vertex in a valid face set for the next iteration. */ - bool count_as_boundary = false; + if (!BLI_BITMAP_TEST(data->is_weighted, index)) { + data->pose_factor[index] = 1.0f; + BLI_BITMAP_ENABLE(data->is_weighted, index); + visit_next = true; + } - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { - int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + /* Fallback origin accumulation. */ + if (symmetry_check) { + add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); + data->fallback_count++; + } - /* Check if we can get a valid face set for the next iteration from this neighbor. */ - if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && - !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { - if (!data->next_face_set_found) { - data->next_face_set = next_face_set_candidate; - data->next_vertex = ni.index; - data->next_face_set_found = true; - } - count_as_boundary = true; - } - } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + if (!symmetry_check || SCULPT_vertex_has_unique_face_set(ss, index)) { + return visit_next; + } - /* Origin accumulation. */ - if (count_as_boundary) { - add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); - data->tot_co++; + /* We only add coordinates for calculating the origin when it is possible to go from this + * vertex to another vertex in a valid face set for the next iteration. */ + bool count_as_boundary = false; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { + int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + + /* Check if we can get a valid face set for the next iteration from this neighbor. */ + if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && + !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { + if (!data->next_face_set_found) { + data->next_face_set = next_face_set_candidate; + data->next_vertex = ni.index; + data->next_face_set_found = true; } + count_as_boundary = true; } } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + /* Origin accumulation. */ + if (count_as_boundary) { + add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); + data->tot_co++; + } return visit_next; } @@ -738,7 +740,7 @@ static SculptPoseIKChain *pose_ik_chain_init_topology(Sculpt *sd, * iteration an the current iteration. */ for (int j = 0; j < totvert; j++) { ik_chain->segments[i].weights[j] = pose_factor_grow[j] - pose_factor_grow_prev[j]; - /* Store the current grow factor status for the next interation. */ + /* Store the current grow factor status for the next iteration. */ pose_factor_grow_prev[j] = pose_factor_grow[j]; } } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 87ee7480c92..4c0795eb0f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -231,24 +231,26 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); - SCULPT_clip(sd, ss, vd.co, disp); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); + SCULPT_clip(sd, ss, vd.co, disp); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -312,33 +314,34 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor( - ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), - vd.index, - thread_id); - if (smooth_mask) { - float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; - val *= fade * bstrength; - *vd.mask += val; - CLAMP(*vd.mask, 0.0f, 1.0f); - } - else { - float avg[3], val[3]; - SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); - sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); - } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor( + ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), + vd.index, + thread_id); + if (smooth_mask) { + float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0.0f, 1.0f); + } + else { + float avg[3], val[3]; + SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); + sub_v3_v3v3(val, avg, vd.co); + madd_v3_v3v3fl(val, vd.co, val, fade); + SCULPT_clip(sd, ss, vd.co, val); + } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -473,32 +476,28 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - SCULPT_surface_smooth_laplacian_step(ss, - disp, - vd.co, - ss->cache->surface_smooth_laplacian_disp, - vd.index, - orig_data.co, - alpha); - madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + SCULPT_surface_smooth_laplacian_step( + ss, disp, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, orig_data.co, alpha); + madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; } static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( @@ -519,19 +518,20 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - SCULPT_surface_smooth_displace_step( - ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + SCULPT_surface_smooth_displace_step( + ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 938080b392d..ec103bd2b98 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -1527,9 +1527,14 @@ static void sculpt_undosys_step_decode_redo(struct bContext *C, } } -static void sculpt_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final)) +static void sculpt_undosys_step_decode(struct bContext *C, + struct Main *bmain, + UndoStep *us_p, + const eUndoStepDir dir, + bool UNUSED(is_final)) { + BLI_assert(dir != STEP_INVALID); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); /* Ensure sculpt mode. */ @@ -1568,10 +1573,10 @@ static void sculpt_undosys_step_decode( } SculptUndoStep *us = (SculptUndoStep *)us_p; - if (dir < 0) { + if (dir == STEP_UNDO) { sculpt_undosys_step_decode_undo(C, depsgraph, us); } - else { + else if (dir == STEP_REDO) { sculpt_undosys_step_decode_redo(C, depsgraph, us); } } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 34617804888..85616f6356d 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -31,7 +31,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_sound_types.h" @@ -877,7 +876,7 @@ static void SOUND_OT_unpack(wmOperatorType *ot) /* properties */ RNA_def_enum( ot->srna, "method", rna_enum_unpack_method_items, PF_USE_LOCAL, "Method", "How to unpack"); - /* XXX, weark!, will fail with library, name collisions */ + /* XXX: weak!, will fail with library, name collisions */ RNA_def_string( ot->srna, "id", NULL, MAX_ID_NAME - 2, "Sound Name", "Sound data-block name to unpack"); } diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c index 5e1c205f1d4..dfc3789a26c 100644 --- a/source/blender/editors/space_action/action_buttons.c +++ b/source/blender/editors/space_action/action_buttons.c @@ -26,33 +26,10 @@ #include <stdio.h> #include <string.h> -#include "DNA_anim_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_fcurve.h" #include "BKE_screen.h" -#include "BKE_unit.h" - -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_access.h" - -#include "ED_anim_api.h" -#include "ED_keyframing.h" -#include "ED_screen.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "action_intern.h" /* own include */ diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index f731fe23b7c..f8389d40831 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -73,7 +73,7 @@ /* ************************************************************************** */ /* POSE MARKERS STUFF */ -/* *************************** Localise Markers ***************************** */ +/* *************************** Localize Markers ***************************** */ /* ensure that there is: * 1) an active action editor @@ -322,7 +322,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, bAnimListElem *ale; int filter; - /* NOTE: not bool, since we want prioritise individual channels over expanders */ + /* NOTE: not bool, since we want prioritize individual channels over expanders. */ short found = 0; /* get all items - we need to do it this way */ @@ -346,7 +346,7 @@ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, found = acf->channel_role; /* only stop our search when we've found an actual channel - * - datablock expanders get less priority so that we don't abort prematurely + * - data-block expanders get less priority so that we don't abort prematurely */ if (found == ACHANNEL_ROLE_CHANNEL) { break; diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index 7422c05511c..7821458d1e5 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -27,9 +27,6 @@ #include "DNA_space_types.h" #include "ED_anim_api.h" -#include "ED_markers.h" -#include "ED_object.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "action_intern.h" diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index ff0201f9702..722005235d3 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -55,7 +55,6 @@ #include "ED_space_api.h" #include "ED_time_scrub_ui.h" -#include "GPU_framebuffer.h" #include "action_intern.h" /* own include */ /* ******************** default callbacks for action space ***************** */ @@ -305,12 +304,11 @@ static void action_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void action_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -356,14 +354,13 @@ static void action_channel_region_listener(wmWindow *UNUSED(win), } } -static void saction_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -401,12 +398,11 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS } } -static void action_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -460,14 +456,14 @@ static void action_main_region_listener(wmWindow *UNUSED(win), } } -static void saction_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *workspace, - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void saction_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, area->spacedata.first, &ptr); @@ -502,15 +498,14 @@ static void saction_main_region_message_subscribe(const struct bContext *C, } /* Now run the general "channels region" one - since channels and main should be in sync */ - saction_channel_region_message_subscribe(C, workspace, scene, screen, area, region, mbus); + saction_channel_region_message_subscribe(params); } /* editor level listener */ -static void action_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void action_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -660,12 +655,11 @@ static void action_listener(wmWindow *UNUSED(win), } } -static void action_header_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_header_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceAction *saction = (SpaceAction *)area->spacedata.first; /* context changes */ @@ -737,12 +731,11 @@ static void action_buttons_area_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void action_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void action_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 10fa2c19919..817760615df 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -70,16 +70,13 @@ #include "io_ops.h" -/* only call once on startup, storage is global in BKE kernel listbase */ +/* Only called once on startup. storage is global in BKE kernel listbase. */ void ED_spacetypes_init(void) { - const ListBase *spacetypes; - SpaceType *type; - - /* UI_UNIT_X is now a variable, is used in some spacetype inits? */ + /* UI unit is a variable, may be used in some space type inits. */ U.widget_unit = 20; - /* create space types */ + /* Create space types. */ ED_spacetype_outliner(); ED_spacetype_view3d(); ED_spacetype_ipo(); @@ -98,9 +95,8 @@ void ED_spacetypes_init(void) ED_spacetype_clip(); ED_spacetype_statusbar(); ED_spacetype_topbar(); - // ... - /* register operator types for screen and all spaces */ + /* Register operator types for screen and all spaces. */ ED_operatortypes_userpref(); ED_operatortypes_workspace(); ED_operatortypes_scene(); @@ -132,7 +128,7 @@ void ED_spacetypes_init(void) ED_screen_user_menu_register(); - /* gizmo types */ + /* Gizmo types. */ ED_gizmotypes_button_2d(); ED_gizmotypes_dial_3d(); ED_gizmotypes_move_3d(); @@ -144,10 +140,10 @@ void ED_spacetypes_init(void) ED_gizmotypes_cage_3d(); ED_gizmotypes_snap_3d(); - /* register types for operators and gizmos */ - spacetypes = BKE_spacetypes_list(); - for (type = spacetypes->first; type; type = type->next) { - /* init gizmo types first, operator-types need them */ + /* Register types for operators and gizmos. */ + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { + /* Initialize gizmo types first, operator types need them. */ if (type->gizmos) { type->gizmos(); } @@ -159,11 +155,8 @@ void ED_spacetypes_init(void) void ED_spacemacros_init(void) { - const ListBase *spacetypes; - SpaceType *type; - - /* Macros's must go last since they reference other operators. - * We need to have them go after python operators too */ + /* Macros must go last since they reference other operators. + * They need to be registered after python operators too. */ ED_operatormacros_armature(); ED_operatormacros_mesh(); ED_operatormacros_uvedit(); @@ -180,24 +173,21 @@ void ED_spacemacros_init(void) ED_operatormacros_paint(); ED_operatormacros_gpencil(); - /* register dropboxes (can use macros) */ - spacetypes = BKE_spacetypes_list(); - for (type = spacetypes->first; type; type = type->next) { + /* Register dropboxes (can use macros). */ + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { if (type->dropboxes) { type->dropboxes(); } } } -/* called in wm.c */ -/* keymap definitions are registered only once per WM initialize, usually on file read, - * using the keymap the actual areas/regions add the handlers */ +/** + * \note Keymap definitions are registered only once per WM initialize, + * usually on file read, using the keymap the actual areas/regions add the handlers. + * \note Called in wm.c. */ void ED_spacetypes_keymap(wmKeyConfig *keyconf) { - const ListBase *spacetypes; - SpaceType *stype; - ARegionType *atype; - ED_keymap_screen(keyconf); ED_keymap_anim(keyconf); ED_keymap_animchannels(keyconf); @@ -219,20 +209,20 @@ void ED_spacetypes_keymap(wmKeyConfig *keyconf) ED_keymap_transform(keyconf); - spacetypes = BKE_spacetypes_list(); - for (stype = spacetypes->first; stype; stype = stype->next) { - if (stype->keymap) { - stype->keymap(keyconf); + const ListBase *spacetypes = BKE_spacetypes_list(); + LISTBASE_FOREACH (const SpaceType *, type, spacetypes) { + if (type->keymap) { + type->keymap(keyconf); } - for (atype = stype->regiontypes.first; atype; atype = atype->next) { - if (atype->keymap) { - atype->keymap(keyconf); + LISTBASE_FOREACH (ARegionType *, region_type, &type->regiontypes) { + if (region_type->keymap) { + region_type->keymap(keyconf); } } } } -/* ********************** custom drawcall api ***************** */ +/* ********************** Custom Draw Call API ***************** */ typedef struct RegionDrawCB { struct RegionDrawCB *next, *prev; @@ -261,9 +251,7 @@ void *ED_region_draw_cb_activate(ARegionType *art, void ED_region_draw_cb_exit(ARegionType *art, void *handle) { - RegionDrawCB *rdc; - - for (rdc = art->drawcalls.first; rdc; rdc = rdc->next) { + LISTBASE_FOREACH (RegionDrawCB *, rdc, &art->drawcalls) { if (rdc == (RegionDrawCB *)handle) { BLI_remlink(&art->drawcalls, rdc); MEM_freeN(rdc); @@ -274,9 +262,7 @@ void ED_region_draw_cb_exit(ARegionType *art, void *handle) void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type) { - RegionDrawCB *rdc; - - for (rdc = region->type->drawcalls.first; rdc; rdc = rdc->next) { + LISTBASE_FOREACH (RegionDrawCB *, rdc, ®ion->type->drawcalls) { if (rdc->type == type) { rdc->draw(C, region, rdc->customdata); @@ -301,7 +287,7 @@ static void xxx_free(SpaceLink *UNUSED(sl)) { } -/* spacetype; init callback for usage, should be redoable */ +/* spacetype; init callback for usage, should be re-doable. */ static void xxx_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) { diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index e2b889bece1..5f347451c4a 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -33,8 +33,6 @@ #include "DNA_armature_types.h" #include "DNA_brush_types.h" -#include "DNA_collection_types.h" -#include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" @@ -53,7 +51,6 @@ #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_screen.h" -#include "BKE_texture.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 6f743eb1a6b..4847e8738df 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -52,10 +52,7 @@ #include "BKE_node.h" #include "BKE_paint.h" #include "BKE_particle.h" -#include "BKE_scene.h" -#include "BKE_workspace.h" #ifdef WITH_FREESTYLE -# include "BKE_freestyle.h" #endif #include "RNA_access.h" diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index e50ca2ec92b..07bc1d42c3f 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -514,12 +514,11 @@ static void buttons_main_region_layout(const bContext *C, ARegion *region) sbuts->mainbo = sbuts->mainb; } -static void buttons_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void buttons_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -567,15 +566,13 @@ static void buttons_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void buttons_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *area, - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceProperties *sbuts = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -621,14 +618,12 @@ static void buttons_navigation_bar_region_draw(const bContext *C, ARegion *regio ED_region_panels_draw(C, region); } -static void buttons_navigation_bar_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void buttons_navigation_bar_region_message_subscribe( + const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -657,11 +652,10 @@ static void buttons_area_redraw(ScrArea *area, short buttons) * \{ */ /* reused! */ -static void buttons_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void buttons_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceProperties *sbuts = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 81bae26efeb..632f3c5147f 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -46,7 +46,6 @@ #include "DEG_depsgraph.h" #include "ED_clip.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index bd11a746e11..af1d082d317 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -327,118 +327,18 @@ void ED_clip_update_frame(const Main *mainp, int cfra) } } -static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2]) +bool ED_clip_view_selection(const bContext *C, ARegion *UNUSED(region), bool fit) { - MovieClip *clip = ED_space_clip_get_clip(sc); - MovieTrackingTrack *track; - int width, height; - bool ok = false; - ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - int framenr = ED_space_clip_get_clip_frame_number(sc); - - INIT_MINMAX2(min, max); - - ED_space_clip_get_size(sc, &width, &height); - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track)) { - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - - if (marker) { - float pos[3]; - - pos[0] = marker->pos[0] + track->offset[0]; - pos[1] = marker->pos[1] + track->offset[1]; - pos[2] = 0.0f; - - /* undistortion happens for normalized coords */ - if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { - /* undistortion happens for normalized coords */ - ED_clip_point_undistorted_pos(sc, pos, pos); - } - - pos[0] *= width; - pos[1] *= height; - - mul_v3_m4v3(pos, sc->stabmat, pos); - - minmax_v2v2_v2(min, max, pos); - - ok = true; - } - } - - track = track->next; - } - - return ok; -} - -static bool selected_boundbox(const bContext *C, float min[2], float max[2]) -{ - SpaceClip *sc = CTX_wm_space_clip(C); - if (sc->mode == SC_MODE_TRACKING) { - return selected_tracking_boundbox(sc, min, max); - } - - if (ED_mask_selected_minmax(C, min, max)) { - MovieClip *clip = ED_space_clip_get_clip(sc); - int width, height; - ED_space_clip_get_size(sc, &width, &height); - BKE_mask_coord_to_movieclip(clip, &sc->user, min, min); - BKE_mask_coord_to_movieclip(clip, &sc->user, max, max); - min[0] *= width; - min[1] *= height; - max[0] *= width; - max[1] *= height; - return true; - } - return false; -} - -bool ED_clip_view_selection(const bContext *C, ARegion *region, bool fit) -{ - SpaceClip *sc = CTX_wm_space_clip(C); - int w, h, frame_width, frame_height; - float min[2], max[2]; - - ED_space_clip_get_size(sc, &frame_width, &frame_height); - - if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) { + float offset_x, offset_y; + float zoom; + if (!clip_view_calculate_view_selection(C, fit, &offset_x, &offset_y, &zoom)) { return false; } - if (!selected_boundbox(C, min, max)) { - return false; - } - - /* center view */ - clip_view_center_to_point( - sc, (max[0] + min[0]) / (2 * frame_width), (max[1] + min[1]) / (2 * frame_height)); - - w = max[0] - min[0]; - h = max[1] - min[1]; - - /* set zoom to see all selection */ - if (w > 0 && h > 0) { - int width, height; - float zoomx, zoomy, newzoom, aspx, aspy; - - ED_space_clip_get_aspect(sc, &aspx, &aspy); - - width = BLI_rcti_size_x(®ion->winrct) + 1; - height = BLI_rcti_size_y(®ion->winrct) + 1; - - zoomx = (float)width / w / aspx; - zoomy = (float)height / h / aspy; - - newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); - - if (fit || sc->zoom > newzoom) { - sc->zoom = newzoom; - } - } + SpaceClip *sc = CTX_wm_space_clip(C); + sc->xof = offset_x; + sc->yof = offset_y; + sc->zoom = zoom; return true; } @@ -1177,3 +1077,47 @@ void clip_start_prefetch_job(const bContext *C) /* and finally start the job */ WM_jobs_start(CTX_wm_manager(C), wm_job); } + +void ED_clip_view_lock_state_store(const bContext *C, ClipViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + BLI_assert(space_clip != NULL); + + state->offset_x = space_clip->xof; + state->offset_y = space_clip->yof; + state->zoom = space_clip->zoom; + + state->lock_offset_x = 0.0f; + state->lock_offset_y = 0.0f; + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return; + } + + if (!clip_view_calculate_view_selection( + C, false, &state->offset_x, &state->offset_y, &state->zoom)) { + return; + } + + state->lock_offset_x = space_clip->xlockof; + state->lock_offset_y = space_clip->ylockof; +} + +void ED_clip_view_lock_state_restore_no_jump(const bContext *C, const ClipViewLockState *state) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + BLI_assert(space_clip != NULL); + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return; + } + + float offset_x, offset_y; + float zoom; + if (!clip_view_calculate_view_selection(C, false, &offset_x, &offset_y, &zoom)) { + return; + } + + space_clip->xlockof = state->offset_x + state->lock_offset_x - offset_x; + space_clip->ylockof = state->offset_y + state->lock_offset_y - offset_y; +} diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 4848ec72f79..202dc00e365 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -171,8 +171,15 @@ void clip_delete_plane_track(struct bContext *C, struct MovieClip *clip, struct MovieTrackingPlaneTrack *plane_track); +void clip_view_offset_for_center_to_point( + SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y); void clip_view_center_to_point(SpaceClip *sc, float x, float y); +bool clip_view_calculate_view_selection( + const struct bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom); + +bool clip_view_has_locked_selection(const struct bContext *C); + void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); /* tracking_ops.c */ @@ -191,6 +198,7 @@ void CLIP_OT_clear_solution(struct wmOperatorType *ot); void CLIP_OT_clear_track_path(struct wmOperatorType *ot); void CLIP_OT_join_tracks(struct wmOperatorType *ot); +void CLIP_OT_average_tracks(struct wmOperatorType *ot); void CLIP_OT_disable_markers(struct wmOperatorType *ot); void CLIP_OT_hide_tracks(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index cd4a1ffb526..38a05eef6e3 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -125,7 +125,7 @@ static void sclip_zoom_set(const bContext *C, dx = ((location[0] - 0.5f) * w - sc->xof) * (sc->zoom - oldzoom) / sc->zoom; dy = ((location[1] - 0.5f) * h - sc->yof) * (sc->zoom - oldzoom) / sc->zoom; - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { sc->xlockof += dx; sc->ylockof += dy; } @@ -396,7 +396,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) vpd->x = event->x; vpd->y = event->y; - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { vpd->vec = &sc->xlockof; } else { @@ -434,7 +434,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) RNA_float_get_array(op->ptr, "offset", offset); - if (sc->flag & SC_LOCK_SELECTION) { + if (clip_view_has_locked_selection(C)) { sc->xlockof += offset[0]; sc->ylockof += offset[1]; } @@ -569,7 +569,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL); } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vpd->timer_lastdraw = PIL_check_seconds_timer(); @@ -662,7 +662,7 @@ static void view_zoom_apply( delta = -delta; } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { SpaceClip *sclip = CTX_wm_space_clip(C); double time = PIL_check_seconds_timer(); float time_step = (float)(time - vpd->timer_lastdraw); @@ -1840,8 +1840,16 @@ void CLIP_OT_cursor_set(wmOperatorType *ot) static int lock_selection_togglee_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceClip *space_clip = CTX_wm_space_clip(C); + + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + space_clip->flag ^= SC_LOCK_SELECTION; + + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL); + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index b02f3fe16f6..da9e82043f0 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -23,29 +23,17 @@ #include <string.h> -#include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" - #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" #include "BKE_screen.h" -#include "RNA_access.h" - -#include "WM_api.h" #include "WM_types.h" #include "ED_screen.h" -#include "ED_undo.h" - -#include "UI_interface.h" -#include "UI_resources.h" #include "clip_intern.h" /* own include */ diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index c7f2a027ba8..bb79eb34129 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -27,10 +27,12 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_rect.h" #include "BLI_utildefines.h" #include "BKE_animsys.h" #include "BKE_context.h" +#include "BKE_mask.h" #include "BKE_movieclip.h" #include "BKE_tracking.h" @@ -44,6 +46,7 @@ #include "WM_types.h" #include "ED_clip.h" +#include "ED_mask.h" #include "ED_screen.h" #include "UI_interface.h" @@ -395,16 +398,232 @@ void clip_delete_plane_track(bContext *C, MovieClip *clip, MovieTrackingPlaneTra DEG_id_tag_update(&clip->id, 0); } -void clip_view_center_to_point(SpaceClip *sc, float x, float y) +/* Calculate space clip offset to be centered at the given point. */ +void clip_view_offset_for_center_to_point( + SpaceClip *sc, const float x, const float y, float *r_offset_x, float *r_offset_y) { int width, height; + ED_space_clip_get_size(sc, &width, &height); + float aspx, aspy; + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + *r_offset_x = (x - 0.5f) * width * aspx; + *r_offset_y = (y - 0.5f) * height * aspy; +} + +void clip_view_center_to_point(SpaceClip *sc, float x, float y) +{ + clip_view_offset_for_center_to_point(sc, x, y, &sc->xof, &sc->yof); +} + +static bool selected_tracking_boundbox(SpaceClip *sc, float min[2], float max[2]) +{ + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTrackingTrack *track; + int width, height; + bool ok = false; + ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + int framenr = ED_space_clip_get_clip_frame_number(sc); + + INIT_MINMAX2(min, max); ED_space_clip_get_size(sc, &width, &height); - ED_space_clip_get_aspect(sc, &aspx, &aspy); - sc->xof = (x - 0.5f) * width * aspx; - sc->yof = (y - 0.5f) * height * aspy; + track = tracksbase->first; + while (track) { + if (TRACK_VIEW_SELECTED(sc, track)) { + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + + if (marker) { + float pos[3]; + + pos[0] = marker->pos[0] + track->offset[0]; + pos[1] = marker->pos[1] + track->offset[1]; + pos[2] = 0.0f; + + /* undistortion happens for normalized coords */ + if (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT) { + /* undistortion happens for normalized coords */ + ED_clip_point_undistorted_pos(sc, pos, pos); + } + + pos[0] *= width; + pos[1] *= height; + + mul_v3_m4v3(pos, sc->stabmat, pos); + + minmax_v2v2_v2(min, max, pos); + + ok = true; + } + } + + track = track->next; + } + + return ok; +} + +static bool tracking_has_selection(SpaceClip *space_clip) +{ + MovieClip *clip = ED_space_clip_get_clip(space_clip); + ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + const int framenr = ED_space_clip_get_clip_frame_number(space_clip); + + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + if (!TRACK_VIEW_SELECTED(space_clip, track)) { + continue; + } + const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + if (marker != NULL) { + return true; + } + } + + return false; +} + +static bool mask_has_selection(const bContext *C) +{ + Mask *mask = CTX_data_edit_mask(C); + if (mask == NULL) { + return false; + } + + LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { + if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + continue; + } + LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { + for (int i = 0; i < spline->tot_point; i++) { + const MaskSplinePoint *point = &spline->points[i]; + const BezTriple *bezt = &point->bezt; + if (!MASKPOINT_ISSEL_ANY(point)) { + continue; + } + if (bezt->f2 & SELECT) { + return true; + } + + if (BKE_mask_point_handles_mode_get(point) == MASK_HANDLE_MODE_STICK) { + return true; + } + else { + if ((bezt->f1 & SELECT) && (bezt->h1 != HD_VECT)) { + return true; + } + if ((bezt->f3 & SELECT) && (bezt->h2 != HD_VECT)) { + return true; + } + } + } + } + } + + return false; +} + +static bool selected_boundbox(const bContext *C, + float min[2], + float max[2], + bool handles_as_control_point) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + if (sc->mode == SC_MODE_TRACKING) { + return selected_tracking_boundbox(sc, min, max); + } + + if (ED_mask_selected_minmax(C, min, max, handles_as_control_point)) { + MovieClip *clip = ED_space_clip_get_clip(sc); + int width, height; + ED_space_clip_get_size(sc, &width, &height); + BKE_mask_coord_to_movieclip(clip, &sc->user, min, min); + BKE_mask_coord_to_movieclip(clip, &sc->user, max, max); + min[0] *= width; + min[1] *= height; + max[0] *= width; + max[1] *= height; + return true; + } + return false; +} + +bool clip_view_calculate_view_selection( + const bContext *C, bool fit, float *r_offset_x, float *r_offset_y, float *r_zoom) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + int frame_width, frame_height; + ED_space_clip_get_size(sc, &frame_width, &frame_height); + + if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) { + return false; + } + + /* NOTE: The `fit` argument is set to truth when doing "View to Selected" operator, and it set to + * false when this function is used for Lock-to-Selection functionality. When locking to + * selection the handles are to use control point position. So we can derive the + * `handles_as_control_point` from `fit`. + * + * TODO(sergey): Make such decision more explicit. Maybe pass use-case for the calculation to + * tell operator from lock-to-selection apart. */ + float min[2], max[2]; + if (!selected_boundbox(C, min, max, !fit)) { + return false; + } + + /* center view */ + clip_view_offset_for_center_to_point(sc, + (max[0] + min[0]) / (2 * frame_width), + (max[1] + min[1]) / (2 * frame_height), + r_offset_x, + r_offset_y); + + const int w = max[0] - min[0]; + const int h = max[1] - min[1]; + + /* set zoom to see all selection */ + *r_zoom = sc->zoom; + if (w > 0 && h > 0) { + ARegion *region = CTX_wm_region(C); + + int width, height; + float zoomx, zoomy, newzoom, aspx, aspy; + + ED_space_clip_get_aspect(sc, &aspx, &aspy); + + width = BLI_rcti_size_x(®ion->winrct) + 1; + height = BLI_rcti_size_y(®ion->winrct) + 1; + + zoomx = (float)width / w / aspx; + zoomy = (float)height / h / aspy; + + newzoom = 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)); + + if (fit) { + *r_zoom = newzoom; + } + } + + return true; +} + +/* Returns truth if lock-to-selection is enabled and possible. + * Locking to selection is not possible if there is no selection. */ +bool clip_view_has_locked_selection(const bContext *C) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + + if ((space_clip->flag & SC_LOCK_SELECTION) == 0) { + return false; + } + + if (space_clip->mode == SC_MODE_TRACKING) { + return tracking_has_selection(space_clip); + } + + return mask_has_selection(C); } void clip_draw_sfra_efra(View2D *v2d, Scene *scene) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 3bdf016b64c..2a7c64a83f7 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -47,15 +47,12 @@ #include "ED_clip.h" #include "ED_mask.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_space_api.h" #include "ED_time_scrub_ui.h" -#include "ED_transform.h" #include "ED_uvedit.h" /* just for ED_image_draw_cursor */ #include "IMB_imbuf.h" -#include "GPU_framebuffer.h" #include "GPU_matrix.h" #include "WM_api.h" @@ -229,7 +226,7 @@ static void clip_scopes_check_gpencil_change(ScrArea *area) } } -static void clip_area_sync_frame_from_scene(ScrArea *area, Scene *scene) +static void clip_area_sync_frame_from_scene(ScrArea *area, const Scene *scene) { SpaceClip *space_clip = (SpaceClip *)area->spacedata.first; BKE_movieclip_user_set_frame(&space_clip->user, scene->r.cfra); @@ -334,8 +331,12 @@ static SpaceLink *clip_duplicate(SpaceLink *sl) return (SpaceLink *)scn; } -static void clip_listener(wmWindow *UNUSED(win), ScrArea *area, wmNotifier *wmn, Scene *scene) +static void clip_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -514,6 +515,7 @@ static void clip_operatortypes(void) /* clean-up */ WM_operatortype_append(CLIP_OT_clear_track_path); WM_operatortype_append(CLIP_OT_join_tracks); + WM_operatortype_append(CLIP_OT_average_tracks); WM_operatortype_append(CLIP_OT_track_copy_color); WM_operatortype_append(CLIP_OT_clean_tracks); @@ -988,7 +990,14 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) } /* callback */ + /* TODO(sergey): For being consistent with space image the projection needs to be configured + * the way how the commented out code does it. This works correct for tracking data, but it + * causes wrong aspect correction for mask editor (see T84990). */ + // GPU_matrix_push_projection(); + // wmOrtho2(region->v2d.cur.xmin, region->v2d.cur.xmax, region->v2d.cur.ymin, + // region->v2d.cur.ymax); ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); + // GPU_matrix_pop_projection(); /* reset view matrix */ UI_view2d_view_restore(C); @@ -1001,12 +1010,11 @@ static void clip_main_region_draw(const bContext *C, ARegion *region) WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); } -static void clip_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -1137,11 +1145,7 @@ static void clip_preview_region_draw(const bContext *C, ARegion *region) } } -static void clip_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_preview_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1182,11 +1186,7 @@ static void clip_channels_region_draw(const bContext *C, ARegion *region) UI_view2d_view_restore(C); } -static void clip_channels_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void clip_channels_region_listener(const wmRegionListenerParams *UNUSED(params)) { } @@ -1203,12 +1203,11 @@ static void clip_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void clip_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1246,12 +1245,11 @@ static void clip_tools_region_draw(const bContext *C, ARegion *region) /****************** tool properties region ******************/ -static void clip_props_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_props_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -1299,12 +1297,11 @@ static void clip_properties_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void clip_properties_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void clip_properties_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 49313005c43..a903aeed380 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -88,17 +88,16 @@ static int add_marker_exec(bContext *C, wmOperator *op) MovieClip *clip = ED_space_clip_get_clip(sc); float pos[2]; + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + RNA_float_get_array(op->ptr, "location", pos); if (!add_marker(C, pos[0], pos[1])) { return OPERATOR_CANCELLED; } - /* Reset offset from locked position, so frame jumping wouldn't be so - * confusing. - */ - sc->xlockof = 0; - sc->ylockof = 0; + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); @@ -244,8 +243,6 @@ static int delete_track_exec(bContext *C, wmOperator *UNUSED(op)) changed = true; } } - /* Nothing selected now, unlock view so it can be scrolled nice again. */ - sc->flag &= ~SC_LOCK_SELECTION; if (changed) { WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); } @@ -314,11 +311,6 @@ static int delete_marker_exec(bContext *C, wmOperator *UNUSED(op)) } } - if (!has_selection) { - /* Nothing selected now, unlock view so it can be scrolled nice again. */ - sc->flag &= ~SC_LOCK_SELECTION; - } - if (!changed) { return OPERATOR_CANCELLED; } @@ -1225,13 +1217,6 @@ static int hide_tracks_exec(bContext *C, wmOperator *op) clip->tracking.act_plane_track = NULL; } - if (unselected == 0) { - /* No selection on screen now, unlock view so it can be - * scrolled nice again. - */ - sc->flag &= ~SC_LOCK_SELECTION; - } - BKE_tracking_dopesheet_tag_update(tracking); WM_event_add_notifier(C, NC_MOVIECLIP | ND_DISPLAY, NULL); @@ -1490,6 +1475,97 @@ void CLIP_OT_join_tracks(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/********************** Average tracks operator *********************/ + +static int average_tracks_exec(bContext *C, wmOperator *op) +{ + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + /* Collect source tracks. */ + int num_source_tracks; + MovieTrackingTrack **source_tracks = BKE_tracking_selected_tracks_in_active_object( + tracking, &num_source_tracks); + if (num_source_tracks == 0) { + return OPERATOR_CANCELLED; + } + + /* Create new empty track, which will be the averaged result. + * Makes it simple to average all selection to it. */ + ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking); + MovieTrackingTrack *result_track = BKE_tracking_track_add_empty(tracking, tracks_list); + + /* Perform averaging. */ + BKE_tracking_tracks_average(result_track, source_tracks, num_source_tracks); + + const bool keep_original = RNA_boolean_get(op->ptr, "keep_original"); + if (!keep_original) { + for (int i = 0; i < num_source_tracks; i++) { + clip_delete_track(C, clip, source_tracks[i]); + } + } + + /* Update selection, making the result track active and selected. */ + /* TODO(sergey): Should become some sort of utility function available for all operators. */ + + BKE_tracking_track_select(tracks_list, result_track, TRACK_AREA_ALL, 0); + ListBase *plane_tracks_list = BKE_tracking_get_active_plane_tracks(tracking); + BKE_tracking_plane_tracks_deselect_all(plane_tracks_list); + + clip->tracking.act_track = result_track; + clip->tracking.act_plane_track = NULL; + + /* Inform the dependency graph and interface about changes. */ + DEG_id_tag_update(&clip->id, 0); + WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, clip); + + /* Free memory. */ + MEM_freeN(source_tracks); + + return OPERATOR_FINISHED; +} + +static int average_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + PropertyRNA *prop_keep_original = RNA_struct_find_property(op->ptr, "keep_original"); + if (!RNA_property_is_set(op->ptr, prop_keep_original)) { + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + MovieTracking *tracking = &clip->tracking; + + const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking); + + if (num_selected_tracks == 1) { + RNA_property_boolean_set(op->ptr, prop_keep_original, false); + } + } + + return average_tracks_exec(C, op); +} + +void CLIP_OT_average_tracks(wmOperatorType *ot) +{ + /* Identifiers. */ + ot->name = "Average Tracks"; + ot->description = "Average selected tracks into active"; + ot->idname = "CLIP_OT_average_tracks"; + + /* API callbacks. */ + ot->exec = average_tracks_exec; + ot->invoke = average_tracks_invoke; + ot->poll = ED_space_clip_tracking_poll; + + /* Flags. */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Properties. */ + PropertyRNA *prop; + + prop = RNA_def_boolean(ot->srna, "keep_original", 1, "Keep Original", "Keep original tracks"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); +} + /********************** lock tracks operator *********************/ enum { diff --git a/source/blender/editors/space_clip/tracking_ops_detect.c b/source/blender/editors/space_clip/tracking_ops_detect.c index 54ec439471d..86ee94df731 100644 --- a/source/blender/editors/space_clip/tracking_ops_detect.c +++ b/source/blender/editors/space_clip/tracking_ops_detect.c @@ -21,14 +21,10 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_gpencil_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "BKE_movieclip.h" #include "BKE_report.h" diff --git a/source/blender/editors/space_clip/tracking_ops_stabilize.c b/source/blender/editors/space_clip/tracking_ops_stabilize.c index 5e43b7c7ec6..d0b4d18c6d9 100644 --- a/source/blender/editors/space_clip/tracking_ops_stabilize.c +++ b/source/blender/editors/space_clip/tracking_ops_stabilize.c @@ -21,8 +21,6 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_screen_types.h" #include "DNA_space_types.h" diff --git a/source/blender/editors/space_clip/tracking_ops_track.c b/source/blender/editors/space_clip/tracking_ops_track.c index 585b13b426e..e480ec2db05 100644 --- a/source/blender/editors/space_clip/tracking_ops_track.c +++ b/source/blender/editors/space_clip/tracking_ops_track.c @@ -30,7 +30,6 @@ #include "BKE_global.h" #include "BKE_main.h" #include "BKE_movieclip.h" -#include "BKE_report.h" #include "BKE_tracking.h" #include "WM_api.h" diff --git a/source/blender/editors/space_clip/tracking_ops_utils.c b/source/blender/editors/space_clip/tracking_ops_utils.c index 1f959e94309..0f6bd6e039a 100644 --- a/source/blender/editors/space_clip/tracking_ops_utils.c +++ b/source/blender/editors/space_clip/tracking_ops_utils.c @@ -21,12 +21,8 @@ * \ingroup spclip */ -#include "MEM_guardedalloc.h" - #include "DNA_space_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "BKE_tracking.h" diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 063ea9592aa..558c0bec11d 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -304,6 +304,9 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const track = find_nearest_track(sc, tracksbase, co, &distance_to_track); plane_track = find_nearest_plane_track(sc, plane_tracks_base, co, &distance_to_plane_track); + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + /* Do not select beyond some reasonable distance, that is useless and * prevents the 'deselect on nothing' behavior. */ if (distance_to_track > 0.05f) { @@ -377,10 +380,7 @@ static int mouse_select(bContext *C, const float co[2], const bool extend, const ED_mask_deselect_all(C); } - if (!extend) { - sc->xlockof = 0.0f; - sc->ylockof = 0.0f; - } + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); BKE_tracking_dopesheet_tag_update(tracking); @@ -867,14 +867,16 @@ static int select_all_exec(bContext *C, wmOperator *op) MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; - int action = RNA_enum_get(op->ptr, "action"); + const int action = RNA_enum_get(op->ptr, "action"); - bool has_selection = false; + ClipViewLockState lock_state; + ED_clip_view_lock_state_store(C, &lock_state); + bool has_selection = false; ED_clip_select_all(sc, action, &has_selection); - if (!has_selection) { - sc->flag &= ~SC_LOCK_SELECTION; + if (has_selection) { + ED_clip_view_lock_state_restore_no_jump(C, &lock_state); } BKE_tracking_dopesheet_tag_update(tracking); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 77f1111624d..05595e0b393 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -18,7 +18,7 @@ * \ingroup spconsole */ -#include <ctype.h> /* ispunct */ +#include <ctype.h> /* #ispunct */ #include <stdlib.h> #include <string.h> #include <sys/stat.h> @@ -749,7 +749,7 @@ static int console_clear_exec(bContext *C, wmOperator *op) /*ConsoleLine *ci = */ console_history_verify(C); - if (scrollback) { /* last item in mistory */ + if (scrollback) { /* Last item in history. */ while (sc->scrollback.first) { console_scrollback_free(sc, sc->scrollback.first); } diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 9b8e9e0e871..b24579d9871 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -41,7 +41,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "console_intern.h" /* own include */ /* ******************** default callbacks for console space ***************** */ @@ -216,7 +215,7 @@ static void console_main_region_draw(const bContext *C, ARegion *region) /* clear and setup matrix */ UI_ThemeClearColor(TH_BACK); - /* worlks best with no view2d matrix set */ + /* Works best with no view2d matrix set. */ UI_view2d_view_ortho(v2d); /* data... */ @@ -273,13 +272,11 @@ static void console_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void console_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void console_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 8e9093151ba..c1dcf2e56d3 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -131,7 +131,15 @@ static void draw_tile(int sx, int sy, int width, int height, int colorid, int sh UI_GetThemeColorShade4fv(colorid, shade, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox_aa( - true, (float)sx, (float)(sy - height), (float)(sx + width), (float)sy, 5.0f, color); + &(const rctf){ + .xmin = (float)sx, + .xmax = (float)(sx + width), + .ymin = (float)(sy - height), + .ymax = (float)sy, + }, + true, + 5.0f, + color); } static void file_draw_icon(uiBlock *block, @@ -465,7 +473,7 @@ static void file_draw_preview(uiBlock *block, but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL); - /* dragregion */ + /* Drag-region. */ if (drag) { ID *id; @@ -546,7 +554,7 @@ static void draw_background(FileLayout *layout, View2D *v2d) for (i = 2; (i <= layout->rows + 1); i += 2) { sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y; - /* Offsett pattern slightly to add scroll effect. */ + /* Offset pattern slightly to add scroll effect. */ sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height); immRectf(pos, diff --git a/source/blender/editors/space_file/file_utils.c b/source/blender/editors/space_file/file_utils.c index 9d85996c559..186bc04fafe 100644 --- a/source/blender/editors/space_file/file_utils.c +++ b/source/blender/editors/space_file/file_utils.c @@ -19,7 +19,6 @@ */ #include "BLI_fileops.h" -#include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index d66219c7549..33c37875372 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -276,6 +276,7 @@ typedef struct FileListInternEntry { char *redirection_path; /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ char *name; + bool free_name; /** * This is data from the current main, represented by this file. It's crucial that this is @@ -1366,7 +1367,7 @@ static bool filelist_checkdir_main_assets(struct FileList *UNUSED(filelist), static void filelist_entry_clear(FileDirEntry *entry) { - if (entry->name) { + if (entry->name && ((entry->flags & FILE_ENTRY_NAME_FREE) != 0)) { MEM_freeN(entry->name); } if (entry->description) { @@ -1451,7 +1452,7 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) if (entry->redirection_path) { MEM_freeN(entry->redirection_path); } - if (entry->name) { + if (entry->name && entry->free_name) { MEM_freeN(entry->name); } /* If we own the asset-data (it was generated from external file data), free it. */ @@ -1953,7 +1954,13 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->entry = rev; ret->relpath = BLI_strdup(entry->relpath); - ret->name = BLI_strdup(entry->name); + if (entry->free_name) { + ret->name = BLI_strdup(entry->name); + ret->flags |= FILE_ENTRY_NAME_FREE; + } + else { + ret->name = entry->name; + } ret->description = BLI_strdupcat(filelist->filelist.root, entry->relpath); memcpy(ret->uuid, entry->uuid, sizeof(ret->uuid)); ret->blentype = entry->blentype; @@ -3175,6 +3182,7 @@ static void filelist_readjob_do(const bool do_lib, entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' * added by BLI_path_rel to rel_subdir. */ entry->name = BLI_strdup(fileentry_uiname(root, entry->relpath, entry->typeflag, dir)); + entry->free_name = true; /* Here we decide whether current filedirentry is to be listed too, or not. */ if (max_recursion && (is_lib || (recursion_level <= max_recursion))) { @@ -3288,7 +3296,8 @@ static void filelist_readjob_main_assets(Main *current_main, entry = MEM_callocN(sizeof(*entry), __func__); entry->relpath = BLI_strdup(id_code_name); - entry->name = BLI_strdup(id_iter->name + 2); + entry->name = id_iter->name + 2; + entry->free_name = false; entry->typeflag |= FILE_TYPE_BLENDERLIB | FILE_TYPE_ASSET; entry->blentype = GS(id_iter->name); *((uint32_t *)entry->uuid) = atomic_add_and_fetch_uint32( diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 6b74b344375..6e5791cad52 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -460,7 +460,7 @@ bool ED_fileselect_is_asset_browser(const SpaceFile *sfile) void ED_fileselect_window_params_get(const wmWindow *win, int win_size[2], bool *is_maximized) { - /* Get DPI/pixelsize independent size to be stored in preferences. */ + /* Get DPI/pixel-size independent size to be stored in preferences. */ WM_window_set_dpi(win); /* Ensure the DPI is taken from the right window. */ win_size[0] = WM_window_pixels_x(win) / UI_DPI_FAC; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 7f33b0212d6..178ca264182 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -104,6 +104,7 @@ static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_pre BLI_insertlinkafter(&area->regionbase, region_prev, region); region->regiontype = RGN_TYPE_TOOL_PROPS; region->alignment = RGN_ALIGN_RIGHT; + region->flag = RGN_FLAG_HIDDEN; return region; } @@ -246,13 +247,13 @@ static void file_ensure_valid_region_state(bContext *C, BLI_assert(region_tools); if (sfile->browse_mode == FILE_BROWSE_MODE_ASSETS) { - ARegion *region_execute = file_execute_region_ensure(area, region_tools); - ARegion *region_props = file_tool_props_region_ensure(area, region_execute); - - /* Hide specific regions by default. */ - region_props->flag |= RGN_FLAG_HIDDEN; - region_execute->flag |= RGN_FLAG_HIDDEN; + file_tool_props_region_ensure(area, region_tools); + ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } ARegion *region_ui = BKE_area_find_region_type(area, RGN_TYPE_UI); if (region_ui) { ED_region_remove(C, area, region_ui); @@ -260,7 +261,7 @@ static void file_ensure_valid_region_state(bContext *C, } } /* If there's an file-operation, ensure we have the option and execute region */ - else if (sfile->op) { + else if (sfile->op && !BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS)) { ARegion *region_ui = file_ui_region_ensure(area, region_tools); ARegion *region_execute = file_execute_region_ensure(area, region_ui); ARegion *region_props = file_tool_props_region_ensure(area, region_execute); @@ -275,17 +276,18 @@ static void file_ensure_valid_region_state(bContext *C, needs_init = true; } /* If there's _no_ file-operation, ensure we _don't_ have the option and execute region */ - else { + else if (!sfile->op) { ARegion *region_props = BKE_area_find_region_type(area, RGN_TYPE_TOOL_PROPS); ARegion *region_execute = BKE_area_find_region_type(area, RGN_TYPE_EXECUTE); ARegion *region_ui = file_ui_region_ensure(area, region_tools); UNUSED_VARS(region_ui); + if (region_execute) { + ED_region_remove(C, area, region_execute); + needs_init = true; + } if (region_props) { - BLI_assert(region_execute); - ED_region_remove(C, area, region_props); - ED_region_remove(C, area, region_execute); needs_init = true; } } @@ -390,11 +392,10 @@ static void file_refresh(const bContext *C, ScrArea *area) ED_area_tag_redraw(area); } -static void file_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void file_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceFile *sfile = (SpaceFile *)area->spacedata.first; /* context changes */ @@ -445,12 +446,11 @@ static void file_main_region_init(wmWindowManager *wm, ARegion *region) WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); } -static void file_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: @@ -463,19 +463,24 @@ static void file_main_region_listener(wmWindow *UNUSED(win), break; } break; + case NC_ID: + if (ELEM(wmn->action, NA_RENAME)) { + /* In case the filelist shows ID names. */ + ED_region_tag_redraw(region); + } + break; } } -static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void file_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceFile *sfile = area->spacedata.first; - FileSelectParams *params = ED_fileselect_ensure_active_params(sfile); + + FileSelectParams *file_params = ED_fileselect_ensure_active_params(sfile); /* This is a bit odd that a region owns the subscriber for an area, * keep for now since all subscribers for WM are regions. * May be worth re-visiting later. */ @@ -497,7 +502,7 @@ static void file_main_region_message_subscribe(const struct bContext *UNUSED(C), /* FileSelectParams */ { PointerRNA ptr; - RNA_pointer_create(&screen->id, &RNA_FileSelectParams, params, &ptr); + RNA_pointer_create(&screen->id, &RNA_FileSelectParams, file_params, &ptr); /* All properties for this space type. */ WM_msg_subscribe_rna(mbus, &ptr, NULL, &msg_sub_value_area_tag_refresh, __func__); @@ -647,18 +652,23 @@ static void file_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void file_tools_region_listener(const wmRegionListenerParams *UNUSED(params)) { -#if 0 - /* context changes */ +} + +static void file_tool_props_region_listener(const wmRegionListenerParams *params) +{ + const wmNotifier *wmn = params->notifier; + ARegion *region = params->region; + switch (wmn->category) { - /* pass */ + case NC_ID: + if (ELEM(wmn->action, NA_RENAME)) { + /* In case the filelist shows ID names. */ + ED_region_tag_redraw(region); + } + break; } -#endif } /* add handlers, stuff you only do once or on area/region changes */ @@ -715,12 +725,11 @@ static void file_execution_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void file_ui_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void file_ui_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SPACE: @@ -928,7 +937,7 @@ void ED_spacetype_file(void) art->prefsizex = 240; art->prefsizey = 60; art->keymapflag = ED_KEYMAP_UI; - art->listener = file_tools_region_listener; + art->listener = file_tool_props_region_listener; art->init = file_tools_region_init; art->draw = file_tools_region_draw; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index fac38ef7b91..31f606e515d 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -178,7 +178,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode) x = (float)CFRA; } - /* Normalise units of cursor's value. */ + /* Normalize units of cursor's value. */ if (sipo) { y = (sipo->cursorVal / unit_scale) - offset; } @@ -2263,7 +2263,7 @@ static void snap_graph_keys(bAnimContext *ac, short mode) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); - /* Normalise cursor value (for normalised F-Curves display). */ + /* Normalize cursor value (for normalized F-Curves display). */ if (mode == GRAPHKEYS_SNAP_VALUE) { short mapping_flag = ANIM_get_normalization_flags(ac); float offset; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 63acc2a1774..32396a70cce 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -32,15 +32,11 @@ #include "BKE_context.h" #include "BKE_global.h" -#include "BKE_main.h" #include "UI_view2d.h" #include "ED_anim_api.h" -#include "ED_markers.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "graph_intern.h" diff --git a/source/blender/editors/space_graph/graph_slider_ops.c b/source/blender/editors/space_graph/graph_slider_ops.c index 4cda6b34a01..3e52dc7377b 100644 --- a/source/blender/editors/space_graph/graph_slider_ops.c +++ b/source/blender/editors/space_graph/graph_slider_ops.c @@ -380,7 +380,7 @@ static int graphkeys_decimate_modal(bContext *C, wmOperator *op, const wmEvent * break; } - /* Unhandled event - maybe it was some view manip? */ + /* Unhandled event - maybe it was some view manipulation? */ /* Allow to pass through. */ return OPERATOR_RUNNING_MODAL | OPERATOR_PASS_THROUGH; } @@ -505,15 +505,15 @@ void GRAPH_OT_decimate(wmOperatorType *ot) "Mode", "Which mode to use for decimation"); - RNA_def_float_percentage(ot->srna, - "remove_ratio", - 1.0f / 3.0f, - 0.0f, - 1.0f, - "Remove", - "The percentage of keyframes to remove", - 0.0f, - 1.0f); + RNA_def_float_factor(ot->srna, + "remove_ratio", + 1.0f / 3.0f, + 0.0f, + 1.0f, + "Remove", + "The ratio of remaining keyframes after the operation", + 0.0f, + 1.0f); RNA_def_float(ot->srna, "remove_error_margin", 0.0f, diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c index 8463c21b1ad..c37d9f42c12 100644 --- a/source/blender/editors/space_graph/graph_utils.c +++ b/source/blender/editors/space_graph/graph_utils.c @@ -38,8 +38,6 @@ #include "BKE_fcurve.h" #include "BKE_screen.h" -#include "WM_api.h" - #include "ED_anim_api.h" #include "ED_screen.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index 791039498e8..9f01773eadf 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -403,12 +403,11 @@ static void graph_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void graph_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void graph_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -470,14 +469,14 @@ static void graph_region_listener(wmWindow *UNUSED(win), } } -static void graph_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void graph_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceGraphEditor, area->spacedata.first, &ptr); @@ -546,11 +545,10 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C), } /* editor level listener */ -static void graph_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void graph_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceGraph *sipo = (SpaceGraph *)area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 63e5ae64a8c..67d5055ec65 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -466,7 +466,7 @@ static void sima_draw_zbuf_pixels( { const float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - /* Slowwww */ + /* Very slow! */ float *rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp"); for (int a = rectx * recty - 1; a >= 0; a--) { /* zbuffer values are signed, so we need to shift color range */ @@ -874,7 +874,7 @@ void draw_image_main(const bContext *C, ARegion *region) if (show_stereo3d) { if (show_multilayer) { - /* update multiindex and pass for the current eye */ + /* Update multi-index and pass for the current eye. */ BKE_image_multilayer_index(ima->rr, &sima->iuser); } else { diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index 100556ad29a..0044c6072a4 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -71,6 +71,7 @@ void IMAGE_OT_save_all_modified(struct wmOperatorType *ot); void IMAGE_OT_pack(struct wmOperatorType *ot); void IMAGE_OT_unpack(struct wmOperatorType *ot); +void IMAGE_OT_flip(struct wmOperatorType *ot); void IMAGE_OT_invert(struct wmOperatorType *ot); void IMAGE_OT_resize(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 86e52814d6f..4008ca228ac 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -36,9 +36,7 @@ #include "BLI_blenlib.h" #include "BLI_fileops.h" -#include "BLI_fileops_types.h" #include "BLI_ghash.h" -#include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -48,7 +46,6 @@ #include "DNA_camera_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" -#include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -62,14 +59,10 @@ #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_packedFile.h" -#include "BKE_paint.h" #include "BKE_report.h" -#include "BKE_scene.h" -#include "BKE_screen.h" #include "DEG_depsgraph.h" -#include "GPU_immediate.h" #include "GPU_state.h" #include "IMB_colormanagement.h" @@ -467,7 +460,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve UI_view2d_region_to_view( ®ion->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vpd->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vpd->timer_lastdraw = PIL_check_seconds_timer(); @@ -579,12 +572,10 @@ static void image_zoom_apply(ViewZoomData *vpd, delta = -delta; } - if (viewzoom == USER_ZOOM_CONT) { + if (viewzoom == USER_ZOOM_CONTINUE) { double time = PIL_check_seconds_timer(); float time_step = (float)(time - vpd->timer_lastdraw); float zfac; - - /* oldstyle zoom */ zfac = 1.0f + ((delta / 20.0f) * time_step); vpd->timer_lastdraw = time; /* this is the final zoom, but instead make it into a factor */ @@ -900,7 +891,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) } } else if (ED_space_image_check_show_maskedit(sima, obedit)) { - if (!ED_mask_selected_minmax(C, min, max)) { + if (!ED_mask_selected_minmax(C, min, max, false)) { return OPERATOR_CANCELLED; } } @@ -2663,6 +2654,126 @@ void IMAGE_OT_new(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Flip Operator + * \{ */ + +static int image_flip_exec(bContext *C, wmOperator *op) +{ + Image *ima = image_from_context(C); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + SpaceImage *sima = CTX_wm_space_image(C); + const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT)); + + if (ibuf == NULL) { + /* TODO: this should actually never happen, but does for render-results -> cleanup. */ + return OPERATOR_CANCELLED; + } + + const bool flip_horizontal = RNA_boolean_get(op->ptr, "use_flip_horizontal"); + const bool flip_vertical = RNA_boolean_get(op->ptr, "use_flip_vertical"); + + if (!flip_horizontal && !flip_vertical) { + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_FINISHED; + } + + ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser); + + if (is_paint) { + ED_imapaint_clear_partial_redraw(); + } + + const int size_x = ibuf->x; + const int size_y = ibuf->y; + + if (ibuf->rect_float) { + float *float_pixels = (float *)ibuf->rect_float; + + float *orig_float_pixels = MEM_dupallocN(float_pixels); + for (int x = 0; x < size_x; x++) { + for (int y = 0; y < size_y; y++) { + const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; + const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + + float *source_pixel = &orig_float_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + float *target_pixel = &float_pixels[4 * (x + y * size_x)]; + + copy_v4_v4(target_pixel, source_pixel); + } + } + MEM_freeN(orig_float_pixels); + + if (ibuf->rect) { + IMB_rect_from_float(ibuf); + } + } + else if (ibuf->rect) { + char *char_pixels = (char *)ibuf->rect; + char *orig_char_pixels = MEM_dupallocN(char_pixels); + for (int x = 0; x < size_x; x++) { + for (int y = 0; y < size_y; y++) { + const int source_pixel_x = flip_horizontal ? size_x - x - 1 : x; + const int source_pixel_y = flip_vertical ? size_y - y - 1 : y; + + char *source_pixel = &orig_char_pixels[4 * (source_pixel_x + source_pixel_y * size_x)]; + char *target_pixel = &char_pixels[4 * (x + y * size_x)]; + + copy_v4_v4_char(target_pixel, source_pixel); + } + } + MEM_freeN(orig_char_pixels); + } + else { + BKE_image_release_ibuf(ima, ibuf, NULL); + return OPERATOR_CANCELLED; + } + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + BKE_image_mark_dirty(ima, ibuf); + + if (ibuf->mipmap[0]) { + ibuf->userflags |= IB_MIPMAP_INVALID; + } + + ED_image_undo_push_end(); + + /* force GPU re-upload, all image is invalid. */ + BKE_image_free_gputextures(ima); + + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + + BKE_image_release_ibuf(ima, ibuf, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_flip(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Flip Image"; + ot->idname = "IMAGE_OT_flip"; + ot->description = "Flip the image"; + + /* api callbacks */ + ot->exec = image_flip_exec; + ot->poll = image_from_context_has_data_poll_no_image_user; + + /* properties */ + PropertyRNA *prop; + prop = RNA_def_boolean( + ot->srna, "use_flip_horizontal", false, "Horizontal", "Flip the image horizontally"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean( + ot->srna, "use_flip_vertical", false, "Vertical", "Flip the image vertically"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + /* flags */ + ot->flag = OPTYPE_REGISTER; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Invert Operators * \{ */ @@ -2747,7 +2858,7 @@ static int image_invert_exec(bContext *C, wmOperator *op) ED_image_undo_push_end(); - /* force GPU reupload, all image is invalid */ + /* Force GPU re-upload, all image is invalid. */ BKE_image_free_gputextures(ima); WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); @@ -2838,7 +2949,7 @@ static int image_scale_exec(bContext *C, wmOperator *op) ED_image_undo_push_end(); - /* force GPU reupload, all image is invalid */ + /* Force GPU re-upload, all image is invalid. */ BKE_image_free_gputextures(ima); DEG_id_tag_update(&ima->id, 0); diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c index 81f2ced7dee..02546e3e3b3 100644 --- a/source/blender/editors/space_image/image_sequence.c +++ b/source/blender/editors/space_image/image_sequence.c @@ -27,7 +27,6 @@ #include "BLI_fileops.h" #include "BLI_fileops_types.h" -#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_path_util.h" @@ -35,7 +34,6 @@ #include "BLI_utildefines.h" #include "DNA_image_types.h" -#include "DNA_space_types.h" #include "DNA_windowmanager_types.h" #include "RNA_access.h" @@ -45,8 +43,6 @@ #include "ED_image.h" -#include "WM_types.h" - typedef struct ImageFrame { struct ImageFrame *next, *prev; int framenr; diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 1d5725033e0..391c68f4231 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -947,13 +947,15 @@ static void image_undosys_step_decode_redo(ImageUndoStep *us) } static void image_undosys_step_decode( - struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool is_final) + struct bContext *C, struct Main *bmain, UndoStep *us_p, const eUndoStepDir dir, bool is_final) { + BLI_assert(dir != STEP_INVALID); + ImageUndoStep *us = (ImageUndoStep *)us_p; - if (dir < 0) { + if (dir == STEP_UNDO) { image_undosys_step_decode_undo(us, is_final); } - else { + else if (dir == STEP_REDO) { image_undosys_step_decode_redo(us); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 186f2d3a5a8..69976bc088c 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -24,8 +24,6 @@ #include "DNA_gpencil_types.h" #include "DNA_image_types.h" #include "DNA_mask_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -37,14 +35,9 @@ #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_editmesh.h" #include "BKE_image.h" -#include "BKE_layer.h" #include "BKE_lib_id.h" -#include "BKE_material.h" -#include "BKE_scene.h" #include "BKE_screen.h" -#include "BKE_workspace.h" #include "RNA_access.h" #include "RNA_define.h" @@ -56,7 +49,6 @@ #include "ED_image.h" #include "ED_mask.h" -#include "ED_mesh.h" #include "ED_node.h" #include "ED_render.h" #include "ED_screen.h" @@ -65,19 +57,13 @@ #include "ED_uvedit.h" #include "WM_api.h" -#include "WM_message.h" #include "WM_types.h" #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_batch_presets.h" -#include "GPU_framebuffer.h" -#include "GPU_viewport.h" - #include "DRW_engine.h" -#include "DRW_engine_types.h" #include "image_intern.h" @@ -234,6 +220,7 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_pack); WM_operatortype_append(IMAGE_OT_unpack); + WM_operatortype_append(IMAGE_OT_flip); WM_operatortype_append(IMAGE_OT_invert); WM_operatortype_append(IMAGE_OT_resize); @@ -320,8 +307,11 @@ static void image_refresh(const bContext *C, ScrArea *area) } } -static void image_listener(wmWindow *win, ScrArea *area, wmNotifier *wmn, Scene *UNUSED(scene)) +static void image_listener(const wmSpaceTypeListenerParams *params) { + wmWindow *win = params->window; + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceImage *sima = (SpaceImage *)area->spacedata.first; /* context changes */ @@ -728,12 +718,12 @@ static void image_main_region_draw(const bContext *C, ARegion *region) draw_image_cache(C, region); } -static void image_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GEOM: @@ -843,12 +833,11 @@ static void image_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels_draw(C, region); } -static void image_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_TEXTURE: @@ -906,12 +895,11 @@ static void image_tools_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void image_tools_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_tools_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_GPENCIL: @@ -963,12 +951,11 @@ static void image_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void image_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void image_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: diff --git a/source/blender/editors/space_info/info_draw.c b/source/blender/editors/space_info/info_draw.c index 414bce29502..be3b60d581b 100644 --- a/source/blender/editors/space_info/info_draw.c +++ b/source/blender/editors/space_info/info_draw.c @@ -35,7 +35,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "info_intern.h" #include "textview.h" @@ -56,47 +55,11 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc, int shade = (tvc->iter_tmp % 2) ? 4 : -4; UI_GetThemeColorShade4ubv(bg_id, shade, bg); - /* Icon color and backgound depend of report type. */ + /* Don't show icon on subsequent rows of multi-row report. */ + *r_icon = (tvc->iter_char_begin != 0) ? ICON_NONE : UI_icon_from_report_type(report->type); - int icon_fg_id; - int icon_bg_id; - - if (tvc->iter_char_begin != 0) { - *r_icon = ICON_NONE; - } - else if (report->type & RPT_ERROR_ALL) { - icon_fg_id = TH_INFO_ERROR_TEXT; - icon_bg_id = TH_INFO_ERROR; - *r_icon = ICON_CANCEL; - } - else if (report->type & RPT_WARNING_ALL) { - icon_fg_id = TH_INFO_WARNING_TEXT; - icon_bg_id = TH_INFO_WARNING; - *r_icon = ICON_ERROR; - } - else if (report->type & RPT_INFO_ALL) { - icon_fg_id = TH_INFO_INFO_TEXT; - icon_bg_id = TH_INFO_INFO; - *r_icon = ICON_INFO; - } - else if (report->type & RPT_DEBUG_ALL) { - icon_fg_id = TH_INFO_DEBUG_TEXT; - icon_bg_id = TH_INFO_DEBUG; - *r_icon = ICON_SYSTEM; - } - else if (report->type & RPT_PROPERTY) { - icon_fg_id = TH_INFO_PROPERTY_TEXT; - icon_bg_id = TH_INFO_PROPERTY; - *r_icon = ICON_OPTIONS; - } - else if (report->type & RPT_OPERATOR) { - icon_fg_id = TH_INFO_OPERATOR_TEXT; - icon_bg_id = TH_INFO_OPERATOR; - *r_icon = ICON_CHECKMARK; - } - else { - *r_icon = ICON_NONE; - } + int icon_fg_id = UI_text_colorid_from_report_type(report->type); + int icon_bg_id = UI_icon_colorid_from_report_type(report->type); if (report->flag & SELECT) { icon_fg_id = TH_INFO_SELECTED; @@ -105,6 +68,8 @@ static enum eTextViewContext_LineFlag report_line_data(TextViewContext *tvc, if (*r_icon != ICON_NONE) { UI_GetThemeColor4ubv(icon_fg_id, r_icon_fg); + /* This theme color is RGB only, so set alpha. */ + r_icon_fg[3] = 255; UI_GetThemeColor4ubv(icon_bg_id, r_icon_bg); return TVC_LINE_FG | TVC_LINE_BG | TVC_LINE_ICON | TVC_LINE_ICON_FG | TVC_LINE_ICON_BG; } diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 3bd23eab836..0583628be43 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -24,7 +24,6 @@ #include <stdio.h> #include <string.h> -#include "DNA_packedFile_types.h" #include "DNA_space_types.h" #include "DNA_windowmanager_types.h" @@ -52,8 +51,6 @@ #include "UI_interface.h" #include "UI_resources.h" -#include "IMB_imbuf_types.h" - #include "RNA_access.h" #include "RNA_define.h" @@ -567,15 +564,7 @@ static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), co } /* set target color based on report type */ - if (report->type & RPT_ERROR_ALL) { - UI_GetThemeColorType3fv(TH_INFO_ERROR, SPACE_INFO, target_col); - } - else if (report->type & RPT_WARNING_ALL) { - UI_GetThemeColorType3fv(TH_INFO_WARNING, SPACE_INFO, target_col); - } - else if (report->type & RPT_INFO_ALL) { - UI_GetThemeColorType3fv(TH_INFO_INFO, SPACE_INFO, target_col); - } + UI_GetThemeColorType3fv(UI_icon_colorid_from_report_type(report->type), SPACE_INFO, target_col); target_col[3] = 0.65f; if (rti->widthfac == 0.0f) { diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 8d3f21aefeb..dfc0abee704 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -29,8 +29,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "BKE_context.h" #include "BKE_screen.h" @@ -43,12 +41,9 @@ #include "RNA_access.h" -#include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "BLO_readfile.h" -#include "GPU_framebuffer.h" #include "info_intern.h" /* own include */ /* ******************** default callbacks for info space ***************** */ @@ -150,7 +145,7 @@ static void info_main_region_draw(const bContext *C, ARegion *region) info_textview_update_rect(C, region); - /* worlks best with no view2d matrix set */ + /* Works best with no view2d matrix set. */ UI_view2d_view_ortho(v2d); info_textview_main(sinfo, region, CTX_wm_reports(C)); @@ -204,13 +199,10 @@ static void info_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void info_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_main_region_listener(const wmRegionListenerParams *params) { - // SpaceInfo *sinfo = area->spacedata.first; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; /* context changes */ switch (wmn->category) { @@ -223,12 +215,11 @@ static void info_main_region_listener(wmWindow *UNUSED(win), } } -static void info_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void info_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -259,14 +250,11 @@ static void info_header_listener(wmWindow *UNUSED(win), } } -static void info_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void info_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index a489216afd1..aef59e89325 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -225,13 +225,16 @@ static bool textview_draw_string(TextViewDrawState *tds, rgba_uchar_to_float(col, icon_bg); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - hpadding, - line_top - bg_size - vpadding, - bg_size + hpadding, - line_top - vpadding, - 4 * UI_DPI_FAC, - col); + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = hpadding, + .xmax = bg_size + hpadding, + .ymin = line_top - bg_size - vpadding, + .ymax = line_top - vpadding, + }, + true, + 4 * UI_DPI_FAC, + col); } if (icon) { diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index 6fe980cf657..eea81e425c2 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -493,7 +493,18 @@ static void nla_draw_strip(SpaceNla *snla, /* strip is in normal track */ UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */ - UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color); + UI_draw_roundbox_shade_x( + &(const rctf){ + .xmin = strip->start, + .xmax = strip->end, + .ymin = yminc, + .ymax = ymaxc, + }, + true, + 0.0, + 0.5, + 0.1, + color); /* restore current vertex format & program (roundbox trashes it) */ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -547,7 +558,18 @@ static void nla_draw_strip(SpaceNla *snla, } else { /* non-muted - draw solid, rounded outline */ - UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color); + UI_draw_roundbox_shade_x( + &(const rctf){ + .xmin = strip->start, + .xmax = strip->end, + .ymin = yminc, + .ymax = ymaxc, + }, + false, + 0.0, + 0.0, + 0.1, + color); /* restore current vertex format & program (roundbox trashes it) */ shdr_pos = nla_draw_use_dashed_outlines(color, muted); diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index d7bf6c324ac..893d2c0e2c8 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -62,7 +62,6 @@ #include "DEG_depsgraph_build.h" #include "UI_interface.h" -#include "UI_resources.h" #include "UI_view2d.h" #include "nla_intern.h" /* own include */ @@ -215,7 +214,7 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo) return false; } - /* for each AnimData block with NLA-data, try exitting tweak-mode */ + /* For each AnimData block with NLA-data, try exiting tweak-mode. */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; @@ -418,7 +417,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa int filter; SpaceNla *snla = (SpaceNla *)ac->sl; - /* NOTE: not bool, since we want prioritise individual channels over expanders */ + /* NOTE: not bool, since we want prioritize individual channels over expanders. */ short found = 0; /* get all items - we need to do it this way */ @@ -442,7 +441,7 @@ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, floa found = acf->channel_role; /* only stop our search when we've found an actual channel - * - datablock expanders get less priority so that we don't abort prematurely + * - data-block expanders get less priority so that we don't abort prematurely */ if (found == ACHANNEL_ROLE_CHANNEL) { break; @@ -1532,11 +1531,11 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op) const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id); if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) { - /* No re-ordering of strips whithin non-local tracks of override data. */ + /* No re-ordering of strips within non-local tracks of override data. */ continue; } - /* make temporary metastrips so that entire islands of selections can be moved around */ + /* Make temporary meta-strips so that entire islands of selections can be moved around. */ BKE_nlastrips_make_metas(&nlt->strips, 1); /* special case: if there is only 1 island diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 2e32c496170..631dc2e550c 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -30,16 +30,11 @@ #include "BKE_screen.h" #include "ED_anim_api.h" -#include "ED_markers.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "WM_api.h" #include "WM_types.h" -#include "RNA_access.h" - #include "nla_intern.h" /* own include */ /* ************************** poll callbacks for operators **********************************/ diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index c6fe1b8539e..011cd7e2651 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -24,7 +24,6 @@ #include <stdio.h> #include <string.h> -#include "DNA_anim_types.h" #include "DNA_collection_types.h" #include "DNA_scene_types.h" @@ -52,7 +51,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "nla_intern.h" /* own include */ /* ******************** default callbacks for nla space ***************** */ @@ -324,12 +322,11 @@ static void nla_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void nla_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -364,12 +361,11 @@ static void nla_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -423,14 +419,14 @@ static void nla_main_region_listener(wmWindow *UNUSED(win), } } -static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -465,12 +461,11 @@ static void nla_main_region_message_subscribe(const struct bContext *UNUSED(C), } } -static void nla_channel_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void nla_channel_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -508,14 +503,13 @@ static void nla_channel_region_listener(wmWindow *UNUSED(win), } } -static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *screen, - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void nla_channel_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + bScreen *screen = params->screen; + ScrArea *area = params->area; + ARegion *region = params->region; + PointerRNA ptr; RNA_pointer_create(&screen->id, &RNA_SpaceNLA, area->spacedata.first, &ptr); @@ -543,11 +537,11 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C } /* editor level listener */ -static void nla_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void nla_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index f2ee94af9b3..4716f1c29ea 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -190,7 +190,7 @@ static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA cumap->flag &= ~CUMA_DRAW_SAMPLE; } - /* "Tone" (Standard/Filmlike) only used in the Compositor. */ + /* "Tone" (Standard/Film-like) only used in the Compositor. */ bNodeTree *ntree = (bNodeTree *)ptr->owner_id; uiTemplateCurveMapping( layout, ptr, "mapping", 'c', false, false, false, (ntree->type == NTREE_COMPOSIT)); @@ -441,7 +441,7 @@ static void node_draw_frame(const bContext *C, const rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa(rct, true, BASIS_RAD, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { @@ -452,11 +452,11 @@ static void node_draw_frame(const bContext *C, UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -40, color); } - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa(rct, false, BASIS_RAD, color); } /* label */ - node_draw_frame_label(ntree, node, snode->aspect); + node_draw_frame_label(ntree, node, snode->runtime->aspect); UI_block_end(C, node->block); UI_block_draw(C, node->block); @@ -559,7 +559,7 @@ static void node_draw_reroute(const bContext *C, if (node->flag & SELECT) { GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - /* using different shades of TH_TEXT_HI for the empasis, like triangle */ + /* Using different shades of #TH_TEXT_HI for the emphasis, like triangle. */ if (node->flag & NODE_ACTIVE) { UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color); } @@ -3126,270 +3126,6 @@ static void node_texture_set_butfunc(bNodeType *ntype) } } -/* ****************** BUTTON CALLBACKS FOR GEOMETRY NODES ***************** */ - -static void node_geometry_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_compare(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); -} - -static void node_geometry_buts_subdivision_surface(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *UNUSED(ptr)) -{ -#ifndef WITH_OPENSUBDIV - uiItemL(layout, IFACE_("Disabled, built without OpenSubdiv"), ICON_ERROR); -#else - UNUSED_VARS(layout); -#endif -} - -static void node_geometry_buts_triangulate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "quad_method", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "ngon_method", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_random_attribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_math(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); -} - -static void node_geometry_buts_attribute_vector_math(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - bNode *node = (bNode *)ptr->data; - NodeAttributeVectorMath *node_storage = (NodeAttributeVectorMath *)node->storage; - - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); - uiItemR(layout, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("Type A"), ICON_NONE); - - /* These "use input b / c" checks are copied from the node's code. - * They could be de-duplicated if the drawing code was moved to the node's file. */ - if (!ELEM(node_storage->operation, - NODE_VECTOR_MATH_NORMALIZE, - NODE_VECTOR_MATH_FLOOR, - NODE_VECTOR_MATH_CEIL, - NODE_VECTOR_MATH_FRACTION, - NODE_VECTOR_MATH_ABSOLUTE, - NODE_VECTOR_MATH_SINE, - NODE_VECTOR_MATH_COSINE, - NODE_VECTOR_MATH_TANGENT, - NODE_VECTOR_MATH_LENGTH)) { - uiItemR(layout, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("Type B"), ICON_NONE); - } - if (ELEM(node_storage->operation, NODE_VECTOR_MATH_WRAP)) { - uiItemR(layout, ptr, "input_type_c", DEFAULT_FLAGS, IFACE_("Type C"), ICON_NONE); - } -} - -static void node_geometry_buts_point_instance(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "instance_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { - uiItemR(layout, ptr, "use_whole_collection", DEFAULT_FLAGS, NULL, ICON_NONE); - } -} - -static void node_geometry_buts_attribute_fill(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); - // uiItemR(layout, ptr, "domain", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_mix(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_a", DEFAULT_FLAGS, IFACE_("A"), ICON_NONE); - uiItemR(col, ptr, "input_type_b", DEFAULT_FLAGS, IFACE_("B"), ICON_NONE); -} - -static void node_geometry_buts_attribute_point_distribute(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "distribute_method", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_geometry_buts_attribute_color_ramp(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiTemplateColorRamp(layout, ptr, "color_ramp", 0); -} - -static void node_geometry_buts_point_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage; - - uiItemR(layout, ptr, "type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - - uiLayout *col = uiLayoutColumn(layout, false); - if (storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { - uiItemR(col, ptr, "input_type_axis", DEFAULT_FLAGS, IFACE_("Axis"), ICON_NONE); - uiItemR(col, ptr, "input_type_angle", DEFAULT_FLAGS, IFACE_("Angle"), ICON_NONE); - } - else { - uiItemR(col, ptr, "input_type_rotation", DEFAULT_FLAGS, IFACE_("Rotation"), ICON_NONE); - } -} - -static void node_geometry_buts_align_rotation_to_vector(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiLayout *col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "input_type_factor", DEFAULT_FLAGS, IFACE_("Factor"), ICON_NONE); - uiItemR(col, ptr, "input_type_vector", DEFAULT_FLAGS, IFACE_("Vector"), ICON_NONE); -} -static void node_geometry_buts_point_translate(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "input_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); -} - -static void node_geometry_buts_point_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "input_type", DEFAULT_FLAGS, IFACE_("Type"), ICON_NONE); -} - -static void node_geometry_buts_object_info(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); -} - -static void node_geometry_set_butfunc(bNodeType *ntype) -{ - switch (ntype->type) { - case GEO_NODE_BOOLEAN: - ntype->draw_buttons = node_geometry_buts_boolean_math; - break; - case GEO_NODE_SUBDIVISION_SURFACE: - ntype->draw_buttons = node_geometry_buts_subdivision_surface; - break; - case GEO_NODE_TRIANGULATE: - ntype->draw_buttons = node_geometry_buts_triangulate; - break; - case GEO_NODE_ATTRIBUTE_RANDOMIZE: - ntype->draw_buttons = node_geometry_buts_random_attribute; - break; - case GEO_NODE_ATTRIBUTE_MATH: - ntype->draw_buttons = node_geometry_buts_attribute_math; - break; - case GEO_NODE_ATTRIBUTE_COMPARE: - ntype->draw_buttons = node_geometry_buts_attribute_compare; - break; - case GEO_NODE_POINT_INSTANCE: - ntype->draw_buttons = node_geometry_buts_point_instance; - break; - case GEO_NODE_ATTRIBUTE_FILL: - ntype->draw_buttons = node_geometry_buts_attribute_fill; - break; - case GEO_NODE_ATTRIBUTE_MIX: - ntype->draw_buttons = node_geometry_buts_attribute_mix; - break; - case GEO_NODE_ATTRIBUTE_VECTOR_MATH: - ntype->draw_buttons = node_geometry_buts_attribute_vector_math; - break; - case GEO_NODE_POINT_DISTRIBUTE: - ntype->draw_buttons = node_geometry_buts_attribute_point_distribute; - break; - case GEO_NODE_ATTRIBUTE_COLOR_RAMP: - ntype->draw_buttons = node_geometry_buts_attribute_color_ramp; - break; - case GEO_NODE_POINT_ROTATE: - ntype->draw_buttons = node_geometry_buts_point_rotate; - break; - case GEO_NODE_ALIGN_ROTATION_TO_VECTOR: - ntype->draw_buttons = node_geometry_buts_align_rotation_to_vector; - break; - case GEO_NODE_POINT_TRANSLATE: - ntype->draw_buttons = node_geometry_buts_point_translate; - break; - case GEO_NODE_POINT_SCALE: - ntype->draw_buttons = node_geometry_buts_point_scale; - break; - case GEO_NODE_OBJECT_INFO: - ntype->draw_buttons = node_geometry_buts_object_info; - break; - } -} - -/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */ - -static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_float_compare(uiLayout *layout, - bContext *UNUSED(C), - PointerRNA *ptr) -{ - uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); -} - -static void node_function_buts_input_vector(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ - uiLayout *col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "vector", UI_ITEM_R_EXPAND, "", ICON_NONE); -} - -static void node_function_set_butfunc(bNodeType *ntype) -{ - switch (ntype->type) { - case FN_NODE_BOOLEAN_MATH: - ntype->draw_buttons = node_function_buts_boolean_math; - break; - case FN_NODE_FLOAT_COMPARE: - ntype->draw_buttons = node_function_buts_float_compare; - break; - case FN_NODE_SWITCH: - ntype->draw_buttons = node_function_buts_switch; - break; - case FN_NODE_INPUT_VECTOR: - ntype->draw_buttons = node_function_buts_input_vector; - break; - } -} - /* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3489,8 +3225,6 @@ void ED_node_init_butfuncs(void) ntype->draw_nodetype_prepare = node_update_default; ntype->select_area_func = node_select_area_default; ntype->tweak_area_func = node_tweak_area_default; - ntype->draw_buttons = NULL; - ntype->draw_buttons_ex = NULL; ntype->resize_area_func = node_resize_area_default; node_common_set_butfunc(ntype); @@ -3498,8 +3232,6 @@ void ED_node_init_butfuncs(void) node_composit_set_butfunc(ntype); node_shader_set_butfunc(ntype); node_texture_set_butfunc(ntype); - node_geometry_set_butfunc(ntype); - node_function_set_butfunc(ntype); /* define update callbacks for socket properties */ node_template_properties_update(ntype); @@ -3828,18 +3560,18 @@ void draw_nodespace_back_pix(const bContext *C, } /* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */ -static bool node_link_bezier_handles(View2D *v2d, - SpaceNode *snode, - bNodeLink *link, - float vec[4][2]) +bool node_link_bezier_handles(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + float vec[4][2]) { float cursor[2] = {0.0f, 0.0f}; /* this function can be called with snode null (via cut_links_intersect) */ - /* XXX map snode->cursor back to view space */ + /* XXX map snode->runtime->cursor back to view space */ if (snode) { - cursor[0] = snode->cursor[0] * UI_DPI_FAC; - cursor[1] = snode->cursor[1] * UI_DPI_FAC; + cursor[0] = snode->runtime->cursor[0] * UI_DPI_FAC; + cursor[1] = snode->runtime->cursor[1] * UI_DPI_FAC; } /* in v0 and v3 we put begin/end points */ @@ -3859,6 +3591,9 @@ static bool node_link_bezier_handles(View2D *v2d, if (link->tosock) { vec[3][0] = link->tosock->locx; vec[3][1] = link->tosock->locy; + if (!(link->tonode->flag & NODE_HIDDEN) && link->tosock->flag & SOCK_MULTI_INPUT) { + node_link_calculate_multi_input_position(link, vec[3]); + } toreroute = (link->tonode && link->tonode->type == NODE_REROUTE); } else { @@ -3923,8 +3658,11 @@ static bool node_link_bezier_handles(View2D *v2d, } /* if v2d not NULL, it clips and returns 0 if not visible */ -bool node_link_bezier_points( - View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) +bool node_link_bezier_points(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + float coord_array[][2], + const int resol) { float vec[4][2]; @@ -4087,7 +3825,7 @@ static char nodelink_get_color_id(int th_col) return 0; } -static void nodelink_batch_draw(SpaceNode *snode) +static void nodelink_batch_draw(const SpaceNode *snode) { if (g_batch_link.count == 0) { return; @@ -4107,7 +3845,7 @@ static void nodelink_batch_draw(SpaceNode *snode) GPU_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST); GPU_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, colors); - GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(g_batch_link.batch, "arrowSize", ARROW_SIZE); GPU_batch_draw(g_batch_link.batch); @@ -4127,7 +3865,7 @@ void nodelink_batch_end(SpaceNode *snode) g_batch_link.enabled = false; } -static void nodelink_batch_add_link(SpaceNode *snode, +static void nodelink_batch_add_link(const SpaceNode *snode, const float p0[2], const float p1[2], const float p2[2], @@ -4159,11 +3897,15 @@ static void nodelink_batch_add_link(SpaceNode *snode, } /* don't do shadows if th_col3 is -1. */ -void node_draw_link_bezier( - View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int th_col3) +void node_draw_link_bezier(const View2D *v2d, + const SpaceNode *snode, + const bNodeLink *link, + int th_col1, + int th_col2, + int th_col3) { float vec[4][2]; - + const bool highlighted = link->flag & NODE_LINK_TEMP_HIGHLIGHT; if (node_link_bezier_handles(v2d, snode, link, vec)) { int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) && (link->fromnode && (link->fromnode->type == NODE_REROUTE))); @@ -4172,7 +3914,7 @@ void node_draw_link_bezier( nodelink_batch_init(); } - if (g_batch_link.enabled) { + if (g_batch_link.enabled && !highlighted) { /* Add link to batch. */ nodelink_batch_add_link( snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow); @@ -4186,11 +3928,17 @@ void node_draw_link_bezier( UI_GetThemeColor4fv(th_col1, colors[1]); UI_GetThemeColor4fv(th_col2, colors[2]); + if (highlighted) { + float link_preselection_highlight_color[4]; + UI_GetThemeColor4fv(TH_SELECT, link_preselection_highlight_color); + copy_v4_v4(colors[2], link_preselection_highlight_color); + } + GPUBatch *batch = g_batch_link.batch_single; GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK); GPU_batch_uniform_2fv_array(batch, "bezierPts", 4, vec); GPU_batch_uniform_4fv_array(batch, "colors", 3, colors); - GPU_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH); + GPU_batch_uniform_1f(batch, "expandSize", snode->runtime->aspect * LINK_WIDTH); GPU_batch_uniform_1f(batch, "arrowSize", ARROW_SIZE); GPU_batch_uniform_1i(batch, "doArrow", drawarrow); GPU_batch_draw(batch); diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 508c0a47e21..e665f7b1d52 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -104,9 +104,8 @@ static bool add_reroute_intersect_check(bNodeLink *link, if (node_link_bezier_points(NULL, NULL, link, coord_array, NODE_LINK_RESOL)) { for (int i = 0; i < tot - 1; i++) { for (int b = 0; b < NODE_LINK_RESOL; b++) { - if (isect_seg_seg_v2(mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1]) > 0) { - result[0] = (mcoords[i][0] + mcoords[i + 1][0]) / 2.0f; - result[1] = (mcoords[i][1] + mcoords[i + 1][1]) / 2.0f; + if (isect_seg_seg_v2_point( + mcoords[i], mcoords[i + 1], coord_array[b], coord_array[b + 1], result) > 0) { return true; } } @@ -312,6 +311,13 @@ void NODE_OT_add_reroute(wmOperatorType *ot) /* ****************** Add File Node Operator ******************* */ +static bool node_add_file_poll(bContext *C) +{ + const SpaceNode *snode = CTX_wm_space_node(C); + return ED_operator_node_editable(C) && + ELEM(snode->nodetree->type, NTREE_SHADER, NTREE_TEXTURE, NTREE_COMPOSIT); +} + static int node_add_file_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -341,7 +347,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, type, snode->cursor[0], snode->cursor[1]); + node = node_add_node(C, NULL, type, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add an image node"); @@ -370,11 +376,14 @@ static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *even SpaceNode *snode = CTX_wm_space_node(C); /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view( - ®ion->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); + UI_view2d_region_to_view(®ion->v2d, + event->mval[0], + event->mval[1], + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; if (RNA_struct_property_is_set(op->ptr, "filepath") || RNA_struct_property_is_set(op->ptr, "name")) { @@ -393,7 +402,7 @@ void NODE_OT_add_file(wmOperatorType *ot) /* callbacks */ ot->exec = node_add_file_exec; ot->invoke = node_add_file_invoke; - ot->poll = ED_operator_node_editable; + ot->poll = node_add_file_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -435,7 +444,8 @@ static int node_add_mask_exec(bContext *C, wmOperator *op) ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); - node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]); + node = node_add_node( + C, NULL, CMP_NODE_MASK, snode->runtime->cursor[0], snode->runtime->cursor[1]); if (!node) { BKE_report(op->reports, RPT_WARNING, "Could not add a mask node"); diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index c9a0c827a09..fa4d6997c83 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -40,7 +40,6 @@ #include "RNA_access.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index d3fec7257f5..9ef914af75b 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -22,6 +22,8 @@ * \brief higher level node drawing for the node editor. */ +#include "MEM_guardedalloc.h" + #include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" @@ -317,14 +319,14 @@ static void node_uiblocks_init(const bContext *C, bNodeTree *ntree) } } -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_to_view(const bNode *node, float x, float y, float *rx, float *ry) { nodeToView(node, x, y, rx, ry); *rx *= UI_DPI_FAC; *ry *= UI_DPI_FAC; } -void node_to_updated_rect(struct bNode *node, rctf *r_rect) +void node_to_updated_rect(const bNode *node, rctf *r_rect) { node_to_view(node, node->offsetx, node->offsety, &r_rect->xmin, &r_rect->ymax); node_to_view(node, @@ -334,7 +336,7 @@ void node_to_updated_rect(struct bNode *node, rctf *r_rect) &r_rect->ymin); } -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry) +void node_from_view(const bNode *node, float x, float y, float *rx, float *ry) { x /= UI_DPI_FAC; y /= UI_DPI_FAC; @@ -500,6 +502,16 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) PointerRNA sockptr; RNA_pointer_create(&ntree->id, &RNA_NodeSocket, nsock, &sockptr); + /* Add the half the height of a multi-input socket to cursor Y + * to account for the increased height of the taller sockets. */ + float multi_input_socket_offset = 0.0f; + if (nsock->flag & SOCK_MULTI_INPUT) { + if (nsock->total_inputs > 2) { + multi_input_socket_offset = (nsock->total_inputs - 2) * NODE_MULTI_INPUT_LINK_GAP; + } + } + dy -= multi_input_socket_offset * 0.5f; + uiLayout *layout = UI_block_layout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, @@ -533,7 +545,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node) /* place the socket circle in the middle of the layout */ nsock->locy = 0.5f * (dy + buty); - dy = buty; + dy = buty - multi_input_socket_offset * 0.5; if (nsock->next) { dy -= NODE_SOCKDY; } @@ -689,11 +701,11 @@ int node_get_colorid(bNode *node) /* note: in cmp_util.c is similar code, for node_compo_pass_on() * the same goes for shader and texture nodes. */ /* note: in node_edit.c is similar code, for untangle node */ -static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) +static void node_draw_mute_line(const View2D *v2d, const SpaceNode *snode, const bNode *node) { GPU_blend(GPU_BLEND_ALPHA); - LISTBASE_FOREACH (bNodeLink *, link, &node->internal_links) { + LISTBASE_FOREACH (const bNodeLink *, link, &node->internal_links) { node_draw_link_bezier(v2d, snode, link, TH_REDALERT, TH_REDALERT, -1); } @@ -751,6 +763,27 @@ static void node_socket_draw(const bNodeSocket *sock, immVertex2f(pos_id, locx, locy); } +static void node_socket_draw_multi_input(const float color[4], + const float color_outline[4], + const float width, + const float height, + const int locx, + const int locy) +{ + const float outline_width = 1.0f; + /* UI_draw_roundbox draws the outline on the outer side, so compensate for the outline width. */ + const rctf rect = { + .xmin = locx - width + outline_width * 0.5f, + .xmax = locx + width - outline_width * 0.5f, + .ymin = locy - height + outline_width * 0.5f, + .ymax = locy + height - outline_width * 0.5f, + }; + + UI_draw_roundbox_corner_set(UI_CNR_ALL); + UI_draw_roundbox_4fv_ex( + &rect, color, NULL, 1.0f, color_outline, outline_width, width - outline_width * 0.5f); +} + static void node_socket_outline_color_get(bool selected, float r_outline_color[4]) { if (selected) { @@ -947,14 +980,14 @@ static void node_toggle_button_cb(struct bContext *C, void *node_argv, void *op_ WM_operator_name_call(C, opname, WM_OP_INVOKE_DEFAULT, NULL); } -void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha) +void node_draw_shadow(const SpaceNode *snode, const bNode *node, float radius, float alpha) { - rctf *rct = &node->totr; + const rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_ALL); - ui_draw_dropshadow(rct, radius, snode->aspect, alpha, node->flag & SELECT); + ui_draw_dropshadow(rct, radius, snode->runtime->aspect, alpha, node->flag & SELECT); } -void node_draw_sockets(View2D *v2d, +void node_draw_sockets(const View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, @@ -1006,6 +1039,10 @@ void node_draw_sockets(View2D *v2d, selected_input_len++; continue; } + /* Don't draw multi-input sockets here since they are drawn in a different batch. */ + if (sock->flag & SOCK_MULTI_INPUT) { + continue; + } node_socket_draw_nested(C, ntree, @@ -1115,11 +1152,33 @@ void node_draw_sockets(View2D *v2d, GPU_program_point_size(false); GPU_blend(GPU_BLEND_NONE); + + /* Draw multi-nput sockets after the others because they are drawn with "UI_roundbox" + * rather than with GL_POINT. */ + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (nodeSocketIsHidden(socket)) { + continue; + } + if (!(socket->flag & SOCK_MULTI_INPUT)) { + continue; + } + + const bool is_node_hidden = (node->flag & NODE_HIDDEN); + const float width = NODE_SOCKSIZE; + float height = is_node_hidden ? width : node_socket_calculate_height(socket) - width; + + float color[4]; + float outline_color[4]; + node_socket_color_get((bContext *)C, ntree, &node_ptr, socket, color); + node_socket_outline_color_get(selected, outline_color); + + node_socket_draw_multi_input(color, outline_color, width, height, socket->locx, socket->locy); + } } static void node_draw_basis(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) @@ -1127,8 +1186,6 @@ static void node_draw_basis(const bContext *C, /* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */ float iconbutw = 0.8f * UI_UNIT_X; - View2D *v2d = ®ion->v2d; - /* skip if out of view */ if (BLI_rctf_isect(&node->totr, &v2d->cur, NULL) == false) { UI_block_end(C, node->block); @@ -1157,7 +1214,15 @@ static void node_draw_basis(const bContext *C, rctf *rct = &node->totr; UI_draw_roundbox_corner_set(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); UI_draw_roundbox_aa( - true, rct->xmin, rct->ymax - NODE_DY, rct->xmax, rct->ymax, BASIS_RAD, color); + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymax - NODE_DY, + .ymax = rct->ymax, + }, + true, + BASIS_RAD, + color); /* show/hide icons */ float iconofs = rct->xmax - 0.35f * U.widget_unit; @@ -1308,7 +1373,15 @@ static void node_draw_basis(const bContext *C, UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT); UI_draw_roundbox_aa( - true, rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color); + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax - NODE_DY, + }, + true, + BASIS_RAD, + color); /* outline active and selected emphasis */ if (node->flag & SELECT) { @@ -1316,7 +1389,16 @@ static void node_draw_basis(const bContext *C, (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD, color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = rct->xmin, + .xmax = rct->xmax, + .ymin = rct->ymin, + .ymax = rct->ymax, + }, + false, + BASIS_RAD, + color); } /* disable lines */ @@ -1343,8 +1425,8 @@ static void node_draw_basis(const bContext *C, } static void node_draw_hidden(const bContext *C, - ARegion *region, - SpaceNode *snode, + const View2D *v2d, + const SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey UNUSED(key)) @@ -1353,8 +1435,6 @@ static void node_draw_hidden(const bContext *C, float centy = BLI_rctf_cent_y(rct); float hiddenrad = BLI_rctf_size_y(rct) / 2.0f; - View2D *v2d = ®ion->v2d; - float scale; UI_view2d_scale_get(v2d, &scale, NULL); @@ -1373,14 +1453,14 @@ static void node_draw_hidden(const bContext *C, UI_GetThemeColor4fv(color_id, color); } - UI_draw_roundbox_aa(true, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); + UI_draw_roundbox_aa(rct, true, hiddenrad, color); /* outline active and selected emphasis */ if (node->flag & SELECT) { UI_GetThemeColorShadeAlpha4fv( (node->flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, 0, -40, color); - UI_draw_roundbox_aa(false, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad, color); + UI_draw_roundbox_aa(rct, false, hiddenrad, color); } /* custom color inline */ @@ -1388,14 +1468,17 @@ static void node_draw_hidden(const bContext *C, GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - UI_draw_roundbox_3fv_alpha(false, - rct->xmin + 1, - rct->ymin + 1, - rct->xmax - 1, - rct->ymax - 1, - hiddenrad, - node->color, - 1.0f); + UI_draw_roundbox_3fv_alpha( + &(const rctf){ + .xmin = rct->xmin + 1, + .xmax = rct->xmax - 1, + .ymin = rct->ymin + 1, + .ymax = rct->ymax - 1, + }, + false, + hiddenrad, + node->color, + 1.0f); GPU_line_smooth(false); GPU_blend(GPU_BLEND_NONE); @@ -1438,7 +1521,7 @@ static void node_draw_hidden(const bContext *C, /* disable lines */ if (node->flag & NODE_MUTED) { - node_draw_mute_line(®ion->v2d, snode, node); + node_draw_mute_line(v2d, snode, node); } char showname[128]; /* 128 is used below */ @@ -1477,19 +1560,19 @@ static void node_draw_hidden(const bContext *C, immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUniformThemeColorShade(color_id, 30); - dx -= snode->aspect; + dx -= snode->runtime->aspect; immBegin(GPU_PRIM_LINES, 4); immVertex2f(pos, rct->xmax - dx, centy - 4.0f); immVertex2f(pos, rct->xmax - dx, centy + 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f); - immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy - 4.0f); + immVertex2f(pos, rct->xmax - dx - 3.0f * snode->runtime->aspect, centy + 4.0f); immEnd(); immUnbindProgram(); @@ -1550,11 +1633,12 @@ void node_draw_default(const bContext *C, bNode *node, bNodeInstanceKey key) { + const View2D *v2d = ®ion->v2d; if (node->flag & NODE_HIDDEN) { - node_draw_hidden(C, region, snode, ntree, node, key); + node_draw_hidden(C, v2d, snode, ntree, node, key); } else { - node_draw_basis(C, region, snode, ntree, node, key); + node_draw_basis(C, v2d, snode, ntree, node, key); } } @@ -1565,17 +1649,67 @@ static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) } } +static void count_mutli_input_socket_links(bNodeTree *ntree, SpaceNode *snode) +{ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (struct bNodeSocket *, socket, &node->inputs) { + if (socket->flag & SOCK_MULTI_INPUT) { + socket->total_inputs = 0; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (link->tosock == socket) { + socket->total_inputs++; + } + } + /* Count temporary links going into this socket. */ + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { + LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { + bNodeLink *link = (bNodeLink *)linkdata->data; + if (link->tosock == socket) { + socket->total_inputs++; + } + } + } + } + } + } +} + void node_update_nodetree(const bContext *C, bNodeTree *ntree) { /* make sure socket "used" tags are correct, for displaying value buttons */ + SpaceNode *snode = CTX_wm_space_node(C); ntreeTagUsedSockets(ntree); + count_mutli_input_socket_links(ntree, snode); + /* update nodes front to back, so children sizes get updated before parents */ LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree->nodes) { node_update(C, ntree, node); } } +static int compare_link_by_angle_to_node(const void *a, const void *b) +{ + const bNodeLink *link_a = *(const bNodeLink **)a; + const bNodeLink *link_b = *(const bNodeLink **)b; + + BLI_assert(link_a->tosock == link_b->tosock); + const float socket_location[2] = {link_a->tosock->locx, link_a->tosock->locy}; + const float up_direction[2] = {0.0f, 1.0f}; + + float delta_a[2] = {link_a->fromsock->locx - socket_location[0], + link_a->fromsock->locy - socket_location[1]}; + normalize_v2(delta_a); + const float angle_a = angle_normalized_v2v2(up_direction, delta_a); + + float delta_b[2] = {link_b->fromsock->locx - socket_location[0], + link_b->fromsock->locy - socket_location[1]}; + normalize_v2(delta_b); + const float angle_b = angle_normalized_v2v2(up_direction, delta_b); + + return angle_a < angle_b ? 1 : -1; +} + static void node_draw(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1590,6 +1724,46 @@ static void node_draw(const bContext *C, #define USE_DRAW_TOT_UPDATE +/** + * Automatically sort the input links to multi-input sockets to avoid crossing noodles. + */ +static void sort_multi_input_socket_links(bNodeTree *ntree, SpaceNode *snode) +{ + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { + if (socket->flag & SOCK_MULTI_INPUT) { + /* The total is calculated in #node_update_nodetree, which runs before this draw step. */ + const int total_inputs = socket->total_inputs; + bNodeLink **input_links = MEM_malloc_arrayN(total_inputs, sizeof(bNodeLink *), __func__); + + int index = 0; + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { + if (link->tosock == socket) { + input_links[index] = (bNodeLink *)link; + index++; + } + } + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { + LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { + bNodeLink *link = (bNodeLink *)linkdata->data; + if (link->tosock == socket) { + input_links[index] = (bNodeLink *)link; + index++; + } + } + } + + qsort(input_links, total_inputs, sizeof(bNodeLink *), compare_link_by_angle_to_node); + for (int i = 0; i < total_inputs; i++) { + input_links[i]->multi_input_socket_index = i; + } + + MEM_freeN(input_links); + } + } + } +} + void node_draw_nodetree(const bContext *C, ARegion *region, SpaceNode *snode, @@ -1607,8 +1781,7 @@ void node_draw_nodetree(const bContext *C, #endif /* draw background nodes, last nodes in front */ - int a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { #ifdef USE_DRAW_TOT_UPDATE /* unrelated to background nodes, update the v2d->tot, * can be anywhere before we draw the scroll bars */ @@ -1626,6 +1799,9 @@ void node_draw_nodetree(const bContext *C, /* node lines */ GPU_blend(GPU_BLEND_ALPHA); nodelink_batch_start(snode); + + sort_multi_input_socket_links(ntree, snode); + LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) { if (!nodeLinkIsHidden(link)) { node_draw_link(®ion->v2d, snode, link); @@ -1635,8 +1811,7 @@ void node_draw_nodetree(const bContext *C, GPU_blend(GPU_BLEND_NONE); /* draw foreground nodes, last nodes in front */ - a = 0; - LISTBASE_FOREACH_INDEX (bNode *, node, &ntree->nodes, a) { + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { if (node->flag & NODE_BACKGROUND) { continue; } @@ -1666,7 +1841,7 @@ static void snode_setup_v2d(SpaceNode *snode, ARegion *region, const float cente UI_view2d_view_ortho(v2d); /* aspect+font, set each time */ - snode->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; + snode->runtime->aspect = BLI_rctf_size_x(&v2d->cur) / (float)region->winx; // XXX snode->curfont = uiSetCurFont_ext(snode->aspect); } @@ -1686,8 +1861,8 @@ static void draw_nodetree(const bContext *C, /* shade the parent node group and add a uiBlock to clip mouse events */ static void draw_group_overlay(const bContext *C, ARegion *region) { - View2D *v2d = ®ion->v2d; - rctf rect = v2d->cur; + const View2D *v2d = ®ion->v2d; + const rctf rect = v2d->cur; float color[4]; /* shade node groups to separate them visually */ @@ -1695,7 +1870,7 @@ static void draw_group_overlay(const bContext *C, ARegion *region) UI_GetThemeColorShadeAlpha4fv(TH_NODE_GROUP, 0, 0, color); UI_draw_roundbox_corner_set(UI_CNR_NONE); - UI_draw_roundbox_4fv(true, rect.xmin, rect.ymin, rect.xmax, rect.ymax, 0, color); + UI_draw_roundbox_4fv(&rect, true, 0, color); GPU_blend(GPU_BLEND_NONE); /* set the block bounds to clip mouse events from underlying nodes */ @@ -1722,14 +1897,15 @@ void node_draw_space(const bContext *C, ARegion *region) GPU_depth_test(GPU_DEPTH_NONE); GPU_scissor_test(true); - /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */ + /* XXX snode->runtime->cursor set in coordspace for placing new nodes, used for drawing noodles + * too */ UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; int grid_levels = UI_GetThemeValueType(TH_NODE_GRID_LEVELS, SPACE_NODE); @@ -1819,7 +1995,7 @@ void node_draw_space(const bContext *C, ARegion *region) /* temporary links */ GPU_blend(GPU_BLEND_ALPHA); GPU_line_smooth(true); - LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->linkdrag) { + LISTBASE_FOREACH (bNodeLinkDrag *, nldrag, &snode->runtime->linkdrag) { LISTBASE_FOREACH (LinkData *, linkdata, &nldrag->links) { node_draw_link(v2d, snode, (bNodeLink *)linkdata->data); } @@ -1847,7 +2023,7 @@ void node_draw_space(const bContext *C, ARegion *region) if (snode->treepath.last) { if (snode->flag & SNODE_SHOW_GPENCIL) { - /* draw grease-pencil (screen strokes, and also paintbuffer) */ + /* Draw grease-pencil (screen strokes, and also paint-buffer). */ ED_annotation_draw_view2d(C, false); } } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 30eee416b12..04787748937 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -98,6 +98,25 @@ typedef struct CompoJob { float *progress; } CompoJob; +float node_socket_calculate_height(const bNodeSocket *socket) +{ + float sock_height = NODE_SOCKSIZE * 2.0f; + if (socket->flag & SOCK_MULTI_INPUT) { + sock_height += max_ii(NODE_MULTI_INPUT_LINK_GAP * 0.5f * socket->total_inputs, NODE_SOCKSIZE); + } + return sock_height; +} + +void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]) +{ + float offset = (link->tosock->total_inputs * NODE_MULTI_INPUT_LINK_GAP - + NODE_MULTI_INPUT_LINK_GAP) * + 0.5; + r[0] = link->tosock->locx - NODE_SOCKSIZE * 0.5f; + r[1] = link->tosock->locy - offset + + (link->multi_input_socket_index * NODE_MULTI_INPUT_LINK_GAP); +} + static void compo_tag_output_nodes(bNodeTree *nodetree, int recalc_flags) { LISTBASE_FOREACH (bNode *, node, &nodetree->nodes) { @@ -770,7 +789,7 @@ void ED_node_post_apply_transform(bContext *UNUSED(C), bNodeTree *UNUSED(ntree)) * which only exists during actual drawing. Can we rely on valid totr rects? */ /* make sure nodes have correct bounding boxes after transform */ - /* node_update_nodetree(C, ntree, 0.0f, 0.0f); */ + // node_update_nodetree(C, ntree, 0.0f, 0.0f); } /* ***************** generic operator functions for nodes ***************** */ @@ -880,8 +899,8 @@ static void node_resize_init( NodeSizeWidget *nsw = MEM_callocN(sizeof(NodeSizeWidget), "size widget op data"); op->customdata = nsw; - nsw->mxstart = snode->cursor[0] * UI_DPI_FAC; - nsw->mystart = snode->cursor[1] * UI_DPI_FAC; + nsw->mxstart = snode->runtime->cursor[0] * UI_DPI_FAC; + nsw->mystart = snode->runtime->cursor[1] * UI_DPI_FAC; /* store old */ nsw->oldlocx = node->locx; @@ -1104,6 +1123,21 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } /* checks snode->mouse position, and returns found node/socket */ +static bool cursor_isect_multi_input_socket(const float cursor[2], const bNodeSocket *socket) +{ + const float node_socket_height = node_socket_calculate_height(socket); + const rctf multi_socket_rect = { + .xmin = socket->locx - NODE_SOCKSIZE * 4, + .xmax = socket->locx + NODE_SOCKSIZE, + .ymin = socket->locy - node_socket_height * 0.5 - NODE_SOCKSIZE * 2.0f, + .ymax = socket->locy + node_socket_height * 0.5 + NODE_SOCKSIZE * 2.0f, + }; + if (BLI_rctf_isect_pt(&multi_socket_rect, cursor[0], cursor[1])) { + return true; + } + return false; +} + /* type is SOCK_IN and/or SOCK_OUT */ int node_find_indicated_socket( SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out) @@ -1132,7 +1166,16 @@ int node_find_indicated_socket( if (in_out & SOCK_IN) { LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { if (!nodeSocketIsHidden(sock)) { - if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { + if (sock->flag & SOCK_MULTI_INPUT && !(node->flag & NODE_HIDDEN)) { + if (cursor_isect_multi_input_socket(cursor, sock)) { + if (node == visible_node(snode, &rect)) { + *nodep = node; + *sockp = sock; + return 1; + } + } + } + else if (BLI_rctf_isect_pt(&rect, sock->locx, sock->locy)) { if (node == visible_node(snode, &rect)) { *nodep = node; *sockp = sock; @@ -1199,7 +1242,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *op) if (node->flag & SELECT) { BKE_node_copy_store_new_pointers(ntree, node, LIB_ID_COPY_DEFAULT); - /* to ensure redraws or rerenders happen */ + /* To ensure redraws or re-renders happen. */ ED_node_tag_update_id(snode->id); } diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index f2abe272f48..7f530408ec7 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -1039,7 +1039,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) snode_notify(C, snode); snode_dag_update(C, snode); - /* We broke relations in node tree, need to rebuild them in the grahes. */ + /* We broke relations in node tree, need to rebuild them in the graphs. */ DEG_relations_tag_update(bmain); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index aa59b7293a3..2f3fa6996af 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -37,6 +37,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct NodeInsertOfsData; struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -50,25 +51,49 @@ typedef struct bNodeLinkDrag { * This way the links can be added to the node tree while being stored in this list. */ ListBase links; + bool from_multi_input_socket; int in_out; } bNodeLinkDrag; +typedef struct SpaceNode_Runtime { + float aspect; + + /** Mouse position for drawing socket-less links and adding nodes. */ + float cursor[2]; + + /** For auto compositing. */ + bool recalc; + + /** Temporary data for modal linking operator. */ + struct ListBase linkdrag; + + /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ + /** Temporary data for node insert offset (in UI called Auto-offset). */ + struct NodeInsertOfsData *iofsd; +} SpaceNode_Runtime; + /* space_node.c */ /* transform between View2Ds in the tree path */ void space_node_group_offset(struct SpaceNode *snode, float *x, float *y); /* node_draw.c */ +float node_socket_calculate_height(const bNodeSocket *socket); +void node_link_calculate_multi_input_position(const bNodeLink *link, float r[2]); + int node_get_colorid(struct bNode *node); int node_get_resize_cursor(int directions); -void node_draw_shadow(struct SpaceNode *snode, struct bNode *node, float radius, float alpha); +void node_draw_shadow(const struct SpaceNode *snode, + const struct bNode *node, + float radius, + float alpha); void node_draw_default(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node, bNodeInstanceKey key); -void node_draw_sockets(struct View2D *v2d, +void node_draw_sockets(const struct View2D *v2d, const struct bContext *C, struct bNodeTree *ntree, struct bNode *node, @@ -92,9 +117,9 @@ void node_draw_space(const bContext *C, ARegion *region); void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); /* DPI scaled coords */ -void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry); -void node_to_updated_rect(struct bNode *node, rctf *r_rect); -void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_view(const struct bNode *node, float x, float y, float *rx, float *ry); +void node_to_updated_rect(const struct bNode *node, rctf *r_rect); +void node_from_view(const struct bNode *node, float x, float y, float *rx, float *ry); /* node_buttons.c */ void node_buttons_register(struct ARegionType *art); @@ -145,17 +170,21 @@ void nodelink_batch_start(struct SpaceNode *snode); void nodelink_batch_end(struct SpaceNode *snode); void node_draw_link(struct View2D *v2d, struct SpaceNode *snode, struct bNodeLink *link); -void node_draw_link_bezier(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +void node_draw_link_bezier(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, int th_col1, int th_col2, int th_col3); -bool node_link_bezier_points(struct View2D *v2d, - struct SpaceNode *snode, - struct bNodeLink *link, +bool node_link_bezier_points(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, float coord_array[][2], - int resol); + const int resol); +bool node_link_bezier_handles(const struct View2D *v2d, + const struct SpaceNode *snode, + const struct bNodeLink *link, + float vec[4][2]); void draw_nodespace_back_pix(const struct bContext *C, struct ARegion *region, struct SpaceNode *snode, @@ -268,6 +297,7 @@ extern const char *node_context_dir[]; #define NODE_HEIGHT(node) (node->height * UI_DPI_FAC) #define NODE_MARGIN_X (1.10f * U.widget_unit) #define NODE_SOCKSIZE (0.25f * U.widget_unit) +#define NODE_MULTI_INPUT_LINK_GAP (0.25f * U.widget_unit) #define NODE_RESIZE_MARGIN (0.20f * U.widget_unit) #define NODE_LINK_RESOL 12 diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 11933ef0811..d55fd06ddea 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -23,14 +23,10 @@ #include "DNA_node_types.h" -#include "BLI_utildefines.h" - #include "BKE_context.h" #include "ED_node.h" /* own include */ #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index ba1e752e276..d6edfcce8e8 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -32,6 +32,7 @@ #include "BKE_anim_data.h" #include "BKE_context.h" +#include "BKE_curve.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_node.h" @@ -58,7 +59,7 @@ static bool ntree_has_drivers(bNodeTree *ntree) { - AnimData *adt = BKE_animdata_from_id(&ntree->id); + const AnimData *adt = BKE_animdata_from_id(&ntree->id); if (adt == NULL) { return false; } @@ -179,6 +180,137 @@ typedef struct NodeInsertOfsData { float offset_x; /* offset to apply to node chain */ } NodeInsertOfsData; +static void clear_picking_highlight(ListBase *links) +{ + LISTBASE_FOREACH (bNodeLink *, link, links) { + link->flag &= ~NODE_LINK_TEMP_HIGHLIGHT; + } +} + +static LinkData *create_drag_link(Main *bmain, SpaceNode *snode, bNode *node, bNodeSocket *sock) +{ + LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); + linkdata->data = oplink; + if (sock->in_out == SOCK_OUT) { + oplink->fromnode = node; + oplink->fromsock = sock; + } + else { + oplink->tonode = node; + oplink->tosock = sock; + } + oplink->flag |= NODE_LINK_VALID; + oplink->flag &= ~NODE_LINK_TEST; + if (node_connected_to_output(bmain, snode->edittree, node)) { + oplink->flag |= NODE_LINK_TEST; + } + return linkdata; +} + +static void pick_link(const bContext *C, + wmOperator *op, + bNodeLinkDrag *nldrag, + SpaceNode *snode, + bNode *node, + bNodeLink *link_to_pick) +{ + clear_picking_highlight(&snode->edittree->links); + RNA_boolean_set(op->ptr, "has_link_picked", true); + + Main *bmain = CTX_data_main(C); + LinkData *linkdata = create_drag_link( + bmain, snode, link_to_pick->fromnode, link_to_pick->fromsock); + + BLI_addtail(&nldrag->links, linkdata); + nodeRemLink(snode->edittree, link_to_pick); + /* Send changed event to original link->tonode. */ + if (node) { + snode_update(snode, node); + } +} + +static void pick_input_link_by_link_intersect(const bContext *C, + wmOperator *op, + bNodeLinkDrag *nldrag, + const float *cursor) +{ + SpaceNode *snode = CTX_wm_space_node(C); + const ARegion *region = CTX_wm_region(C); + const View2D *v2d = ®ion->v2d; + + float drag_start[2]; + RNA_float_get_array(op->ptr, "drag_start", drag_start); + bNode *node; + bNodeSocket *socket; + node_find_indicated_socket(snode, &node, &socket, drag_start, SOCK_IN); + + const float trigger_drag_distance = 25.0f; + const float cursor_link_touch_distance = 25.0f; + + const float socket_height = node_socket_calculate_height(socket); + + float cursor_to_socket_relative[2]; + float socket_position[2] = {socket->locx, socket->locy}; + sub_v2_v2v2(cursor_to_socket_relative, cursor, socket_position); + float distance_from_socket_v2[2] = { + max_ff(0, fabs(cursor_to_socket_relative[0]) - NODE_SOCKSIZE * 0.5), + max_ff(0, fabs(cursor_to_socket_relative[1]) - socket_height)}; + const float distance_from_socket = len_v2(distance_from_socket_v2); + + const int resolution = NODE_LINK_RESOL; + + bNodeLink *link_to_pick = NULL; + clear_picking_highlight(&snode->edittree->links); + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (link->tosock == socket) { + /* Test if the cursor is near a link. */ + float vec[4][2]; + node_link_bezier_handles(v2d, snode, link, vec); + + float data[NODE_LINK_RESOL * 2 + 2]; + BKE_curve_forward_diff_bezier( + vec[0][0], vec[1][0], vec[2][0], vec[3][0], data, resolution, sizeof(float[2])); + BKE_curve_forward_diff_bezier( + vec[0][1], vec[1][1], vec[2][1], vec[3][1], data + 1, resolution, sizeof(float[2])); + + for (int i = 0; i < resolution * 2; i += 2) { + float *l1 = &data[i]; + float *l2 = &data[i + 2]; + float distance = dist_squared_to_line_segment_v2(cursor, l1, l2); + if (distance < cursor_link_touch_distance) { + link_to_pick = link; + RNA_int_set(op->ptr, "last_picked_link_index", link->multi_input_socket_index); + } + } + } + } + + /* If no linked was picked in this call, try using the one picked in the previous call. + * Not essential for the basic behavior, but can make interaction feel a bit better if + * the mouse moves to the right and loses the "selection." */ + if (!link_to_pick) { + int last_picked_link_index = RNA_int_get(op->ptr, "last_picked_link_index"); + if (last_picked_link_index > -1) { + LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) { + if (link->multi_input_socket_index == last_picked_link_index) { + link_to_pick = link; + } + } + } + } + + if (link_to_pick) { + /* Highlight is set here and cleared in the next iteration or if the operation finishes. */ + link_to_pick->flag |= NODE_LINK_TEMP_HIGHLIGHT; + ED_area_tag_redraw(CTX_wm_area(C)); + + if (distance_from_socket > trigger_drag_distance) { + pick_link(C, op, nldrag, snode, node, link_to_pick); + } + } +} + static int sort_nodes_locx(const void *a, const void *b) { const bNodeListItem *nli1 = a; @@ -600,6 +732,13 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeLink *link) tlink = NULL; to_count--; } + else if (tlink->fromsock == from) { + /* Also remove link if it comes from the same output. */ + nodeRemLink(ntree, tlink); + tlink = NULL; + to_count--; + from_count--; + } } } } @@ -663,7 +802,7 @@ static void node_link_exit(bContext *C, wmOperator *op, bool apply_links) snode_dag_update(C, snode); } - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); /* links->data pointers are either held by the tree or freed already */ BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); @@ -736,7 +875,7 @@ static void node_link_find_socket(bContext *C, wmOperator *op, float cursor[2]) } } -/* loop that adds a nodelink, called by function below */ +/* Loop that adds a node-link, called by function below. */ /* in_out = starting socket */ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) { @@ -748,10 +887,15 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) switch (event->type) { case MOUSEMOVE: - node_link_find_socket(C, op, cursor); + if (nldrag->from_multi_input_socket && !RNA_boolean_get(op->ptr, "has_link_picked")) { + pick_input_link_by_link_intersect(C, op, nldrag, cursor); + } + else { + node_link_find_socket(C, op, cursor); - node_link_update_header(C, nldrag); - ED_region_tag_redraw(region); + node_link_update_header(C, nldrag); + ED_region_tag_redraw(region); + } break; case LEFTMOUSE: @@ -762,6 +906,8 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) ED_workspace_status_text(C, NULL); ED_region_tag_redraw(region); + SpaceNode *snode = CTX_wm_space_node(C); + clear_picking_highlight(&snode->edittree->links); return OPERATOR_FINISHED; } break; @@ -817,16 +963,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor /* dragged links are fixed on output side */ nldrag->in_out = SOCK_OUT; /* create a new link */ - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - oplink->fromnode = node; - oplink->fromsock = sock; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, node)) { - oplink->flag |= NODE_LINK_TEST; - } + LinkData *linkdata = create_drag_link(bmain, snode, node, sock); BLI_addtail(&nldrag->links, linkdata); } @@ -836,31 +973,38 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); const int num_links = nodeCountSocketLinks(snode->edittree, sock); - int link_limit = nodeSocketLinkLimit(sock); - if (num_links > 0 && (num_links >= link_limit || detach)) { + if (num_links > 0) { /* dragged links are fixed on output side */ nldrag->in_out = SOCK_OUT; /* detach current links and store them in the operator data */ + bNodeLink *link_to_pick; LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &snode->edittree->links) { if (link->tosock == sock) { - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - *oplink = *link; - oplink->next = oplink->prev = NULL; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, link->tonode)) { - oplink->flag |= NODE_LINK_TEST; + if (sock->flag & SOCK_MULTI_INPUT) { + nldrag->from_multi_input_socket = true; } + link_to_pick = link; + } + } - BLI_addtail(&nldrag->links, linkdata); - nodeRemLink(snode->edittree, link); + if (link_to_pick != NULL && !nldrag->from_multi_input_socket) { + LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); + bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); + linkdata->data = oplink; + *oplink = *link_to_pick; + oplink->next = oplink->prev = NULL; + oplink->flag |= NODE_LINK_VALID; + oplink->flag &= ~NODE_LINK_TEST; + if (node_connected_to_output(bmain, snode->edittree, link_to_pick->tonode)) { + oplink->flag |= NODE_LINK_TEST; + } - /* send changed event to original link->tonode */ - if (node) { - snode_update(snode, node); - } + BLI_addtail(&nldrag->links, linkdata); + nodeRemLink(snode->edittree, link_to_pick); + + /* send changed event to original link->tonode */ + if (node) { + snode_update(snode, node); } } } @@ -868,16 +1012,7 @@ static bNodeLinkDrag *node_link_init(Main *bmain, SpaceNode *snode, float cursor /* dragged links are fixed on input side */ nldrag->in_out = SOCK_IN; /* create a new link */ - LinkData *linkdata = MEM_callocN(sizeof(LinkData), "drag link op link data"); - bNodeLink *oplink = MEM_callocN(sizeof(bNodeLink), "drag link op link"); - linkdata->data = oplink; - oplink->tonode = node; - oplink->tosock = sock; - oplink->flag |= NODE_LINK_VALID; - oplink->flag &= ~NODE_LINK_TEST; - if (node_connected_to_output(bmain, snode->edittree, node)) { - oplink->flag |= NODE_LINK_TEST; - } + LinkData *linkdata = create_drag_link(bmain, snode, node, sock); BLI_addtail(&nldrag->links, linkdata); } @@ -896,6 +1031,9 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) float cursor[2]; UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); + RNA_float_set_array(op->ptr, "drag_start", cursor); + RNA_int_set(op->ptr, "last_picked_link_index", -1); + RNA_boolean_set(op->ptr, "has_link_picked", false); ED_preview_kill_jobs(CTX_wm_manager(C), bmain); @@ -903,7 +1041,7 @@ static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) if (nldrag) { op->customdata = nldrag; - BLI_addtail(&snode->linkdrag, nldrag); + BLI_addtail(&snode->runtime->linkdrag, nldrag); /* add modal handler */ WM_event_add_modal_handler(C, op); @@ -918,10 +1056,11 @@ static void node_link_cancel(bContext *C, wmOperator *op) SpaceNode *snode = CTX_wm_space_node(C); bNodeLinkDrag *nldrag = op->customdata; - BLI_remlink(&snode->linkdrag, nldrag); + BLI_remlink(&snode->runtime->linkdrag, nldrag); BLI_freelistN(&nldrag->links); MEM_freeN(nldrag); + clear_picking_highlight(&snode->edittree->links); } void NODE_OT_link(wmOperatorType *ot) @@ -941,7 +1080,38 @@ void NODE_OT_link(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + PropertyRNA *prop; + RNA_def_boolean(ot->srna, "detach", false, "Detach", "Detach and redirect existing links"); + prop = RNA_def_boolean( + ot->srna, + "has_link_picked", + false, + "Has Link Picked", + "The operation has placed a link. Only used for multi-input sockets, where the " + "link is picked later"); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_float_array(ot->srna, + "drag_start", + 2, + 0, + -UI_PRECISION_FLOAT_MAX, + UI_PRECISION_FLOAT_MAX, + "Drag Start", + "The position of the mouse cursor at the start of the operation", + -UI_PRECISION_FLOAT_MAX, + UI_PRECISION_FLOAT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN); + RNA_def_int(ot->srna, + "last_picked_link_index", + -1, + -1, + 4095, + "Last Picked Link Index", + "The index of the last picked link on a multi-input socket", + -1, + 4095); + RNA_def_property_flag(prop, PROP_HIDDEN); } /* ********************** Make Link operator ***************** */ @@ -1513,7 +1683,7 @@ void ED_node_link_intersect_test(ScrArea *area, int test) /* loop over link coords to find shortest dist to * upper left node edge of a intersected line segment */ for (int i = 0; i < NODE_LINK_RESOL; i++) { - /* check if the node rect intersetcts the line from this point to next one */ + /* Check if the node rectangle intersects the line from this point to next one. */ if (BLI_rctf_isect_segment(&select->totr, coord_array[i], coord_array[i + 1])) { /* store the shortest distance to the upper left edge * of all intersections found so far */ @@ -1798,7 +1968,7 @@ static void node_link_insert_offset_ntree(NodeInsertOfsData *iofsd, static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; bool redraw = false; if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) { @@ -1837,7 +2007,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w node->anim_init_locx = node->anim_ofsx = 0.0f; } - snode->iofsd = NULL; + snode->runtime->iofsd = NULL; MEM_freeN(iofsd); return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); @@ -1851,7 +2021,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w static int node_insert_offset_invoke(bContext *C, wmOperator *op, const wmEvent *event) { const SpaceNode *snode = CTX_wm_space_node(C); - NodeInsertOfsData *iofsd = snode->iofsd; + NodeInsertOfsData *iofsd = snode->runtime->iofsd; if (!iofsd || !iofsd->insert) { return OPERATOR_CANCELLED; @@ -1927,7 +2097,7 @@ void ED_node_link_insert(Main *bmain, ScrArea *area) iofsd->prev = link->fromnode; iofsd->next = node; - snode->iofsd = iofsd; + snode->runtime->iofsd = iofsd; } ntreeUpdateTree(bmain, snode->edittree); /* needed for pointers */ diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 5060ac0db8a..1e6ca66dd31 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -26,7 +26,6 @@ #include "DNA_node_types.h" #include "DNA_windowmanager_types.h" -#include "BLI_alloca.h" #include "BLI_lasso_2d.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -62,14 +61,15 @@ #include "node_intern.h" /* own include */ -/* Function to detect if there is a visible view3d that uses workbench in texture mode. +/** + * Function to detect if there is a visible view3d that uses workbench in texture mode. * This function is for fixing T76970 for Blender 2.83. The actual fix should add a mechanism in * the depsgraph that can be used by the draw engines to check if they need to be redrawn. * * We don't want to add these risky changes this close before releasing 2.83 without good testing * hence this workaround. There are still cases were too many updates happen. For example when you * have both a Cycles and workbench with textures viewport. - * */ + */ static bool has_workbench_in_texture_color(const wmWindowManager *wm, const Scene *scene, const Object *ob) diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 553971cd0a5..f0e3f5442cc 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -35,7 +35,6 @@ #include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_main.h" -#include "BKE_scene.h" #include "RNA_access.h" diff --git a/source/blender/editors/space_node/node_toolbar.c b/source/blender/editors/space_node/node_toolbar.c index 7afd3fef4db..2e7d6ab6cd5 100644 --- a/source/blender/editors/space_node/node_toolbar.c +++ b/source/blender/editors/space_node/node_toolbar.c @@ -29,9 +29,6 @@ #include "BKE_screen.h" #include "WM_api.h" -#include "WM_types.h" - -#include "ED_screen.h" #include "node_intern.h" /* own include */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index d938cb38270..8f1dc3c8c3e 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -52,7 +52,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "NOD_composite.h" #include "node_intern.h" /* own include */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index ad7632377a3..73c6a28a5dc 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -35,7 +35,6 @@ #include "BKE_context.h" #include "BKE_lib_id.h" #include "BKE_node.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "ED_node.h" @@ -321,18 +320,25 @@ static void node_free(SpaceLink *sl) LISTBASE_FOREACH_MUTABLE (bNodeTreePath *, path, &snode->treepath) { MEM_freeN(path); } + + MEM_SAFE_FREE(snode->runtime); } /* spacetype; init callback */ -static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(area)) +static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *area) { + SpaceNode *snode = (SpaceNode *)area->spacedata.first; + + if (snode->runtime == NULL) { + snode->runtime = MEM_callocN(sizeof(SpaceNode_Runtime), __func__); + } } -static void node_area_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void node_area_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* note, ED_area_tag_refresh will re-execute compositor */ SpaceNode *snode = area->spacedata.first; /* shaderfrom is only used for new shading nodes, otherwise all shaders are from objects */ @@ -362,7 +368,7 @@ static void node_area_listener(wmWindow *UNUSED(win), case ND_TRANSFORM_DONE: if (ED_node_is_compositor(snode)) { if (snode->flag & SNODE_AUTO_RENDER) { - snode->recalc = 1; + snode->runtime->recalc = true; ED_area_tag_refresh(area); } } @@ -521,8 +527,8 @@ static void node_area_refresh(const struct bContext *C, ScrArea *area) Scene *scene = (Scene *)snode->id; if (scene->use_nodes) { /* recalc is set on 3d view changes for auto compo */ - if (snode->recalc) { - snode->recalc = 0; + if (snode->runtime->recalc) { + snode->runtime->recalc = false; node_render_changed_exec((struct bContext *)C, NULL); } else { @@ -546,8 +552,10 @@ static SpaceLink *node_duplicate(SpaceLink *sl) BLI_duplicatelist(&snoden->treepath, &snode->treepath); - /* clear or remove stuff from old */ - BLI_listbase_clear(&snoden->linkdrag); + if (snode->runtime != NULL) { + snoden->runtime = MEM_dupallocN(snode->runtime); + BLI_listbase_clear(&snoden->runtime->linkdrag); + } /* Note: no need to set node tree user counts, * the editor only keeps at least 1 (id_us_ensure_real), @@ -589,6 +597,16 @@ static void node_toolbar_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } +void ED_node_cursor_location_get(const SpaceNode *snode, float value[2]) +{ + copy_v2_v2(value, snode->runtime->cursor); +} + +void ED_node_cursor_location_set(SpaceNode *snode, const float value[2]) +{ + copy_v2_v2(snode->runtime->cursor, value); +} + static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) { SpaceNode *snode = area->spacedata.first; @@ -597,15 +615,15 @@ static void node_cursor(wmWindow *win, ScrArea *area, ARegion *region) UI_view2d_region_to_view(®ion->v2d, win->eventstate->x - region->winrct.xmin, win->eventstate->y - region->winrct.ymin, - &snode->cursor[0], - &snode->cursor[1]); + &snode->runtime->cursor[0], + &snode->runtime->cursor[1]); - /* here snode->cursor is used to detect the node edge for sizing */ - node_set_cursor(win, snode, snode->cursor); + /* here snode->runtime->cursor is used to detect the node edge for sizing */ + node_set_cursor(win, snode, snode->runtime->cursor); - /* XXX snode->cursor is in placing new nodes space */ - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + /* XXX snode->runtime->cursor is in placing new nodes space */ + snode->runtime->cursor[0] /= UI_DPI_FAC; + snode->runtime->cursor[1] /= UI_DPI_FAC; } /* Initialize main region, setting handlers. */ @@ -645,7 +663,7 @@ static bool node_ima_drop_poll(bContext *UNUSED(C), /* rule might not work? */ return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_get_local_ID(drag, ID_IM) != NULL; + return WM_drag_is_ID_type(drag, ID_IM); } static bool node_mask_drop_poll(bContext *UNUSED(C), @@ -653,19 +671,19 @@ static bool node_mask_drop_poll(bContext *UNUSED(C), const wmEvent *UNUSED(event), const char **UNUSED(r_tooltip)) { - return WM_drag_get_local_ID(drag, ID_MSK) != NULL; + return WM_drag_is_ID_type(drag, ID_MSK); } static void node_id_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); } static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); if (id) { RNA_string_set(drop->ptr, "name", id->name + 2); @@ -703,12 +721,10 @@ static void node_header_region_draw(const bContext *C, ARegion *region) } /* used for header + main region */ -static void node_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void node_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; wmGizmoMap *gzmap = region->gizmo_map; /* context changes */ diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index e0262371559..d54265aa292 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC ../../makesrna ../../sequencer ../../windowmanager + ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/space_outliner/outliner_context.c b/source/blender/editors/space_outliner/outliner_context.c index a314a640e42..e2b3b79e027 100644 --- a/source/blender/editors/space_outliner/outliner_context.c +++ b/source/blender/editors/space_outliner/outliner_context.c @@ -27,8 +27,6 @@ #include "DNA_space_types.h" -#include "RNA_access.h" - #include "outliner_intern.h" static void outliner_context_selected_ids_recursive(const ListBase *subtree, diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index ab515c0c3a8..70aeef76234 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -140,6 +140,11 @@ static TreeElement *outliner_drop_insert_find(bContext *C, TreeElement *te_hovered; float view_mval[2]; + /* Empty tree, e.g. while filtered. */ + if (BLI_listbase_is_empty(&space_outliner->tree)) { + return NULL; + } + UI_view2d_region_to_view( ®ion->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]); te_hovered = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 8104c1e0d58..76c710b3db1 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -314,7 +314,7 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, /** * Object properties. - * */ + */ static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void *poin2) { Object *ob = poin; @@ -324,7 +324,7 @@ static void outliner__object_set_flag_recursive_fn(bContext *C, void *poin, void /** * Base properties. - * */ + */ static void outliner__base_set_flag_recursive_fn(bContext *C, void *poin, void *poin2) { Base *base = poin; @@ -697,13 +697,13 @@ static void namebutton_fn(bContext *C, void *tsep, char *oldname) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); } DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE); - WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } default: - WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); break; } + WM_event_add_notifier(C, NC_ID | NA_RENAME, NULL); + /* Check the library target exists */ if (te->idcode == ID_LI) { Library *lib = (Library *)tselem->id; @@ -2287,12 +2287,6 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case TSE_R_LAYER: data.icon = ICON_RENDER_RESULT; break; - case TSE_LINKED_LAMP: - data.icon = ICON_LIGHT_DATA; - break; - case TSE_LINKED_MAT: - data.icon = ICON_MATERIAL_DATA; - break; case TSE_POSEGRP_BASE: case TSE_POSEGRP: data.icon = ICON_GROUP_BONE; @@ -2695,13 +2689,16 @@ static void outliner_draw_iconrow_number(const uiFontStyle *fstyle, float offset_x = (float)offsx + UI_UNIT_X * 0.35f; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, - offset_x + ufac, - (float)ys - UI_UNIT_Y * 0.2f + ufac, - offset_x + UI_UNIT_X - ufac, - (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, - (float)UI_UNIT_Y / 2.0f - ufac, - color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = offset_x + ufac, + .xmax = offset_x + UI_UNIT_X - ufac, + .ymin = (float)ys - UI_UNIT_Y * 0.2f + ufac, + .ymax = (float)ys - UI_UNIT_Y * 0.2f + UI_UNIT_Y - ufac, + }, + true, + (float)UI_UNIT_Y / 2.0f - ufac, + color); /* Now the numbers. */ uchar text_col[4]; @@ -2751,8 +2748,26 @@ static void outliner_draw_active_indicator(const float minx, const float radius = UI_UNIT_Y / 4.0f; UI_draw_roundbox_corner_set(UI_CNR_ALL); - UI_draw_roundbox_aa(true, minx, miny + ufac, maxx, maxy - ufac, radius, icon_color); - UI_draw_roundbox_aa(false, minx, miny + ufac, maxx, maxy - ufac, radius, icon_border); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = minx, + .xmax = maxx, + .ymin = miny + ufac, + .ymax = maxy - ufac, + }, + true, + radius, + icon_color); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = minx, + .xmax = maxx, + .ymin = miny + ufac, + .ymax = maxy - ufac, + }, + false, + radius, + icon_border); GPU_blend(GPU_BLEND_ALPHA); /* Roundbox disables. */ } @@ -3038,7 +3053,7 @@ static void outliner_draw_tree_element(bContext *C, } else { active = tree_element_type_active(C, tvc, space_outliner, te, tselem, OL_SETSEL_NONE, false); - /* active collection*/ + /* Active collection. */ } /* active circle */ @@ -3058,7 +3073,7 @@ static void outliner_draw_tree_element(bContext *C, } else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) { - /* open/close icon, only when sublevels, except for scene */ + /* Open/close icon, only when sub-levels, except for scene. */ int icon_x = startx; /* Icons a bit higher. */ @@ -3496,7 +3511,7 @@ static void outliner_draw_tree(bContext *C, GPU_scissor(0, 0, mask_x, region->winy); } - /* Draw hierarhcy lines for collections and object children. */ + /* Draw hierarchy lines for collections and object children. */ starty = (int)region->v2d.tot.ymax - OL_Y_OFFSET; startx = mode_column_offset + UI_UNIT_X / 2 - (U.pixelsize + 1) / 2; outliner_draw_hierarchy_lines(space_outliner, &space_outliner->tree, startx, &starty); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index acda5ae82f0..7e5b0c90714 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -21,22 +21,9 @@ * \ingroup spoutliner */ -#include "MEM_guardedalloc.h" - -#include "DNA_collection_types.h" - -#include "BLT_translation.h" - -#include "RNA_access.h" - -#include "UI_interface.h" -#include "UI_view2d.h" - #include "WM_api.h" -#include "WM_types.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "outliner_intern.h" diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index 600047c4b11..4a58736966c 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -927,25 +927,6 @@ static eOLDrawState tree_element_active_sequence_dup(Scene *scene, return OL_DRAWSEL_NONE; } -static eOLDrawState tree_element_active_keymap_item(bContext *UNUSED(C), - Scene *UNUSED(scene), - ViewLayer *UNUSED(sl), - TreeElement *te, - TreeStoreElem *UNUSED(tselem), - const eOLSetState set) -{ - wmKeyMapItem *kmi = te->directdata; - - if (set == OL_SETSEL_NONE) { - if (kmi->flag & KMI_INACTIVE) { - return OL_DRAWSEL_NONE; - } - return OL_DRAWSEL_NORMAL; - } - kmi->flag ^= KMI_INACTIVE; - return OL_DRAWSEL_NONE; -} - static eOLDrawState tree_element_active_master_collection(bContext *C, TreeElement *UNUSED(te), const eOLSetState set) @@ -1071,8 +1052,6 @@ eOLDrawState tree_element_type_active(bContext *C, return tree_element_active_sequence(C, tvc->scene, te, tselem, set); case TSE_SEQUENCE_DUP: return tree_element_active_sequence_dup(tvc->scene, te, tselem, set); - case TSE_KEYMAP_ITEM: - return tree_element_active_keymap_item(C, tvc->scene, tvc->view_layer, te, tselem, set); case TSE_GP_LAYER: return tree_element_active_gplayer(C, tvc->scene, te, tselem, set); break; @@ -1543,7 +1522,7 @@ static bool outliner_is_co_within_active_mode_column(bContext *C, * Action to run when clicking in the outliner, * * May expend/collapse branches or activate items. - * */ + */ static int outliner_item_do_activate_from_cursor(bContext *C, const int mval[2], const bool extend, diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c index 0b2d1ce34ec..8bd5e3a130a 100644 --- a/source/blender/editors/space_outliner/outliner_sync.c +++ b/source/blender/editors/space_outliner/outliner_sync.c @@ -38,7 +38,6 @@ #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_main.h" -#include "BKE_object.h" #include "DEG_depsgraph.h" @@ -378,7 +377,7 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_out selected_items_free(&selected_items); - /* Tag for updates and clear dirty flag toprevent a sync to the outliner on draw */ + /* Tag for updates and clear dirty flag to prevent a sync to the outliner on draw. */ if (sync_types.object) { space_outliner->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT; DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); @@ -545,7 +544,7 @@ static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData active_data->sequence = SEQ_select_active_get(scene); } -/* If outliner is dirty sync selection from view layer and sequwncer */ +/* If outliner is dirty sync selection from view layer and sequencer. */ void outliner_sync_selection(const bContext *C, SpaceOutliner *space_outliner) { /* Set which types of data to sync from sync dirty flag and outliner display mode */ diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 2a2803c58dd..8b522d41af8 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -23,6 +23,8 @@ #include "MEM_guardedalloc.h" +#include "CLG_log.h" + #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_collection_types.h" @@ -92,6 +94,8 @@ #include "outliner_intern.h" +static CLG_LogRef LOG = {"ed.outliner.tools"}; + /* -------------------------------------------------------------------- */ /** \name ID/Library/Data Set/Un-link Utilities * \{ */ @@ -790,7 +794,7 @@ static void id_override_library_create_fn(bContext *C, id_root->tag |= LIB_TAG_DOIT; - /* For now, remapp all local usages of linked ID to local override one here. */ + /* For now, remap all local usages of linked ID to local override one here. */ ID *id_iter; FOREACH_MAIN_ID_BEGIN (bmain, id_iter) { if (ID_IS_LINKED(id_iter)) { @@ -824,6 +828,9 @@ static void id_override_library_create_fn(bContext *C, BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); } } + else { + CLOG_WARN(&LOG, "Could not create library override for data block '%s'", id_root->name); + } } static void id_override_library_reset_fn(bContext *C, @@ -852,6 +859,9 @@ static void id_override_library_reset_fn(bContext *C, WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); } + else { + CLOG_WARN(&LOG, "Could not reset library override of data block '%s'", id_root->name); + } } static void id_override_library_resync_fn(bContext *C, @@ -883,6 +893,9 @@ static void id_override_library_resync_fn(bContext *C, BKE_lib_override_library_resync(bmain, scene, CTX_data_view_layer(C), id_root); } + else { + CLOG_WARN(&LOG, "Could not resync library override of data block '%s'", id_root->name); + } } static void id_override_library_delete_fn(bContext *C, @@ -914,6 +927,9 @@ static void id_override_library_delete_fn(bContext *C, BKE_lib_override_library_delete(bmain, id_root); } + else { + CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name); + } } static void id_fake_user_set_fn(bContext *UNUSED(C), @@ -1789,21 +1805,44 @@ static bool outliner_id_operation_item_poll(bContext *C, const int enum_value) { SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); + TreeElement *te = get_target_element(space_outliner); + TreeStoreElem *tselem = TREESTORE(te); + if (!TSE_IS_REAL_ID(tselem)) { + return false; + } + + Object *ob = NULL; + if (GS(tselem->id->name) == ID_OB) { + ob = (Object *)tselem->id; + } switch (enum_value) { case OUTLINER_IDOP_MARK_ASSET: case OUTLINER_IDOP_CLEAR_ASSET: return U.experimental.use_asset_browser; case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: + if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id)) { + return true; + } + return false; case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY: - return true; + if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id) || (ID_IS_LINKED(tselem->id))) { + return true; + } + return false; + case OUTLINER_IDOP_OVERRIDE_LIBRARY_PROXY_CONVERT: + if (ob != NULL && ob->proxy != NULL) { + return true; + } + return false; case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: - return true; case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY: - return true; case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: - return true; + if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id)) { + return true; + } + return false; case OUTLINER_IDOP_SINGLE: if (!space_outliner || ELEM(space_outliner->outlinevis, SO_SCENES, SO_VIEW_LAYER)) { return true; diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index acfeccca175..f94f19246fa 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -167,8 +167,6 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) static void check_persistent( SpaceOutliner *space_outliner, TreeElement *te, ID *id, short type, short nr) { - TreeStoreElem *tselem; - if (space_outliner->treestore == NULL) { /* if treestore was not created in readfile.c, create it here */ space_outliner->treestore = BLI_mempool_create( @@ -181,7 +179,8 @@ static void check_persistent( /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id); + TreeStoreElem *tselem = BKE_outliner_treehash_lookup_unused( + space_outliner->runtime->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -204,8 +203,7 @@ static void check_persistent( void outliner_free_tree(ListBase *tree) { - for (TreeElement *element = tree->first, *element_next; element; element = element_next) { - element_next = element->next; + LISTBASE_FOREACH_MUTABLE (TreeElement *, element, tree) { outliner_free_tree_element(element, tree); } } @@ -271,8 +269,8 @@ static void outliner_add_bone(SpaceOutliner *space_outliner, te->name = curBone->name; te->directdata = curBone; - for (curBone = curBone->childbase.first; curBone; curBone = curBone->next) { - outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, a); + LISTBASE_FOREACH (Bone *, child_bone, &curBone->childbase) { + outliner_add_bone(space_outliner, &te->subtree, id, child_bone, te, a); } } @@ -381,35 +379,30 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (ob->pose) { bArmature *arm = ob->data; - bPoseChannel *pchan; TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_POSE_BASE, 0); - tenla->name = IFACE_("Pose"); /* channels undefined in editmode, but we want the 'tenla' pose icon itself */ if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) { - TreeElement *ten; - int a = 0, const_index = 1000; /* ensure unique id for bone constraints */ - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next, a++) { - ten = outliner_add_element( + int const_index = 1000; /* ensure unique id for bone constraints */ + int a; + LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob->pose->chanbase, a) { + TreeElement *ten = outliner_add_element( space_outliner, &tenla->subtree, ob, tenla, TSE_POSE_CHANNEL, a); ten->name = pchan->name; ten->directdata = pchan; pchan->temp = (void *)ten; - if (pchan->constraints.first) { + if (!BLI_listbase_is_empty(&pchan->constraints)) { /* Object *target; */ - bConstraint *con; - TreeElement *ten1; TreeElement *tenla1 = outliner_add_element( space_outliner, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0); + tenla1->name = IFACE_("Constraints"); /* char *str; */ - tenla1->name = IFACE_("Constraints"); - for (con = pchan->constraints.first; con; con = con->next, const_index++) { - ten1 = outliner_add_element( + LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { + TreeElement *ten1 = outliner_add_element( space_outliner, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index); #if 0 /* disabled as it needs to be reworked for recoded constraints system */ target = get_constraint_target(con, &str); @@ -427,15 +420,16 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, ten1->directdata = con; /* possible add all other types links? */ } + const_index++; } } /* make hierarchy */ - ten = tenla->subtree.first; + TreeElement *ten = tenla->subtree.first; while (ten) { TreeElement *nten = ten->next, *par; tselem = TREESTORE(ten); if (tselem->type == TSE_POSE_CHANNEL) { - pchan = (bPoseChannel *)ten->directdata; + bPoseChannel *pchan = (bPoseChannel *)ten->directdata; if (pchan->parent) { BLI_remlink(&tenla->subtree, ten); par = (TreeElement *)pchan->parent->temp; @@ -448,17 +442,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* Pose Groups */ - if (ob->pose->agroups.first) { - bActionGroup *agrp; + if (!BLI_listbase_is_empty(&ob->pose->agroups)) { TreeElement *ten_bonegrp = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0); - int a = 0; - ten_bonegrp->name = IFACE_("Bone Groups"); - for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) { - TreeElement *ten; - ten = outliner_add_element( - space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, a); + + int index; + LISTBASE_FOREACH_INDEX (bActionGroup *, agrp, &ob->pose->agroups, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &ten_bonegrp->subtree, ob, ten_bonegrp, TSE_POSEGRP, index); ten->name = agrp->name; ten->directdata = agrp; } @@ -469,18 +461,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, outliner_add_element(space_outliner, &te->subtree, ob->mat[a], te, 0, a); } - if (ob->constraints.first) { - /* Object *target; */ - bConstraint *con; - TreeElement *ten; + if (!BLI_listbase_is_empty(&ob->constraints)) { TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0); - /* char *str; */ - int a; - tenla->name = IFACE_("Constraints"); - for (con = ob->constraints.first, a = 0; con; con = con->next, a++) { - ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a); + + int index; + LISTBASE_FOREACH_INDEX (bConstraint *, con, &ob->constraints, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, index); #if 0 /* disabled due to constraints system targets recode... code here needs review */ target = get_constraint_target(con, &str); if (str && str[0]) { @@ -499,14 +488,13 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } } - if (ob->modifiers.first) { - ModifierData *md; + if (!BLI_listbase_is_empty(&ob->modifiers)) { TreeElement *ten_mod = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); - int index; - ten_mod->name = IFACE_("Modifiers"); - for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) { + + int index; + LISTBASE_FOREACH_INDEX (ModifierData *, md, &ob->modifiers, index) { TreeElement *ten = outliner_add_element( space_outliner, &ten_mod->subtree, ob, ten_mod, TSE_MODIFIER, index); ten->name = md->name; @@ -559,8 +547,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (!BLI_listbase_is_empty(&ob->greasepencil_modifiers)) { TreeElement *ten_mod = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); - ten_mod->name = IFACE_("Modifiers"); + int index; LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &ob->greasepencil_modifiers, index) { TreeElement *ten = outliner_add_element( @@ -599,8 +587,8 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, if (!BLI_listbase_is_empty(&ob->shader_fx)) { TreeElement *ten_fx = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_GPENCIL_EFFECT_BASE, 0); - ten_fx->name = IFACE_("Effects"); + int index; LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &ob->shader_fx, index) { TreeElement *ten = outliner_add_element( @@ -620,16 +608,15 @@ static void outliner_add_object_contents(SpaceOutliner *space_outliner, } /* vertex groups */ - if (ob->defbase.first) { - bDeformGroup *defgroup; - TreeElement *ten; + if (!BLI_listbase_is_empty(&ob->defbase)) { TreeElement *tenla = outliner_add_element( space_outliner, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); - int a; - tenla->name = IFACE_("Vertex Groups"); - for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) { - ten = outliner_add_element(space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a); + + int index; + LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, &ob->defbase, index) { + TreeElement *ten = outliner_add_element( + space_outliner, &tenla->subtree, ob, tenla, TSE_DEFGROUP, index); ten->name = defgroup->name; ten->directdata = defgroup; } @@ -694,14 +681,13 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_ME: { Mesh *me = (Mesh *)id; - int a; if (outliner_animdata_test(me->adt)) { outliner_add_element(space_outliner, &te->subtree, me, te, TSE_ANIM_DATA, 0); } outliner_add_element(space_outliner, &te->subtree, me->key, te, 0, 0); - for (a = 0; a < me->totcol; a++) { + for (int a = 0; a < me->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, me->mat[a], te, 0, a); } /* could do tfaces with image links, but the images are not grouped nicely. @@ -710,33 +696,30 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CU: { Curve *cu = (Curve *)id; - int a; if (outliner_animdata_test(cu->adt)) { outliner_add_element(space_outliner, &te->subtree, cu, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < cu->totcol; a++) { + for (int a = 0; a < cu->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, cu->mat[a], te, 0, a); } break; } case ID_MB: { MetaBall *mb = (MetaBall *)id; - int a; if (outliner_animdata_test(mb->adt)) { outliner_add_element(space_outliner, &te->subtree, mb, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < mb->totcol; a++) { + for (int a = 0; a < mb->totcol; a++) { outliner_add_element(space_outliner, &te->subtree, mb->mat[a], te, 0, a); } break; } case ID_MA: { Material *ma = (Material *)id; - if (outliner_animdata_test(ma->adt)) { outliner_add_element(space_outliner, &te->subtree, ma, te, TSE_ANIM_DATA, 0); } @@ -744,7 +727,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_TE: { Tex *tex = (Tex *)id; - if (outliner_animdata_test(tex->adt)) { outliner_add_element(space_outliner, &te->subtree, tex, te, TSE_ANIM_DATA, 0); } @@ -753,7 +735,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CA: { Camera *ca = (Camera *)id; - if (outliner_animdata_test(ca->adt)) { outliner_add_element(space_outliner, &te->subtree, ca, te, TSE_ANIM_DATA, 0); } @@ -761,7 +742,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_CF: { CacheFile *cache_file = (CacheFile *)id; - if (outliner_animdata_test(cache_file->adt)) { outliner_add_element(space_outliner, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0); } @@ -770,7 +750,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LA: { Light *la = (Light *)id; - if (outliner_animdata_test(la->adt)) { outliner_add_element(space_outliner, &te->subtree, la, te, TSE_ANIM_DATA, 0); } @@ -778,7 +757,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_SPK: { Speaker *spk = (Speaker *)id; - if (outliner_animdata_test(spk->adt)) { outliner_add_element(space_outliner, &te->subtree, spk, te, TSE_ANIM_DATA, 0); } @@ -786,7 +764,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LP: { LightProbe *prb = (LightProbe *)id; - if (outliner_animdata_test(prb->adt)) { outliner_add_element(space_outliner, &te->subtree, prb, te, TSE_ANIM_DATA, 0); } @@ -794,7 +771,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_WO: { World *wrld = (World *)id; - if (outliner_animdata_test(wrld->adt)) { outliner_add_element(space_outliner, &te->subtree, wrld, te, TSE_ANIM_DATA, 0); } @@ -802,7 +778,6 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_KE: { Key *key = (Key *)id; - if (outliner_animdata_test(key->adt)) { outliner_add_element(space_outliner, &te->subtree, key, te, TSE_ANIM_DATA, 0); } @@ -815,27 +790,25 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_AR: { bArmature *arm = (bArmature *)id; - int a = 0; if (outliner_animdata_test(arm->adt)) { outliner_add_element(space_outliner, &te->subtree, arm, te, TSE_ANIM_DATA, 0); } if (arm->edbo) { - EditBone *ebone; - TreeElement *ten; - - for (ebone = arm->edbo->first; ebone; ebone = ebone->next, a++) { - ten = outliner_add_element(space_outliner, &te->subtree, id, te, TSE_EBONE, a); + int a = 0; + LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm->edbo, a) { + TreeElement *ten = outliner_add_element( + space_outliner, &te->subtree, id, te, TSE_EBONE, a); ten->directdata = ebone; ten->name = ebone->name; ebone->temp.p = ten; } /* make hierarchy */ - ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; + TreeElement *ten = arm->edbo->first ? ((EditBone *)arm->edbo->first)->temp.p : NULL; while (ten) { TreeElement *nten = ten->next, *par; - ebone = (EditBone *)ten->directdata; + EditBone *ebone = (EditBone *)ten->directdata; if (ebone->parent) { BLI_remlink(&te->subtree, ten); par = ebone->parent->temp.p; @@ -852,9 +825,9 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, /* pass */ } else { - Bone *curBone; - for (curBone = arm->bonebase.first; curBone; curBone = curBone->next) { - outliner_add_bone(space_outliner, &te->subtree, id, curBone, te, &a); + int a = 0; + LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { + outliner_add_bone(space_outliner, &te->subtree, id, bone, te, &a); } } } @@ -862,13 +835,12 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_LS: { FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; - int a; if (outliner_animdata_test(linestyle->adt)) { outliner_add_element(space_outliner, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0); } - for (a = 0; a < MAX_MTEX; a++) { + for (int a = 0; a < MAX_MTEX; a++) { if (linestyle->mtex[a]) { outliner_add_element(space_outliner, &te->subtree, linestyle->mtex[a]->tex, te, 0, a); } @@ -877,17 +849,16 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, } case ID_GD: { bGPdata *gpd = (bGPdata *)id; - bGPDlayer *gpl; - int a = 0; if (outliner_animdata_test(gpd->adt)) { outliner_add_element(space_outliner, &te->subtree, gpd, te, TSE_ANIM_DATA, 0); } /* TODO: base element for layers? */ - for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) { - outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, a); - a++; + int index = 0; + LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd->layers) { + outliner_add_element(space_outliner, &te->subtree, gpl, te, TSE_GP_LAYER, index); + index++; } break; } @@ -957,8 +928,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, short type, short index) { - TreeElement *te; - TreeStoreElem *tselem; ID *id = idv; if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { @@ -985,12 +954,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, BLI_assert(TREESTORE_ID_TYPE(id)); } - te = MEM_callocN(sizeof(TreeElement), "tree elem"); + TreeElement *te = MEM_callocN(sizeof(TreeElement), __func__); /* add to the visual tree */ BLI_addtail(lb, te); /* add to the storage */ check_persistent(space_outliner, te, id, type, index); - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* if we are searching for something expand to see child elements */ if (SEARCHING_OUTLINER(space_outliner)) { @@ -1022,9 +991,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, else if (type == TSE_ID_BASE) { /* pass */ } - else if (ELEM(type, TSE_KEYMAP, TSE_KEYMAP_ITEM)) { - /* pass */ - } else { /* Other cases must be caught above. */ BLI_assert(TSE_IS_REAL_ID(tselem)); @@ -1062,7 +1028,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_SEQUENCE) { Sequence *seq = (Sequence *)idv; - Sequence *p; /* * The idcode is a little hack, but the outliner @@ -1081,10 +1046,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, */ if (seq->type == SEQ_TYPE_META) { - p = seq->seqbase.first; - while (p) { + LISTBASE_FOREACH (Sequence *, p, &seq->seqbase) { outliner_add_element(space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); - p = p->next; } } else { @@ -1112,17 +1075,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->name = seq->strip->stripdata->name; } else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - PointerRNA pptr, propptr, *ptr = (PointerRNA *)idv; - PropertyRNA *prop, *iterprop; - PropertyType proptype; + PointerRNA *ptr = (PointerRNA *)idv; /* Don't display arrays larger, weak but index is stored as a short, * also the outliner isn't intended for editing such large data-sets. */ BLI_STATIC_ASSERT(sizeof(te->index) == 2, "Index is no longer short!") const int tot_limit = SHRT_MAX; - int a, tot; - /* we do lazy build, for speed and to avoid infinite recursion */ if (ptr->data == NULL) { @@ -1144,8 +1103,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, tselem->flag &= ~TSE_CHILDSEARCH; } - iterprop = RNA_struct_iterator_property(ptr->type); - tot = RNA_property_collection_length(ptr, iterprop); + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); + int tot = RNA_property_collection_length(ptr, iterprop); CLAMP_MAX(tot, tot_limit); /* auto open these cases */ @@ -1156,7 +1115,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { + PointerRNA propptr; RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr); if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) { outliner_add_element( @@ -1172,11 +1132,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } else if (type == TSE_RNA_PROPERTY) { /* property */ - iterprop = RNA_struct_iterator_property(ptr->type); + PointerRNA propptr; + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); - prop = propptr.data; - proptype = RNA_property_type(prop); + PropertyRNA *prop = propptr.data; + PropertyType proptype = RNA_property_type(prop); te->name = RNA_property_ui_name(prop); te->directdata = prop; @@ -1188,7 +1149,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } if (proptype == PROP_POINTER) { - pptr = RNA_property_pointer_get(ptr, prop); + PointerRNA pptr = RNA_property_pointer_get(ptr, prop); if (pptr.data) { if (TSELEM_OPEN(tselem, space_outliner)) { @@ -1201,11 +1162,12 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (proptype == PROP_COLLECTION) { - tot = RNA_property_collection_length(ptr, prop); + int tot = RNA_property_collection_length(ptr, prop); CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { + PointerRNA pptr; RNA_property_collection_lookup_int(ptr, prop, a, &pptr); outliner_add_element( space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a); @@ -1216,11 +1178,11 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { - tot = RNA_property_array_length(ptr, prop); + int tot = RNA_property_array_length(ptr, prop); CLAMP_MAX(tot, tot_limit); if (TSELEM_OPEN(tselem, space_outliner)) { - for (a = 0; a < tot; a++) { + for (int a = 0; a < tot; a++) { outliner_add_element( space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a); } @@ -1231,15 +1193,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } } else if (type == TSE_RNA_ARRAY_ELEM) { - char c; - - prop = parent->directdata; + PropertyRNA *prop = parent->directdata; te->directdata = prop; te->rnaptr = *ptr; te->index = index; - c = RNA_property_array_item_char(prop, index); + char c = RNA_property_array_item_char(prop, index); te->name = MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName"); if (c) { @@ -1251,52 +1211,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->flag |= TE_FREE_NAME; } } - else if (type == TSE_KEYMAP) { - wmKeyMap *km = (wmKeyMap *)idv; - wmKeyMapItem *kmi; - char opname[OP_MAX_TYPENAME]; - - te->directdata = idv; - te->name = km->idname; - - if (TSELEM_OPEN(tselem, space_outliner)) { - int a = 0; - - for (kmi = km->items.first; kmi; kmi = kmi->next, a++) { - const char *key = WM_key_event_string(kmi->type, false); - - if (key[0]) { - wmOperatorType *ot = NULL; - - if (kmi->propvalue) { - /* pass */ - } - else { - ot = WM_operatortype_find(kmi->idname, 0); - } - - if (ot || kmi->propvalue) { - TreeElement *ten = outliner_add_element( - space_outliner, &te->subtree, kmi, te, TSE_KEYMAP_ITEM, a); - - ten->directdata = kmi; - - if (kmi->propvalue) { - ten->name = IFACE_("Modal map, not yet"); - } - else { - WM_operator_py_idname(opname, ot->idname); - ten->name = BLI_strdup(opname); - ten->flag |= TE_FREE_NAME; - } - } - } - } - } - else { - te->flag |= TE_LAZY_CLOSED; - } - } return te; } @@ -1344,21 +1258,18 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli /* make sure elements are correctly nested */ void outliner_make_object_parent_hierarchy(ListBase *lb) { - TreeElement *te, *ten, *tep; - TreeStoreElem *tselem; - /* build hierarchy */ /* XXX also, set extents here... */ - te = lb->first; + TreeElement *te = lb->first; while (te) { - ten = te->next; - tselem = TREESTORE(te); + TreeElement *ten = te->next; + TreeStoreElem *tselem = TREESTORE(te); if (tselem->type == 0 && te->idcode == ID_OB) { Object *ob = (Object *)tselem->id; if (ob->parent && ob->parent->id.newid) { BLI_remlink(lb, te); - tep = (TreeElement *)ob->parent->id.newid; + TreeElement *tep = (TreeElement *)ob->parent->id.newid; BLI_addtail(&tep->subtree, te); te->parent = tep; } @@ -1380,10 +1291,9 @@ typedef struct tTreeSort { static int treesort_alpha_ob(const void *v1, const void *v2) { const tTreeSort *x1 = v1, *x2 = v2; - int comp; /* first put objects last (hierarchy) */ - comp = (x1->idcode == ID_OB); + int comp = (x1->idcode == ID_OB); if (x2->idcode == ID_OB) { comp += 2; } @@ -1432,9 +1342,8 @@ static int treesort_child_not_in_collection(const void *v1, const void *v2) static int treesort_alpha(const void *v1, const void *v2) { const tTreeSort *x1 = v1, *x2 = v2; - int comp; - comp = BLI_strcasecmp_natural(x1->name, x2->name); + int comp = BLI_strcasecmp_natural(x1->name, x2->name); if (comp > 0) { return 1; @@ -1489,14 +1398,11 @@ static int treesort_obtype_alpha(const void *v1, const void *v2) /* sort happens on each subtree individual */ static void outliner_sort(ListBase *lb) { - TreeElement *te; - TreeStoreElem *tselem; - - te = lb->last; + TreeElement *te = lb->last; if (te == NULL) { return; } - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* sorting rules; only object lists, ID lists, or deformgroups */ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || @@ -1558,14 +1464,11 @@ static void outliner_sort(ListBase *lb) static void outliner_collections_children_sort(ListBase *lb) { - TreeElement *te; - TreeStoreElem *tselem; - - te = lb->last; + TreeElement *te = lb->last; if (te == NULL) { return; } - tselem = TREESTORE(te); + TreeStoreElem *tselem = TREESTORE(te); /* Sorting rules: only object lists. */ if (tselem->type == 0 && te->idcode == ID_OB) { @@ -1687,8 +1590,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner const float view_co, const float view_co_limit) { - TreeElement *te, *te_sub; - te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); + TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_co); bool (*callback_test)(TreeElement *); if ((space_outliner->outlinevis == SO_VIEW_LAYER) && @@ -1700,7 +1602,7 @@ static TreeElement *outliner_find_first_desired_element_at_y(const SpaceOutliner } while (te != NULL) { - te_sub = outliner_find_first_desired_element_at_y_recursive( + TreeElement *te_sub = outliner_find_first_desired_element_at_y_recursive( space_outliner, te, view_co_limit, callback_test); if (te_sub != NULL) { /* Skip the element if it was not visible to start with. */ @@ -1742,12 +1644,12 @@ static void outliner_store_scrolling_position(SpaceOutliner *space_outliner, ARegion *region, OutlinerTreeElementFocus *focus) { - TreeElement *te; float limit = region->v2d.cur.ymin; outliner_set_coordinates(region, space_outliner); - te = outliner_find_first_desired_element_at_y(space_outliner, region->v2d.cur.ymax, limit); + TreeElement *te = outliner_find_first_desired_element_at_y( + space_outliner, region->v2d.cur.ymax, limit); if (te != NULL) { focus->tselem = TREESTORE(te); diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c index e0d63dfcf81..92178cfdfc9 100644 --- a/source/blender/editors/space_outliner/outliner_utils.c +++ b/source/blender/editors/space_outliner/outliner_utils.c @@ -169,7 +169,7 @@ TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *space_outliner, return te; } -/* Find specific item from the treestore */ +/* Find specific item from the trees-tore. */ TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem) { LISTBASE_FOREACH (TreeElement *, te, lb) { diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 6c9d4433abd..87f81a2cc0e 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -31,9 +31,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_layer.h" #include "BKE_outliner_treehash.h" -#include "BKE_scene.h" #include "BKE_screen.h" #include "ED_screen.h" @@ -51,7 +49,6 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "GPU_framebuffer.h" #include "outliner_intern.h" #include "tree/tree_display.h" @@ -102,12 +99,11 @@ static void outliner_main_region_free(ARegion *UNUSED(region)) { } -static void outliner_main_region_listener(wmWindow *UNUSED(win), - ScrArea *area, - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_main_region_listener(const wmRegionListenerParams *params) { + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; SpaceOutliner *space_outliner = area->spacedata.first; /* context changes */ @@ -264,15 +260,13 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win), } } -static void outliner_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void outliner_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ScrArea *area = params->area; + ARegion *region = params->region; SpaceOutliner *space_outliner = area->spacedata.first; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -301,12 +295,11 @@ static void outliner_header_region_free(ARegion *UNUSED(region)) { } -static void outliner_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void outliner_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -332,7 +325,7 @@ static SpaceLink *outliner_create(const ScrArea *UNUSED(area), const Scene *UNUS space_outliner = MEM_callocN(sizeof(SpaceOutliner), "initoutliner"); space_outliner->spacetype = SPACE_OUTLINER; space_outliner->filter_id_type = ID_GR; - space_outliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE; + space_outliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE | SO_RESTRICT_RENDER; space_outliner->outlinevis = SO_VIEW_LAYER; space_outliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL; space_outliner->flag = SO_SYNC_SELECT | SO_MODE_COLUMN; diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index d2070fb9b1c..6632c057814 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -18,8 +18,6 @@ * \ingroup spoutliner */ -#include "BLI_listbase.h" - #include "DNA_listBase.h" #include "tree_display.hh" diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index ce2a8fa634d..27846614994 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -20,8 +20,6 @@ #include "DNA_listBase.h" -#include "../outliner_intern.h" - #include "tree_element_anim_data.hh" #include "tree_element_driver_base.hh" #include "tree_element_nla.hh" diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 3330ba14530..4ce0e454df8 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -36,7 +36,6 @@ #include "ED_space_api.h" #include "WM_api.h" -#include "WM_types.h" #include "UI_resources.h" #include "UI_view2d.h" @@ -44,7 +43,6 @@ #ifdef WITH_PYTHON #endif -#include "GPU_framebuffer.h" #include "script_intern.h" /* own include */ // static script_run_python(char *funcname, ) @@ -156,13 +154,8 @@ static void script_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void script_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void script_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { -/* context changes */ /* XXX - Todo, need the ScriptSpace accessible to get the python script to run. */ #if 0 BPY_run_script_space_listener() diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index f9076145f2f..e605cf4a889 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -66,8 +66,6 @@ #include "UI_interface.h" -#include "BKE_sound.h" - #ifdef WITH_AUDASPACE # include <AUD_Sequence.h> #endif @@ -1069,6 +1067,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) else if (seq->type == SEQ_TYPE_TEXT) { seq->blend_mode = SEQ_TYPE_ALPHAOVER; } + else if (SEQ_effect_get_num_inputs(seq->type) == 1) { + seq->blend_mode = seq1->blend_mode; + } /* Set channel. If unset, use lowest free one above strips. */ if (!RNA_struct_property_is_set(op->ptr, "channel")) { diff --git a/source/blender/editors/space_sequencer/sequencer_buttons.c b/source/blender/editors/space_sequencer/sequencer_buttons.c index a8c13d63259..11614d94862 100644 --- a/source/blender/editors/space_sequencer/sequencer_buttons.c +++ b/source/blender/editors/space_sequencer/sequencer_buttons.c @@ -35,13 +35,9 @@ #include "BKE_global.h" #include "BKE_screen.h" -#include "ED_gpencil.h" #include "ED_screen.h" #include "ED_sequencer.h" -#include "WM_api.h" -#include "WM_types.h" - #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 72c3e43185b..201df1ceed6 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1447,15 +1447,24 @@ static void sequencer_draw_borders_overlay(const SpaceSeq *sseq, if (sseq->flag & SEQ_SHOW_SAFE_MARGINS) { immUniformThemeColorBlend(TH_VIEW_OVERLAY, TH_BACK, 0.25f); - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); + UI_draw_safe_areas(shdr_pos, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + scene->safe_areas.title, + scene->safe_areas.action); if (sseq->flag & SEQ_SHOW_SAFE_CENTER) { UI_draw_safe_areas(shdr_pos, - x1, - x2, - y1, - y2, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, scene->safe_areas.title_center, scene->safe_areas.action_center); } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7474f8034de..608e220c582 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -28,7 +28,6 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" -#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c index 7bfc8600544..48e6cfcdcd0 100644 --- a/source/blender/editors/space_sequencer/sequencer_ops.c +++ b/source/blender/editors/space_sequencer/sequencer_ops.c @@ -29,12 +29,7 @@ #include "WM_api.h" #include "WM_types.h" -#include "ED_markers.h" -#include "ED_select_utils.h" #include "ED_sequencer.h" -#include "ED_transform.h" /* Transform keymap. */ - -#include "SEQ_sequencer.h" #include "sequencer_intern.h" diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index b9698492aa5..24fa4ad7a17 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -25,7 +25,6 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" -#include "BLI_timecode.h" #include "DNA_scene_types.h" diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index f5707d1ea65..16768e09cb8 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -30,8 +30,6 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "atomic_ops.h" - #include "sequencer_intern.h" /* XXX, why is this function better than BLI_math version? diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 3b476fefe47..ffcb3d35d5a 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -26,6 +26,7 @@ #include <string.h> #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -771,69 +772,83 @@ void SEQUENCER_OT_select(wmOperatorType *ot) * \{ */ /* Run recursively to select linked. */ -static bool select_more_less_seq__internal(Scene *scene, bool sel, const bool linked) +static bool select_linked_internal(Scene *scene) { Editing *ed = SEQ_editing_get(scene, false); - Sequence *seq, *neighbor; - bool changed = false; - int isel; if (ed == NULL) { - return changed; + return false; } - if (sel) { - sel = SELECT; - isel = 0; + bool changed = false; + + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != 0) { + continue; + } + /* Only get unselected neighbors. */ + Sequence *neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, 0); + if (neighbor) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + changed = true; + } + neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, 0); + if (neighbor) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + changed = true; + } } - else { - sel = 0; - isel = SELECT; + + return changed; +} + +/* Select only one linked strip on each side. */ +static bool select_more_less_seq__internal(Scene *scene, bool select_more) +{ + Editing *ed = SEQ_editing_get(scene, false); + + if (ed == NULL) { + return false; } - if (!linked) { - /* If not linked we only want to touch each seq once, newseq. */ - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - seq->tmp = NULL; + GSet *neighbors = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "Linked strips"); + const int neighbor_selection_filter = select_more ? 0 : SELECT; + const int selection_filter = select_more ? SELECT : 0; + + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != selection_filter) { + continue; + } + Sequence *neighbor = find_neighboring_sequence( + scene, seq, SEQ_SIDE_LEFT, neighbor_selection_filter); + if (neighbor) { + BLI_gset_add(neighbors, neighbor); + } + neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, neighbor_selection_filter); + if (neighbor) { + BLI_gset_add(neighbors, neighbor); } } - for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->flag & SELECT) == sel) { - if (linked || (seq->tmp == NULL)) { - /* Only get unselected neighbors. */ - neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel); - if (neighbor) { - if (sel) { - neighbor->flag |= SELECT; - recurs_sel_seq(neighbor); - } - else { - neighbor->flag &= ~SELECT; - } - if (!linked) { - neighbor->tmp = (Sequence *)1; - } - changed = true; - } - neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel); - if (neighbor) { - if (sel) { - neighbor->flag |= SELECT; - recurs_sel_seq(neighbor); - } - else { - neighbor->flag &= ~SELECT; - } - if (!linked) { - neighbor->tmp = (Sequence *)1; - } - changed = true; - } - } + bool changed = false; + GSetIterator gsi; + BLI_gsetIterator_init(&gsi, neighbors); + while (!BLI_gsetIterator_done(&gsi)) { + Sequence *neighbor = BLI_gsetIterator_getKey(&gsi); + if (select_more) { + neighbor->flag |= SELECT; + recurs_sel_seq(neighbor); + } + else { + neighbor->flag &= ~SELECT; } + changed = true; + BLI_gsetIterator_step(&gsi); } + BLI_gset_free(neighbors, NULL); return changed; } @@ -841,7 +856,7 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - if (!select_more_less_seq__internal(scene, true, false)) { + if (!select_more_less_seq__internal(scene, true)) { return OPERATOR_CANCELLED; } @@ -877,7 +892,7 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - if (!select_more_less_seq__internal(scene, false, false)) { + if (!select_more_less_seq__internal(scene, false)) { return OPERATOR_CANCELLED; } @@ -934,7 +949,7 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons selected = 1; while (selected) { - selected = select_more_less_seq__internal(scene, 1, 1); + selected = select_linked_internal(scene); } ED_outliner_select_sync_from_sequence_tag(C); @@ -975,7 +990,7 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) selected = true; while (selected) { - selected = select_more_less_seq__internal(scene, true, true); + selected = select_linked_internal(scene); } ED_outliner_select_sync_from_sequence_tag(C); diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index b11e2a32b87..b17482cd3a4 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -51,7 +51,6 @@ #include "RNA_access.h" -#include "SEQ_sequencer.h" #include "SEQ_utils.h" #include "UI_interface.h" @@ -334,11 +333,11 @@ static SpaceLink *sequencer_duplicate(SpaceLink *sl) return (SpaceLink *)sseqn; } -static void sequencer_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void sequencer_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -534,12 +533,11 @@ static void sequencer_main_region_draw_overlay(const bContext *C, ARegion *regio draw_timeline_seq_display(C, region); } -static void sequencer_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_SCENE: @@ -579,14 +577,12 @@ static void sequencer_main_region_listener(wmWindow *UNUSED(win), } } -static void sequencer_main_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *scene, - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void sequencer_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + Scene *scene = params->scene; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, @@ -746,12 +742,11 @@ static void sequencer_preview_region_draw(const bContext *C, ARegion *region) } } -static void sequencer_preview_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_preview_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: @@ -816,12 +811,11 @@ static void sequencer_buttons_region_draw(const bContext *C, ARegion *region) ED_region_panels(C, region); } -static void sequencer_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void sequencer_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* Context changes. */ switch (wmn->category) { case NC_GPENCIL: @@ -959,7 +953,7 @@ void ED_spacetype_sequencer(void) art->listener = sequencer_main_region_listener; BLI_addhead(&st->regiontypes, art); - /* Hud. */ + /* HUD. */ art = ED_area_type_hud(st->spaceid); BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index ae56b111360..0b4f483c114 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -34,7 +34,6 @@ #include "RNA_access.h" #include "UI_interface.h" -#include "UI_view2d.h" #include "WM_api.h" #include "WM_message.h" @@ -95,12 +94,11 @@ static void statusbar_keymap(struct wmKeyConfig *UNUSED(keyconf)) { } -static void statusbar_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void statusbar_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCREEN: @@ -131,14 +129,11 @@ static void statusbar_header_region_listener(wmWindow *UNUSED(win), } } -static void statusbar_header_region_message_subscribe(const bContext *UNUSED(C), - WorkSpace *UNUSED(workspace), - Scene *UNUSED(scene), - bScreen *UNUSED(screen), - ScrArea *UNUSED(area), - ARegion *region, - struct wmMsgBus *mbus) +static void statusbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index 0f5ac5abe1d..ea55eaea388 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -33,7 +33,6 @@ #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_screen.h" -#include "BKE_text.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -47,7 +46,6 @@ #include "RNA_access.h" -#include "GPU_framebuffer.h" #include "text_format.h" #include "text_intern.h" /* own include */ @@ -122,11 +120,10 @@ static SpaceLink *text_duplicate(SpaceLink *sl) return (SpaceLink *)stextn; } -static void text_listener(wmWindow *UNUSED(win), - ScrArea *area, - wmNotifier *wmn, - Scene *UNUSED(scene)) +static void text_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; SpaceText *st = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 849766851aa..883556948e2 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -722,7 +722,7 @@ static void text_update_drawcache(SpaceText *st, ARegion *region) void text_drawcache_tag_update(SpaceText *st, int full) { - /* this happens if text editor ops are caled from python */ + /* This happens if text editor ops are called from Python. */ if (st == NULL) { return; } @@ -1010,13 +1010,16 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back) BLI_rcti_size_y(&st->runtime.scroll_region_select)); UI_GetThemeColor3fv(TH_HILITE, col); col[3] = 0.18f; - UI_draw_roundbox_aa(true, - st->runtime.scroll_region_select.xmin + 1, - st->runtime.scroll_region_select.ymin, - st->runtime.scroll_region_select.xmax - 1, - st->runtime.scroll_region_select.ymax, - rad, - col); + UI_draw_roundbox_aa( + &(const rctf){ + .xmin = st->runtime.scroll_region_select.xmin + 1, + .xmax = st->runtime.scroll_region_select.xmax - 1, + .ymin = st->runtime.scroll_region_select.ymin, + .ymax = st->runtime.scroll_region_select.ymax, + }, + true, + rad, + col); } /*********************** draw documentation *******************************/ @@ -1180,7 +1183,14 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc } /* not needed but stands out nicer */ - UI_draw_box_shadow(220, x, y - boxh, x + boxw, y); + UI_draw_box_shadow( + &(const rctf){ + .xmin = x, + .xmax = x + boxw, + .ymin = y - boxh, + .ymax = y, + }, + 220); uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c index d099f2a20d8..66765206fa6 100644 --- a/source/blender/editors/space_text/text_format.c +++ b/source/blender/editors/space_text/text_format.c @@ -237,7 +237,7 @@ bool ED_text_is_syntax_highlight_supported(Text *text) const char *text_ext = BLI_path_extension(text->id.name + 2); if (text_ext == NULL) { - /* Extensionless datablocks are considered highlightable as Python. */ + /* Extensionless data-blocks are considered highlightable as Python. */ return true; } text_ext++; /* skip the '.' */ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 932bacfb8a0..526285c076a 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -3832,7 +3832,7 @@ static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEve switch (BKE_text_file_modified_check(text)) { case 1: if (text->flags & TXT_ISDIRTY) { - /* modified locally and externally, ahhh. offer more possibilities. */ + /* Modified locally and externally, ah. offer more possibilities. */ pup = UI_popup_menu_begin( C, IFACE_("File Modified Outside and Inside Blender"), ICON_NONE); layout = UI_popup_menu_layout(pup); diff --git a/source/blender/editors/space_text/text_undo.c b/source/blender/editors/space_text/text_undo.c index 61b786b2b13..f55db8c3cc9 100644 --- a/source/blender/editors/space_text/text_undo.c +++ b/source/blender/editors/space_text/text_undo.c @@ -196,14 +196,19 @@ static bool text_undosys_step_encode(struct bContext *C, return true; } -static void text_undosys_step_decode( - struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, int dir, bool is_final) +static void text_undosys_step_decode(struct bContext *C, + struct Main *UNUSED(bmain), + UndoStep *us_p, + const eUndoStepDir dir, + bool is_final) { + BLI_assert(dir != STEP_INVALID); + TextUndoStep *us = (TextUndoStep *)us_p; Text *text = us->text_ref.ptr; TextState *state; - if ((us->states[0].buf_array_state != NULL) && (dir == -1) && !is_final) { + if ((us->states[0].buf_array_state != NULL) && (dir == STEP_UNDO) && !is_final) { state = &us->states[0]; } else { diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index dc357cdd355..419721cf89e 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -38,7 +38,6 @@ #include "ED_screen.h" #include "ED_space_api.h" -#include "ED_undo.h" #include "UI_interface.h" #include "UI_resources.h" @@ -129,12 +128,11 @@ static void topbar_header_region_init(wmWindowManager *UNUSED(wm), ARegion *regi ED_region_header_init(region); } -static void topbar_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_main_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -160,12 +158,11 @@ static void topbar_main_region_listener(wmWindow *UNUSED(win), } } -static void topbar_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void topbar_header_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_WM: @@ -191,14 +188,12 @@ static void topbar_header_listener(wmWindow *UNUSED(win), } } -static void topbar_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *workspace, - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void topbar_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + WorkSpace *workspace = params->workspace; + ARegion *region = params->region; + wmMsgSubscribeValue msg_sub_value_region_tag_redraw = { .owner = region, .user_data = region, diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 3efdee9cec9..d4692f156d3 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -183,46 +183,20 @@ static void userpref_execute_region_init(wmWindowManager *wm, ARegion *region) region->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y; } -static void userpref_main_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_main_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_header_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_header_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ -#if 0 - switch (wmn->category) { - default: - break; - } -#endif } -static void userpref_navigation_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_navigation_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } -static void userpref_execute_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *UNUSED(region), - wmNotifier *UNUSED(wmn), - const Scene *UNUSED(scene)) +static void userpref_execute_region_listener(const wmRegionListenerParams *UNUSED(params)) { - /* context changes */ } /* only called once, from space/spacetypes.c */ diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c index f05d6df9944..7c799f0d97b 100644 --- a/source/blender/editors/space_userpref/userpref_ops.c +++ b/source/blender/editors/space_userpref/userpref_ops.c @@ -28,10 +28,8 @@ #include "BLI_listbase.h" #include "BKE_context.h" -#include "BKE_global.h" #include "BKE_main.h" #include "BKE_preferences.h" -#include "BKE_report.h" #include "RNA_access.h" #include "RNA_define.h" @@ -39,8 +37,6 @@ #include "UI_interface.h" -#include "../interface/interface_intern.h" - #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 4c168c7a243..26441bde6b6 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -393,7 +393,7 @@ static void view3d_main_region_init(wmWindowManager *wm, ARegion *region) keymap = WM_keymap_ensure(wm->defaultconf, "Paint Vertex Selection (Weight, Vertex)", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); - /* Before 'Weight/Vertex Paint' so adding curve points is not overriden. */ + /* Before 'Weight/Vertex Paint' so adding curve points is not overridden. */ keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0); WM_event_add_keymap_handler(®ion->handlers, keymap); @@ -469,16 +469,30 @@ static bool view3d_drop_in_main_region_poll(bContext *C, const wmEvent *event) return ED_region_overlap_isect_any_xy(area, &event->x) == false; } -static ID *view3d_drop_id_in_main_region_poll_id(bContext *C, - wmDrag *drag, - const wmEvent *event, - ID_Type id_type) +static ID_Type view3d_drop_id_in_main_region_poll_get_id_type(bContext *C, + wmDrag *drag, + const wmEvent *event) { - ScrArea *area = CTX_wm_area(C); + const ScrArea *area = CTX_wm_area(C); + if (ED_region_overlap_isect_any_xy(area, &event->x)) { - return NULL; + return 0; + } + if (!view3d_drop_in_main_region_poll(C, event)) { + return 0; + } + + ID *local_id = WM_drag_get_local_ID(drag, 0); + if (local_id) { + return GS(local_id->name); + } + + wmDragAsset *asset_drag = WM_drag_get_asset_data(drag, 0); + if (asset_drag) { + return asset_drag->id_type; } - return view3d_drop_in_main_region_poll(C, event) ? WM_drag_get_local_ID(drag, id_type) : NULL; + + return 0; } static bool view3d_drop_id_in_main_region_poll(bContext *C, @@ -490,7 +504,7 @@ static bool view3d_drop_id_in_main_region_poll(bContext *C, return false; } - return WM_drag_get_local_ID(drag, id_type) || WM_drag_get_asset_data(drag, id_type); + return WM_drag_is_ID_type(drag, id_type); } static bool view3d_ob_drop_poll(bContext *C, @@ -522,9 +536,9 @@ static bool view3d_object_data_drop_poll(bContext *C, const wmEvent *event, const char **r_tooltip) { - ID *id = view3d_drop_id_in_main_region_poll_id(C, drag, event, 0); - if (id != NULL) { - if (BKE_object_obdata_to_type(id) != -1) { + ID_Type id_type = view3d_drop_id_in_main_region_poll_get_id_type(C, drag, event); + if (id_type) { + if (OB_DATA_SUPPORT_ID(id_type)) { *r_tooltip = TIP_("Create object instance from object-data"); return true; } @@ -545,7 +559,7 @@ static bool view3d_ima_drop_poll(bContext *C, return (ELEM(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_MOVIE)); } - return WM_drag_get_local_ID(drag, ID_IM) || WM_drag_get_asset_data(drag, ID_IM); + return WM_drag_is_ID_type(drag, ID_IM); } static bool view3d_ima_bg_is_camera_view(bContext *C) @@ -629,7 +643,7 @@ static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop) { - ID *id = WM_drag_get_local_ID(drag, 0); + ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, 0); RNA_string_set(drop->ptr, "name", id->name + 2); RNA_enum_set(drop->ptr, "type", GS(id->name)); @@ -784,9 +798,13 @@ static void *view3d_main_region_duplicate(void *poin) return NULL; } -static void view3d_main_region_listener( - wmWindow *win, ScrArea *area, ARegion *region, wmNotifier *wmn, const Scene *scene) +static void view3d_main_region_listener(const wmRegionListenerParams *params) { + wmWindow *window = params->window; + ScrArea *area = params->area; + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + const Scene *scene = params->scene; View3D *v3d = area->spacedata.first; RegionView3D *rv3d = region->regiondata; wmGizmoMap *gzmap = region->gizmo_map; @@ -1007,10 +1025,10 @@ static void view3d_main_region_listener( ED_view3d_xr_shading_update(G_MAIN->wm.first, v3d, scene); #endif - ViewLayer *view_layer = WM_window_get_active_view_layer(win); + ViewLayer *view_layer = WM_window_get_active_view_layer(window); Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer); if (depsgraph) { - ED_render_view3d_update(depsgraph, win, area, true); + ED_render_view3d_update(depsgraph, window, area, true); } } ED_region_tag_redraw(region); @@ -1048,14 +1066,13 @@ static void view3d_main_region_listener( } } -static void view3d_main_region_message_subscribe(const struct bContext *C, - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *area, - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_main_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + const bContext *C = params->context; + ScrArea *area = params->area; + ARegion *region = params->region; + /* Developer note: there are many properties that impact 3D view drawing, * so instead of subscribing to individual properties, just subscribe to types * accepting some redundant redraws. @@ -1170,12 +1187,11 @@ static void view3d_header_region_draw(const bContext *C, ARegion *region) ED_region_header(C, region); } -static void view3d_header_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_header_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_SCENE: @@ -1240,14 +1256,11 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win), #endif } -static void view3d_header_region_message_subscribe(const struct bContext *UNUSED(C), - struct WorkSpace *UNUSED(workspace), - struct Scene *UNUSED(scene), - struct bScreen *UNUSED(screen), - struct ScrArea *UNUSED(area), - struct ARegion *region, - struct wmMsgBus *mbus) +static void view3d_header_region_message_subscribe(const wmRegionMessageSubscribeParams *params) { + struct wmMsgBus *mbus = params->message_bus; + ARegion *region = params->region; + wmMsgParams_RNA msg_key_params = {{0}}; /* Only subscribe to types. */ @@ -1385,12 +1398,11 @@ static void view3d_buttons_region_layout(const bContext *C, ARegion *region) ED_view3d_buttons_region_layout_ex(C, region, NULL); } -static void view3d_buttons_region_listener(wmWindow *UNUSED(win), - ScrArea *UNUSED(area), - ARegion *region, - wmNotifier *wmn, - const Scene *UNUSED(scene)) +static void view3d_buttons_region_listener(const wmRegionListenerParams *params) { + ARegion *region = params->region; + wmNotifier *wmn = params->notifier; + /* context changes */ switch (wmn->category) { case NC_ANIMATION: @@ -1509,11 +1521,10 @@ static void view3d_tools_region_draw(const bContext *C, ARegion *region) } /* area (not region) level listener */ -static void space_view3d_listener(wmWindow *UNUSED(win), - ScrArea *area, - struct wmNotifier *wmn, - Scene *UNUSED(scene)) +static void space_view3d_listener(const wmSpaceTypeListenerParams *params) { + ScrArea *area = params->area; + wmNotifier *wmn = params->notifier; View3D *v3d = area->spacedata.first; /* context changes */ diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c index 11643960595..0edd6aeb2ca 100644 --- a/source/blender/editors/space_view3d/view3d_camera_control.c +++ b/source/blender/editors/space_view3d/view3d_camera_control.c @@ -50,12 +50,8 @@ #include "DEG_depsgraph.h" -#include "ED_screen.h" - #include "view3d_intern.h" /* own include */ -#include "BLI_strict_flags.h" - typedef struct View3DCameraControl { /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 9982d44b6be..478f48700ea 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -165,7 +165,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph, rv3d->viewcamtexcofac[2] = rv3d->viewcamtexcofac[3] = 0.0f; } - /* calculate pixelsize factor once, is used for lights and obcenters */ + /* Calculate pixel-size factor once, this is used for lights and object-centers. */ { /* note: '1.0f / len_v3(v1)' replaced 'len_v3(rv3d->viewmat[0])' * because of float point precision problems at large values T23908. */ @@ -723,15 +723,24 @@ static void drawviewborder(Scene *scene, Depsgraph *depsgraph, ARegion *region, } if (ca->flag & CAM_SHOW_SAFE_MARGINS) { - UI_draw_safe_areas( - shdr_pos, x1, x2, y1, y2, scene->safe_areas.title, scene->safe_areas.action); + UI_draw_safe_areas(shdr_pos, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, + scene->safe_areas.title, + scene->safe_areas.action); if (ca->flag & CAM_SHOW_SAFE_CENTER) { UI_draw_safe_areas(shdr_pos, - x1, - x2, - y1, - y2, + &(const rctf){ + .xmin = x1, + .xmax = x2, + .ymin = y1, + .ymax = y2, + }, scene->safe_areas.title_center, scene->safe_areas.action_center); } @@ -1960,13 +1969,13 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph, /* XXX(jbakker): `do_color_management` should be controlled by the caller. Currently when doing a * viewport render animation and saving to an 8bit file format, color management would be applied * twice. Once here, and once when saving the saving to disk. In this case the Save As Render - * option cannot be controlled either. But when doing an offscreen render you want to do the + * option cannot be controlled either. But when doing an off-screen render you want to do the * color management here. * - * This option was added here to increase the performance when rendering for a playblast. When - * using workbench the color differences haven't been reported as a bug. But users also use the - * viewport rendering to render Eevee scenes. In the later situation the saved colors - * are totally wrong. */ + * This option was added here to increase the performance for quick view-port preview renders. + * When using workbench the color differences haven't been reported as a bug. But users also use + * the viewport rendering to render Eevee scenes. In the later situation the saved colors are + * totally wrong. */ const bool do_color_management = (ibuf->rect_float == NULL); ED_view3d_draw_offscreen(depsgraph, scene, @@ -2335,7 +2344,7 @@ void ED_view3d_depth_update(ARegion *region) } } -/* Utility function to find the closest Z value, use for autodepth. */ +/* Utility function to find the closest Z value, use for auto-depth. */ float view3d_depth_near(ViewDepths *d) { /* Convert to float for comparisons. */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index ab4e7be88fe..2f8cd5a7517 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2025,7 +2025,7 @@ static float viewzoom_scale_value(const rcti *winrct, { float zfac; - if (viewzoom == USER_ZOOM_CONT) { + if (viewzoom == USER_ZOOM_CONTINUE) { double time = PIL_check_seconds_timer(); float time_step = (float)(time - *r_timer_lastdraw); float fac; @@ -2043,7 +2043,6 @@ static float viewzoom_scale_value(const rcti *winrct, fac = -fac; } - /* oldstyle zoom */ zfac = 1.0f + ((fac / 20.0f) * time_step); *r_timer_lastdraw = time; } @@ -2405,7 +2404,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } - if (U.viewzoom == USER_ZOOM_CONT) { + if (U.viewzoom == USER_ZOOM_CONTINUE) { /* needs a timer to continue redrawing */ vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); vod->prev.time = PIL_check_seconds_timer(); @@ -2888,7 +2887,7 @@ static void view3d_from_minmax(bContext *C, }); } - /* smooth view does viewlock RV3D_BOXVIEW copy */ + /* Smooth-view does view-lock #RV3D_BOXVIEW copy. */ } /** @@ -3021,7 +3020,6 @@ void VIEW3D_OT_view_all(wmOperatorType *ot) * Move & Zoom the view to fit selected contents. * \{ */ -/* like a localview without local!, was centerview() in 2.4x */ static int viewselected_exec(bContext *C, wmOperator *op) { ARegion *region = CTX_wm_region(C); @@ -3282,7 +3280,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op) ED_view3d_smooth_view( C, v3d, region, smooth_viewtx, &(const V3D_SmoothParams){.ofs = new_ofs}); - /* smooth view does viewlock RV3D_BOXVIEW copy */ + /* Smooth view does view-lock #RV3D_BOXVIEW copy. */ } return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 6824c526888..2d499cf85c7 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -48,7 +48,7 @@ #include "ED_screen.h" #include "ED_space_api.h" -#include "PIL_time.h" /* smoothview */ +#include "PIL_time.h" /* Smooth-view. */ #include "UI_interface.h" #include "UI_resources.h" @@ -84,7 +84,7 @@ enum { FLY_MODAL_PRECISION_DISABLE, FLY_MODAL_FREELOOK_ENABLE, FLY_MODAL_FREELOOK_DISABLE, - FLY_MODAL_SPEED, /* mousepan typically */ + FLY_MODAL_SPEED, /* mouse-pan typically. */ }; /* relative view axis locking - xlock, zlock */ @@ -537,7 +537,7 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event) fly->state = FLY_CONFIRM; break; - /* speed adjusting with mousepan (trackpad) */ + /* Speed adjusting with mouse-pan (track-pad). */ case FLY_MODAL_SPEED: { float fac = 0.02f * (event->prevy - event->y); @@ -768,7 +768,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) /* this is the direction that's added to the view offset per redraw */ float dvec[3] = {0, 0, 0}; - /* Camera Uprighting variables */ + /* Camera Up-righting variables. */ float moffset[2]; /* mouse offset from the views center */ float tmp_quat[4]; /* used for rotating the view */ @@ -950,7 +950,7 @@ static int flyApply(bContext *C, FlyInfo *fly, bool is_confirm) } } - /* only apply xcorrect when mouse isn't applying x rot */ + /* Only apply X-axis correction when mouse isn't applying x rotation. */ if (fly->xlock == FLY_AXISLOCK_STATE_ACTIVE && moffset[1] == 0) { float upvec[3]; copy_v3_fl3(upvec, 0.0f, 0.0f, 1.0f); diff --git a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c index 242a0a802a6..98597cb2986 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_forcefield.c @@ -22,7 +22,6 @@ #include "BKE_context.h" #include "BKE_layer.h" -#include "BKE_object.h" #include "DNA_object_force_types.h" #include "DNA_object_types.h" diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c index 7a201d8841c..6fa974cdb09 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c @@ -22,7 +22,6 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_object.h" #include "DNA_object_types.h" @@ -45,14 +44,17 @@ /** \name View3D Navigation Gizmo Group * \{ */ -/* Offset from screen edge. */ -#define GIZMO_OFFSET_FAC 1.2f /* Size of main icon. */ -#define GIZMO_SIZE 80 -/* Factor for size of smaller button. */ -#define GIZMO_MINI_FAC 0.35f -/* How much mini buttons offset from the primary. */ -#define GIZMO_MINI_OFFSET_FAC 0.38f +#define GIZMO_SIZE U.gizmo_size_navigate_v3d + +/* Main gizmo offset from screen edges in unscaled pixels. */ +#define GIZMO_OFFSET 10.0f + +/* Width of smaller buttons in unscaled pixels. */ +#define GIZMO_MINI_SIZE 28.0f + +/* Margin around the smaller buttons. */ +#define GIZMO_MINI_OFFSET 2.0f enum { GZ_INDEX_MOVE = 0, @@ -174,7 +176,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) } /* may be overwritten later */ - gz->scale_basis = (GIZMO_SIZE * GIZMO_MINI_FAC) / 2; + gz->scale_basis = GIZMO_MINI_SIZE / 2.0f; if (info->icon != 0) { PropertyRNA *prop = RNA_struct_find_property(gz->ptr, "icon"); RNA_property_enum_set(gz->ptr, prop, info->icon); @@ -212,7 +214,7 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup) { wmGizmo *gz = navgroup->gz_array[GZ_INDEX_ROTATE]; - gz->scale_basis = GIZMO_SIZE / 2; + gz->scale_basis = GIZMO_SIZE / 2.0f; const char mapping[6] = { RV3D_VIEW_LEFT, RV3D_VIEW_RIGHT, @@ -263,9 +265,8 @@ static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmGizmoGroup *g const bool show_navigate = (U.uiflag & USER_SHOW_GIZMO_NAVIGATE) != 0; const bool show_rotate_gizmo = (U.mini_axis_type == USER_MINI_AXIS_TYPE_GIZMO); - const float icon_size = GIZMO_SIZE; - const float icon_offset = (icon_size * 0.52f) * GIZMO_OFFSET_FAC * UI_DPI_FAC; - const float icon_offset_mini = icon_size * GIZMO_MINI_OFFSET_FAC * UI_DPI_FAC; + const float icon_offset = ((GIZMO_SIZE / 2.0f) + GIZMO_OFFSET) * UI_DPI_FAC; + const float icon_offset_mini = (GIZMO_MINI_SIZE + GIZMO_MINI_OFFSET) * UI_DPI_FAC; const float co_rotate[2] = { rect_visible->xmax - icon_offset, rect_visible->ymax - icon_offset, diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c index 8f3d40584aa..4ac16e8fbe8 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate_type.c @@ -40,6 +40,8 @@ #include "GPU_matrix.h" #include "GPU_state.h" +#include "BLF_api.h" + #include "RNA_access.h" #include "RNA_define.h" @@ -53,169 +55,34 @@ #include "view3d_intern.h" -#define USE_AXIS_FONT -#define USE_FADE_BACKGROUND - -#ifdef USE_AXIS_FONT -# include "BLF_api.h" -#endif - -#define DIAL_RESOLUTION 32 - -/* Sizes of axis spheres containing XYZ characters. */ -#define AXIS_HANDLE_SIZE_FG 0.19f -/* When pointing away from the view. */ -#define AXIS_HANDLE_SIZE_BG 0.15f -/* How far axis handles are away from the center. */ -#define AXIS_HANDLE_OFFSET (1.0f - AXIS_HANDLE_SIZE_FG) - -struct AxisDrawInfo { - /* Matrix is needed for screen-aligned font drawing. */ -#ifdef USE_AXIS_FONT - float matrix_final[4][4]; -#endif -#ifdef USE_FADE_BACKGROUND - float color_bg[3]; -#endif -}; - -#ifndef USE_AXIS_FONT -/** - * \param viewmat_local_unit: is typically the 'rv3d->viewmatob' - * copied into a 3x3 matrix and normalized. - */ -static void draw_xyz_wire( - uint pos_id, const float viewmat_local_unit[3][3], const float c[3], float size, int axis) -{ - int line_type; - float buffer[4][3]; - int n = 0; - - float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3] = {0.0f, 0.0f, 0.0f}; - float dim = size * 0.1f; - float dx[3], dy[3]; - - dx[0] = dim; - dx[1] = 0.0f; - dx[2] = 0.0f; - dy[0] = 0.0f; - dy[1] = dim; - dy[2] = 0.0f; - - switch (axis) { - case 0: /* x axis */ - line_type = GPU_PRIM_LINES; - - /* bottom left to top right */ - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - /* top left to bottom right */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - sub_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - break; - case 1: /* y axis */ - line_type = GPU_PRIM_LINES; - - /* bottom left to top right */ - mul_v3_fl(dx, 0.75f); - negate_v3_v3(v1, dx); - sub_v3_v3(v1, dy); - copy_v3_v3(v2, dx); - add_v3_v3(v2, dy); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - /* top left to center */ - mul_v3_fl(dy, 2.0f); - add_v3_v3(v1, dy); - zero_v3(v2); - - copy_v3_v3(buffer[n++], v1); - copy_v3_v3(buffer[n++], v2); - - break; - case 2: /* z axis */ - line_type = GPU_PRIM_LINE_STRIP; - - /* start at top left */ - negate_v3_v3(v1, dx); - add_v3_v3(v1, dy); - - copy_v3_v3(buffer[n++], v1); - - mul_v3_fl(dx, 2.0f); - add_v3_v3(v1, dx); +/* Radius of the entire background. */ +#define WIDGET_RADIUS ((U.gizmo_size_navigate_v3d / 2.0f) * UI_DPI_FAC) - copy_v3_v3(buffer[n++], v1); +/* Sizes of axis spheres containing XYZ characters in relation to above. */ +#define AXIS_HANDLE_SIZE 0.20f - mul_v3_fl(dy, 2.0f); - sub_v3_v3(v1, dx); - sub_v3_v3(v1, dy); +#define AXIS_LINE_WIDTH ((U.gizmo_size_navigate_v3d / 40.0f) * U.pixelsize) +#define AXIS_RING_WIDTH ((U.gizmo_size_navigate_v3d / 60.0f) * U.pixelsize) +#define AXIS_TEXT_SIZE (WIDGET_RADIUS * AXIS_HANDLE_SIZE * 1.25f) - copy_v3_v3(buffer[n++], v1); +/* distance within this from center is considered positive. */ +#define AXIS_DEPTH_BIAS 0.01f - add_v3_v3(v1, dx); - - copy_v3_v3(buffer[n++], v1); - - break; - default: - BLI_assert(0); - return; - } - - for (int i = 0; i < n; i++) { - mul_transposed_m3_v3((float(*)[3])viewmat_local_unit, buffer[i]); - add_v3_v3(buffer[i], c); - } - - immBegin(line_type, n); - for (int i = 0; i < n; i++) { - immVertex3fv(pos_id, buffer[i]); - } - immEnd(); -} -#endif /* !USE_AXIS_FONT */ - -/** - * \param draw_info: Extra data needed for drawing. - */ -static void axis_geom_draw(const wmGizmo *gz, - const float color[4], - const bool select, - const struct AxisDrawInfo *draw_info) +static void gizmo_axis_draw(const bContext *C, wmGizmo *gz) { - float viewport[4]; - GPU_viewport_size_get_f(viewport); - - GPUVertFormat *format = immVertexFormat(); - const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - struct { float depth; char index; char axis; + char axis_opposite; bool is_pos; } axis_order[6] = { - {-gz->matrix_offset[0][2], 0, 0, false}, - {+gz->matrix_offset[0][2], 1, 0, true}, - {-gz->matrix_offset[1][2], 2, 1, false}, - {+gz->matrix_offset[1][2], 3, 1, true}, - {-gz->matrix_offset[2][2], 4, 2, false}, - {+gz->matrix_offset[2][2], 5, 2, true}, + {-gz->matrix_offset[0][2], 0, 0, 1, false}, + {+gz->matrix_offset[0][2], 1, 0, 0, true}, + {-gz->matrix_offset[1][2], 2, 1, 3, false}, + {+gz->matrix_offset[1][2], 3, 1, 2, true}, + {-gz->matrix_offset[2][2], 4, 2, 5, false}, + {+gz->matrix_offset[2][2], 5, 2, 4, true}, }; int axis_align = -1; @@ -226,25 +93,35 @@ static void axis_geom_draw(const wmGizmo *gz, } } - /* Show backwards pointing highlight on-top (else we can't see it at all). */ - if ((select == false) && (gz->highlight_part > 0) && (axis_align != -1)) { - if (axis_order[gz->highlight_part - 1].is_pos == false) { - axis_order[gz->highlight_part - 1].depth = FLT_MAX; - } - } - qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float); - static const float axis_highlight[4] = {1, 1, 1, 1}; - static const float axis_black[4] = {0, 0, 0, 1}; - static float axis_color[3][4]; + /* When the cursor is over any of the gizmos (show circle backdrop). */ + const bool is_active = ((gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0); - const float axis_depth_bias = 0.01f; - const float sphere_scale = 1.15f; - /* TODO(fclem): Is there a way to get the widget radius? */ - const float widget_pix_size = 40.0f * U.dpi_fac; + /* Background color of the View3D, used to mix colors. */ + float view_color[4]; + ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), view_color); + view_color[3] = 1.0f; + + float matrix_screen[4][4]; + float matrix_unit[4][4]; + unit_m4(matrix_unit); + WM_gizmo_calc_matrix_final_params(gz, + &((struct WM_GizmoMatrixParams){ + .matrix_offset = matrix_unit, + }), + matrix_screen); + GPU_matrix_push(); + GPU_matrix_mul(matrix_screen); + + GPUVertFormat *format = immVertexFormat(); + const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + const uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + + static float axis_color[3][4]; -#ifdef USE_AXIS_FONT struct { float matrix[4][4]; float matrix_m3[3][3]; @@ -252,38 +129,29 @@ static void axis_geom_draw(const wmGizmo *gz, int id; } font; - if (select == false) { - font.id = blf_mono_font; - BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); - BLF_color4fv(font.id, axis_black); - BLF_size(font.id, 12 * U.dpi_fac, 72); - - /* The view matrix is used to position the text. */ - BLF_position(font.id, 0, 0, 0); - - /* Calculate the inverse of the (matrix_final * matrix_offset). - * This allows us to use the final location, while reversing the rotation so fonts - * show without any rotation. */ - float m3[3][3]; - float m3_offset[3][3]; - copy_m3_m4(m3, draw_info->matrix_final); - copy_m3_m4(m3_offset, gz->matrix_offset); - mul_m3_m3m3(m3, m3, m3_offset); - copy_m3_m3(font.matrix_m3_invert, m3); - invert_m3(m3); - copy_m3_m3(font.matrix_m3, m3); - copy_m4_m3(font.matrix, m3); - } -#endif - - /* When the cursor is over any of the gizmos (show circle backdrop). */ - const bool is_active = (color[3] != 0.0f); - - const float clip_range = gz->scale_final * sphere_scale; - bool use_project_matrix = (clip_range >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT); + font.id = BLF_default(); + BLF_disable(font.id, BLF_ROTATION | BLF_SHADOW | BLF_MATRIX | BLF_ASPECT | BLF_WORD_WRAP); + BLF_enable(font.id, BLF_BOLD); + BLF_size(font.id, AXIS_TEXT_SIZE, 72); + BLF_position(font.id, 0, 0, 0); + + /* Calculate the inverse of the (matrix_final * matrix_offset). + * This allows us to use the final location, while reversing the rotation so fonts + * show without any rotation. */ + float m3[3][3]; + float m3_offset[3][3]; + copy_m3_m4(m3, matrix_screen); + copy_m3_m4(m3_offset, gz->matrix_offset); + mul_m3_m3m3(m3, m3, m3_offset); + copy_m3_m3(font.matrix_m3_invert, m3); + invert_m3(m3); + copy_m3_m3(font.matrix_m3, m3); + copy_m4_m3(font.matrix, m3); + + bool use_project_matrix = (gz->scale_final >= -GPU_MATRIX_ORTHO_CLIP_NEAR_DEFAULT); if (use_project_matrix) { GPU_matrix_push_projection(); - GPU_matrix_ortho_set_z(-clip_range, clip_range); + GPU_matrix_ortho_set_z(-gz->scale_final, gz->scale_final); } UI_draw_roundbox_corner_set(UI_CNR_ALL); @@ -291,263 +159,161 @@ static void axis_geom_draw(const wmGizmo *gz, /* Circle defining active area. */ if (is_active) { - immUnbindProgram(); - - float rad = widget_pix_size; + const float rad = WIDGET_RADIUS; GPU_matrix_push(); GPU_matrix_scale_1f(1.0f / rad); - - UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, color); - + UI_draw_roundbox_4fv( + &(const rctf){ + .xmin = -rad, + .xmax = rad, + .ymin = -rad, + .ymax = rad, + }, + true, + rad, + gz->color_hi); GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } - GPU_matrix_push(); GPU_matrix_mul(gz->matrix_offset); for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) { const int index = axis_order[axis_index].index; const int axis = axis_order[axis_index].axis; const bool is_pos = axis_order[axis_index].is_pos; - const bool is_highlight = index + 1 == gz->highlight_part; + const float depth = axis_order[axis_index].depth; + const bool is_behind = (depth <= (AXIS_DEPTH_BIAS * (is_pos ? -1 : 1))); + bool is_aligned_front = (axis_align != -1 && axis_align == axis && !is_behind); + bool is_aligned_back = (axis_align != -1 && axis_align == axis && is_behind); + + const float v[3] = {0, 0, (1.0f - AXIS_HANDLE_SIZE) * (is_pos ? 1 : -1)}; + const float v_final[3] = {v[(axis + 2) % 3], v[(axis + 1) % 3], v[axis]}; + + bool is_highlight = index + 1 == gz->highlight_part; + /* Check if highlight part is the other side when axis aligned. */ + if (is_aligned_front && (axis_order[axis_index].axis_opposite + 1 == gz->highlight_part)) { + is_highlight = true; + } UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]); axis_color[axis][3] = 1.0f; - const int index_z = axis; - const int index_y = (axis + 1) % 3; - const int index_x = (axis + 2) % 3; - - bool ok = true; - - /* Skip view align axis when selecting (allows to switch to opposite side). */ - if (select && ((axis_align == axis) && (gz->matrix_offset[axis][2] > 0.0f) == is_pos)) { - ok = false; + /* Color that is full at front, but 50% view background when in back. */ + float fading_color[4]; + interp_v4_v4v4(fading_color, view_color, axis_color[axis], ((depth + 1) * 0.25) + 0.5); + + /* Color that is midway between front and back. */ + float middle_color[4]; + interp_v4_v4v4(middle_color, view_color, axis_color[axis], 0.75f); + + GPU_blend(GPU_BLEND_ALPHA); + + /* Axis Line. */ + if (is_pos || axis_align != -1) { + + /* Extend slightly to meet better at the center. */ + float v_start[3] = {0.0f, 0.0f, 0.0f}; + mul_v3_v3fl(v_start, v_final, -(AXIS_LINE_WIDTH / WIDGET_RADIUS * 0.66f)); + + /* Decrease length of line by ball radius. */ + float v_end[3] = {0.0f, 0.0f, 0.0f}; + mul_v3_v3fl(v_end, v_final, 1.0f - AXIS_HANDLE_SIZE); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_SMOOTH_COLOR); + immUniform2fv("viewportSize", &viewport_size[2]); + immUniform1f("lineWidth", AXIS_LINE_WIDTH); + immBegin(GPU_PRIM_LINES, 2); + immAttr4fv(color_id, middle_color); + immVertex3fv(pos_id, v_start); + immAttr4fv(color_id, fading_color); + immVertex3fv(pos_id, v_end); + immEnd(); + immUnbindProgram(); } - if (ok) { - /* Check aligned, since the front axis won't display in this case, - * and we want to make sure all 3 axes have a character at all times. */ - const bool show_axis_char = (is_pos || (axis == axis_align)); - const float v[3] = {0, 0, AXIS_HANDLE_OFFSET * (is_pos ? 1 : -1)}; - const float v_final[3] = {v[index_x], v[index_y], v[index_z]}; - const float *color_current = is_highlight ? axis_highlight : axis_color[axis]; - float color_current_fade[4]; - - /* Flip the faded state when axis aligned, since we're hiding the front-mode axis - * otherwise we see the color for the back-most axis, which is useful for - * click-to-rotate 180d but not useful to visualize. - * - * Use depth bias so axis-aligned views show the positive axis as being in-front. - * This is a detail so primary axes show as dominant. - */ - const bool is_pos_color = (axis_order[axis_index].depth > - (axis_depth_bias * (is_pos ? -1 : 1))); - - if (select == false) { -#ifdef USE_FADE_BACKGROUND - interp_v3_v3v3( - color_current_fade, draw_info->color_bg, color_current, is_highlight ? 1.0 : 0.5f); - color_current_fade[3] = color_current[3]; -#else - copy_v4_v4(color_current_fade, color_current); - color_current_fade[3] *= 0.2; -#endif - } - else { - copy_v4_fl(color_current_fade, 1.0f); - } - - /* Axis Line. */ - if (is_pos) { - float v_start[3]; - immUnbindProgram(); - - GPU_blend(GPU_BLEND_ALPHA); - - immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); - immUniform2fv("viewportSize", &viewport[2]); - immUniform1f("lineWidth", 2.0f * U.pixelsize); - immUniformColor4fv(is_pos_color ? color_current : color_current_fade); - immBegin(GPU_PRIM_LINES, 2); - if (axis_align == -1) { - zero_v3(v_start); + /* Axis Ball. */ + if (!is_aligned_back) { + float *inner_color = fading_color; + float *outline_color = fading_color; + float negative_color[4]; + if (!is_pos) { + if (is_aligned_front) { + interp_v4_v4v4( + negative_color, (float[4]){1.0f, 1.0f, 1.0f, 1.0f}, axis_color[axis], 0.5f); + negative_color[3] = MIN2(depth + 1, 1.0f); + outline_color = negative_color; } else { - /* When axis aligned we don't draw the front most axis - * (allowing us to switch to the opposite side). - * In this case don't draw lines over axis pointing away from us - * because it obscures character and looks noisy. - */ - mul_v3_v3fl(v_start, v_final, 0.3f); + interp_v4_v4v4(negative_color, view_color, axis_color[axis], 0.25f); + negative_color[3] = MIN2(depth + 1, 1.0f); + inner_color = negative_color; } - immVertex3fv(pos_id, v_start); - immVertex3fv(pos_id, v_final); - immEnd(); - - immUnbindProgram(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); } - /* Axis Ball. */ -#ifdef USE_AXIS_FONT - if (select == false) { - immUnbindProgram(); - - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_mul(font.matrix); - - float rad = widget_pix_size * (is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); - - /* Black outlines for negative axis balls, otherwise they can be hard to see since - * they use a faded color which can be similar to the circle backdrop in tone. */ - if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { - static const float axis_black_faded[4] = {0.0f, 0.0f, 0.0f, 0.2f}; - float outline = rad * sphere_scale; - UI_draw_roundbox_4fv( - true, -outline, -outline, outline, outline, outline, axis_black_faded); - } - - const float *col = is_pos_color ? color_current : color_current_fade; - UI_draw_roundbox_4fv(true, -rad, -rad, rad, rad, rad, col); - - GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - } - else -#endif - { - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final); - GPU_matrix_scale_1f(is_pos ? AXIS_HANDLE_SIZE_FG : AXIS_HANDLE_SIZE_BG); - - GPUBatch *sphere = GPU_batch_preset_sphere(0); - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - - /* Black outlines for negative axis balls, otherwise they can be hard to see since - * they use a faded color which can be similar to the circle backdrop in tone. */ - if (is_active && !is_highlight && !is_pos && !select && !(axis_align == axis)) { - static const float axis_black_faded[4] = {0, 0, 0, 0.2f}; - GPU_matrix_scale_1f(sphere_scale); - GPU_batch_uniform_4fv(sphere, "color", axis_black_faded); - GPU_batch_draw(sphere); - GPU_matrix_scale_1f(1.0 / sphere_scale); - } + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final); + GPU_matrix_mul(font.matrix); + /* Size change from back to front: 0.92f - 1.08f. */ + float scale = ((depth + 1) * 0.08f) + 0.92f; + const float rad = WIDGET_RADIUS * AXIS_HANDLE_SIZE * scale; + UI_draw_roundbox_4fv_ex( + &(const rctf){ + .xmin = -rad, + .xmax = rad, + .ymin = -rad, + .ymax = rad, + }, + inner_color, + NULL, + 0.0f, + outline_color, + AXIS_RING_WIDTH, + rad); + GPU_matrix_pop(); + } - GPU_batch_program_set_builtin(sphere, GPU_SHADER_3D_UNIFORM_COLOR); - GPU_batch_uniform_4fv(sphere, "color", is_pos_color ? color_current : color_current_fade); - GPU_batch_draw(sphere); - GPU_matrix_pop(); + /* Axis XYZ Character. */ + if ((is_pos || is_highlight || (axis == axis_align)) && !is_aligned_back) { + float axis_str_width, axis_string_height; + char axis_str[3] = {'X' + axis, 0, 0}; + if (!is_pos) { + axis_str[0] = '-'; + axis_str[1] = 'X' + axis; } - - /* Axis XYZ Character. */ - if (show_axis_char && (select == false)) { -#ifdef USE_AXIS_FONT - float axis_str_size[2] = {0}; - const char axis_str[2] = {'X' + axis, 0}; - BLF_width_and_height(font.id, axis_str, 2, &axis_str_size[0], &axis_str_size[1]); - - /* Calculate pixel aligned location, without this text draws fuzzy. */ - float v_final_px[3]; - mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final); - /* Center the test and pixel align, it's important to round once - * otherwise the characters are noticeably not-centered. - * If this wasn't an issue we could use #BLF_position to place the text. */ - v_final_px[0] = roundf(v_final_px[0] - (axis_str_size[0] / 2.0f)); - v_final_px[1] = roundf(v_final_px[1] - (axis_str_size[1] / 2.0f)); - mul_m3_v3(font.matrix_m3, v_final_px); - - immUnbindProgram(); - - GPU_matrix_push(); - GPU_matrix_translate_3fv(v_final_px); - GPU_matrix_mul(font.matrix); - - BLF_draw_ascii(font.id, axis_str, 2); - GPU_blend(GPU_BLEND_ALPHA); /* XXX, blf disables */ - GPU_matrix_pop(); - - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); -#else - immUnbindProgram(); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - GPU_line_width(1.0f); - float m3[3][3]; - copy_m3_m4(m3, gz->matrix_offset); - immUniformColor4fv(axis_black); - draw_xyz_wire(pos_id, m3, v_final, 1.0, axis); - immUnbindProgram(); -#endif + BLF_width_and_height(font.id, axis_str, 3, &axis_str_width, &axis_string_height); + + /* Calculate pixel-aligned location, without this text draws fuzzy. */ + float v_final_px[3]; + mul_v3_m3v3(v_final_px, font.matrix_m3_invert, v_final); + /* Center the text and pixel align, it's important to round once + * otherwise the characters are noticeably not-centered. + * If this wasn't an issue we could use #BLF_position to place the text. */ + v_final_px[0] = roundf(v_final_px[0] - (axis_str_width * (is_pos ? 0.5f : 0.55f))); + v_final_px[1] = roundf(v_final_px[1] - (axis_string_height / 2.0f)); + mul_m3_v3(font.matrix_m3, v_final_px); + GPU_matrix_push(); + GPU_matrix_translate_3fv(v_final_px); + GPU_matrix_mul(font.matrix); + float text_color[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + if (!is_highlight) { + zero_v4(text_color); + text_color[3] = is_active ? 1.0f : 0.9f; } + BLF_color4fv(font.id, text_color); + BLF_draw_ascii(font.id, axis_str, 2); + GPU_matrix_pop(); } } - GPU_matrix_pop(); - immUnbindProgram(); - if (use_project_matrix) { GPU_matrix_pop_projection(); } -} - -static void axis3d_draw_intern(const bContext *C, - wmGizmo *gz, - const bool select, - const bool highlight) -{ - const float *color = highlight ? gz->color_hi : gz->color; - float matrix_final[4][4]; - float matrix_unit[4][4]; - - unit_m4(matrix_unit); - - WM_gizmo_calc_matrix_final_params(gz, - &((struct WM_GizmoMatrixParams){ - .matrix_offset = matrix_unit, - }), - matrix_final); - - GPU_matrix_push(); - GPU_matrix_mul(matrix_final); - - struct AxisDrawInfo draw_info; -#ifdef USE_AXIS_FONT - if (select == false) { - copy_m4_m4(draw_info.matrix_final, matrix_final); - } -#endif -#ifdef USE_FADE_BACKGROUND - if (select == false) { - ED_view3d_background_color_get(CTX_data_scene(C), CTX_wm_view3d(C), draw_info.color_bg); - } -#else - UNUSED_VARS(C); -#endif - - GPU_blend(GPU_BLEND_ALPHA); - axis_geom_draw(gz, color, select, &draw_info); GPU_blend(GPU_BLEND_NONE); + BLF_disable(font.id, BLF_BOLD); GPU_matrix_pop(); } -static void gizmo_axis_draw(const bContext *C, wmGizmo *gz) -{ - const bool is_modal = gz->state & WM_GIZMO_STATE_MODAL; - const bool is_highlight = (gz->state & WM_GIZMO_STATE_HIGHLIGHT) != 0; - - (void)is_modal; - - GPU_blend(GPU_BLEND_ALPHA); - axis3d_draw_intern(C, gz, false, is_highlight); - GPU_blend(GPU_BLEND_NONE); -} - static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mval[2]) { float point_local[2] = {UNPACK2(mval)}; @@ -601,12 +367,19 @@ static int gizmo_axis_test_select(bContext *UNUSED(C), wmGizmo *gz, const int mv return -1; } -static int gizmo_axis_cursor_get(wmGizmo *gz) +static int gizmo_axis_cursor_get(wmGizmo *UNUSED(gz)) { - if (gz->highlight_part > 0) { - return WM_CURSOR_EDIT; - } - return WM_CURSOR_NSEW_SCROLL; + return WM_CURSOR_DEFAULT; +} + +static void gizmo_axis_screen_bounds_get(bContext *C, wmGizmo *gz, rcti *r_bounding_box) +{ + ScrArea *area = CTX_wm_area(C); + const float rad = WIDGET_RADIUS; + r_bounding_box->xmin = gz->matrix_basis[3][0] + area->totrct.xmin - rad; + r_bounding_box->ymin = gz->matrix_basis[3][1] + area->totrct.ymin - rad; + r_bounding_box->xmax = r_bounding_box->xmin + rad; + r_bounding_box->ymax = r_bounding_box->ymin + rad; } void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt) @@ -618,6 +391,7 @@ void VIEW3D_GT_navigate_rotate(wmGizmoType *gzt) gzt->draw = gizmo_axis_draw; gzt->test_select = gizmo_axis_test_select; gzt->cursor_get = gizmo_axis_cursor_get; + gzt->screen_bounds_get = gizmo_axis_screen_bounds_get; gzt->struct_size = sizeof(wmGizmo); } diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c index 3f07653fb2f..171cf721343 100644 --- a/source/blender/editors/space_view3d/view3d_gizmo_preselect.c +++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect.c @@ -30,7 +30,6 @@ #include "UI_resources.h" #include "WM_api.h" -#include "WM_toolsystem.h" #include "WM_types.h" #include "view3d_intern.h" /* own include */ diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index f2e42cd1725..607ca110d0f 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -40,14 +40,11 @@ #include "DEG_depsgraph.h" #include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" #include "ED_mesh.h" -#include "ED_screen.h" #include "ED_undo.h" #include "UI_interface.h" diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 0770bac1313..344168e895b 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -24,7 +24,6 @@ #include <math.h> #include <stdlib.h> -#include "DNA_collection_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -36,7 +35,6 @@ #include "BKE_appdir.h" #include "BKE_blender_copybuffer.h" -#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_main.h" #include "BKE_report.h" @@ -49,7 +47,6 @@ #include "ED_outliner.h" #include "ED_screen.h" -#include "ED_select_utils.h" #include "ED_transform.h" #include "view3d_intern.h" diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 35ec4de5077..0605ea30806 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -596,7 +596,7 @@ static bool do_lasso_select_objects(ViewContext *vc, } for (base = vc->view_layer->object_bases.first; base; base = base->next) { - if (BASE_SELECTABLE(v3d, base)) { /* use this to avoid un-needed lasso lookups */ + if (BASE_SELECTABLE(v3d, base)) { /* Use this to avoid unnecessary lasso look-ups. */ const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) && BLI_lasso_is_point_inside( @@ -1447,7 +1447,7 @@ static const EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, int totitem = 0; int i = 0; - /* don't need context but avoid docgen using this */ + /* Don't need context but avoid API doc-generation using this. */ if (C == NULL || object_mouse_select_menu_data[i].idname[0] == '\0') { return DummyRNA_NULL_items; } @@ -2494,8 +2494,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) } /* Pass-through allows tweaks - * FINISHED to signal one operator worked - * */ + * FINISHED to signal one operator worked */ if (retval) { WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index 148a0986c5c..cce9287679c 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -27,7 +27,6 @@ #include "DNA_object_types.h" #include "BLI_array.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c index 2b7b8255068..a6a77ecd5f7 100644 --- a/source/blender/editors/space_view3d/view3d_utils.c +++ b/source/blender/editors/space_view3d/view3d_utils.c @@ -224,13 +224,11 @@ void view3d_region_operator_needs_opengl(wmWindow *UNUSED(win), ARegion *region) */ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist) { - float viewdist; - if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) { return; } - viewdist = rv3d->dist; + float viewdist = rv3d->dist; /* special exception for ortho camera (viewdist isnt used for perspective cameras) */ if (dist != 0.0f) { @@ -248,7 +246,6 @@ bool ED_view3d_context_activate(bContext *C) { bScreen *screen = CTX_wm_screen(C); ScrArea *area = CTX_wm_area(C); - ARegion *region; /* area can be NULL when called from python */ if (area == NULL || area->spacetype != SPACE_VIEW3D) { @@ -259,7 +256,7 @@ bool ED_view3d_context_activate(bContext *C) return false; } - region = BKE_area_find_region_active_win(area); + ARegion *region = BKE_area_find_region_active_win(area); if (region == NULL) { return false; } @@ -282,9 +279,7 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip) { - int val; - - for (val = 0; val < 4; val++) { + for (int val = 0; val < 4; val++) { normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]); if (UNLIKELY(is_flip)) { negate_v3(clip[val]); @@ -752,14 +747,12 @@ bool ED_view3d_camera_lock_autokey(View3D *v3d, static void view3d_boxview_clip(ScrArea *area) { - ARegion *region; BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); float clip[6][4]; float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; - int val; /* create bounding box */ - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = region->regiondata; @@ -794,7 +787,7 @@ static void view3d_boxview_clip(ScrArea *area) } } - for (val = 0; val < 8; val++) { + for (int val = 0; val < 8; val++) { if (ELEM(val, 0, 3, 4, 7)) { bb->vec[val][0] = -x1 - ofs[0]; } @@ -826,12 +819,12 @@ static void view3d_boxview_clip(ScrArea *area) normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]); /* then plane equations */ - for (val = 0; val < 6; val++) { + for (int val = 0; val < 6; val++) { clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]); } /* create bounding box */ - for (region = area->regionbase.first; region; region = region->next) { + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->regiontype == RGN_TYPE_WINDOW) { RegionView3D *rv3d = region->regiondata; @@ -950,11 +943,10 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip) { ARegion *region_sync = NULL; RegionView3D *rv3d = region->regiondata; - short viewlock; /* this function copies flags from the first of the 3 other quadview * regions to the 2 other, so it assumes this is the region whose * properties are always being edited, weak */ - viewlock = rv3d->viewlock; + short viewlock = rv3d->viewlock; if ((viewlock & RV3D_LOCK_ROTATION) == 0) { do_clip = (viewlock & RV3D_BOXCLIP) != 0; @@ -1015,10 +1007,7 @@ void ED_view3d_quadview_update(ScrArea *area, ARegion *region, bool do_clip) static float view_autodist_depth_margin(ARegion *region, const int mval[2], int margin) { - ViewDepths depth_temp = {0}; rcti rect; - float depth_close; - if (margin == 0) { /* Get Z Depths, needed for perspective, nice for ortho */ rect.xmin = mval[0]; @@ -1030,8 +1019,9 @@ static float view_autodist_depth_margin(ARegion *region, const int mval[2], int BLI_rcti_init_pt_radius(&rect, mval, margin); } + ViewDepths depth_temp = {0}; view3d_update_depths_rect(region, &depth_temp, &rect); - depth_close = view3d_depth_near(&depth_temp); + float depth_close = view3d_depth_near(&depth_temp); MEM_SAFE_FREE(depth_temp.depths); return depth_close; } @@ -1053,14 +1043,13 @@ bool ED_view3d_autodist(Depsgraph *depsgraph, { float depth_close; int margin_arr[] = {0, 2, 4}; - int i; bool depth_ok = false; /* Get Z Depths, needed for perspective, nice for ortho */ ED_view3d_draw_depth(depsgraph, region, v3d, alphaoverride); /* Attempt with low margin's first */ - i = 0; + int i = 0; do { depth_close = view_autodist_depth_margin(region, mval, margin_arr[i++] * U.pixelsize); depth_ok = (depth_close != FLT_MAX); @@ -1104,9 +1093,8 @@ bool ED_view3d_autodist_simple(ARegion *region, int margin, const float *force_depth) { - float depth; - /* Get Z Depths, needed for perspective, nice for ortho */ + float depth; if (force_depth) { depth = *force_depth; } @@ -1237,7 +1225,6 @@ float ED_view3d_radius_to_dist(const View3D *v3d, } else { float lens, sensor_size, zoom; - float angle; if (persp == RV3D_CAMOB) { CameraParams params; @@ -1259,7 +1246,7 @@ float ED_view3d_radius_to_dist(const View3D *v3d, zoom = CAMERA_PARAM_ZOOM_INIT_PERSP; } - angle = focallength_to_fov(lens, sensor_size); + float angle = focallength_to_fov(lens, sensor_size); /* zoom influences lens, correct this by scaling the angle as a distance * (by the zoom-level) */ @@ -1319,14 +1306,13 @@ float ED_view3d_offset_distance(const float mat[4][4], { float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f}; - float dist; mul_m4_v4(mat, pos); add_v3_v3(pos, ofs); mul_m4_v4(mat, dir); normalize_v3(dir); - dist = dot_v3v3(pos, dir); + float dist = dot_v3v3(pos, dir); if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) { dist = fallback_dist; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 9d947384bf0..5c0ca1582a6 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -142,7 +142,7 @@ void ED_view3d_smooth_view_ex( /* initialize sms */ view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d); view3d_smooth_view_state_backup(&sms.src, v3d, rv3d); - /* if smoothview runs multiple times... */ + /* If smooth-view runs multiple times. */ if (rv3d->sms == NULL) { view3d_smooth_view_state_backup(&sms.org, v3d, rv3d); } @@ -396,7 +396,7 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *region, b /* note: this doesn't work right because the v3d->lens is now used in ortho mode r51636, * when switching camera in quad-view the other ortho views would zoom & reset. * - * For now only redraw all regions when smoothview finishes. + * For now only redraw all regions when smooth-view finishes. */ if (step >= 1.0f) { WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); @@ -423,7 +423,7 @@ static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const w } /** - * Apply the smoothview immediately, use when we need to start a new view operation. + * Apply the smooth-view immediately, use when we need to start a new view operation. * (so we don't end up half-applying a view operation when pressing keys quickly). */ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region) diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 5b42f221c80..cbd65e3175d 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -48,7 +48,7 @@ #include "ED_space_api.h" #include "ED_transform_snap_object_context.h" -#include "PIL_time.h" /* smoothview */ +#include "PIL_time.h" /* Smooth-view. */ #include "UI_interface.h" #include "UI_resources.h" @@ -872,7 +872,7 @@ static void walkEvent(bContext *C, WalkInfo *walk, const wmEvent *event) /* delta time */ t = (float)(PIL_check_seconds_timer() - walk->teleport.initial_time); - /* reduce the veolocity, if JUMP wasn't hold for long enough */ + /* Reduce the velocity, if JUMP wasn't hold for long enough. */ t = min_ff(t, JUMP_TIME_MAX); walk->speed_jump = JUMP_SPEED_MIN + t * (JUMP_SPEED_MAX - JUMP_SPEED_MIN) / JUMP_TIME_MAX; diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index faed8abb202..b0bc5c6abda 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC transform_convert_nla.c transform_convert_node.c transform_convert_object.c + transform_convert_object_texspace.c transform_convert_paintcurve.c transform_convert_particle.c transform_convert_sculpt.c diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 2a7c247ff2b..2fbcbe22349 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -135,7 +135,7 @@ void setTransformViewAspect(TransInfo *t, float r_aspect[3]) } } else if (t->spacetype == SPACE_GRAPH) { - /* depemds on context of usage */ + /* Depends on context of usage. */ } } @@ -440,7 +440,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else { /* Do we need more refined tags? */ - if (t->flag & T_POSE) { + if (t->options & CTX_POSE_BONE) { WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); } else { @@ -471,7 +471,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_SEQ) { WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, NULL); - /* Keyframes on strips has been moved, so make sure related editos are informed. */ + /* Key-frames on strips has been moved, so make sure related editors are informed. */ WM_event_add_notifier(C, NC_ANIMATION, NULL); } else if (t->spacetype == SPACE_IMAGE) { @@ -484,7 +484,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t) wmWindow *window = CTX_wm_window(C); WM_paint_cursor_tag_redraw(window, t->region); } - else if (t->flag & T_CURSOR) { + else if (t->options & CTX_CURSOR) { ED_area_tag_redraw(t->area); } else { @@ -695,6 +695,7 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) {TFM_MODAL_RESIZE, "RESIZE", 0, "Resize", ""}, {TFM_MODAL_AUTOCONSTRAINT, "AUTOCONSTRAIN", 0, "Automatic Constraint", ""}, {TFM_MODAL_AUTOCONSTRAINTPLANE, "AUTOCONSTRAINPLANE", 0, "Automatic Constraint Plane", ""}, + {TFM_MODAL_PRECISION, "PRECISION", 0, "Precision Mode", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -806,8 +807,6 @@ int transformEvent(TransInfo *t, const wmEvent *event) const int modifiers_prev = t->modifiers; const int mode_prev = t->mode; - t->redraw |= handleMouseInput(t, &t->mouse, event); - /* Handle modal numinput events first, if already activated. */ if (((event->val == KM_PRESS) || (event->type == EVT_MODAL_MAP)) && hasNumInput(&t->num) && handleNumInput(t->context, &(t->num), event)) { @@ -895,7 +894,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_ROTATE: /* only switch when... */ - if (!(t->options & CTX_TEXTURE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { + if (!(t->options & CTX_TEXTURE_SPACE) && !(t->options & (CTX_MOVIECLIP | CTX_MASK))) { if (transform_mode_is_changeable(t->mode)) { restoreTransObjects(t); resetTransModal(t); @@ -1069,7 +1068,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) t->modifiers &= ~(MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE); } else { - if (t->flag & T_CAMERA) { + if (t->options & CTX_CAMERA) { /* Exception for switching to dolly, or trackball, in camera view. */ if (t->mode == TFM_TRANSLATION) { setLocalConstraint(t, (CON_AXIS2), TIP_("along local Z")); @@ -1095,6 +1094,19 @@ int transformEvent(TransInfo *t, const wmEvent *event) handled = true; } break; + case TFM_MODAL_PRECISION: + if (event->prevval == KM_PRESS) { + t->modifiers |= MOD_PRECISION; + /* Shift is modifier for higher precision transform. */ + t->mouse.precision = 1; + t->redraw |= TREDRAW_HARD; + } + else if (event->prevval == KM_RELEASE) { + t->modifiers &= ~MOD_PRECISION; + t->mouse.precision = 0; + t->redraw |= TREDRAW_HARD; + } + break; /* Those two are only handled in transform's own handler, see T44634! */ case TFM_MODAL_EDGESLIDE_UP: case TFM_MODAL_EDGESLIDE_DOWN: @@ -1249,7 +1261,7 @@ bool calculateTransformCenter(bContext *C, int centerMode, float cent3d[3], floa createTransData(C, t); /* make TransData structs from selection */ - t->around = centerMode; /* override userdefined mode */ + t->around = centerMode; /* override user-defined mode. */ if (t->data_len_all == 0) { success = false; @@ -1382,7 +1394,7 @@ static void drawTransformPixel(const struct bContext *C, ARegion *region, void * */ if ((U.autokey_flag & AUTOKEY_FLAG_NOWARNING) == 0) { if (region == t->region) { - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { if (ob && autokeyframe_cfra_can_key(scene, &ob->id)) { drawAutoKeyWarning(t, region); } @@ -1652,7 +1664,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((prop = RNA_struct_find_property(op->ptr, "texture_space")) && RNA_property_is_set(op->ptr, prop)) { if (RNA_property_boolean_get(op->ptr, prop)) { - options |= CTX_TEXTURE; + options |= CTX_TEXTURE_SPACE; } } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index fff7d47cc5b..24335b6b6b7 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -36,6 +36,11 @@ #include "transform_data.h" +/* use node center for transform instead of upper-left corner. + * disabled since it makes absolute snapping not work so nicely + */ +// #define USE_NODE_CENTER + /* -------------------------------------------------------------------- */ /** \name Types/ * \{ */ @@ -60,6 +65,134 @@ struct wmKeyMap; struct wmOperator; struct wmTimer; +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Enums and Flags + * \{ */ + +/** #TransInfo.options */ +typedef enum { + CTX_NONE = 0, + + /* These are similar to TransInfo::data_type. */ + CTX_CAMERA = (1 << 0), + CTX_CURSOR = (1 << 1), + CTX_EDGE_DATA = (1 << 2), + CTX_GPENCIL_STROKES = (1 << 3), + CTX_MASK = (1 << 4), + CTX_MOVIECLIP = (1 << 5), + CTX_OBJECT = (1 << 6), + CTX_PAINT_CURVE = (1 << 7), + CTX_POSE_BONE = (1 << 8), + CTX_TEXTURE_SPACE = (1 << 9), + + CTX_NO_PET = (1 << 10), + CTX_NO_MIRROR = (1 << 11), + CTX_AUTOCONFIRM = (1 << 12), + /** When transforming object's, adjust the object data so it stays in the same place. */ + CTX_OBMODE_XFORM_OBDATA = (1 << 13), + /** Transform object parents without moving their children. */ + CTX_OBMODE_XFORM_SKIP_CHILDREN = (1 << 14), +} eTContext; + +/** #TransInfo.flag */ +typedef enum { + /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */ + T_EDIT = 1 << 0, + /** Transform points, having no rotation/scale. */ + T_POINTS = 1 << 1, + /** restrictions flags */ + T_NO_CONSTRAINT = 1 << 2, + T_NULL_ONE = 1 << 3, + T_NO_ZERO = 1 << 4, + T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, + + T_PROP_EDIT = 1 << 5, + T_PROP_CONNECTED = 1 << 6, + T_PROP_PROJECTED = 1 << 7, + T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, + + T_V3D_ALIGN = 1 << 8, + /** For 2D views such as UV or f-curve. */ + T_2D_EDIT = 1 << 9, + T_CLIP_UV = 1 << 10, + + /** Auto-IK is on. */ + T_AUTOIK = 1 << 11, + + /** Don't use mirror even if the data-block option is set. */ + T_NO_MIRROR = 1 << 12, + + /** To indicate that the value set in the `value` parameter is the final + * value of the transformation, modified only by the constrain. */ + T_INPUT_IS_VALUES_FINAL = 1 << 13, + + /** To specify if we save back settings at the end. */ + T_MODAL = 1 << 14, + + /** No re-topology (projection). */ + T_NO_PROJECT = 1 << 15, + + T_RELEASE_CONFIRM = 1 << 16, + + /** Alternative transformation. used to add offset to tracking markers. */ + T_ALT_TRANSFORM = 1 << 17, + + /** #TransInfo.center has been set, don't change it. */ + T_OVERRIDE_CENTER = 1 << 18, + + T_MODAL_CURSOR_SET = 1 << 19, + + T_CLNOR_REBUILD = 1 << 20, + + /** Merges unselected into selected after transforming (runs after transforming). */ + T_AUTOMERGE = 1 << 21, + /** Runs auto-merge & splits. */ + T_AUTOSPLIT = 1 << 22, +} eTFlag; + +/** #TransInfo.modifiers */ +typedef enum { + MOD_CONSTRAINT_SELECT = 1 << 0, + MOD_PRECISION = 1 << 1, + MOD_SNAP = 1 << 2, + MOD_SNAP_INVERT = 1 << 3, + MOD_CONSTRAINT_PLANE = 1 << 4, +} eTModifier; + +/** #TransSnap.status */ +typedef enum { + SNAP_FORCED = 1 << 0, + TARGET_INIT = 1 << 1, + /* Special flag for snap to grid. */ + TARGET_GRID_INIT = 1 << 2, + POINT_INIT = 1 << 3, + MULTI_POINTS = 1 << 4, +} eTSnap; + +/** #TransCon.mode, #TransInfo.con.mode */ +typedef enum { + /** When set constraints are in use. */ + CON_APPLY = 1 << 0, + /** These are only used for modal execution. */ + CON_AXIS0 = 1 << 1, + CON_AXIS1 = 1 << 2, + CON_AXIS2 = 1 << 3, + CON_SELECT = 1 << 4, + /** Does not reorient vector to face viewport when on. */ + CON_NOFLIP = 1 << 5, + CON_USER = 1 << 6, +} eTConstraint; + +/** #TransInfo.state */ +typedef enum { + TRANS_STARTING = 0, + TRANS_RUNNING = 1, + TRANS_CONFIRM = 2, + TRANS_CANCEL = 3, +} eTState; + /** #TransInfo.redraw */ typedef enum { TREDRAW_NOTHING = 0, @@ -67,6 +200,97 @@ typedef enum { TREDRAW_SOFT = 2, } eRedrawFlag; +/** #TransInfo.helpline */ +typedef enum { + HLP_NONE = 0, + HLP_SPRING = 1, + HLP_ANGLE = 2, + HLP_HARROW = 3, + HLP_VARROW = 4, + HLP_CARROW = 5, + HLP_TRACKBALL = 6, +} eTHelpline; + +typedef enum { + TC_NONE = 0, + TC_ACTION_DATA, + TC_POSE, + TC_ARMATURE_VERTS, + TC_CURSOR_IMAGE, + TC_CURSOR_VIEW3D, + TC_CURVE_VERTS, + TC_GRAPH_EDIT_DATA, + TC_GPENCIL, + TC_LATTICE_VERTS, + TC_MASKING_DATA, + TC_MBALL_VERTS, + TC_MESH_VERTS, + TC_MESH_EDGES, + TC_MESH_SKIN, + TC_MESH_UV, + TC_NLA_DATA, + TC_NODE_DATA, + TC_OBJECT, + TC_OBJECT_TEXSPACE, + TC_PAINT_CURVE_VERTS, + TC_PARTICLE_VERTS, + TC_SCULPT, + TC_SEQ_DATA, + TC_TRACKING_DATA, +} eTConvertType; + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keymap Modal Items + * + * \note these values are saved in key-map files, do not change then but just add new ones. + * \{ */ + +enum { + TFM_MODAL_CANCEL = 1, + TFM_MODAL_CONFIRM = 2, + TFM_MODAL_TRANSLATE = 3, + TFM_MODAL_ROTATE = 4, + TFM_MODAL_RESIZE = 5, + TFM_MODAL_SNAP_INV_ON = 6, + TFM_MODAL_SNAP_INV_OFF = 7, + TFM_MODAL_SNAP_TOGGLE = 8, + TFM_MODAL_AXIS_X = 9, + TFM_MODAL_AXIS_Y = 10, + TFM_MODAL_AXIS_Z = 11, + TFM_MODAL_PLANE_X = 12, + TFM_MODAL_PLANE_Y = 13, + TFM_MODAL_PLANE_Z = 14, + TFM_MODAL_CONS_OFF = 15, + TFM_MODAL_ADD_SNAP = 16, + TFM_MODAL_REMOVE_SNAP = 17, + + /* 18 and 19 used by number-input, defined in `ED_numinput.h`. */ + // NUM_MODAL_INCREMENT_UP = 18, + // NUM_MODAL_INCREMENT_DOWN = 19, + + TFM_MODAL_PROPSIZE_UP = 20, + TFM_MODAL_PROPSIZE_DOWN = 21, + TFM_MODAL_AUTOIK_LEN_INC = 22, + TFM_MODAL_AUTOIK_LEN_DEC = 23, + + TFM_MODAL_EDGESLIDE_UP = 24, + TFM_MODAL_EDGESLIDE_DOWN = 25, + + /** For analog input, like track-pad. */ + TFM_MODAL_PROPSIZE = 26, + /** Node editor insert offset (also called auto-offset) direction toggle. */ + TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, + + TFM_MODAL_AUTOCONSTRAINT = 28, + TFM_MODAL_AUTOCONSTRAINTPLANE = 29, + + TFM_MODAL_PRECISION = 30, +}; + +/** \} */ + typedef struct TransSnapPoint { struct TransSnapPoint *next, *prev; float co[3]; @@ -82,13 +306,14 @@ typedef struct TransSnap { bool snap_self; bool peel; bool use_backface_culling; - char status; + eTSnap status; /* Snapped Element Type (currently for objects only). */ char snapElem; /** snapping from this point (in global-space). */ float snapPoint[3]; /** to this point (in global-space). */ float snapTarget[3]; + float snapTargetGrid[3]; float snapNormal[3]; char snapNodeBorder; ListBase points; @@ -120,7 +345,7 @@ typedef struct TransCon { * the one in #TransInfo is not guarantee to stay the same (Rotates change it). */ int imval[2]; /** Mode flags of the constraint. */ - int mode; + eTConstraint mode; void (*drawExtra)(struct TransInfo *t); /* Note: if 'tc' is NULL, 'td' must also be NULL. @@ -266,37 +491,45 @@ typedef struct TransInfo { TransDataContainer *data_container; int data_container_len; - /** #eTransConvertType - * TODO: It should be a member of #TransDataContainer. */ - int data_type; - /** Combine length of all #TransDataContainer.data_len * Use to check if nothing is selected or if we have a single selection. */ int data_len_all; - /** Current mode. */ - int mode; + /** TODO: It should be a member of #TransDataContainer. */ + eTConvertType data_type; + + /** Current context/options for transform. */ + eTContext options; /** Generic flags for special behaviors. */ - int flag; + eTFlag flag; /** Special modifiers, by function, not key. */ - int modifiers; + eTModifier modifiers; /** Current state (running, canceled. */ - short state; - /** Current context/options for transform. */ - int options; + eTState state; + /** Redraw flag. */ + eRedrawFlag redraw; + /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */ + eTHelpline helpline; + /** Current mode. */ + eTfmMode mode; + + /** Main transform mode function. */ void (*transform)(struct TransInfo *, const int[2]); - /** Transform function pointer. */ + /* Event handler function that determines whether the viewport needs to be redrawn. */ eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *); - /* event handler function pointer RETURN 1 if redraw is needed */ - /** transformed constraint. */ + + /** Constraint Data. */ TransCon con; + + /** Snap Data. */ TransSnap tsnap; - /** numerical input. */ + + /** Numerical input. */ NumInput num; - /** mouse input. */ + + /** Mouse input. */ MouseInput mouse; - /** redraw flag. */ - eRedrawFlag redraw; + /** proportional circle radius. */ float prop_size; /** proportional falloff text. */ @@ -310,9 +543,6 @@ typedef struct TransInfo { float center_global[3]; /** center in screen coordinates. */ float center2d[2]; - /* Lazy initialize center data for when we need other center values. - * V3D_AROUND_ACTIVE + 1 (static assert checks this) */ - TransCenterData center_cache[5]; /** maximum index on the input vector. */ short idx_max; /** Snapping Gears. */ @@ -333,8 +563,6 @@ typedef struct TransInfo { short around; /** space-type where transforming is. */ char spacetype; - /** Choice of custom cursor with or without a help line from the gizmo to the mouse position. */ - char helpline; /** Avoid looking inside #TransDataContainer.obedit. */ short obedit_type; @@ -422,178 +650,6 @@ typedef struct TransInfo { /** \} */ /* -------------------------------------------------------------------- */ -/** \name Flags - * \{ */ - -/** #TransInfo.state */ -enum { - TRANS_STARTING = 0, - TRANS_RUNNING = 1, - TRANS_CONFIRM = 2, - TRANS_CANCEL = 3, -}; - -/** #TransInfo.flag */ -enum { - T_OBJECT = 1 << 0, - /** \note We could remove 'T_EDIT' and use 'obedit_type', for now ensure they're in sync. */ - T_EDIT = 1 << 1, - T_POSE = 1 << 2, - T_TEXTURE = 1 << 3, - /** Transforming the 3d view. */ - T_CAMERA = 1 << 4, - /** Transforming the 3D cursor. */ - T_CURSOR = 1 << 5, - /** Transform points, having no rotation/scale. */ - T_POINTS = 1 << 6, - /** restrictions flags */ - T_NO_CONSTRAINT = 1 << 7, - T_NULL_ONE = 1 << 8, - T_NO_ZERO = 1 << 9, - T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO, - - T_PROP_EDIT = 1 << 10, - T_PROP_CONNECTED = 1 << 11, - T_PROP_PROJECTED = 1 << 12, - T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED, - - T_V3D_ALIGN = 1 << 13, - /** For 2D views such as UV or f-curve. */ - T_2D_EDIT = 1 << 14, - T_CLIP_UV = 1 << 15, - - /** Auto-IK is on. */ - T_AUTOIK = 1 << 16, - - /** Don't use mirror even if the data-block option is set. */ - T_NO_MIRROR = 1 << 17, - - /** To indicate that the value set in the `value` parameter is the final - * value of the transformation, modified only by the constrain. */ - T_INPUT_IS_VALUES_FINAL = 1 << 18, - - /** To specify if we save back settings at the end. */ - T_MODAL = 1 << 19, - - /** No re-topology (projection). */ - T_NO_PROJECT = 1 << 20, - - T_RELEASE_CONFIRM = 1 << 21, - - /** Alternative transformation. used to add offset to tracking markers. */ - T_ALT_TRANSFORM = 1 << 22, - - /** #TransInfo.center has been set, don't change it. */ - T_OVERRIDE_CENTER = 1 << 23, - - T_MODAL_CURSOR_SET = 1 << 24, - - T_CLNOR_REBUILD = 1 << 25, - - /** Merges unselected into selected after transforming (runs after transforming). */ - T_AUTOMERGE = 1 << 26, - /** Runs auto-merge & splits. */ - T_AUTOSPLIT = 1 << 27, -}; - -/** #TransInfo.modifiers */ -enum { - MOD_CONSTRAINT_SELECT = 1 << 0, - MOD_PRECISION = 1 << 1, - MOD_SNAP = 1 << 2, - MOD_SNAP_INVERT = 1 << 3, - MOD_CONSTRAINT_PLANE = 1 << 4, -}; - -/* use node center for transform instead of upper-left corner. - * disabled since it makes absolute snapping not work so nicely - */ -// #define USE_NODE_CENTER - -/** #TransInfo.helpline */ -enum { - HLP_NONE = 0, - HLP_SPRING = 1, - HLP_ANGLE = 2, - HLP_HARROW = 3, - HLP_VARROW = 4, - HLP_CARROW = 5, - HLP_TRACKBALL = 6, -}; - -/** #TransCon.mode, #TransInfo.con.mode */ -enum { - /** When set constraints are in use. */ - CON_APPLY = 1 << 0, - /** These are only used for modal execution. */ - CON_AXIS0 = 1 << 1, - CON_AXIS1 = 1 << 2, - CON_AXIS2 = 1 << 3, - CON_SELECT = 1 << 4, - /** Does not reorient vector to face viewport when on. */ - CON_NOFLIP = 1 << 5, - CON_USER = 1 << 6, -}; - -/** #TransSnap.status */ -enum { - SNAP_FORCED = 1 << 0, - TARGET_INIT = 1 << 1, - POINT_INIT = 1 << 2, - MULTI_POINTS = 1 << 3, -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Keymap Modal Items - * - * \note these values are saved in key-map files, do not change then but just add new ones. - * \{ */ - -enum { - TFM_MODAL_CANCEL = 1, - TFM_MODAL_CONFIRM = 2, - TFM_MODAL_TRANSLATE = 3, - TFM_MODAL_ROTATE = 4, - TFM_MODAL_RESIZE = 5, - TFM_MODAL_SNAP_INV_ON = 6, - TFM_MODAL_SNAP_INV_OFF = 7, - TFM_MODAL_SNAP_TOGGLE = 8, - TFM_MODAL_AXIS_X = 9, - TFM_MODAL_AXIS_Y = 10, - TFM_MODAL_AXIS_Z = 11, - TFM_MODAL_PLANE_X = 12, - TFM_MODAL_PLANE_Y = 13, - TFM_MODAL_PLANE_Z = 14, - TFM_MODAL_CONS_OFF = 15, - TFM_MODAL_ADD_SNAP = 16, - TFM_MODAL_REMOVE_SNAP = 17, - - /* 18 and 19 used by number-input, defined in `ED_numinput.h`. */ - // NUM_MODAL_INCREMENT_UP = 18, - // NUM_MODAL_INCREMENT_DOWN = 19, - - TFM_MODAL_PROPSIZE_UP = 20, - TFM_MODAL_PROPSIZE_DOWN = 21, - TFM_MODAL_AUTOIK_LEN_INC = 22, - TFM_MODAL_AUTOIK_LEN_DEC = 23, - - TFM_MODAL_EDGESLIDE_UP = 24, - TFM_MODAL_EDGESLIDE_DOWN = 25, - - /** For analog input, like track-pad. */ - TFM_MODAL_PROPSIZE = 26, - /** Node editor insert offset (also called auto-offset) direction toggle. */ - TFM_MODAL_INSERTOFS_TOGGLE_DIR = 27, - - TFM_MODAL_AUTOCONSTRAINT = 28, - TFM_MODAL_AUTOCONSTRAINTPLANE = 29, -}; - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Public Transform API * \{ */ @@ -666,9 +722,6 @@ typedef enum { void initMouseInput( TransInfo *t, MouseInput *mi, const float center[2], const int mval[2], const bool precision); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); -eRedrawFlag handleMouseInput(struct TransInfo *t, - struct MouseInput *mi, - const struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], @@ -684,10 +737,6 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val /** \name Generics * \{ */ -void initTransDataContainers_FromObjectData(TransInfo *t, - struct Object *obact, - struct Object **objects, - uint objects_len); void initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, @@ -709,7 +758,6 @@ void recalcData(TransInfo *t); void calculateCenter2D(TransInfo *t); void calculateCenterLocal(TransInfo *t, const float center_global[3]); -const TransCenterData *transformCenter_from_type(TransInfo *t, int around); void calculateCenter(TransInfo *t); /* API functions for getting center points */ @@ -724,6 +772,8 @@ void calculatePropRatio(TransInfo *t); void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot); +struct Object *transform_object_deform_pose_armature_get(const TransInfo *t, struct Object *ob); + void freeCustomNormalArray(TransInfo *t, TransDataContainer *tc, TransCustomData *custom_data); /* TODO. transform_query.c */ diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index 2ac7e41a7c9..1f589a830fc 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -58,6 +58,10 @@ static void drawObjectConstraint(TransInfo *t); +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + static void projection_matrix_calc(const TransInfo *t, float r_pmtx[3][3]) { unit_m3(r_pmtx); @@ -380,14 +384,13 @@ static void planeProjection(const TransInfo *t, const float in[3], float out[3]) add_v3_v3v3(out, in, vec); } -/* +/** * Generic callback for constant spatial constraints applied to linear motion * - * The IN vector in projected into the constrained space and then further + * The `in` vector in projected into the constrained space and then further * projected along the view vector. * (in perspective mode, the view vector is relative to the position on screen) */ - static void applyAxisConstraintVec( TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3]) { @@ -459,17 +462,16 @@ static void applyAxisConstraintVec( } } -/* +/** * Generic callback for object based spatial constraints applied to linear motion * * At first, the following is applied without orientation * The IN vector in projected into the constrained space and then further * projected along the view vector. - * (in perspective mode, the view vector is relative to the position on screen) + * (in perspective mode, the view vector is relative to the position on screen). * * Further down, that vector is mapped to each data's space. */ - static void applyObjectConstraintVec( TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3]) { @@ -489,10 +491,9 @@ static void applyObjectConstraintVec( } } -/* - * Generic callback for constant spatial constraints applied to resize motion +/** + * Generic callback for constant spatial constraints applied to resize motion. */ - static void applyAxisConstraintSize(TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, @@ -516,10 +517,9 @@ static void applyAxisConstraintSize(TransInfo *t, } } -/* - * Callback for object based spatial constraints applied to resize motion +/** + * Callback for object based spatial constraints applied to resize motion. */ - static void applyObjectConstraintSize(TransInfo *t, TransDataContainer *tc, TransData *td, @@ -549,10 +549,10 @@ static void applyObjectConstraintSize(TransInfo *t, } } -static void constraints_rotation_imp(TransInfo *t, - float axismtx[3][3], - float r_vec[3], - float *r_angle) +static void constraints_rotation_impl(TransInfo *t, + float axismtx[3][3], + float r_vec[3], + float *r_angle) { BLI_assert(t->con.mode & CON_APPLY); int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2); @@ -581,15 +581,15 @@ static void constraints_rotation_imp(TransInfo *t, } } -/* +/** * Generic callback for constant spatial constraints applied to rotations * - * The rotation axis is copied into VEC. + * The rotation axis is copied into `vec`. * * In the case of single axis constraints, the rotation axis is directly the one constrained to. * For planar constraints (2 axis), the rotation axis is the normal of the plane. * - * The following only applies when CON_NOFLIP is not set. + * The following only applies when #CON_NOFLIP is not set. * The vector is then modified to always point away from the screen (in global space) * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). @@ -598,19 +598,19 @@ static void applyAxisConstraintRot( TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, float vec[3], float *angle) { if (!td && t->con.mode & CON_APPLY) { - constraints_rotation_imp(t, t->spacemtx, vec, angle); + constraints_rotation_impl(t, t->spacemtx, vec, angle); } } -/* +/** * Callback for object based spatial constraints applied to rotations * - * The rotation axis is copied into VEC. + * The rotation axis is copied into `vec`. * * In the case of single axis constraints, the rotation axis is directly the one constrained to. * For planar constraints (2 axis), the rotation axis is the normal of the plane. * - * The following only applies when CON_NOFLIP is not set. + * The following only applies when #CON_NOFLIP is not set. * The vector is then modified to always point away from the screen (in global space) * This insures that the rotation is always logically following the mouse. * (ie: not doing counterclockwise rotations when the mouse moves clockwise). @@ -637,11 +637,15 @@ static void applyObjectConstraintRot( axismtx = td->axismtx; } - constraints_rotation_imp(t, axismtx, vec, angle); + constraints_rotation_impl(t, axismtx, vec, angle); } } -/*--------------------- INTERNAL SETUP CALLS ------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Setup Calls + * \{ */ void setConstraint(TransInfo *t, int mode, const char text[]) { @@ -676,7 +680,7 @@ void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[]) void setLocalConstraint(TransInfo *t, int mode, const char text[]) { - if (t->flag & T_EDIT) { + if ((t->flag & T_EDIT) || t->data_len_all == 1) { /* Although in edit-mode each object has its local space, use the * orientation of the active object. */ setConstraint(t, mode, text); @@ -686,10 +690,10 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[]) } } -/* +/** * Set the constraint according to the user defined orientation * - * ftext is a format string passed to BLI_snprintf. It will add the name of + * `ftext` is a format string passed to #BLI_snprintf. It will add the name of * the orientation where %s is (logically). */ void setUserConstraint(TransInfo *t, int mode, const char ftext[]) @@ -704,40 +708,35 @@ void setUserConstraint(TransInfo *t, int mode, const char ftext[]) const char *spacename = transform_orientations_spacename_get(t, orientation); BLI_snprintf(text, sizeof(text), ftext, spacename); - if (t->modifiers & (MOD_CONSTRAINT_SELECT | MOD_CONSTRAINT_PLANE)) { - /* Force the orientation of the active object. - * Although possible, it is not convenient to use the local or axis constraint - * with the modifier to select constraint. - * This also follows the convention of older versions. */ - setConstraint(t, mode, text); - } - else { - switch (orientation) { - case V3D_ORIENT_LOCAL: - setLocalConstraint(t, mode, text); - break; - case V3D_ORIENT_NORMAL: - if (checkUseAxisMatrix(t)) { - setAxisMatrixConstraint(t, mode, text); - break; - } - ATTR_FALLTHROUGH; - case V3D_ORIENT_GLOBAL: - case V3D_ORIENT_VIEW: - case V3D_ORIENT_CURSOR: - case V3D_ORIENT_GIMBAL: - case V3D_ORIENT_CUSTOM_MATRIX: - case V3D_ORIENT_CUSTOM: - default: { - setConstraint(t, mode, text); + switch (orientation) { + case V3D_ORIENT_LOCAL: + setLocalConstraint(t, mode, text); + break; + case V3D_ORIENT_NORMAL: + if (checkUseAxisMatrix(t)) { + setAxisMatrixConstraint(t, mode, text); break; } + ATTR_FALLTHROUGH; + case V3D_ORIENT_GLOBAL: + case V3D_ORIENT_VIEW: + case V3D_ORIENT_CURSOR: + case V3D_ORIENT_GIMBAL: + case V3D_ORIENT_CUSTOM_MATRIX: + case V3D_ORIENT_CUSTOM: + default: { + setConstraint(t, mode, text); + break; } } t->con.mode |= CON_USER; } -/*----------------- DRAWING CONSTRAINTS -------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Drawing Constraints + * \{ */ void drawConstraint(TransInfo *t) { @@ -915,7 +914,7 @@ static void drawObjectConstraint(TransInfo *t) mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx); axismtx = tmp_axismtx; } - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { mul_v3_m4v3(co, tc->mat, td->center); axismtx = td->axismtx; } @@ -938,7 +937,11 @@ static void drawObjectConstraint(TransInfo *t) } } -/*--------------------- START / STOP CONSTRAINTS ---------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Start / Stop Constraints + * \{ */ void startConstraint(TransInfo *t) { @@ -959,7 +962,11 @@ void stopConstraint(TransInfo *t) t->num.idx_max = t->idx_max; } -/*------------------------- MMB Select -------------------------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Middle Mouse Button Select + * \{ */ void initSelectConstraint(TransInfo *t) { @@ -1106,7 +1113,11 @@ void setNearestAxis(TransInfo *t) projection_matrix_calc(t, t->con.pmtx); } -/*-------------- HELPER FUNCTIONS ----------------*/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Helper Functions + * \{ */ int constraintModeToIndex(const TransInfo *t) { @@ -1147,14 +1158,13 @@ bool isLockConstraint(TransInfo *t) return false; } -/* +/** * Returns the dimension of the constraint space. * * For that reason, the flags always needs to be set to properly evaluate here, - * even if they aren't actually used in the callback function. (Which could happen - * for weird constraints not yet designed. Along a path for example.) + * even if they aren't actually used in the callback function. + * (Which could happen for weird constraints not yet designed. Along a path for example.) */ - int getConstraintSpaceDimension(TransInfo *t) { int n = 0; @@ -1172,11 +1182,12 @@ int getConstraintSpaceDimension(TransInfo *t) } return n; - /* - * Someone willing to do it cryptically could do the following instead: + /* Someone willing to do it cryptically could do the following instead: * - * return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2); + * `return t->con & (CON_AXIS0|CON_AXIS1|CON_AXIS2);` * * Based on the assumptions that the axis flags are one after the other and start at 1 */ } + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 3ea0b0a0a70..6b2e9dd9840 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -23,6 +23,7 @@ #include "DNA_anim_types.h" #include "DNA_constraint_types.h" +#include "DNA_mesh_types.h" #include "MEM_guardedalloc.h" @@ -892,7 +893,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t) special_aftertrans_update__node(C, t); break; case TC_OBJECT: - case TC_OBJECT_TEXSPACE: special_aftertrans_update__object(C, t); break; case TC_SCULPT: @@ -912,6 +912,8 @@ void special_aftertrans_update(bContext *C, TransInfo *t) case TC_LATTICE_VERTS: case TC_MBALL_VERTS: case TC_MESH_UV: + case TC_MESH_SKIN: + case TC_OBJECT_TEXSPACE: case TC_PAINT_CURVE_VERTS: case TC_PARTICLE_VERTS: case TC_NONE: @@ -928,10 +930,10 @@ int special_transform_moving(TransInfo *t) if (t->spacetype == SPACE_GRAPH) { return G_TRANSFORM_FCURVES; } - if ((t->flag & T_EDIT) || (t->flag & T_POSE)) { + if ((t->flag & T_EDIT) || (t->options & CTX_POSE_BONE)) { return G_TRANSFORM_EDIT; } - if (t->flag & (T_OBJECT | T_TEXTURE)) { + if (t->options & (CTX_OBJECT | CTX_TEXTURE_SPACE)) { return G_TRANSFORM_OBJ; } @@ -973,53 +975,254 @@ static int countAndCleanTransDataContainer(TransInfo *t) return t->data_len_all; } -void createTransData(bContext *C, TransInfo *t) +static void init_proportional_edit(TransInfo *t) { - Scene *scene = t->scene; - ViewLayer *view_layer = t->view_layer; - Object *ob = OBACT(view_layer); + eTConvertType convert_type = t->data_type; + switch (convert_type) { + case TC_ACTION_DATA: + case TC_CURVE_VERTS: + case TC_GRAPH_EDIT_DATA: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MASKING_DATA: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_EDGES: + case TC_MESH_SKIN: + case TC_MESH_UV: + case TC_NODE_DATA: + case TC_OBJECT: + case TC_PARTICLE_VERTS: + break; + case TC_POSE: /* Disable PET, its not usable in pose mode yet T32444. */ + case TC_ARMATURE_VERTS: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_NLA_DATA: + case TC_OBJECT_TEXSPACE: + case TC_PAINT_CURVE_VERTS: + case TC_SCULPT: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + case TC_NONE: + default: + t->options |= CTX_NO_PET; + t->flag &= ~T_PROP_EDIT_ALL; + return; + } - t->data_len_all = -1; + if (t->data_len_all && (t->flag & T_PROP_EDIT)) { + if (convert_type == TC_OBJECT) { + /* Selected objects are already first, no need to presort. */ + } + else { + sort_trans_data_selected_first(t); + } - eTransConvertType convert_type = TC_NONE; + if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { + /* Distance has already been set. */ + } + else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { + if (t->flag & T_PROP_CONNECTED) { + /* Already calculated by transform_convert_mesh_connectivity_distance. */ + } + else { + set_prop_dist(t, false); + } + } + else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { + /* Already calculated by uv_set_connectivity_distance. */ + } + else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) { + set_prop_dist(t, false); + } + else { + set_prop_dist(t, true); + } + + sort_trans_data_dist(t); + } + else if (ELEM(t->obedit_type, OB_CURVE)) { + /* Needed because bezier handles can be partially selected + * and are still added into transform data. */ + sort_trans_data_selected_first(t); + } +} + +/* For multi object editing. */ +static void init_TransDataContainers(TransInfo *t, + Object *obact, + Object **objects, + uint objects_len) +{ + switch (t->data_type) { + case TC_POSE: + case TC_ARMATURE_VERTS: + case TC_CURVE_VERTS: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_EDGES: + case TC_MESH_SKIN: + case TC_MESH_UV: + break; + case TC_ACTION_DATA: + case TC_GRAPH_EDIT_DATA: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_MASKING_DATA: + case TC_NLA_DATA: + case TC_NODE_DATA: + case TC_OBJECT: + case TC_OBJECT_TEXSPACE: + case TC_PAINT_CURVE_VERTS: + case TC_PARTICLE_VERTS: + case TC_SCULPT: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + case TC_NONE: + default: + /* Does not support Multi object editing. */ + return; + } + + const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; + const short object_type = obact ? obact->type : -1; + + if ((object_mode & OB_MODE_EDIT) || (t->data_type == TC_GPENCIL) || + ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) { + if (t->data_container) { + MEM_freeN(t->data_container); + } + + bool free_objects = false; + if (objects == NULL) { + objects = BKE_view_layer_array_from_objects_in_mode( + t->view_layer, + (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, + &objects_len, + { + .object_mode = object_mode, + .no_dup_data = true, + }); + free_objects = true; + } + + t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__); + t->data_container_len = objects_len; + + for (int i = 0; i < objects_len; i++) { + TransDataContainer *tc = &t->data_container[i]; + if (((t->flag & T_NO_MIRROR) == 0) && ((t->options & CTX_NO_MIRROR) == 0) && + (objects[i]->type == OB_MESH)) { + tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0; + tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0; + tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0; + } + + if (object_mode & OB_MODE_EDIT) { + tc->obedit = objects[i]; + /* Check needed for UV's */ + if ((t->flag & T_2D_EDIT) == 0) { + tc->use_local_mat = true; + } + } + else if (object_mode & OB_MODE_POSE) { + tc->poseobj = objects[i]; + tc->use_local_mat = true; + } + else if (t->data_type == TC_GPENCIL) { + tc->use_local_mat = true; + } + + if (tc->use_local_mat) { + BLI_assert((t->flag & T_2D_EDIT) == 0); + copy_m4_m4(tc->mat, objects[i]->obmat); + copy_m3_m4(tc->mat3, tc->mat); + /* for non-invertible scale matrices, invert_m4_m4_fallback() + * can still provide a valid pivot */ + invert_m4_m4_fallback(tc->imat, tc->mat); + invert_m3_m3(tc->imat3, tc->mat3); + normalize_m3_m3(tc->mat3_unit, tc->mat3); + } + /* Otherwise leave as zero. */ + } + + if (free_objects) { + MEM_freeN(objects); + } + } +} + +static eTFlag flags_from_data_type(eTConvertType data_type) +{ + switch (data_type) { + case TC_ACTION_DATA: + case TC_GRAPH_EDIT_DATA: + case TC_MASKING_DATA: + case TC_NLA_DATA: + case TC_NODE_DATA: + case TC_PAINT_CURVE_VERTS: + case TC_SEQ_DATA: + case TC_TRACKING_DATA: + return T_POINTS | T_2D_EDIT; + case TC_ARMATURE_VERTS: + case TC_CURVE_VERTS: + case TC_GPENCIL: + case TC_LATTICE_VERTS: + case TC_MBALL_VERTS: + case TC_MESH_VERTS: + case TC_MESH_SKIN: + return T_EDIT | T_POINTS; + case TC_MESH_EDGES: + return T_EDIT; + case TC_MESH_UV: + return T_EDIT | T_POINTS | T_2D_EDIT; + case TC_PARTICLE_VERTS: + return T_POINTS; + case TC_POSE: + case TC_CURSOR_IMAGE: + case TC_CURSOR_VIEW3D: + case TC_OBJECT: + case TC_OBJECT_TEXSPACE: + case TC_SCULPT: + case TC_NONE: + default: + break; + } + return 0; +} + +static eTConvertType convert_type_get(const TransInfo *t, Object **r_obj_armature) +{ + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); + eTConvertType convert_type = TC_NONE; /* if tests must match recalcData for correct updates */ if (t->options & CTX_CURSOR) { - t->flag |= T_CURSOR; - if (t->spacetype == SPACE_IMAGE) { convert_type = TC_CURSOR_IMAGE; } else { convert_type = TC_CURSOR_VIEW3D; } - - /* Since we're transforming the cursor, initialize this value before it's modified. - * Needed for #snap_grid_apply to access the cursor location. */ - transformCenter_from_type(t, V3D_AROUND_CURSOR); } else if (!(t->options & CTX_PAINT_CURVE) && (t->spacetype == SPACE_VIEW3D) && ob && (ob->mode == OB_MODE_SCULPT) && ob->sculpt) { convert_type = TC_SCULPT; } - else if (t->options & CTX_TEXTURE) { - t->flag |= T_TEXTURE; + else if (t->options & CTX_TEXTURE_SPACE) { convert_type = TC_OBJECT_TEXSPACE; } - else if (t->options & CTX_EDGE) { - t->flag |= T_EDIT; + else if (t->options & CTX_EDGE_DATA) { convert_type = TC_MESH_EDGES; - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } else if (t->options & CTX_GPENCIL_STROKES) { - t->options |= CTX_GPENCIL_STROKES; - t->flag |= T_POINTS | T_EDIT; convert_type = TC_GPENCIL; - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } else if (t->spacetype == SPACE_IMAGE) { - t->flag |= T_POINTS | T_2D_EDIT; if (t->options & CTX_MASK) { convert_type = TC_MASKING_DATA; } @@ -1029,41 +1232,25 @@ void createTransData(bContext *C, TransInfo *t) } } else if (t->obedit_type == OB_MESH) { - t->flag |= T_EDIT; convert_type = TC_MESH_UV; - initTransDataContainers_FromObjectData(t, ob, NULL, 0); } } else if (t->spacetype == SPACE_ACTION) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_ACTION_DATA; } else if (t->spacetype == SPACE_NLA) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_NLA_DATA; } else if (t->spacetype == SPACE_SEQ) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; - t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point trasnform */ convert_type = TC_SEQ_DATA; } else if (t->spacetype == SPACE_GRAPH) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_GRAPH_EDIT_DATA; } else if (t->spacetype == SPACE_NODE) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; convert_type = TC_NODE_DATA; } else if (t->spacetype == SPACE_CLIP) { - t->flag |= T_POINTS | T_2D_EDIT; - t->obedit_type = -1; - if (t->options & CTX_MOVIECLIP) { convert_type = TC_TRACKING_DATA; } @@ -1072,11 +1259,6 @@ void createTransData(bContext *C, TransInfo *t) } } else if (t->obedit_type != -1) { - t->flag |= T_EDIT | T_POINTS; - - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); - if (t->obedit_type == OB_MESH) { if (t->mode == TFM_SKIN_RESIZE) { convert_type = TC_MESH_SKIN; @@ -1095,46 +1277,25 @@ void createTransData(bContext *C, TransInfo *t) convert_type = TC_MBALL_VERTS; } else if (t->obedit_type == OB_ARMATURE) { - t->flag &= ~T_PROP_EDIT; convert_type = TC_ARMATURE_VERTS; } } else if (ob && (ob->mode & OB_MODE_POSE)) { - /* XXX this is currently limited to active armature only... */ - - /* XXX active-layer checking isn't done - * as that should probably be checked through context instead. */ - - /* Multi object editing. */ - initTransDataContainers_FromObjectData(t, ob, NULL, 0); convert_type = TC_POSE; } else if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { - /* Important that ob_armature can be set even when its not selected T23412. - * Lines below just check is also visible. */ - Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); - if (ob_armature && ob_armature->mode & OB_MODE_POSE) { - Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); - if (base_arm) { - View3D *v3d = t->view; - if (BASE_VISIBLE(v3d, base_arm)) { - Object *objects[1]; - objects[0] = ob_armature; - uint objects_len = 1; - initTransDataContainers_FromObjectData(t, ob_armature, objects, objects_len); - convert_type = TC_POSE; - } - } + Object *ob_armature = transform_object_deform_pose_armature_get(t, ob); + if (ob_armature) { + *r_obj_armature = ob_armature; + convert_type = TC_POSE; } } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && - PE_start_edit(PE_get_current(t->depsgraph, scene, ob))) { - t->flag |= T_POINTS; + PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) { convert_type = TC_PARTICLE_VERTS; } else if (ob && (ob->mode & OB_MODE_ALL_PAINT)) { if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) { - t->flag |= T_POINTS | T_2D_EDIT; convert_type = TC_PAINT_CURVE_VERTS; } } @@ -1146,47 +1307,55 @@ void createTransData(bContext *C, TransInfo *t) /* In grease pencil all transformations must be canceled if not Object or Edit. */ } else { - /* Needed for correct Object.obmat after duplication, see: T62135. */ - BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); - - if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { - t->options |= CTX_OBMODE_XFORM_OBDATA; - } - if ((scene->toolsettings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { - t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; - } - - t->flag |= T_OBJECT; convert_type = TC_OBJECT; } - t->data_type = convert_type; - bool init_prop_edit = (t->flag & T_PROP_EDIT) != 0; + return convert_type; +} + +void createTransData(bContext *C, TransInfo *t) +{ + t->data_len_all = -1; + + Object *ob_armature = NULL; + t->data_type = convert_type_get(t, &ob_armature); + t->flag |= flags_from_data_type(t->data_type); - switch (convert_type) { + if (ob_armature) { + init_TransDataContainers(t, ob_armature, &ob_armature, 1); + } + else { + ViewLayer *view_layer = t->view_layer; + Object *ob = OBACT(view_layer); + init_TransDataContainers(t, ob, NULL, 0); + } + + switch (t->data_type) { case TC_ACTION_DATA: + t->obedit_type = -1; createTransActionData(C, t); break; case TC_POSE: + t->options |= CTX_POSE_BONE; + + /* XXX active-layer checking isn't done + * as that should probably be checked through context instead. */ createTransPose(t); - /* Disable PET, its not usable in pose mode yet T32444. */ - init_prop_edit = false; break; case TC_ARMATURE_VERTS: createTransArmatureVerts(t); break; case TC_CURSOR_IMAGE: createTransCursor_image(t); - init_prop_edit = false; break; case TC_CURSOR_VIEW3D: createTransCursor_view3d(t); - init_prop_edit = false; break; case TC_CURVE_VERTS: createTransCurveVerts(t); break; case TC_GRAPH_EDIT_DATA: + t->obedit_type = -1; createTransGraphEditData(C, t); break; case TC_GPENCIL: @@ -1196,6 +1365,9 @@ void createTransData(bContext *C, TransInfo *t) createTransLatticeVerts(t); break; case TC_MASKING_DATA: + if (t->spacetype == SPACE_CLIP) { + t->obedit_type = -1; + } createTransMaskingData(C, t); break; case TC_MBALL_VERTS: @@ -1214,13 +1386,25 @@ void createTransData(bContext *C, TransInfo *t) createTransUVs(C, t); break; case TC_NLA_DATA: + t->obedit_type = -1; createTransNlaData(C, t); - init_prop_edit = false; break; case TC_NODE_DATA: + t->obedit_type = -1; createTransNodeData(t); break; case TC_OBJECT: + t->options |= CTX_OBJECT; + + /* Needed for correct Object.obmat after duplication, see: T62135. */ + BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); + + if ((t->settings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) { + t->options |= CTX_OBMODE_XFORM_OBDATA; + } + if ((t->settings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) { + t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN; + } createTransObject(C, t); /* Check if we're transforming the camera from the camera */ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { @@ -1229,36 +1413,34 @@ void createTransData(bContext *C, TransInfo *t) if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) { /* we could have a flag to easily check an object is being transformed */ if (v3d->camera->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; + t->options |= CTX_CAMERA; } } else if (v3d->ob_center && v3d->ob_center->id.tag & LIB_TAG_DOIT) { - t->flag |= T_CAMERA; + t->options |= CTX_CAMERA; } } break; case TC_OBJECT_TEXSPACE: createTransTexspace(t); - init_prop_edit = false; break; case TC_PAINT_CURVE_VERTS: createTransPaintCurveVerts(C, t); - init_prop_edit = false; break; case TC_PARTICLE_VERTS: createTransParticleVerts(t); break; case TC_SCULPT: createTransSculpt(C, t); - init_prop_edit = false; break; case TC_SEQ_DATA: + t->obedit_type = -1; + t->num.flag |= NUM_NO_FRACTION; /* sequencer has no use for floating point transform. */ createTransSeqData(t); - init_prop_edit = false; break; case TC_TRACKING_DATA: + t->obedit_type = -1; createTransTrackingData(C, t); - init_prop_edit = false; break; case TC_NONE: default: @@ -1270,48 +1452,7 @@ void createTransData(bContext *C, TransInfo *t) countAndCleanTransDataContainer(t); - if (t->data_len_all && init_prop_edit) { - if (convert_type == TC_OBJECT) { - /* Selected objects are already first, no need to presort. */ - } - else { - sort_trans_data_selected_first(t); - } - - if (ELEM(convert_type, TC_ACTION_DATA, TC_GRAPH_EDIT_DATA)) { - /* Distance has already been set. */ - } - else if (ELEM(convert_type, TC_MESH_VERTS, TC_MESH_SKIN)) { - if (t->flag & T_PROP_CONNECTED) { - /* Already calculated by transform_convert_mesh_connectivity_distance. */ - } - else { - set_prop_dist(t, false); - } - } - else if (convert_type == TC_MESH_UV && t->flag & T_PROP_CONNECTED) { - /* Already calculated by uv_set_connectivity_distance. */ - } - else if (convert_type == TC_CURVE_VERTS && t->obedit_type == OB_CURVE) { - set_prop_dist(t, false); - } - else { - set_prop_dist(t, true); - } - - sort_trans_data_dist(t); - } - else { - if (ELEM(t->obedit_type, OB_CURVE)) { - /* Needed because bezier handles can be partially selected - * and are still added into transform data. */ - sort_trans_data_selected_first(t); - } - - if (!init_prop_edit) { - t->flag &= ~T_PROP_EDIT_ALL; - } - } + init_proportional_edit(t); BLI_assert((!(t->flag & T_EDIT)) == (!(t->obedit_type != -1))); } @@ -1557,9 +1698,11 @@ void recalcData(TransInfo *t) flushTransNodes(t); break; case TC_OBJECT: - case TC_OBJECT_TEXSPACE: recalcData_objects(t); break; + case TC_OBJECT_TEXSPACE: + recalcData_texspace(t); + break; case TC_PAINT_CURVE_VERTS: flushTransPaintCurve(t); break; diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index 466bfd6b226..bd7569b3771 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -49,37 +49,9 @@ void mesh_customdatacorrect_init(TransInfo *t); /* transform_convert_sequencer.c */ int transform_convert_sequencer_get_snap_bound(TransInfo *t); - +void transform_convert_sequencer_channel_clamp(TransInfo *t); /********************* intern **********************/ -typedef enum eTransConvertType { - TC_NONE = 0, - TC_ACTION_DATA, - TC_POSE, - TC_ARMATURE_VERTS, - TC_CURSOR_IMAGE, - TC_CURSOR_VIEW3D, - TC_CURVE_VERTS, - TC_GRAPH_EDIT_DATA, - TC_GPENCIL, - TC_LATTICE_VERTS, - TC_MASKING_DATA, - TC_MBALL_VERTS, - TC_MESH_VERTS, - TC_MESH_EDGES, - TC_MESH_SKIN, - TC_MESH_UV, - TC_NLA_DATA, - TC_NODE_DATA, - TC_OBJECT, - TC_OBJECT_TEXSPACE, - TC_PAINT_CURVE_VERTS, - TC_PARTICLE_VERTS, - TC_SCULPT, - TC_SEQ_DATA, - TC_TRACKING_DATA, -} eTransConvertType; - /* transform_convert.c */ bool transform_mode_use_local_origins(const TransInfo *t); void transform_around_single_fallback_ex(TransInfo *t, int data_len_all); @@ -215,10 +187,13 @@ void special_aftertrans_update__node(bContext *C, TransInfo *t); /* transform_convert_object.c */ void createTransObject(bContext *C, TransInfo *t); -void createTransTexspace(TransInfo *t); void recalcData_objects(TransInfo *t); void special_aftertrans_update__object(bContext *C, TransInfo *t); +/* transform_convert_object_texspace.c */ +void createTransTexspace(TransInfo *t); +void recalcData_texspace(TransInfo *t); + /* transform_convert_paintcurve.c */ void createTransPaintCurveVerts(bContext *C, TransInfo *t); void flushTransPaintCurve(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index e9b2273b343..71b9e11b51f 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -444,7 +444,7 @@ static short pose_grab_with_ik(Main *bmain, Object *ob) for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->layer & arm->layer) { if (pchan->bone->flag & (BONE_SELECTED | BONE_TRANSFORM_MIRROR)) { - /* Rule: no IK for solitatry (unconnected) bones */ + /* Rule: no IK for solitary (unconnected) bones. */ for (bonec = pchan->bone->childbase.first; bonec; bonec = bonec->next) { if (bonec->flag & BONE_CONNECTED) { break; @@ -870,8 +870,6 @@ void createTransPose(TransInfo *t) t->mode = TFM_RESIZE; } } - - t->flag |= T_POSE; } void createTransArmatureVerts(TransInfo *t) @@ -1354,7 +1352,7 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O } mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); if (pid) { - /* TODO(germano): Realitve Mirror support */ + /* TODO(germano): Relative Mirror support. */ } data->flag |= CONSTRAINT_IK_AUTO; /* Add a temporary auto IK constraint here, as we will only temporarily active this diff --git a/source/blender/editors/transform/transform_convert_curve.c b/source/blender/editors/transform/transform_convert_curve.c index 445253d5446..3c01c716123 100644 --- a/source/blender/editors/transform/transform_convert_curve.c +++ b/source/blender/editors/transform/transform_convert_curve.c @@ -298,7 +298,7 @@ void createTransCurveVerts(TransInfo *t) } if ((bezt_tx & SEL_F1) == 0 && (bezt_tx & SEL_F3) == 0) { - /* If the middle is selected but the sides arnt, this is needed */ + /* If the middle is selected but the sides aren't, this is needed. */ if (hdata == NULL) { /* if the handle was not saved by the previous handle */ hdata = initTransDataCurveHandles(td, bezt); diff --git a/source/blender/editors/transform/transform_convert_gpencil.c b/source/blender/editors/transform/transform_convert_gpencil.c index deb18b50a22..eaa8962326a 100644 --- a/source/blender/editors/transform/transform_convert_gpencil.c +++ b/source/blender/editors/transform/transform_convert_gpencil.c @@ -135,7 +135,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -242,7 +242,7 @@ static void createTransGPencil_curves(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); copy_m3_m4(mtx, diff_mat); pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); @@ -263,7 +263,7 @@ static void createTransGPencil_curves(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* Check if stroke has an editcurve */ @@ -436,7 +436,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* Check if the color is editable. */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } @@ -507,7 +507,7 @@ static void createTransGPencil_strokes(bContext *C, } /* Calculate difference matrix. */ - BKE_gpencil_parent_matrix_get(depsgraph, obact, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, obact, gpl, diff_mat); /* Undo matrix. */ invert_m4_m4(inverse_diff_mat, diff_mat); @@ -551,7 +551,7 @@ static void createTransGPencil_strokes(bContext *C, continue; } /* check if the color is editable */ - if (ED_gpencil_stroke_color_use(obact, gpl, gps) == false) { + if (ED_gpencil_stroke_material_editable(obact, gpl, gps) == false) { continue; } /* What we need to include depends on proportional editing settings... */ diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index b3bd6b31879..ce74c5f5a36 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -251,29 +251,55 @@ void transform_convert_mesh_islanddata_free(struct TransIslandData *island_data) * * \{ */ -static bool bmesh_test_dist_add(BMVert *v, - BMVert *v_other, +/* Propagate distance from v1 and v2 to v0. */ +static bool bmesh_test_dist_add(BMVert *v0, + BMVert *v1, + BMVert *v2, float *dists, - const float *dists_prev, /* optionally track original index */ int *index, - const int *index_prev, const float mtx[3][3]) { - if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) && - (BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0)) { - const int i = BM_elem_index_get(v); - const int i_other = BM_elem_index_get(v_other); - float vec[3]; - float dist_other; - sub_v3_v3v3(vec, v->co, v_other->co); - mul_m3_v3(mtx, vec); - - dist_other = dists_prev[i] + len_v3(vec); - if (dist_other < dists[i_other]) { - dists[i_other] = dist_other; + if ((BM_elem_flag_test(v0, BM_ELEM_SELECT) == 0) && + (BM_elem_flag_test(v0, BM_ELEM_HIDDEN) == 0)) { + const int i0 = BM_elem_index_get(v0); + const int i1 = BM_elem_index_get(v1); + + BLI_assert(dists[i1] != FLT_MAX); + if (dists[i0] <= dists[i1]) { + return false; + } + + float dist0; + + if (v2) { + /* Distance across triangle. */ + const int i2 = BM_elem_index_get(v2); + BLI_assert(dists[i2] != FLT_MAX); + if (dists[i0] <= dists[i2]) { + return false; + } + + float vm0[3], vm1[3], vm2[3]; + mul_v3_m3v3(vm0, mtx, v0->co); + mul_v3_m3v3(vm1, mtx, v1->co); + mul_v3_m3v3(vm2, mtx, v2->co); + + dist0 = geodesic_distance_propagate_across_triangle(vm0, vm1, vm2, dists[i1], dists[i2]); + } + else { + /* Distance along edge. */ + float vec[3]; + sub_v3_v3v3(vec, v1->co, v0->co); + mul_m3_v3(mtx, vec); + + dist0 = dists[i1] + len_v3(vec); + } + + if (dist0 < dists[i0]) { + dists[i0] = dist0; if (index != NULL) { - index[i_other] = index_prev[i]; + index[i0] = index[i1]; } return true; } @@ -292,15 +318,16 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, float *dists, int *index) { - BLI_LINKSTACK_DECLARE(queue, BMVert *); + BLI_LINKSTACK_DECLARE(queue, BMEdge *); - /* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */ - BLI_LINKSTACK_DECLARE(queue_next, BMVert *); + /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */ + BLI_LINKSTACK_DECLARE(queue_next, BMEdge *); BLI_LINKSTACK_INIT(queue); BLI_LINKSTACK_INIT(queue_next); { + /* Set indexes and initial distances for selected vertices. */ BMIter viter; BMVert *v; int i; @@ -308,7 +335,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { float dist; BM_elem_index_set(v, i); /* set_inline */ - BM_elem_flag_disable(v, BM_ELEM_TAG); if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { dist = FLT_MAX; @@ -317,7 +343,6 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, } } else { - BLI_LINKSTACK_PUSH(queue, v); dist = 0.0f; if (index != NULL) { index[i] = i; @@ -329,103 +354,99 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm, bm->elem_index_dirty &= ~BM_VERT; } - /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */ - float *dists_prev = MEM_dupallocN(dists); - int *index_prev = MEM_dupallocN(index); /* may be NULL */ + { + /* Add edges with at least one selected vertex to the queue. */ + BMIter eiter; + BMEdge *e; + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) { + BLI_LINKSTACK_PUSH(queue, e); + } + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } do { - BMVert *v; - LinkNode *lnk; - - /* this is correct but slow to do each iteration, - * instead sync the dist's while clearing BM_ELEM_TAG (below) */ -#if 0 - memcpy(dists_prev, dists, sizeof(float) * bm->totvert); -#endif - - while ((v = BLI_LINKSTACK_POP(queue))) { - BLI_assert(dists[BM_elem_index_get(v)] != FLT_MAX); - - /* connected edge-verts */ - if (v->e != NULL) { - BMEdge *e_iter, *e_first; - - e_iter = e_first = v->e; - - /* would normally use BM_EDGES_OF_VERT, but this runs so often, - * its faster to iterate on the data directly */ - do { - - if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == 0) { + BMEdge *e; + + while ((e = BLI_LINKSTACK_POP(queue))) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + int i1 = BM_elem_index_get(v1); + int i2 = BM_elem_index_get(v2); + + if (e->l == NULL || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) { + /* Propagate along edge from vertex with smallest to largest distance. */ + if (dists[i1] > dists[i2]) { + SWAP(int, i1, i2); + SWAP(BMVert *, v1, v2); + } - /* edge distance */ - { - BMVert *v_other = BM_edge_other_vert(e_iter, v); - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (bmesh_test_dist_add(v2, v1, NULL, dists, index, mtx)) { + /* Add adjacent loose edges to the queue, or all edges if this is a loose edge. + * Other edges are handled by propagation across edges below. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e->l == NULL || e_other->l == NULL)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } + } + } + } - /* face distance */ - if (e_iter->l) { - BMLoop *l_iter_radial, *l_first_radial; - /** - * imaginary edge diagonally across quad. - * \note This takes advantage of the rules of winding that we - * know 2 or more of a verts edges wont reference the same face twice. - * Also, if the edge is hidden, the face will be hidden too. - */ - l_iter_radial = l_first_radial = e_iter->l; - - do { - if ((l_iter_radial->v == v) && (l_iter_radial->f->len == 4) && - (BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0)) { - BMVert *v_other = l_iter_radial->next->next->v; - if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) { - if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) { - BM_elem_flag_enable(v_other, BM_ELEM_TAG); - BLI_LINKSTACK_PUSH(queue_next, v_other); - } - } + if (e->l != NULL) { + /* Propagate across edge to vertices in adjacent faces. */ + BMLoop *l; + BMIter liter; + BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { + for (BMLoop *l_other = l->next->next; l_other != l; l_other = l_other->next) { + BMVert *v_other = l_other->v; + BLI_assert(!ELEM(v_other, v1, v2)); + + if (bmesh_test_dist_add(v_other, v1, v2, dists, index, mtx)) { + /* Add adjacent edges to the queue, if they are ready to propagate across/along. + * Always propagate along loose edges, and for other edges only propagate across + * if both vertices have a known distances. */ + BMEdge *e_other; + BMIter eiter; + BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) { + if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 && + (e_other->l == NULL || + dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) { + BM_elem_flag_enable(e_other, BM_ELEM_TAG); + BLI_LINKSTACK_PUSH(queue_next, e_other); } - } while ((l_iter_radial = l_iter_radial->radial_next) != l_first_radial); + } } } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first); + } } } - /* clear for the next loop */ - for (lnk = queue_next; lnk; lnk = lnk->next) { - BMVert *v_link = lnk->link; - const int i = BM_elem_index_get(v_link); + /* Clear for the next loop. */ + for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) { + BMEdge *e_link = lnk->link; - BM_elem_flag_disable(v_link, BM_ELEM_TAG); - - /* keep in sync, avoid having to do full memcpy each iteration */ - dists_prev[i] = dists[i]; - if (index != NULL) { - index_prev[i] = index[i]; - } + BM_elem_flag_disable(e_link, BM_ELEM_TAG); } BLI_LINKSTACK_SWAP(queue, queue_next); - /* none should be tagged now since 'queue_next' is empty */ - BLI_assert(BM_iter_mesh_count_flag(BM_VERTS_OF_MESH, bm, BM_ELEM_TAG, true) == 0); - + /* None should be tagged now since 'queue_next' is empty. */ + BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, BM_ELEM_TAG, true) == 0); } while (BLI_LINKSTACK_SIZE(queue)); BLI_LINKSTACK_FREE(queue); BLI_LINKSTACK_FREE(queue_next); - - MEM_freeN(dists_prev); - if (index_prev != NULL) { - MEM_freeN(index_prev); - } } /** \} */ @@ -1445,7 +1466,7 @@ static void mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld, * * Interpolate from every other loop (not ideal) * However values will only be taken from loops which overlap other mdisps. - * */ + */ const bool update_loop_mdisps = is_moved && do_loop_mdisps && (tcld->cd_loop_mdisp_offset != -1); if (update_loop_mdisps) { float(*faces_center)[3] = BLI_array_alloca(faces_center, l_num); diff --git a/source/blender/editors/transform/transform_convert_mesh_skin.c b/source/blender/editors/transform/transform_convert_mesh_skin.c index 1807e9adcd1..b1024f5efe4 100644 --- a/source/blender/editors/transform/transform_convert_mesh_skin.c +++ b/source/blender/editors/transform/transform_convert_mesh_skin.c @@ -55,9 +55,7 @@ static float *mesh_skin_transdata_center(const struct TransIslandData *island_da if (island_data->center && island_index != -1) { return island_data->center[island_index]; } - else { - return eve->co; - } + return eve->co; } static void mesh_skin_transdata_create(TransDataBasic *td, diff --git a/source/blender/editors/transform/transform_convert_nla.c b/source/blender/editors/transform/transform_convert_nla.c index adc2d03e2dc..5eb3f68787a 100644 --- a/source/blender/editors/transform/transform_convert_nla.c +++ b/source/blender/editors/transform/transform_convert_nla.c @@ -304,7 +304,7 @@ void recalcData_nla(TransInfo *t) for (i = 0; i < tc->data_len; i++, tdn++) { NlaStrip *strip = tdn->strip; PointerRNA strip_ptr; - short pExceeded, nExceeded, iter; + short iter; int delta_y1, delta_y2; /* if this tdn has no handles, that means it is just a dummy that should be skipped */ @@ -358,21 +358,31 @@ void recalcData_nla(TransInfo *t) * * this is done as a iterative procedure (done 5 times max for now) */ + NlaStrip *prev = strip->prev; + while (prev != NULL && (prev->type & NLASTRIP_TYPE_TRANSITION)) { + prev = prev->prev; + } + + NlaStrip *next = strip->next; + while (next != NULL && (next->type & NLASTRIP_TYPE_TRANSITION)) { + next = next->next; + } + for (iter = 0; iter < 5; iter++) { - pExceeded = ((strip->prev) && (strip->prev->type != NLASTRIP_TYPE_TRANSITION) && - (tdn->h1[0] < strip->prev->end)); - nExceeded = ((strip->next) && (strip->next->type != NLASTRIP_TYPE_TRANSITION) && - (tdn->h2[0] > strip->next->start)); + + const bool pExceeded = (prev != NULL) && (tdn->h1[0] < prev->end); + const bool nExceeded = (next != NULL) && (tdn->h2[0] > next->start); if ((pExceeded && nExceeded) || (iter == 4)) { - /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a compromise) + /* both endpoints exceeded (or iteration ping-pong'd meaning that we need a + * compromise) * - Simply crop strip to fit within the bounds of the strips bounding it * - If there were no neighbors, clear the transforms * (make it default to the strip's current values). */ - if (strip->prev && strip->next) { - tdn->h1[0] = strip->prev->end; - tdn->h2[0] = strip->next->start; + if (prev && next) { + tdn->h1[0] = prev->end; + tdn->h2[0] = next->start; } else { tdn->h1[0] = strip->start; @@ -381,14 +391,14 @@ void recalcData_nla(TransInfo *t) } else if (nExceeded) { /* move backwards */ - float offset = tdn->h2[0] - strip->next->start; + float offset = tdn->h2[0] - next->start; tdn->h1[0] -= offset; tdn->h2[0] -= offset; } else if (pExceeded) { /* more forwards */ - float offset = strip->prev->end - tdn->h1[0]; + float offset = prev->end - tdn->h1[0]; tdn->h1[0] += offset; tdn->h2[0] += offset; @@ -564,7 +574,7 @@ void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t)) /* free temp memory */ ANIM_animdata_freelist(&anim_data); - /* perform after-transfrom validation */ + /* Perform after-transform validation. */ ED_nla_postop_refresh(&ac); } } diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 90ffccfdd7b..5f6f00716f9 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -21,12 +21,8 @@ * \ingroup edtransform */ -#include "DNA_mesh_types.h" - #include "MEM_guardedalloc.h" -#include "BLI_compiler_compat.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -46,11 +42,11 @@ #include "DEG_depsgraph_query.h" #include "transform.h" +#include "transform_orientations.h" #include "transform_snap.h" /* Own include. */ #include "transform_convert.h" -#include "transform_orientations.h" /* -------------------------------------------------------------------- */ /** \name Object Mode Custom Data @@ -713,66 +709,6 @@ void createTransObject(bContext *C, TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Texture Space Transform Creation - * - * Instead of transforming the selection, move the 2D/3D cursor. - * - * \{ */ - -void createTransTexspace(TransInfo *t) -{ - ViewLayer *view_layer = t->view_layer; - TransData *td; - Object *ob; - ID *id; - short *texflag; - - ob = OBACT(view_layer); - - if (ob == NULL) { /* Shouldn't logically happen, but still. */ - return; - } - - id = ob->data; - if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { - BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); - return; - } - - if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); - return; - } - - { - BLI_assert(t->data_container_len == 1); - TransDataContainer *tc = t->data_container; - tc->data_len = 1; - td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); - td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); - } - - td->flag = TD_SELECTED; - copy_v3_v3(td->center, ob->obmat[3]); - td->ob = ob; - - copy_m3_m4(td->mtx, ob->obmat); - copy_m3_m4(td->axismtx, ob->obmat); - normalize_m3(td->axismtx); - pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); - - if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size)) { - ob->dtx |= OB_TEXSPACE; - *texflag &= ~ME_AUTOSPACE; - } - - copy_v3_v3(td->iloc, td->loc); - copy_v3_v3(td->ext->isize, td->ext->size); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Transform (Auto-Keyframing) * \{ */ @@ -962,10 +898,6 @@ void recalcData_objects(TransInfo *t) * otherwise proxies don't function correctly */ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); - - if (t->flag & T_TEXTURE) { - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - } } } @@ -991,7 +923,7 @@ void recalcData_objects(TransInfo *t) void special_aftertrans_update__object(bContext *C, TransInfo *t) { - BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); + BLI_assert(t->options & CTX_OBJECT); Object *ob; const bool canceled = (t->state == TRANS_CANCEL); diff --git a/source/blender/editors/transform/transform_convert_object_texspace.c b/source/blender/editors/transform/transform_convert_object_texspace.c new file mode 100644 index 00000000000..195eb941b3b --- /dev/null +++ b/source/blender/editors/transform/transform_convert_object_texspace.c @@ -0,0 +1,126 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup edtransform + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" + +#include "BKE_animsys.h" +#include "BKE_context.h" +#include "BKE_object.h" +#include "BKE_report.h" + +#include "DNA_mesh_types.h" + +#include "transform.h" +#include "transform_snap.h" + +/* Own include. */ +#include "transform_convert.h" + +/* -------------------------------------------------------------------- */ +/** \name Texture Space Transform Creation + * + * Instead of transforming the selection, move the 2D/3D cursor. + * + * \{ */ + +void createTransTexspace(TransInfo *t) +{ + ViewLayer *view_layer = t->view_layer; + TransData *td; + Object *ob; + ID *id; + short *texflag; + + ob = OBACT(view_layer); + + if (ob == NULL) { /* Shouldn't logically happen, but still. */ + return; + } + + id = ob->data; + if (id == NULL || !ELEM(GS(id->name), ID_ME, ID_CU, ID_MB)) { + BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); + return; + } + + if (BKE_object_obdata_is_libdata(ob)) { + BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); + return; + } + + { + BLI_assert(t->data_container_len == 1); + TransDataContainer *tc = t->data_container; + tc->data_len = 1; + td = tc->data = MEM_callocN(sizeof(TransData), "TransTexspace"); + td->ext = tc->data_ext = MEM_callocN(sizeof(TransDataExtension), "TransTexspace"); + } + + td->flag = TD_SELECTED; + copy_v3_v3(td->center, ob->obmat[3]); + td->ob = ob; + + copy_m3_m4(td->mtx, ob->obmat); + copy_m3_m4(td->axismtx, ob->obmat); + normalize_m3(td->axismtx); + pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); + + if (BKE_object_obdata_texspace_get(ob, &texflag, &td->loc, &td->ext->size)) { + ob->dtx |= OB_TEXSPACE; + *texflag &= ~ME_AUTOSPACE; + } + + copy_v3_v3(td->iloc, td->loc); + copy_v3_v3(td->ext->isize, td->ext->size); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Recalc Data object + * + * \{ */ + +/* helper for recalcData() - for object transforms, typically in the 3D view */ +void recalcData_texspace(TransInfo *t) +{ + + if (t->state != TRANS_CANCEL) { + applyProject(t); + } + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + + for (int i = 0; i < tc->data_len; i++, td++) { + if (td->flag & TD_SKIP) { + continue; + } + DEG_id_tag_update(&td->ob->id, ID_RECALC_GEOMETRY); + } + } +} + +/** \} */ diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c index ebb0b6823a3..22b1f9fd8d7 100644 --- a/source/blender/editors/transform/transform_convert_sequencer.c +++ b/source/blender/editors/transform/transform_convert_sequencer.c @@ -25,6 +25,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_context.h" @@ -64,6 +65,8 @@ typedef struct TransSeq { int min; int max; bool snap_left; + int selection_channel_range_min; + int selection_channel_range_max; } TransSeq; /* -------------------------------------------------------------------- */ @@ -623,6 +626,14 @@ void createTransSeqData(TransInfo *t) } } + ts->selection_channel_range_min = MAXSEQ + 1; + LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { + if ((seq->flag & SELECT) != 0) { + ts->selection_channel_range_min = min_ii(ts->selection_channel_range_min, seq->machine); + ts->selection_channel_range_max = max_ii(ts->selection_channel_range_max, seq->machine); + } + } + #undef XXX_DURIAN_ANIM_TX_HACK } @@ -834,7 +845,7 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) /* Marker transform, not especially nice but we may want to move markers * at the same time as strips in the Video Sequencer. */ if (sseq->flag & SEQ_MARKER_TRANS) { - /* cant use TFM_TIME_EXTEND + /* can't use TFM_TIME_EXTEND * for some reason EXTEND is changed into TRANSLATE, so use frame_side instead */ if (t->mode == TFM_SEQ_SLIDE) { @@ -850,6 +861,21 @@ void special_aftertrans_update__sequencer(bContext *UNUSED(C), TransInfo *t) } } +void transform_convert_sequencer_channel_clamp(TransInfo *t) +{ + const TransSeq *ts = (TransSeq *)TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; + const int channel_offset = round_fl_to_int(t->values[1]); + const int min_channel_after_transform = ts->selection_channel_range_min + channel_offset; + const int max_channel_after_transform = ts->selection_channel_range_max + channel_offset; + + if (max_channel_after_transform > MAXSEQ) { + t->values[1] -= max_channel_after_transform - MAXSEQ; + } + if (min_channel_after_transform < 1) { + t->values[1] -= min_channel_after_transform - 1; + } +} + int transform_convert_sequencer_get_snap_bound(TransInfo *t) { TransSeq *ts = TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->custom.type.data; diff --git a/source/blender/editors/transform/transform_convert_tracking.c b/source/blender/editors/transform/transform_convert_tracking.c index c3f48adca68..5f5f06e388f 100644 --- a/source/blender/editors/transform/transform_convert_tracking.c +++ b/source/blender/editors/transform/transform_convert_tracking.c @@ -52,6 +52,7 @@ typedef struct TransDataTracking { float (*smarkers)[2]; int markersnr; + int framenr; MovieTrackingMarker *markers; /* marker transformation from curves editor */ @@ -73,9 +74,25 @@ enum transDataTracking_Mode { * * \{ */ -static void markerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +typedef struct TransformInitContext { + SpaceClip *space_clip; + + TransInfo *t; + TransDataContainer *tc; + + /* NOTE: These pointers will be `nullptr` during counting step. + * This means, that the transformation data initialization functions are to increment + * `tc->data_len` instead of filling in the transformation data when these pointers are + * `nullptr`. For simplicity, check the `current.td` against `nullptr`. + * Do not `tc->data_len` when filling in the transformation data. */ + struct { + TransData *td; + TransData2D *td2d; + TransDataTracking *tdt; + } current; +} TransformInitContext; + +static void markerToTransDataInit(TransformInitContext *init_context, MovieTrackingTrack *track, MovieTrackingMarker *marker, int area, @@ -84,8 +101,19 @@ static void markerToTransDataInit(TransData *td, const float off[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + int anchor = area == TRACK_AREA_POINT && off; + tdt->flag = marker->flag; + tdt->framenr = marker->framenr; tdt->mode = transDataTracking_ModeTracks; if (anchor) { @@ -143,23 +171,20 @@ static void markerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void trackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingTrack *track, const float aspect[2]) { MovieTrackingMarker *marker = BKE_tracking_marker_ensure(track, framenr); - tdt->flag = marker->flag; - marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); - - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_POINT, @@ -170,16 +195,14 @@ static void trackToTransData(const int framenr, if (track->flag & SELECT) { markerToTransDataInit( - td++, td2d++, tdt++, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); + init_context, track, marker, TRACK_AREA_POINT, marker->pos, NULL, NULL, aspect); } if (track->pat_flag & SELECT) { int a; for (a = 0; a < 4; a++) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_PAT, @@ -191,9 +214,7 @@ static void trackToTransData(const int framenr, } if (track->search_flag & SELECT) { - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -202,9 +223,7 @@ static void trackToTransData(const int framenr, NULL, aspect); - markerToTransDataInit(td++, - td2d++, - tdt++, + markerToTransDataInit(init_context, track, marker, TRACK_AREA_SEARCH, @@ -213,15 +232,43 @@ static void trackToTransData(const int framenr, NULL, aspect); } + + if (init_context->current.td != NULL) { + marker->flag &= ~(MARKER_DISABLED | MARKER_TRACKED); + } } -static void planeMarkerToTransDataInit(TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void trackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingTrack *track, + const float aspect[2]) +{ + if (!TRACK_VIEW_SELECTED(init_context->space_clip, track)) { + return; + } + if (track->flag & TRACK_LOCKED) { + return; + } + trackToTransData(init_context, framenr, track, aspect); +} + +static void planeMarkerToTransDataInit(TransformInitContext *init_context, MovieTrackingPlaneTrack *plane_track, + MovieTrackingPlaneMarker *plane_marker, float corner[2], const float aspect[2]) { + TransData *td = init_context->current.td; + TransData2D *td2d = init_context->current.td2d; + TransDataTracking *tdt = init_context->current.tdt; + + if (td == NULL) { + init_context->tc->data_len++; + return; + } + + tdt->flag = plane_marker->flag; + tdt->framenr = plane_marker->framenr; tdt->mode = transDataTracking_ModePlaneTracks; tdt->plane_track = plane_track; @@ -247,24 +294,38 @@ static void planeMarkerToTransDataInit(TransData *td, unit_m3(td->mtx); unit_m3(td->smtx); + + init_context->current.td++; + init_context->current.td2d++; + init_context->current.tdt++; } -static void planeTrackToTransData(const int framenr, - TransData *td, - TransData2D *td2d, - TransDataTracking *tdt, +static void planeTrackToTransData(TransformInitContext *init_context, + const int framenr, MovieTrackingPlaneTrack *plane_track, const float aspect[2]) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_ensure(plane_track, framenr); - int i; - tdt->flag = plane_marker->flag; - plane_marker->flag &= ~PLANE_MARKER_TRACKED; + for (int i = 0; i < 4; i++) { + planeMarkerToTransDataInit( + init_context, plane_track, plane_marker, plane_marker->corners[i], aspect); + } - for (i = 0; i < 4; i++) { - planeMarkerToTransDataInit(td++, td2d++, tdt++, plane_track, plane_marker->corners[i], aspect); + if (init_context->current.td != NULL) { + plane_marker->flag &= ~PLANE_MARKER_TRACKED; + } +} + +static void planeTrackToTransDataIfNeeded(TransformInitContext *init_context, + const int framenr, + MovieTrackingPlaneTrack *plane_track, + const float aspect[2]) +{ + if (!PLANE_TRACK_VIEW_SELECTED(plane_track)) { + return; } + planeTrackToTransData(init_context, framenr, plane_track, aspect); } static void transDataTrackingFree(TransInfo *UNUSED(t), @@ -284,101 +345,53 @@ static void transDataTrackingFree(TransInfo *UNUSED(t), static void createTransTrackingTracksData(bContext *C, TransInfo *t) { - TransData *td; - TransData2D *td2d; - SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); - ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - MovieTrackingTrack *track; - MovieTrackingPlaneTrack *plane_track; - TransDataTracking *tdt; - int framenr = ED_space_clip_get_clip_frame_number(sc); + SpaceClip *space_clip = CTX_wm_space_clip(C); + MovieClip *clip = ED_space_clip_get_clip(space_clip); + const ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); + const ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); + const int framenr = ED_space_clip_get_clip_frame_number(space_clip); TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - /* count */ - tc->data_len = 0; - - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - tc->data_len++; /* offset */ + TransformInitContext init_context = {NULL}; + init_context.space_clip = space_clip; + init_context.t = t; + init_context.tc = tc; - if (track->flag & SELECT) { - tc->data_len++; - } + /* Count required transformation data. */ - if (track->pat_flag & SELECT) { - tc->data_len += 4; - } - - if (track->search_flag & SELECT) { - tc->data_len += 2; - } - } + tc->data_len = 0; - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - tc->data_len += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } if (tc->data_len == 0) { return; } - td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); - td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), - "TransTracking TransData2D"); - tdt = tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), - "TransTracking TransDataTracking"); - + tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransTracking TransData"); + tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D), "TransTracking TransData2D"); + tc->custom.type.data = MEM_callocN(tc->data_len * sizeof(TransDataTracking), + "TransTracking TransDataTracking"); tc->custom.type.free_cb = transDataTrackingFree; - /* create actual data */ - track = tracksbase->first; - while (track) { - if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { - trackToTransData(framenr, td, td2d, tdt, track, t->aspect); - - /* offset */ - td++; - td2d++; - tdt++; + init_context.current.td = tc->data; + init_context.current.td2d = tc->data_2d; + init_context.current.tdt = tc->custom.type.data; - if (track->flag & SELECT) { - td++; - td2d++; - tdt++; - } - - if (track->pat_flag & SELECT) { - td += 4; - td2d += 4; - tdt += 4; - } + /* Create actual transformation data. */ - if (track->search_flag & SELECT) { - td += 2; - td2d += 2; - tdt += 2; - } - } - - track = track->next; + LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) { + trackToTransDataIfNeeded(&init_context, framenr, track, t->aspect); } - for (plane_track = plane_tracks_base->first; plane_track; plane_track = plane_track->next) { - if (PLANE_TRACK_VIEW_SELECTED(plane_track)) { - planeTrackToTransData(framenr, td, td2d, tdt, plane_track, t->aspect); - td += 4; - td2d += 4; - tdt += 4; - } + LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { + planeTrackToTransDataIfNeeded(&init_context, framenr, plane_track, t->aspect); } } @@ -560,17 +573,17 @@ void createTransTrackingData(bContext *C, TransInfo *t) static void cancelTransTracking(TransInfo *t) { TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); - SpaceClip *sc = t->area->spacedata.first; - int i, framenr = ED_space_clip_get_clip_frame_number(sc); TransDataTracking *tdt_array = tc->custom.type.data; - i = 0; + int i = 0; while (i < tc->data_len) { TransDataTracking *tdt = &tdt_array[i]; if (tdt->mode == transDataTracking_ModeTracks) { MovieTrackingTrack *track = tdt->track; - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, tdt->framenr); + + BLI_assert(marker != NULL); marker->flag = tdt->flag; @@ -606,7 +619,10 @@ static void cancelTransTracking(TransInfo *t) } else if (tdt->mode == transDataTracking_ModePlaneTracks) { MovieTrackingPlaneTrack *plane_track = tdt->plane_track; - MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); + MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get_exact(plane_track, + tdt->framenr); + + BLI_assert(plane_marker != NULL); plane_marker->flag = tdt->flag; i += 3; diff --git a/source/blender/editors/transform/transform_data.h b/source/blender/editors/transform/transform_data.h index b59197fcd39..5b01433c96b 100644 --- a/source/blender/editors/transform/transform_data.h +++ b/source/blender/editors/transform/transform_data.h @@ -122,11 +122,11 @@ typedef struct TransDataCurveHandleFlags { typedef struct TransData { TRANSDATABASIC; - /** Distance needed to affect element (for Proportionnal Editing). */ + /** Distance needed to affect element (for Proportional Editing). */ float dist; - /** Distance to the nearest element (for Proportionnal Editing). */ + /** Distance to the nearest element (for Proportional Editing). */ float rdist; - /** Factor of the transformation (for Proportionnal Editing). */ + /** Factor of the transformation (for Proportional Editing). */ float factor; /** Value pointer for special transforms. */ float *val; @@ -141,11 +141,11 @@ typedef struct TransData { struct Object *ob; /** For objects/bones, the first constraint in its constraint stack. */ struct bConstraint *con; - /** For objects, poses. 1 single malloc per TransInfo! */ + /** For objects, poses. 1 single allocation per #TransInfo! */ TransDataExtension *ext; /** for curves, stores handle flags for modification/cancel. */ TransDataCurveHandleFlags *hdata; - /** If set, copy of Object or PoseChannel protection. */ + /** If set, copy of Object or #bPoseChannel protection. */ short protectflag; } TransData; diff --git a/source/blender/editors/transform/transform_draw_cursors.c b/source/blender/editors/transform/transform_draw_cursors.c index 84fc45e2b45..ead8eae0997 100644 --- a/source/blender/editors/transform/transform_draw_cursors.c +++ b/source/blender/editors/transform/transform_draw_cursors.c @@ -45,99 +45,45 @@ enum eArrowDirection { RIGHT, }; -struct ArrowDims { - int offset; - int length; - int size; -}; - -#define POS_INDEX 0 -/* NOTE: this --^ is a bit hackish, but simplifies GPUVertFormat usage among functions - * private to this file - merwin - */ +#define ARROW_WIDTH (2.0f * U.pixelsize) +#define DASH_WIDTH (1.0f) +#define DASH_LENGTH (8.0f * DASH_WIDTH * U.pixelsize) -static void drawArrow(enum eArrowDirection dir, const struct ArrowDims *arrow_dims) +static void drawArrow(const uint pos_id, const enum eArrowDirection dir) { - int offset = arrow_dims->offset; - int length = arrow_dims->length; - int size = arrow_dims->size; - - immBegin(GPU_PRIM_LINES, 6); - - switch (dir) { - case LEFT: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, offset, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, -size); - immVertex2f(POS_INDEX, offset + length, 0); - immVertex2f(POS_INDEX, offset + length - size, size); - break; - - case DOWN: - offset = -offset; - length = -length; - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, offset); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, -size, offset + length - size); - immVertex2f(POS_INDEX, 0, offset + length); - immVertex2f(POS_INDEX, size, offset + length - size); - break; + int offset = 5.0f * UI_DPI_FAC; + int length = (6.0f * UI_DPI_FAC) + (4.0f * U.pixelsize); + int size = (3.0f * UI_DPI_FAC) + (2.0f * U.pixelsize); + + /* To line up the arrow point nicely, one end has to be extended by half its width. But + * being on a 45 degree angle, Pythagoras says a movement of sqrt(2)/2 * (line width /2) */ + float adjust = (M_SQRT2 * ARROW_WIDTH / 4.0f); + + if (ELEM(dir, LEFT, DOWN)) { + offset = -offset; + length = -length; + size = -size; + adjust = -adjust; } - immEnd(); -} - -static void drawArrowHead(enum eArrowDirection dir, int size) -{ - immBegin(GPU_PRIM_LINES, 4); - - switch (dir) { - case LEFT: - size = -size; - ATTR_FALLTHROUGH; - case RIGHT: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, size); - break; + immBegin(GPU_PRIM_LINES, 6); - case DOWN: - size = -size; - ATTR_FALLTHROUGH; - case UP: - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, -size, -size); - immVertex2f(POS_INDEX, 0, 0); - immVertex2f(POS_INDEX, size, -size); - break; + if (ELEM(dir, LEFT, RIGHT)) { + immVertex2f(pos_id, offset, 0); + immVertex2f(pos_id, offset + length, 0); + immVertex2f(pos_id, offset + length + adjust, adjust); + immVertex2f(pos_id, offset + length - size, -size); + immVertex2f(pos_id, offset + length, 0); + immVertex2f(pos_id, offset + length - size, size); } - - immEnd(); -} - -static void drawArc(float angle_start, float angle_end, int segments, float size) -{ - float delta = (angle_end - angle_start) / segments; - float angle; - int a; - - immBegin(GPU_PRIM_LINE_STRIP, segments + 1); - - for (angle = angle_start, a = 0; a < segments; angle += delta, a++) { - immVertex2f(POS_INDEX, cosf(angle) * size, sinf(angle) * size); + else { + immVertex2f(pos_id, 0, offset); + immVertex2f(pos_id, 0, offset + length); + immVertex2f(pos_id, adjust, offset + length + adjust); + immVertex2f(pos_id, -size, offset + length - size); + immVertex2f(pos_id, 0, offset + length); + immVertex2f(pos_id, size, offset + length - size); } - immVertex2f(POS_INDEX, cosf(angle_end) * size, sinf(angle_end) * size); immEnd(); } @@ -149,11 +95,7 @@ static void drawArc(float angle_start, float angle_end, int segments, float size bool transform_draw_cursor_poll(bContext *C) { ARegion *region = CTX_wm_region(C); - - if (region && region->regiontype == RGN_TYPE_WINDOW) { - return 1; - } - return 0; + return (region && region->regiontype == RGN_TYPE_WINDOW) ? 1 : 0; } /** @@ -164,181 +106,117 @@ void transform_draw_cursor_draw(bContext *UNUSED(C), int x, int y, void *customd { TransInfo *t = (TransInfo *)customdata; - if (t->helpline != HLP_NONE) { - struct ArrowDims arrow_dims = { - .offset = 5 * UI_DPI_FAC, - .length = 10 * UI_DPI_FAC, - .size = 5 * UI_DPI_FAC, - }; - - float cent[2]; - const float mval[3] = {x, y, 0.0f}; - float tmval[2] = { - (float)t->mval[0], - (float)t->mval[1], - }; - - projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); - /* Offset the values for the area region. */ - const float offset[2] = { - t->region->winrct.xmin, - t->region->winrct.ymin, - }; - - for (int i = 0; i < 2; i++) { - cent[i] += offset[i]; - tmval[i] += offset[i]; - } - - GPU_line_smooth(true); - GPU_blend(GPU_BLEND_ALPHA); - - GPU_matrix_push(); - - /* Dashed lines first. */ - if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { - const uint shdr_pos = GPU_vertformat_attr_add( - immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - - UNUSED_VARS_NDEBUG(shdr_pos); /* silence warning */ - BLI_assert(shdr_pos == POS_INDEX); + if (t->helpline == HLP_NONE) { + return; + } - GPU_line_width(1.0f); + float cent[2]; + const float mval[3] = {x, y, 0.0f}; + float tmval[2] = { + (float)t->mval[0], + (float)t->mval[1], + }; + + projectFloatViewEx(t, t->center_global, cent, V3D_PROJ_TEST_CLIP_ZERO); + /* Offset the values for the area region. */ + const float offset[2] = { + t->region->winrct.xmin, + t->region->winrct.ymin, + }; + + for (int i = 0; i < 2; i++) { + cent[i] += offset[i]; + tmval[i] += offset[i]; + } - immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + float viewport_size[4]; + GPU_viewport_size_get_f(viewport_size); + + GPU_line_smooth(true); + GPU_blend(GPU_BLEND_ALPHA); + const uint pos_id = GPU_vertformat_attr_add( + immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + + /* Dashed lines first. */ + if (ELEM(t->helpline, HLP_SPRING, HLP_ANGLE)) { + GPU_line_width(DASH_WIDTH); + immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR); + immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + immUniform1i("colors_len", 0); /* "simple" mode */ + immUniformThemeColor3(TH_VIEW_OVERLAY); + immUniform1f("dash_width", DASH_LENGTH); + immUniform1f("dash_factor", 0.5f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2fv(pos_id, cent); + immVertex2f(pos_id, tmval[0], tmval[1]); + immEnd(); + immUnbindProgram(); + } - float viewport_size[4]; - GPU_viewport_size_get_f(viewport_size); - immUniform2f("viewport_size", viewport_size[2], viewport_size[3]); + /* And now, solid lines. */ - immUniform1i("colors_len", 0); /* "simple" mode */ - immUniformThemeColor3(TH_VIEW_OVERLAY); - immUniform1f("dash_width", 6.0f * UI_DPI_FAC); - immUniform1f("dash_factor", 0.5f); + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniformThemeColor3(TH_VIEW_OVERLAY); + immUniform2fv("viewportSize", &viewport_size[2]); + immUniform1f("lineWidth", ARROW_WIDTH); - immBegin(GPU_PRIM_LINES, 2); - immVertex2fv(POS_INDEX, cent); - immVertex2f(POS_INDEX, tmval[0], tmval[1]); - immEnd(); + GPU_matrix_push(); + GPU_matrix_translate_3fv(mval); - immUnbindProgram(); + switch (t->helpline) { + case HLP_SPRING: + GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + case HLP_HARROW: + drawArrow(pos_id, RIGHT); + drawArrow(pos_id, LEFT); + break; + case HLP_VARROW: + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + case HLP_CARROW: { + /* Draw arrow based on direction defined by custom-points. */ + const int *data = t->mouse.data; + const float angle = -atan2f(data[2] - data[0], data[3] - data[1]); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; } - - /* And now, solid lines. */ - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - UNUSED_VARS_NDEBUG(pos); /* silence warning */ - BLI_assert(pos == POS_INDEX); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - - switch (t->helpline) { - case HLP_SPRING: - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - GPU_matrix_rotate_axis(-RAD2DEGF(atan2f(cent[0] - tmval[0], cent[1] - tmval[1])), 'Z'); - - GPU_line_width(3.0f); - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - case HLP_HARROW: - immUniformThemeColor3(TH_VIEW_OVERLAY); - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - drawArrow(RIGHT, &arrow_dims); - drawArrow(LEFT, &arrow_dims); - break; - case HLP_VARROW: - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - case HLP_CARROW: { - /* Draw arrow based on direction defined by custom-points. */ - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - - const int *data = t->mouse.data; - const float dx = data[2] - data[0], dy = data[3] - data[1]; - const float angle = -atan2f(dx, dy); - - GPU_matrix_push(); - - GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); - - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - - GPU_matrix_pop(); - break; - } - case HLP_ANGLE: { - float dx = tmval[0] - cent[0], dy = tmval[1] - cent[1]; - float angle = atan2f(dy, dx); - float dist = hypotf(dx, dy); - float delta_angle = min_ff(15.0f / (dist / UI_DPI_FAC), (float)M_PI / 4.0f); - float spacing_angle = min_ff(5.0f / (dist / UI_DPI_FAC), (float)M_PI / 12.0f); - - immUniformThemeColor3(TH_VIEW_OVERLAY); - - GPU_matrix_translate_3f(cent[0] - tmval[0] + mval[0], cent[1] - tmval[1] + mval[1], 0); - - GPU_line_width(3.0f); - drawArc(angle - delta_angle, angle - spacing_angle, 10, dist); - drawArc(angle + spacing_angle, angle + delta_angle, 10, dist); - - GPU_matrix_push(); - - GPU_matrix_translate_3f( - cosf(angle - delta_angle) * dist, sinf(angle - delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle - delta_angle), 'Z'); - - drawArrowHead(DOWN, arrow_dims.size); - - GPU_matrix_pop(); - - GPU_matrix_translate_3f( - cosf(angle + delta_angle) * dist, sinf(angle + delta_angle) * dist, 0); - GPU_matrix_rotate_axis(RAD2DEGF(angle + delta_angle), 'Z'); - - drawArrowHead(UP, arrow_dims.size); - break; - } - case HLP_TRACKBALL: { - uchar col[3], col2[3]; - UI_GetThemeColor3ubv(TH_GRID, col); - - GPU_matrix_translate_3fv(mval); - - GPU_line_width(3.0f); - - UI_make_axis_color(col, col2, 'X'); - immUniformColor3ubv(col2); - - drawArrow(RIGHT, &arrow_dims); - drawArrow(LEFT, &arrow_dims); - - UI_make_axis_color(col, col2, 'Y'); - immUniformColor3ubv(col2); - - drawArrow(UP, &arrow_dims); - drawArrow(DOWN, &arrow_dims); - break; - } + case HLP_ANGLE: { + GPU_matrix_push(); + float angle = atan2f(tmval[1] - cent[1], tmval[0] - cent[0]); + GPU_matrix_translate_3f(cosf(angle), sinf(angle), 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, DOWN); + GPU_matrix_pop(); + GPU_matrix_translate_3f(cosf(angle), sinf(angle), 0); + GPU_matrix_rotate_axis(RAD2DEGF(angle), 'Z'); + drawArrow(pos_id, UP); + break; } - - immUnbindProgram(); - GPU_matrix_pop(); - - GPU_line_smooth(false); - GPU_blend(GPU_BLEND_NONE); + case HLP_TRACKBALL: { + uchar col[3], col2[3]; + UI_GetThemeColor3ubv(TH_GRID, col); + UI_make_axis_color(col, col2, 'X'); + immUniformColor3ubv(col2); + drawArrow(pos_id, RIGHT); + drawArrow(pos_id, LEFT); + UI_make_axis_color(col, col2, 'Y'); + immUniformColor3ubv(col2); + drawArrow(pos_id, UP); + drawArrow(pos_id, DOWN); + break; + } + case HLP_NONE: + break; } + + GPU_matrix_pop(); + immUnbindProgram(); + GPU_line_smooth(false); + GPU_blend(GPU_BLEND_NONE); } diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index b092b3e3e0b..6fca49495e9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -26,7 +26,6 @@ #include "MEM_guardedalloc.h" #include "DNA_gpencil_types.h" -#include "DNA_mesh_types.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -44,6 +43,7 @@ #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_mask.h" +#include "BKE_modifier.h" #include "BKE_paint.h" #include "ED_clip.h" @@ -119,79 +119,6 @@ void resetTransRestrictions(TransInfo *t) t->flag &= ~T_ALL_RESTRICTIONS; } -void initTransDataContainers_FromObjectData(TransInfo *t, - Object *obact, - Object **objects, - uint objects_len) -{ - const eObjectMode object_mode = obact ? obact->mode : OB_MODE_OBJECT; - const short object_type = obact ? obact->type : -1; - - if ((object_mode & OB_MODE_EDIT) || (t->options & CTX_GPENCIL_STROKES) || - ((object_mode & OB_MODE_POSE) && (object_type == OB_ARMATURE))) { - if (t->data_container) { - MEM_freeN(t->data_container); - } - - bool free_objects = false; - if (objects == NULL) { - objects = BKE_view_layer_array_from_objects_in_mode( - t->view_layer, - (t->spacetype == SPACE_VIEW3D) ? t->view : NULL, - &objects_len, - { - .object_mode = object_mode, - .no_dup_data = true, - }); - free_objects = true; - } - - t->data_container = MEM_callocN(sizeof(*t->data_container) * objects_len, __func__); - t->data_container_len = objects_len; - - for (int i = 0; i < objects_len; i++) { - TransDataContainer *tc = &t->data_container[i]; - if (((t->flag & T_NO_MIRROR) == 0) && ((t->options & CTX_NO_MIRROR) == 0) && - (objects[i]->type == OB_MESH)) { - tc->use_mirror_axis_x = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_X) != 0; - tc->use_mirror_axis_y = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Y) != 0; - tc->use_mirror_axis_z = (((Mesh *)objects[i]->data)->symmetry & ME_SYMMETRY_Z) != 0; - } - - if (object_mode & OB_MODE_EDIT) { - tc->obedit = objects[i]; - /* Check needed for UV's */ - if ((t->flag & T_2D_EDIT) == 0) { - tc->use_local_mat = true; - } - } - else if (object_mode & OB_MODE_POSE) { - tc->poseobj = objects[i]; - tc->use_local_mat = true; - } - else if (t->options & CTX_GPENCIL_STROKES) { - tc->use_local_mat = true; - } - - if (tc->use_local_mat) { - BLI_assert((t->flag & T_2D_EDIT) == 0); - copy_m4_m4(tc->mat, objects[i]->obmat); - copy_m3_m4(tc->mat3, tc->mat); - /* for non-invertible scale matrices, invert_m4_m4_fallback() - * can still provide a valid pivot */ - invert_m4_m4_fallback(tc->imat, tc->mat); - invert_m3_m3(tc->imat3, tc->mat3); - normalize_m3_m3(tc->mat3_unit, tc->mat3); - } - /* Otherwise leave as zero. */ - } - - if (free_objects) { - MEM_freeN(objects); - } - } -} - /** * Setup internal data, mouse, vectors * @@ -225,7 +152,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->flag = 0; - if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE)) && + if (obact && !(t->options & (CTX_CURSOR | CTX_TEXTURE_SPACE)) && ELEM(object_mode, OB_MODE_EDIT, OB_MODE_EDIT_GPENCIL)) { t->obedit_type = obact->type; } @@ -272,7 +199,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve /* Crease needs edge flag */ if (ELEM(t->mode, TFM_CREASE, TFM_BWEIGHT)) { - t->options |= CTX_EDGE; + t->options |= CTX_EDGE_DATA; } t->remove_on_cancel = false; @@ -1110,7 +1037,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3]) return true; } } - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { ViewLayer *view_layer = t->view_layer; Object *ob = OBACT(view_layer); if (ED_object_calc_active_center_for_posemode(ob, select_only, r_center)) { @@ -1184,20 +1111,13 @@ void calculateCenter(TransInfo *t) } calculateCenterLocal(t, t->center_global); - /* avoid calculating again */ - { - TransCenterData *cd = &t->center_cache[t->around]; - copy_v3_v3(cd->global, t->center_global); - cd->is_set = true; - } - calculateCenter2D(t); - /* for panning from cameraview */ - if ((t->flag & T_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) { + /* For panning from the camera-view. */ + if ((t->options & CTX_OBJECT) && (t->flag & T_OVERRIDE_CENTER) == 0) { if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) { - if (t->flag & T_CAMERA) { + if (t->options & CTX_CAMERA) { float axis[3]; /* persinv is nasty, use viewinv instead, always right */ copy_v3_v3(axis, t->viewinv[2]); @@ -1237,23 +1157,6 @@ void calculateCenter(TransInfo *t) } } -BLI_STATIC_ASSERT(ARRAY_SIZE(((TransInfo *)NULL)->center_cache) == (V3D_AROUND_ACTIVE + 1), - "test size"); - -/** - * Lazy initialize transform center data, when we need to access center values from other types. - */ -const TransCenterData *transformCenter_from_type(TransInfo *t, int around) -{ - BLI_assert(around <= V3D_AROUND_ACTIVE); - TransCenterData *cd = &t->center_cache[around]; - if (cd->is_set == false) { - calculateCenter_FromAround(t, around, cd->global); - cd->is_set = true; - } - return cd; -} - void calculatePropRatio(TransInfo *t) { int i; @@ -1416,7 +1319,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) if (td->ext->rotOrder == ROT_MODE_QUAT) { float quat[4]; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ quat_to_mat3(obmat, td->ext->iquat); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1437,7 +1340,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { float axis[3], angle; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ axis_angle_to_mat3(obmat, td->ext->irotAxis, td->ext->irotAngle); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1459,7 +1362,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) else { float eul[3]; - /* calculate the total rotatation */ + /* Calculate the total rotation. */ eulO_to_mat3(obmat, td->ext->irot, td->ext->rotOrder); if (use_drot) { mul_m3_m3m3(obmat, dmat, obmat); @@ -1478,3 +1381,23 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot) copy_v3_v3(td->ext->rot, eul); } } + +Object *transform_object_deform_pose_armature_get(const TransInfo *t, Object *ob) +{ + if (!(ob->mode & OB_MODE_ALL_WEIGHT_PAINT)) { + return NULL; + } + /* Important that ob_armature can be set even when its not selected T23412. + * Lines below just check is also visible. */ + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); + if (ob_armature && ob_armature->mode & OB_MODE_POSE) { + Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); + if (base_arm) { + View3D *v3d = t->view; + if (BASE_VISIBLE(v3d, base_arm)) { + return ob_armature; + } + } + } + return NULL; +} diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index 9c08159cf07..27df29afd8d 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -532,7 +532,7 @@ static void protectflag_to_drawflags_ebone(RegionView3D *rv3d, const EditBone *e /* could move into BLI_math however this is only useful for display/editing purposes */ static void axis_angle_to_gimbal_axis(float gmat[3][3], const float axis[3], const float angle) { - /* X/Y are arbitrary axies, most importantly Z is the axis of rotation */ + /* X/Y are arbitrary axes, most importantly Z is the axis of rotation. */ float cross_vec[3]; float quat[4]; @@ -704,7 +704,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, if (BKE_gpencil_layer_is_editable(gpl) && (gpl->actframe != NULL)) { /* calculate difference matrix */ - BKE_gpencil_parent_matrix_get(depsgraph, ob, gpl, diff_mat); + BKE_gpencil_layer_transform_matrix_get(depsgraph, ob, gpl, diff_mat); LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) { /* skip strokes that are invalid for current view */ diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 70ef5fcde7a..bfeb96d18c4 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -499,28 +499,4 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } -eRedrawFlag handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event) -{ - eRedrawFlag redraw = TREDRAW_NOTHING; - - switch (event->type) { - case EVT_LEFTSHIFTKEY: - case EVT_RIGHTSHIFTKEY: - if (event->val == KM_PRESS) { - t->modifiers |= MOD_PRECISION; - /* shift is modifier for higher precision transforn */ - mi->precision = 1; - redraw = TREDRAW_HARD; - } - else if (event->val == KM_RELEASE) { - t->modifiers &= ~MOD_PRECISION; - mi->precision = 0; - redraw = TREDRAW_HARD; - } - break; - } - - return redraw; -} - /** \} */ diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index a4d999b868d..9e6e4d8807e 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -70,7 +70,7 @@ int transform_mode_really_used(bContext *C, int mode) bool transdata_check_local_center(TransInfo *t, short around) { return ((around == V3D_AROUND_LOCAL_ORIGINS) && - ((t->flag & (T_OBJECT | T_POSE)) || + ((t->options & (CTX_OBJECT | CTX_POSE_BONE)) || /* implicit: (t->flag & T_EDIT) */ (ELEM(t->obedit_type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE, OB_GPENCIL)) || (t->spacetype == SPACE_GRAPH) || @@ -513,7 +513,7 @@ void constraintSizeLim(TransInfo *t, TransData *td) return; } - /* extrace scale from matrix and apply back sign */ + /* Extract scale from matrix and apply back sign. */ mat4_to_size(td->ext->size, cob.matrix); mul_v3_v3(td->ext->size, size_sign); } @@ -629,7 +629,7 @@ void ElementRotation_ex(TransInfo *t, * matrix (and inverse). That is not all though. Once the proper translation * has been computed, it has to be converted back into the bone's space. */ - else if (t->flag & T_POSE) { + else if (t->options & CTX_POSE_BONE) { /* Extract and invert armature object matrix */ if ((td->flag & TD_NO_LOC) == 0) { @@ -705,7 +705,7 @@ void ElementRotation_ex(TransInfo *t, mul_m3_m3m3(totmat, mat, td->ext->r_mtx); mul_m3_m3m3(smat, td->ext->r_smtx, totmat); - /* calculate the total rotatation in eulers */ + /* Calculate the total rotation in eulers. */ copy_v3_v3(eul, td->ext->irot); eulO_to_mat3(eulmat, eul, td->ext->rotOrder); @@ -778,7 +778,7 @@ void ElementRotation_ex(TransInfo *t, mul_m3_m3m3(totmat, mat, td->mtx); mul_m3_m3m3(smat, td->smtx, totmat); - /* calculate the total rotatation in eulers */ + /* Calculate the total rotation in eulers. */ add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ eulO_to_mat3(obmat, eul, td->ext->rotOrder); /* mat = transform, obmat = object rotation */ @@ -902,7 +902,7 @@ static void TransMat3ToSize(const float mat[3][3], const float smat[3][3], float mat3_to_rot_size(rmat, size, mat); - /* first tried with dotproduct... but the sign flip is crucial */ + /* First tried with dot-product... but the sign flip is crucial. */ if (dot_v3v3(rmat[0], smat[0]) < 0.0f) { size[0] = -size[0]; } @@ -1026,7 +1026,7 @@ void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float ma mul_v3_fl(vec, td->factor); } - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { mul_m3_v3(td->smtx, vec); } diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c index f16021914f1..5bc2aa68443 100644 --- a/source/blender/editors/transform/transform_mode_align.c +++ b/source/blender/editors/transform/transform_mode_align.c @@ -55,7 +55,7 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2])) } /* around local centers */ - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { copy_v3_v3(tc->center_local, td->center); } else { diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c index 7ccfd0149bd..4330d5e79be 100644 --- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c @@ -35,10 +35,12 @@ #include "WM_types.h" #include "UI_interface.h" +#include "UI_view2d.h" #include "BLT_translation.h" #include "transform.h" +#include "transform_convert.h" #include "transform_mode.h" #include "transform_snap.h" @@ -49,9 +51,9 @@ static eRedrawFlag seq_slide_handleEvent(struct TransInfo *t, const wmEvent *event) { BLI_assert(t->mode == TFM_SEQ_SLIDE); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi && event->type == kmi->type && event->val == kmi->val) { - /* Allows the 'Expand to fit' effect to be enabled as a toogle. */ + /* Allows the "Expand to Fit" effect to be enabled as a toggle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; } @@ -73,7 +75,7 @@ static void headerSeqSlide(TransInfo *t, const float val[2], char str[UI_MAX_DRA ofs += BLI_snprintf( str + ofs, UI_MAX_DRAW_STR - ofs, TIP_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, UI_MAX_DRAW_STR - ofs); } @@ -106,6 +108,7 @@ static void applySeqSlide(TransInfo *t, const int mval[2]) float values_final[3] = {0.0f}; snapSequenceBounds(t, mval); + transform_convert_sequencer_channel_clamp(t); if (applyNumInput(&t->num, values_final)) { if (t->con.mode & CON_APPLY) { if (t->con.mode & CON_AXIS0) { @@ -158,7 +161,7 @@ void initSeqSlide(TransInfo *t) if (t->keymap) { /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); + t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); } } /** \} */ diff --git a/source/blender/editors/transform/transform_mode_edge_slide.c b/source/blender/editors/transform/transform_mode_edge_slide.c index dae3fe6f7b4..dff9ded6b29 100644 --- a/source/blender/editors/transform/transform_mode_edge_slide.c +++ b/source/blender/editors/transform/transform_mode_edge_slide.c @@ -143,7 +143,7 @@ static BMEdge *get_other_edge(BMVert *v, BMEdge *e) return NULL; } -/* interpoaltes along a line made up of 2 segments (used for edge slide) */ +/* Interpolates along a line made up of 2 segments (used for edge slide). */ static void interp_line_v3_v3v3v3( float p[3], const float v1[3], const float v2[3], const float v3[3], float t) { diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c index 3aa99975fda..9891af8b9a4 100644 --- a/source/blender/editors/transform/transform_mode_mirror.c +++ b/source/blender/editors/transform/transform_mode_mirror.c @@ -152,7 +152,7 @@ static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, i sub_v3_v3(vec, td->center); } - if (t->flag & (T_OBJECT | T_POSE)) { + if (t->options & (CTX_OBJECT | CTX_POSE_BONE)) { mul_m3_v3(td->smtx, vec); } diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c index 62a4fbd6f04..4d0bb7fbe9c 100644 --- a/source/blender/editors/transform/transform_mode_resize.c +++ b/source/blender/editors/transform/transform_mode_resize.c @@ -132,7 +132,7 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2])) } } - /* evil hack - redo resize if cliping needed */ + /* Evil hack - redo resize if clipping needed. */ if (t->flag & T_CLIP_UV && clipUVTransform(t, t->values_final, 1)) { size_to_mat3(mat, t->values_final); diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c index ba5b1229f3e..6e497d85417 100644 --- a/source/blender/editors/transform/transform_mode_shrink_fatten.c +++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c @@ -49,9 +49,9 @@ static eRedrawFlag shrinkfatten_handleEvent(struct TransInfo *t, const wmEvent *event) { BLI_assert(t->mode == TFM_SHRINKFATTEN); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi && event->type == kmi->type && event->val == kmi->val) { - /* Allows the 'Even Thickness' effect to be enabled as a toogle. */ + /* Allows the "Even Thickness" effect to be enabled as a toggle. */ t->flag ^= T_ALT_TRANSFORM; return TREDRAW_HARD; } @@ -84,8 +84,13 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) else { /* default header print */ if (unit != NULL) { - ofs += BKE_unit_value_as_string( - str + ofs, sizeof(str) - ofs, distance * unit->scale_length, 4, B_UNIT_LENGTH, unit, true); + ofs += BKE_unit_value_as_string(str + ofs, + sizeof(str) - ofs, + distance * unit->scale_length, + 4, + B_UNIT_LENGTH, + unit, + true); } else { ofs += BLI_snprintf(str + ofs, sizeof(str) - ofs, "%.4f", distance); @@ -97,7 +102,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) } ofs += BLI_strncpy_rlen(str + ofs, ", (", sizeof(str) - ofs); - wmKeyMapItem *kmi = t->custom.mode.data; + const wmKeyMapItem *kmi = t->custom.mode.data; if (kmi) { ofs += WM_keymap_item_to_string(kmi, false, str + ofs, sizeof(str) - ofs); } @@ -157,7 +162,7 @@ void initShrinkFatten(TransInfo *t) if (t->keymap) { /* Workaround to use the same key as the modal keymap. */ - t->custom.mode.data = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); + t->custom.mode.data = (void *)WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); } } } diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c index 851e0feb5f5..41fc6ee0aaf 100644 --- a/source/blender/editors/transform/transform_mode_translate.c +++ b/source/blender/editors/transform/transform_mode_translate.c @@ -294,7 +294,7 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) const float *original_normal; /* In pose mode, we want to align normals with Y axis of bones... */ - if (t->flag & T_POSE) { + if (t->options & CTX_POSE_BONE) { original_normal = td->axismtx[1]; } else { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 15c215c426d..01c00247a7a 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -411,7 +411,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) int exit_code; TransInfo *t = op->customdata; - const enum TfmMode mode_prev = t->mode; + const eTfmMode mode_prev = t->mode; #if defined(WITH_INPUT_NDOF) && 0 /* Stable 2D mouse coords map to different 3D coords while the 3D mouse is active @@ -432,7 +432,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) * since we're not reading from 'td->center' in this case. see: T40241 */ if (t->tsnap.target == SCE_SNAP_TARGET_ACTIVE) { /* In camera view, tsnap callback is not set - * (see initSnappingMode() in transfrom_snap.c, and T40348). */ + * (see #initSnappingMode() in transform_snap.c, and T40348). */ if (t->tsnap.targetSnap && ((t->tsnap.status & TARGET_INIT) == 0)) { t->tsnap.targetSnap(t); } @@ -444,7 +444,7 @@ static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) if ((exit_code & OPERATOR_RUNNING_MODAL) == 0) { transformops_exit(C, op); - exit_code &= ~OPERATOR_PASS_THROUGH; /* preventively remove passthrough */ + exit_code &= ~OPERATOR_PASS_THROUGH; /* Preventively remove pass-through. */ } else { if (mode_prev != t->mode) { diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 3b39f4d06ad..1470d3b7059 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -521,23 +521,19 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, const int pivot_point) { switch (orientation_type) { - case V3D_ORIENT_GLOBAL: { - unit_m3(r_mat); - return V3D_ORIENT_GLOBAL; - } case V3D_ORIENT_GIMBAL: { if (ob && gimbal_axis(ob, r_mat)) { - return V3D_ORIENT_GIMBAL; + break; } - /* if not gimbal, fall through to normal */ + /* If not gimbal, fall through to normal. */ ATTR_FALLTHROUGH; } case V3D_ORIENT_NORMAL: { if (obedit || (ob && ob->mode & OB_MODE_POSE)) { ED_getTransformOrientationMatrix(C, ob, obedit, pivot_point, r_mat); - return V3D_ORIENT_NORMAL; + break; } - /* no break we define 'normal' as 'local' in Object mode */ + /* No break we define 'normal' as 'local' in Object mode. */ ATTR_FALLTHROUGH; } case V3D_ORIENT_LOCAL: { @@ -552,10 +548,14 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, else { transform_orientations_create_from_axis(r_mat, UNPACK3(ob->obmat)); } - return V3D_ORIENT_LOCAL; + break; } + /* If not local, fall through to global. */ + ATTR_FALLTHROUGH; + } + case V3D_ORIENT_GLOBAL: { unit_m3(r_mat); - return V3D_ORIENT_GLOBAL; + break; } case V3D_ORIENT_VIEW: { if (rv3d != NULL) { @@ -565,11 +565,11 @@ short ED_transform_calc_orientation_from_type_ex(const bContext *C, else { unit_m3(r_mat); } - return V3D_ORIENT_VIEW; + break; } case V3D_ORIENT_CURSOR: { BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat); - return V3D_ORIENT_CURSOR; + break; } case V3D_ORIENT_CUSTOM_MATRIX: { /* Do nothing. */; @@ -609,6 +609,12 @@ short transform_orientation_matrix_get( orientation_index_custom = orientation - V3D_ORIENT_CUSTOM; orientation = V3D_ORIENT_CUSTOM; } + else if (ob && (ob->mode & OB_MODE_ALL_WEIGHT_PAINT) && !(t->options & CTX_PAINT_CURVE)) { + Object *ob_armature = transform_object_deform_pose_armature_get(t, ob); + if (ob_armature) { + ob = ob_armature; + } + } if ((t->spacetype == SPACE_VIEW3D) && t->region && (t->region->regiontype == RGN_TYPE_WINDOW)) { rv3d = t->region->regiondata; diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index c19dd4598cf..6d04de34016 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -235,7 +235,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_IMAGE) { if (validSnap(t)) { - /* This will not draw, and Im nor sure why - campbell */ + /* This will not draw, and I'm nor sure why - campbell */ /* TODO: see 2.7x for non-working code */ } } @@ -299,83 +299,93 @@ eRedrawFlag handleSnapping(TransInfo *t, const wmEvent *event) void applyProject(TransInfo *t) { - /* XXX FLICKER IN OBJECT MODE */ - if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { - float tvec[3]; - int i; + if (!t->tsnap.project) { + return; + } - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - for (i = 0; i < tc->data_len; i++, td++) { - float iloc[3], loc[3], no[3]; - float mval_fl[2]; - if (td->flag & TD_SKIP) { - continue; - } + if (!activeSnap(t) || (t->flag & T_NO_PROJECT)) { + return; + } - if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { - continue; - } + if (doForceIncrementSnap(t)) { + return; + } - copy_v3_v3(iloc, td->loc); - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, iloc); - } - else if (t->flag & T_OBJECT) { - BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); - copy_v3_v3(iloc, td->ob->obmat[3]); - } + float tvec[3]; + int i; - if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == - V3D_PROJ_RET_OK) { - if (ED_transform_snap_object_project_view3d( - t->tsnap.object_context, - t->depsgraph, - SCE_SNAP_MODE_FACE, - &(const struct SnapObjectParams){ - .snap_select = t->tsnap.modeSelect, - .use_object_edit_cage = (t->flag & T_EDIT) != 0, - .use_occlusion_test = false, - .use_backface_culling = t->tsnap.use_backface_culling, - }, - mval_fl, - NULL, - 0, - loc, - no)) { + /* XXX FLICKER IN OBJECT MODE */ + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + for (i = 0; i < tc->data_len; i++, td++) { + float iloc[3], loc[3], no[3]; + float mval_fl[2]; + if (td->flag & TD_SKIP) { + continue; + } + + if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { + continue; + } + + copy_v3_v3(iloc, td->loc); + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, iloc); + } + else if (t->options & CTX_OBJECT) { + BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); + copy_v3_v3(iloc, td->ob->obmat[3]); + } + + if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == + V3D_PROJ_RET_OK) { + if (ED_transform_snap_object_project_view3d( + t->tsnap.object_context, + t->depsgraph, + SCE_SNAP_MODE_FACE, + &(const struct SnapObjectParams){ + .snap_select = t->tsnap.modeSelect, + .use_object_edit_cage = (t->flag & T_EDIT) != 0, + .use_occlusion_test = false, + .use_backface_culling = t->tsnap.use_backface_culling, + }, + mval_fl, + NULL, + 0, + loc, + no)) { #if 0 if (tc->use_local_mat) { mul_m4_v3(tc->imat, loc); } #endif - sub_v3_v3v3(tvec, loc, iloc); + sub_v3_v3v3(tvec, loc, iloc); - mul_m3_v3(td->smtx, tvec); + mul_m3_v3(td->smtx, tvec); - add_v3_v3(td->loc, tvec); + add_v3_v3(td->loc, tvec); - if (t->tsnap.align && (t->flag & T_OBJECT)) { - /* handle alignment as well */ - const float *original_normal; - float mat[3][3]; + if (t->tsnap.align && (t->options & CTX_OBJECT)) { + /* handle alignment as well */ + const float *original_normal; + float mat[3][3]; - /* In pose mode, we want to align normals with Y axis of bones... */ - original_normal = td->axismtx[2]; + /* In pose mode, we want to align normals with Y axis of bones... */ + original_normal = td->axismtx[2]; - rotation_between_vecs_to_mat3(mat, original_normal, no); + rotation_between_vecs_to_mat3(mat, original_normal, no); - transform_data_ext_rotate(td, mat, true); + transform_data_ext_rotate(td, mat, true); - /* TODO support constraints for rotation too? see ElementRotation */ - } + /* TODO support constraints for rotation too? see ElementRotation */ } } + } -#if 0 /* TODO: sipport this? */ +#if 0 /* TODO: support this? */ constraintTransLim(t, td); #endif - } } } } @@ -412,7 +422,7 @@ void applyGridAbsolute(TransInfo *t) if (tc->use_local_mat) { mul_m4_v3(tc->mat, iloc); } - else if (t->flag & T_OBJECT) { + else if (t->options & CTX_OBJECT) { BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); copy_v3_v3(iloc, td->ob->obmat[3]); } @@ -561,7 +571,8 @@ static void initSnappingMode(TransInfo *t) } } - if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && (t->flag & T_CAMERA) == 0) { + if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && + (t->options & CTX_CAMERA) == 0) { /* Only 3D view or UV. */ /* Not with camera selected in camera view. */ @@ -916,6 +927,64 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) /** \name Target * \{ */ +static void snap_target_median_impl(TransInfo *t, float r_median[3]) +{ + int i_accum = 0; + + zero_v3(r_median); + + FOREACH_TRANS_DATA_CONTAINER (t, tc) { + TransData *td = tc->data; + int i; + float v[3]; + zero_v3(v); + + for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { + add_v3_v3(v, td->center); + } + + if (i == 0) { + /* Is this possible? */ + continue; + } + + mul_v3_fl(v, 1.0 / i); + + if (tc->use_local_mat) { + mul_m4_v3(tc->mat, v); + } + + add_v3_v3(r_median, v); + i_accum++; + } + + mul_v3_fl(r_median, 1.0 / i_accum); + + // TargetSnapOffset(t, NULL); +} + +static void snap_target_grid_ensure(TransInfo *t) +{ + /* Only need to calculate once. */ + if ((t->tsnap.status & TARGET_GRID_INIT) == 0) { + if (t->data_type == TC_CURSOR_VIEW3D) { + /* Use a fallback when transforming the cursor. + * In this case the center is _not_ derived from the cursor which is being transformed. */ + copy_v3_v3(t->tsnap.snapTargetGrid, TRANS_DATA_CONTAINER_FIRST_SINGLE(t)->data->iloc); + } + else if (t->around == V3D_AROUND_CURSOR) { + /* Use a fallback for cursor selection, + * this isn't useful as a global center for absolute grid snapping + * since its not based on the position of the selection. */ + snap_target_median_impl(t, t->tsnap.snapTargetGrid); + } + else { + copy_v3_v3(t->tsnap.snapTargetGrid, t->center_global); + } + t->tsnap.status |= TARGET_GRID_INIT; + } +} + static void TargetSnapOffset(TransInfo *t, TransData *td) { if (t->spacetype == SPACE_NODE && td != NULL) { @@ -987,41 +1056,7 @@ static void TargetSnapMedian(TransInfo *t) { /* Only need to calculate once. */ if ((t->tsnap.status & TARGET_INIT) == 0) { - int i_accum = 0; - - t->tsnap.snapTarget[0] = 0; - t->tsnap.snapTarget[1] = 0; - t->tsnap.snapTarget[2] = 0; - - FOREACH_TRANS_DATA_CONTAINER (t, tc) { - TransData *td = tc->data; - int i; - float v[3]; - zero_v3(v); - - for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { - add_v3_v3(v, td->center); - } - - if (i == 0) { - /* Is this possible? */ - continue; - } - - mul_v3_fl(v, 1.0 / i); - - if (tc->use_local_mat) { - mul_m4_v3(tc->mat, v); - } - - add_v3_v3(t->tsnap.snapTarget, v); - i_accum++; - } - - mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum); - - TargetSnapOffset(t, NULL); - + snap_target_median_impl(t, t->tsnap.snapTarget); t->tsnap.status |= TARGET_INIT; } } @@ -1034,7 +1069,7 @@ static void TargetSnapClosest(TransInfo *t) TransData *closest = NULL; /* Object mode */ - if (t->flag & T_OBJECT) { + if (t->options & CTX_OBJECT) { int i; FOREACH_TRANS_DATA_CONTAINER (t, tc) { TransData *td = tc->data; @@ -1421,28 +1456,10 @@ static void snap_grid_apply( TransInfo *t, const int max_index, const float grid_dist, const float loc[3], float r_out[3]) { BLI_assert(max_index <= 2); - const float *center_global = t->center_global; + snap_target_grid_ensure(t); + const float *center_global = t->tsnap.snapTargetGrid; const float *asp = t->aspect; - if (t->options & CTX_CURSOR) { - /* Note that we must already have called #transformCenter_from_type, otherwise - * we would be lazy-initializing data which is being transformed, - * causing the transformed cursor location to be used instead of it's initial location. */ - BLI_assert(t->center_cache[V3D_AROUND_CURSOR].is_set); - - /* Use a fallback when transforming the cursor. - * In this case the center is _not_ derived from the cursor which is being transformed. */ - const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CURSOR); - center_global = cd->global; - } - else if (t->around == V3D_AROUND_CURSOR) { - /* Use a fallback for cursor selection, - * this isn't useful as a global center for absolute grid snapping - * since its not based on the position of the selection. */ - const TransCenterData *cd = transformCenter_from_type(t, V3D_AROUND_CENTER_MEDIAN); - center_global = cd->global; - } - float in[3]; if (t->con.mode & CON_APPLY) { BLI_assert(t->tsnap.snapElem == 0); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index b610369f82d..58198f21ba2 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -1959,7 +1959,7 @@ static short snapCurve(SnapData *snapdata, int clip_plane_len = snapdata->clip_plane_len; if (snapdata->has_occlusion_plane) { - /* We snap to vertices even if coccluded. */ + /* We snap to vertices even if occluded. */ clip_planes++; clip_plane_len--; } diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c index 533416bf85e..baa178a6a94 100644 --- a/source/blender/editors/undo/ed_undo.c +++ b/source/blender/editors/undo/ed_undo.c @@ -169,16 +169,16 @@ void ED_undo_push(bContext *C, const char *str) } /** - * \note Also check #undo_history_exec in bottom if you change notifiers. + * Common pre management of undo/redo (killing all running jobs, calling pre handlers, etc.). */ -static int ed_undo_step_impl( - bContext *C, int step, const char *undoname, int undo_index, ReportList *reports) +static void ed_undo_step_pre(bContext *C, + wmWindowManager *wm, + const enum eUndoStepDir undo_dir, + ReportList *reports) { - /* Mutually exclusives, ensure correct input. */ - BLI_assert(((undoname || undo_index != -1) && !step) || - (!(undoname || undo_index != -1) && step)); - CLOG_INFO(&LOG, 1, "name='%s', step=%d", undoname, step); - wmWindowManager *wm = CTX_wm_manager(C); + BLI_assert(ELEM(undo_dir, STEP_UNDO, STEP_REDO)); + + Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ScrArea *area = CTX_wm_area(C); @@ -187,18 +187,12 @@ static int ed_undo_step_impl( WM_jobs_kill_all(wm); if (G.debug & G_DEBUG_IO) { - Main *bmain = CTX_data_main(C); if (bmain->lock != NULL) { BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* undo step"); BLO_main_validate_libraries(bmain, reports); } } - /* TODO(campbell): undo_system: use undo system */ - /* grease pencil can be can be used in plenty of spaces, so check it first */ - if (ED_gpencil_session_active()) { - return ED_undo_gpencil_step(C, step, undoname); - } if (area && (area->spacetype == SPACE_VIEW3D)) { Object *obact = CTX_data_active_object(C); if (obact && (obact->type == OB_GPENCIL)) { @@ -206,89 +200,40 @@ static int ed_undo_step_impl( } } - UndoStep *step_data_from_name = NULL; - int step_for_callback = step; - if (undoname != NULL) { - step_data_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undoname); - if (step_data_from_name == NULL) { - return OPERATOR_CANCELLED; - } - - /* TODO(campbell), could use simple optimization. */ - /* Pointers match on redo. */ - step_for_callback = (BLI_findindex(&wm->undo_stack->steps, step_data_from_name) < - BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; - } - else if (undo_index != -1) { - step_for_callback = (undo_index < - BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active)) ? - 1 : - -1; - } - /* App-Handlers (pre). */ { /* Note: ignore grease pencil for now. */ - Main *bmain = CTX_data_main(C); wm->op_undo_depth++; BKE_callback_exec_id( - bmain, &scene->id, (step_for_callback > 0) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); + bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_PRE : BKE_CB_EVT_REDO_PRE); wm->op_undo_depth--; } +} - /* Undo System */ - { - if (undoname) { - BKE_undosys_step_undo_with_data(wm->undo_stack, C, step_data_from_name); - } - else if (undo_index != -1) { - BKE_undosys_step_undo_from_index(wm->undo_stack, C, undo_index); - } - else { - if (step == 1) { - BKE_undosys_step_undo(wm->undo_stack, C); - } - else { - BKE_undosys_step_redo(wm->undo_stack, C); - } - } +/** + * Common post management of undo/redo (calling post handlers, adding notifiers etc.). + * + * \note Also check #undo_history_exec in bottom if you change notifiers. + */ +static void ed_undo_step_post(bContext *C, + wmWindowManager *wm, + const enum eUndoStepDir undo_dir, + ReportList *reports) +{ + BLI_assert(ELEM(undo_dir, STEP_UNDO, STEP_REDO)); - /* Set special modes for grease pencil */ - if (area && (area->spacetype == SPACE_VIEW3D)) { - Object *obact = CTX_data_active_object(C); - if (obact && (obact->type == OB_GPENCIL)) { - /* set cursor */ - if (ELEM(obact->mode, - OB_MODE_PAINT_GPENCIL, - OB_MODE_SCULPT_GPENCIL, - OB_MODE_WEIGHT_GPENCIL, - OB_MODE_VERTEX_GPENCIL)) { - ED_gpencil_toggle_brush_cursor(C, true, NULL); - } - else { - ED_gpencil_toggle_brush_cursor(C, false, NULL); - } - /* set workspace mode */ - Base *basact = CTX_data_active_base(C); - ED_object_base_activate(C, basact); - } - } - } + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); /* App-Handlers (post). */ { - Main *bmain = CTX_data_main(C); - scene = CTX_data_scene(C); wm->op_undo_depth++; BKE_callback_exec_id( - bmain, &scene->id, step_for_callback > 0 ? BKE_CB_EVT_UNDO_POST : BKE_CB_EVT_REDO_POST); + bmain, &scene->id, (undo_dir == STEP_UNDO) ? BKE_CB_EVT_UNDO_POST : BKE_CB_EVT_REDO_POST); wm->op_undo_depth--; } if (G.debug & G_DEBUG_IO) { - Main *bmain = CTX_data_main(C); if (bmain->lock != NULL) { BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *AFTER* undo step"); BLO_main_validate_libraries(bmain, reports); @@ -299,30 +244,123 @@ static int ed_undo_step_impl( WM_event_add_notifier(C, NC_WM | ND_UNDO, NULL); WM_toolsystem_refresh_active(C); - - Main *bmain = CTX_data_main(C); WM_toolsystem_refresh_screen_all(bmain); if (CLOG_CHECK(&LOG, 1)) { BKE_undosys_print(wm->undo_stack); } - - return OPERATOR_FINISHED; } -static int ed_undo_step_direction(bContext *C, int step, ReportList *reports) +/** Undo or redo one step from current active one. + * May undo or redo several steps at once only if the target step is a 'skipped' one. + * The target step will be the one immediately before or after the active one. */ +static int ed_undo_step_direction(bContext *C, enum eUndoStepDir step, ReportList *reports) { - return ed_undo_step_impl(C, step, NULL, -1, reports); + BLI_assert(ELEM(step, STEP_UNDO, STEP_REDO)); + + CLOG_INFO(&LOG, 1, "direction=%s", (step == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + /* TODO(campbell): undo_system: use undo system */ + /* grease pencil can be can be used in plenty of spaces, so check it first */ + /* FIXME: This gpencil undo effectively only supports the one step undo/redo, undo based on name + * or index is fully not implemented. + * FIXME: However, it seems to never be used in current code (`ED_gpencil_session_active` seems + * to always return false). */ + if (ED_gpencil_session_active()) { + return ED_undo_gpencil_step(C, step); + } + + wmWindowManager *wm = CTX_wm_manager(C); + + ed_undo_step_pre(C, wm, step, reports); + + if (step == STEP_UNDO) { + BKE_undosys_step_undo(wm->undo_stack, C); + } + else { + BKE_undosys_step_redo(wm->undo_stack, C); + } + + ed_undo_step_post(C, wm, step, reports); + + return OPERATOR_FINISHED; } +/** Undo the step matching given name. + * May undo several steps at once. + * The target step will be the one immediately before given named one. */ static int ed_undo_step_by_name(bContext *C, const char *undo_name, ReportList *reports) { - return ed_undo_step_impl(C, 0, undo_name, -1, reports); + BLI_assert(undo_name != NULL); + + /* FIXME: See comments in `ed_undo_step_direction`. */ + if (ED_gpencil_session_active()) { + BLI_assert(!"Not implemented currently."); + } + + wmWindowManager *wm = CTX_wm_manager(C); + UndoStep *undo_step_from_name = BKE_undosys_step_find_by_name(wm->undo_stack, undo_name); + if (undo_step_from_name == NULL) { + CLOG_ERROR(&LOG, "Step name='%s' not found in current undo stack", undo_name); + + return OPERATOR_CANCELLED; + } + + UndoStep *undo_step_target = undo_step_from_name->prev; + if (undo_step_target == NULL) { + CLOG_ERROR(&LOG, "Step name='%s' cannot be undone", undo_name); + + return OPERATOR_CANCELLED; + } + + const int undo_dir_i = BKE_undosys_step_calc_direction(wm->undo_stack, undo_step_target, NULL); + BLI_assert(ELEM(undo_dir_i, -1, 1)); + const enum eUndoStepDir undo_dir = (undo_dir_i == -1) ? STEP_UNDO : STEP_REDO; + + CLOG_INFO(&LOG, + 1, + "name='%s', found direction=%s", + undo_name, + (undo_dir == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + ed_undo_step_pre(C, wm, undo_dir, reports); + + BKE_undosys_step_load_data_ex(wm->undo_stack, C, undo_step_target, NULL, true); + + ed_undo_step_post(C, wm, undo_dir, reports); + + return OPERATOR_FINISHED; } -static int ed_undo_step_by_index(bContext *C, int index, ReportList *reports) +/** Load the step matching given index in the stack. + * May undo or redo several steps at once. + * The target step will be the one indicated by the given index. */ +static int ed_undo_step_by_index(bContext *C, const int undo_index, ReportList *reports) { - return ed_undo_step_impl(C, 0, NULL, index, reports); + BLI_assert(undo_index >= 0); + + /* FIXME: See comments in `ed_undo_step_direction`. */ + if (ED_gpencil_session_active()) { + BLI_assert(!"Not implemented currently."); + } + + wmWindowManager *wm = CTX_wm_manager(C); + const int active_step_index = BLI_findindex(&wm->undo_stack->steps, wm->undo_stack->step_active); + const enum eUndoStepDir undo_dir = (undo_index < active_step_index) ? STEP_UNDO : STEP_REDO; + + CLOG_INFO(&LOG, + 1, + "index='%d', found direction=%s", + undo_index, + (undo_dir == STEP_UNDO) ? "STEP_UNDO" : "STEP_REDO"); + + ed_undo_step_pre(C, wm, undo_dir, reports); + + BKE_undosys_step_load_from_index(wm->undo_stack, C, undo_index); + + ed_undo_step_post(C, wm, undo_dir, reports); + + return OPERATOR_FINISHED; } void ED_undo_grouped_push(bContext *C, const char *str) @@ -340,11 +378,11 @@ void ED_undo_grouped_push(bContext *C, const char *str) void ED_undo_pop(bContext *C) { - ed_undo_step_direction(C, 1, NULL); + ed_undo_step_direction(C, STEP_UNDO, NULL); } void ED_undo_redo(bContext *C) { - ed_undo_step_direction(C, -1, NULL); + ed_undo_step_direction(C, STEP_REDO, NULL); } void ED_undo_push_op(bContext *C, wmOperator *op) @@ -448,7 +486,7 @@ static int ed_undo_exec(bContext *C, wmOperator *op) { /* "last operator" should disappear, later we can tie this with undo stack nicer */ WM_operator_stack_clear(CTX_wm_manager(C)); - int ret = ed_undo_step_direction(C, 1, op->reports); + int ret = ed_undo_step_direction(C, STEP_UNDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); @@ -477,7 +515,7 @@ static int ed_undo_push_exec(bContext *C, wmOperator *op) static int ed_redo_exec(bContext *C, wmOperator *op) { - int ret = ed_undo_step_direction(C, -1, op->reports); + int ret = ed_undo_step_direction(C, STEP_REDO, op->reports); if (ret & OPERATOR_FINISHED) { /* Keep button under the cursor active. */ WM_event_add_mousemove(CTX_wm_window(C)); diff --git a/source/blender/editors/undo/memfile_undo.c b/source/blender/editors/undo/memfile_undo.c index eea0f29d295..4fd8c180a4b 100644 --- a/source/blender/editors/undo/memfile_undo.c +++ b/source/blender/editors/undo/memfile_undo.c @@ -145,19 +145,18 @@ static int memfile_undosys_step_id_reused_cb(LibraryIDLinkCallbackData *cb_data) static void memfile_undosys_step_decode(struct bContext *C, struct Main *bmain, UndoStep *us_p, - int undo_direction, + const eUndoStepDir undo_direction, bool UNUSED(is_final)) { - BLI_assert(undo_direction != 0); + BLI_assert(undo_direction != STEP_INVALID); bool use_old_bmain_data = true; if (USER_EXPERIMENTAL_TEST(&U, use_undo_legacy)) { use_old_bmain_data = false; } - else if (undo_direction > 0) { - /* Redo case. - * The only time we should have to force a complete redo is when current step is tagged as a + else if (undo_direction == STEP_REDO) { + /* The only time we should have to force a complete redo is when current step is tagged as a * redo barrier. * If previous step was not a memfile one should not matter here, current data in old bmain * should still always be valid for unchanged data-blocks. */ @@ -165,9 +164,8 @@ static void memfile_undosys_step_decode(struct bContext *C, use_old_bmain_data = false; } } - else { - /* Undo case. - * Here we do not care whether current step is an undo barrier, since we are coming from + else if (undo_direction == STEP_UNDO) { + /* Here we do not care whether current step is an undo barrier, since we are coming from * 'the future' we can still re-use old data. However, if *next* undo step * (i.e. the one immediately in the future, the one we are coming from) * is a barrier, then we have to force a complete undo. @@ -316,8 +314,8 @@ struct MemFile *ED_undosys_stack_memfile_get_active(UndoStack *ustack) * If the last undo step is a memfile one, find the first #MemFileChunk matching given ID * (using its session UUID), and tag it as "changed in the future". * - * Since non-memfile undos cannot automatically set this flag in the previous step as done with - * memfile ones, this has to be called manually by relevant undo code. + * Since non-memfile undo-steps cannot automatically set this flag in the previous step as done + * with memfile ones, this has to be called manually by relevant undo code. * * \note Only current known case for this is undoing a switch from Object to Sculpt mode (see * T82388). diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0aab3810254..38655b8490e 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -39,7 +39,7 @@ set(SRC ed_transverts.c ed_util.c ed_util_imbuf.c - ed_util_ops.c + ed_util_ops.cc gizmo_utils.c numinput.c select_utils.c diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 1075f256a09..d0234dee856 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -495,8 +495,8 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const } if (!tvs->transverts_tot && tvs->transverts) { - /* prevent memory leak. happens for curves/latticies due to */ - /* difficult condition of adding points to trans data */ + /* Prevent memory leak. happens for curves/lattices due to + * difficult condition of adding points to trans data. */ MEM_freeN(tvs->transverts); tvs->transverts = NULL; } diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index c59fbbe1646..695db9ba246 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -183,7 +183,7 @@ void ED_editors_exit(Main *bmain, bool do_undo_system) return; } - /* frees all editmode undos */ + /* Frees all edit-mode undo-steps. */ if (do_undo_system && G_MAIN->wm.first) { wmWindowManager *wm = G_MAIN->wm.first; /* normally we don't check for NULL undo stack, diff --git a/source/blender/editors/util/ed_util_ops.c b/source/blender/editors/util/ed_util_ops.cc index bb531b11b12..cb7ff9f3a63 100644 --- a/source/blender/editors/util/ed_util_ops.c +++ b/source/blender/editors/util/ed_util_ops.cc @@ -22,6 +22,9 @@ #include <string.h> +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + #include "BLI_fileops.h" #include "BLI_utildefines.h" @@ -33,9 +36,6 @@ #include "BLT_translation.h" -#include "DNA_space_types.h" -#include "DNA_windowmanager_types.h" - #include "ED_render.h" #include "ED_undo.h" #include "ED_util.h" @@ -56,7 +56,7 @@ static bool lib_id_preview_editing_poll(bContext *C) const PointerRNA idptr = CTX_data_pointer_get(C, "id"); BLI_assert(!idptr.data || RNA_struct_is_ID(idptr.type)); - const ID *id = idptr.data; + const ID *id = (ID *)idptr.data; if (!id) { return false; } @@ -88,11 +88,11 @@ static int lib_id_load_custom_preview_exec(bContext *C, wmOperator *op) } PointerRNA idptr = CTX_data_pointer_get(C, "id"); - ID *id = idptr.data; + ID *id = (ID *)idptr.data; BKE_previewimg_id_custom_set(id, path); - WM_event_add_notifier(C, NC_ASSET, NULL); + WM_event_add_notifier(C, NC_ASSET, nullptr); return OPERATOR_FINISHED; } @@ -123,7 +123,7 @@ static void ED_OT_lib_id_load_custom_preview(wmOperatorType *ot) static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) { PointerRNA idptr = CTX_data_pointer_get(C, "id"); - ID *id = idptr.data; + ID *id = (ID *)idptr.data; ED_preview_kill_jobs(CTX_wm_manager(C), CTX_data_main(C)); @@ -131,9 +131,9 @@ static int lib_id_generate_preview_exec(bContext *C, wmOperator *UNUSED(op)) if (preview) { BKE_previewimg_clear(preview); } - UI_icon_render_id(C, NULL, id, ICON_SIZE_PREVIEW, true); + UI_icon_render_id(C, nullptr, id, ICON_SIZE_PREVIEW, true); - WM_event_add_notifier(C, NC_ASSET, NULL); + WM_event_add_notifier(C, NC_ASSET, nullptr); return OPERATOR_FINISHED; } @@ -169,15 +169,15 @@ static int lib_id_fake_user_toggle_exec(bContext *C, wmOperator *op) idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); } - if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { BKE_report( op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); return OPERATOR_CANCELLED; } - ID *id = idptr.data; + ID *id = (ID *)idptr.data; - if ((id->lib != NULL) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { + if ((id->lib != nullptr) || (ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { BKE_report(op->reports, RPT_ERROR, "Data-block type does not support fake user"); return OPERATOR_CANCELLED; } @@ -217,14 +217,14 @@ static int lib_id_unlink_exec(bContext *C, wmOperator *op) idptr = RNA_property_pointer_get(&pprop.ptr, pprop.prop); } - if ((pprop.prop == NULL) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { + if ((pprop.prop == nullptr) || RNA_pointer_is_null(&idptr) || !RNA_struct_is_ID(idptr.type)) { BKE_report( op->reports, RPT_ERROR, "Incorrect context for running data-block fake user toggling"); return OPERATOR_CANCELLED; } memset(&idptr, 0, sizeof(idptr)); - RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, NULL); + RNA_property_pointer_set(&pprop.ptr, pprop.prop, idptr, nullptr); RNA_property_update(C, &pprop.ptr, pprop.prop); return OPERATOR_FINISHED; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index ba22bcca0e1..91ec8546225 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -508,7 +508,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event) #endif case EVT_CKEY: if (event->ctrl) { - /* Copy current str to the copypaste buffer. */ + /* Copy current `str` to the copy/paste buffer. */ WM_clipboard_text_set(n->str, 0); updated = true; } diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index ed9e5053f10..e94aaa49839 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -978,7 +978,7 @@ static int p_connect_pairs(PHandle *handle, PBool topology_from_uvs) PChart *chart = handle->construction_chart; int ncharts = 0; - /* connect pairs, count edges, set vertex-edge pointer to a pairless edge */ + /* Connect pairs, count edges, set vertex-edge pointer to a pair-less edge. */ for (first = chart->faces; first; first = first->nextlink) { if (first->flag & PFACE_CONNECTED) { continue; @@ -1974,7 +1974,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) b[1] = p_vec_angle(v2->co, v1->co, keepv->co); b[2] = M_PI - b[0] - b[1]; - /* abf criterion 1: avoid sharp and obtuse angles */ + /* ABF criterion 1: avoid sharp and obtuse angles. */ minangle = 15.0f * M_PI / 180.0f; maxangle = M_PI - minangle; @@ -1991,7 +1991,7 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) } while (e && (e != oldv->edge)); if (p_vert_interior(oldv)) { - /* hlscm criterion: angular defect smaller than threshold */ + /* HLSCM criterion: angular defect smaller than threshold. */ if (fabsf(angulardefect) > (float)(M_PI * 30.0 / 180.0)) { return P_FALSE; } @@ -2000,12 +2000,12 @@ static PBool p_collapse_allowed_geometric(PEdge *edge, PEdge *pair) PVert *v1 = p_boundary_edge_next(oldv->edge)->vert; PVert *v2 = p_boundary_edge_prev(oldv->edge)->vert; - /* abf++ criterion 2: avoid collapsing verts inwards */ + /* ABF++ criterion 2: avoid collapsing verts inwards. */ if (p_vert_interior(keepv)) { return P_FALSE; } - /* don't collapse significant boundary changes */ + /* Don't collapse significant boundary changes. */ angle = p_vec_angle(v1->co, oldv->co, v2->co); if (angle < (M_PI * 160.0 / 180.0)) { return P_FALSE; @@ -3837,7 +3837,7 @@ static void p_chart_rotate_fit_aabb(PChart *chart) /* Area Smoothing */ -/* 2d bsp tree for inverse mapping - that's a bit silly */ +/* 2d BSP tree for inverse mapping - that's a bit silly. */ typedef struct SmoothTriangle { float co1[2], co2[2], co3[2]; @@ -4288,7 +4288,7 @@ static void p_smooth(PChart *chart) MEM_freeN(hedges); MEM_freeN(vedges); - /* create bsp */ + /* Create BSP. */ t = triangles = MEM_mallocN(sizeof(SmoothTriangle) * esize * 2, "PSmoothTris"); trip = tri = MEM_mallocN(sizeof(SmoothTriangle *) * esize * 2, "PSmoothTriP"); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 7b27bb570cc..8ebf000baaa 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -129,8 +129,10 @@ typedef struct UvEdge { /** general use flag * (Used to check if edge is boundary here, and propagates to adjacency elements) */ uchar flag; - /** element that guarantees element->face - * has the edge on element->tfindex and element->tfindex+1 is the second uv */ + /** + * Element that guarantees `element.l` has the edge on + * `element.loop_of_poly_index` and `element->loop_of_poly_index + 1` is the second UV. + */ UvElement *element; /** next uv edge with the same exact vertices as this one. * Calculated at startup to save time */ @@ -224,13 +226,13 @@ enum StitchModes { STITCH_EDGE, }; -/* UvElement identification. */ +/** #UvElement identification. */ typedef struct UvElementID { int faceIndex; int elementIndex; } UvElementID; -/* StitchState initializition. */ +/** #StitchState initialization. */ typedef struct StitchStateInit { int uv_selected_count; UvElementID *to_select; @@ -2050,7 +2052,7 @@ static StitchState *stitch_init(bContext *C, BLI_ghash_free(edge_hash, NULL, NULL); - /* refill an edge hash to create edge connnectivity data */ + /* Refill an edge hash to create edge connectivity data. */ state->edge_hash = edge_hash = BLI_ghash_new(uv_edge_hash, uv_edge_compare, "stitch_edge_hash"); for (i = 0; i < total_edges; i++) { BLI_ghash_insert(edge_hash, edges + i, edges + i); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index be54df1ce9e..fc5f41e8ed5 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -1336,9 +1336,9 @@ static void uv_map_rotation_matrix_ex(float result[4][4], zero_m4(rotup); zero_m4(rotside); - /* compensate front/side.. against opengl x,y,z world definition */ - /* this is "kanonen gegen spatzen", a few plus minus 1 will do here */ - /* i wanted to keep the reason here, so we're rotating*/ + /* Compensate front/side.. against opengl x,y,z world definition. + * This is "a sledgehammer to crack a nut" (overkill), a few plus minus 1 will do here. + * I wanted to keep the reason here, so we're rotating. */ sideangle = (float)M_PI * (sideangledeg + 180.0f) / 180.0f; rotside[0][0] = cosf(sideangle); rotside[0][1] = -sinf(sideangle); diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index ddd11729e67..9c675c93a2e 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -580,7 +580,7 @@ void Controller::ComputeViewMap() vmBuilder.setRenderMonitor(_pRenderMonitor); #if 0 - // Builds a tesselated form of the silhouette for display purpose: + // Builds a tessellated form of the silhouette for display purpose: //--------------------------------------------------------------- ViewMapTesselator3D sTesselator3d; ViewMapTesselator2D sTesselator2d; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp index 930da3ef471..a16479873e7 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp @@ -56,11 +56,6 @@ NodeGroup *BlenderFileLoader::Load() // creation of the scene root node _Scene = new NodeGroup; - _viewplane_left = _re->viewplane.xmin; - _viewplane_right = _re->viewplane.xmax; - _viewplane_bottom = _re->viewplane.ymin; - _viewplane_top = _re->viewplane.ymax; - if (_re->clip_start < 0.0f) { // Adjust clipping start/end and set up a Z offset when the viewport preview // is used with the orthographic view. In this case, _re->clip_start is negative, @@ -76,14 +71,6 @@ NodeGroup *BlenderFileLoader::Load() _z_offset = 0.0f; } -#if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Frustum: l " << _viewplane_left << " r " << _viewplane_right << " b " - << _viewplane_bottom << " t " << _viewplane_top << " n " << _z_near << " f " << _z_far - << endl; - } -#endif - int id = 0; const eEvaluationMode eval_mode = DEG_get_mode(_depsgraph); diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h index 50834db3c5c..1be2fc3bc99 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.h @@ -152,10 +152,6 @@ class BlenderFileLoader { real _minEdgeSize; #endif bool _smooth; /* if true, face smoothness is taken into account */ - float _viewplane_left; - float _viewplane_right; - float _viewplane_bottom; - float _viewplane_top; float _z_near, _z_far; float _z_offset; diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp index 51727fd2288..d3a3d8bc76e 100644 --- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp +++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp @@ -435,12 +435,12 @@ bool overlapTriangleBox(Vec3r &boxcenter, Vec3r &boxhalfsize, Vec3r triverts[3]) // Tomas Möller // Prosolvia Clarus AB // Sweden -// tompa@clarus.se +// <tompa@clarus.se> // // Ben Trumbore // Cornell University // Ithaca, New York -// wbt@graphics.cornell.edu +// <wbt@graphics.cornell.edu> bool intersectRayTriangle(const Vec3r &orig, const Vec3r &dir, const Vec3r &v0, diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp index 5b5d9582e8f..95a24d85677 100644 --- a/source/blender/freestyle/intern/geometry/matrix_util.cpp +++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp @@ -17,7 +17,7 @@ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000 Bruno Levy * Contact: Bruno Levy - * levy@loria.fr + * <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h index 8a20cb31300..8c2eb799d13 100644 --- a/source/blender/freestyle/intern/geometry/matrix_util.h +++ b/source/blender/freestyle/intern/geometry/matrix_util.h @@ -17,7 +17,7 @@ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000 Bruno Levy * Contact: Bruno Levy - * levy@loria.fr + * <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp index 01d52646eb0..2310525a1e1 100644 --- a/source/blender/freestyle/intern/geometry/normal_cycle.cpp +++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp @@ -17,7 +17,7 @@ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000 Bruno Levy * Contact: Bruno Levy - * levy@loria.fr + * <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h index 6ac9779e7c2..5adef773be1 100644 --- a/source/blender/freestyle/intern/geometry/normal_cycle.h +++ b/source/blender/freestyle/intern/geometry/normal_cycle.h @@ -17,7 +17,7 @@ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000 Bruno Levy * Contact: Bruno Levy - * levy@loria.fr + * <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/freestyle/intern/python/BPy_BBox.cpp b/source/blender/freestyle/intern/python/BPy_BBox.cpp index d66a74bc83f..39dd55f0cc1 100644 --- a/source/blender/freestyle/intern/python/BPy_BBox.cpp +++ b/source/blender/freestyle/intern/python/BPy_BBox.cpp @@ -24,6 +24,9 @@ extern "C" { #endif +using namespace Freestyle; +using namespace Freestyle::Geometry; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_BBox.h b/source/blender/freestyle/intern/python/BPy_BBox.h index a284deed10c..889dbc62a41 100644 --- a/source/blender/freestyle/intern/python/BPy_BBox.h +++ b/source/blender/freestyle/intern/python/BPy_BBox.h @@ -27,9 +27,6 @@ extern "C" { #include "../geometry/BBox.h" #include "../geometry/Geom.h" -using namespace Freestyle; -using namespace Freestyle::Geometry; - #ifdef __cplusplus extern "C" { #endif @@ -42,7 +39,7 @@ extern PyTypeObject BBox_Type; /*---------------------------Python BPy_BBox structure definition----------*/ typedef struct { - PyObject_HEAD BBox<Vec3r> *bb; + PyObject_HEAD Freestyle::BBox<Freestyle::Geometry::Vec3r> *bb; } BPy_BBox; /*---------------------------Python BPy_BBox visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp index 2359d79f7d0..d12804761f0 100644 --- a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h index cdf81f3e4fc..a368d4cd47e 100644 --- a/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate0D.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Predicates0D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject BinaryPredicate0D_Type; /*---------------------------Python BPy_BinaryPredicate0D structure definition----------*/ typedef struct { - PyObject_HEAD BinaryPredicate0D *bp0D; + PyObject_HEAD Freestyle::BinaryPredicate0D *bp0D; } BPy_BinaryPredicate0D; /*---------------------------Python BPy_BinaryPredicate0D visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp index 7d554e0abe1..969041702b5 100644 --- a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.cpp @@ -33,6 +33,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h index b761f6f6ace..b34fad9e213 100644 --- a/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h +++ b/source/blender/freestyle/intern/python/BPy_BinaryPredicate1D.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Predicates1D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject BinaryPredicate1D_Type; /*---------------------------Python BPy_BinaryPredicate1D structure definition----------*/ typedef struct { - PyObject_HEAD BinaryPredicate1D *bp1D; + PyObject_HEAD Freestyle::BinaryPredicate1D *bp1D; } BPy_BinaryPredicate1D; /*---------------------------Python BPy_BinaryPredicate1D visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_Convert.cpp b/source/blender/freestyle/intern/python/BPy_Convert.cpp index f1d7a242a93..99ba3090137 100644 --- a/source/blender/freestyle/intern/python/BPy_Convert.cpp +++ b/source/blender/freestyle/intern/python/BPy_Convert.cpp @@ -61,6 +61,9 @@ extern "C" { #endif +using namespace Freestyle; +using namespace Freestyle::Geometry; + /////////////////////////////////////////////////////////////////////////////////////////// //============================== diff --git a/source/blender/freestyle/intern/python/BPy_Convert.h b/source/blender/freestyle/intern/python/BPy_Convert.h index 5a1c11ec086..e0916196808 100644 --- a/source/blender/freestyle/intern/python/BPy_Convert.h +++ b/source/blender/freestyle/intern/python/BPy_Convert.h @@ -28,9 +28,6 @@ extern "C" { #include "../geometry/Geom.h" -using namespace Freestyle; -using namespace Freestyle::Geometry; - // BBox #include "../geometry/BBox.h" @@ -94,76 +91,81 @@ extern "C" { //============================== PyObject *PyBool_from_bool(bool b); -PyObject *Vector_from_Vec2f(Vec2f &v); -PyObject *Vector_from_Vec3f(Vec3f &v); -PyObject *Vector_from_Vec3r(Vec3r &v); - -PyObject *Any_BPy_Interface0D_from_Interface0D(Interface0D &if0D); -PyObject *Any_BPy_Interface1D_from_Interface1D(Interface1D &if1D); -PyObject *Any_BPy_FEdge_from_FEdge(FEdge &fe); -PyObject *Any_BPy_ViewVertex_from_ViewVertex(ViewVertex &vv); - -PyObject *BPy_BBox_from_BBox(const BBox<Vec3r> &bb); -PyObject *BPy_CurvePoint_from_CurvePoint(CurvePoint &cp); -PyObject *BPy_directedViewEdge_from_directedViewEdge(ViewVertex::directedViewEdge &dve); -PyObject *BPy_FEdge_from_FEdge(FEdge &fe); -PyObject *BPy_FEdgeSharp_from_FEdgeSharp(FEdgeSharp &fes); -PyObject *BPy_FEdgeSmooth_from_FEdgeSmooth(FEdgeSmooth &fes); -PyObject *BPy_Id_from_Id(Id &id); -PyObject *BPy_Interface0D_from_Interface0D(Interface0D &if0D); -PyObject *BPy_Interface1D_from_Interface1D(Interface1D &if1D); -PyObject *BPy_IntegrationType_from_IntegrationType(IntegrationType i); -PyObject *BPy_FrsMaterial_from_FrsMaterial(const FrsMaterial &m); +PyObject *Vector_from_Vec2f(Freestyle::Geometry::Vec2f &v); +PyObject *Vector_from_Vec3f(Freestyle::Geometry::Vec3f &v); +PyObject *Vector_from_Vec3r(Freestyle::Geometry::Vec3r &v); + +PyObject *Any_BPy_Interface0D_from_Interface0D(Freestyle::Interface0D &if0D); +PyObject *Any_BPy_Interface1D_from_Interface1D(Freestyle::Interface1D &if1D); +PyObject *Any_BPy_FEdge_from_FEdge(Freestyle::FEdge &fe); +PyObject *Any_BPy_ViewVertex_from_ViewVertex(Freestyle::ViewVertex &vv); + +PyObject *BPy_BBox_from_BBox(const Freestyle::BBox<Freestyle::Geometry::Vec3r> &bb); +PyObject *BPy_CurvePoint_from_CurvePoint(Freestyle::CurvePoint &cp); +PyObject *BPy_directedViewEdge_from_directedViewEdge(Freestyle::ViewVertex::directedViewEdge &dve); +PyObject *BPy_FEdge_from_FEdge(Freestyle::FEdge &fe); +PyObject *BPy_FEdgeSharp_from_FEdgeSharp(Freestyle::FEdgeSharp &fes); +PyObject *BPy_FEdgeSmooth_from_FEdgeSmooth(Freestyle::FEdgeSmooth &fes); +PyObject *BPy_Id_from_Id(Freestyle::Id &id); +PyObject *BPy_Interface0D_from_Interface0D(Freestyle::Interface0D &if0D); +PyObject *BPy_Interface1D_from_Interface1D(Freestyle::Interface1D &if1D); +PyObject *BPy_IntegrationType_from_IntegrationType(Freestyle::IntegrationType i); +PyObject *BPy_FrsMaterial_from_FrsMaterial(const Freestyle::FrsMaterial &m); PyObject *BPy_Nature_from_Nature(unsigned short n); -PyObject *BPy_MediumType_from_MediumType(Stroke::MediumType n); -PyObject *BPy_SShape_from_SShape(SShape &ss); -PyObject *BPy_Stroke_from_Stroke(Stroke &s); -PyObject *BPy_StrokeAttribute_from_StrokeAttribute(StrokeAttribute &sa); -PyObject *BPy_StrokeVertex_from_StrokeVertex(StrokeVertex &sv); -PyObject *BPy_SVertex_from_SVertex(SVertex &sv); -PyObject *BPy_ViewVertex_from_ViewVertex(ViewVertex &vv); -PyObject *BPy_NonTVertex_from_NonTVertex(NonTVertex &ntv); -PyObject *BPy_TVertex_from_TVertex(TVertex &tv); -PyObject *BPy_ViewEdge_from_ViewEdge(ViewEdge &ve); -PyObject *BPy_Chain_from_Chain(Chain &c); -PyObject *BPy_ViewShape_from_ViewShape(ViewShape &vs); - -PyObject *BPy_AdjacencyIterator_from_AdjacencyIterator(AdjacencyIterator &a_it); -PyObject *BPy_Interface0DIterator_from_Interface0DIterator(Interface0DIterator &if0D_it, +PyObject *BPy_MediumType_from_MediumType(Freestyle::Stroke::MediumType n); +PyObject *BPy_SShape_from_SShape(Freestyle::SShape &ss); +PyObject *BPy_Stroke_from_Stroke(Freestyle::Stroke &s); +PyObject *BPy_StrokeAttribute_from_StrokeAttribute(Freestyle::StrokeAttribute &sa); +PyObject *BPy_StrokeVertex_from_StrokeVertex(Freestyle::StrokeVertex &sv); +PyObject *BPy_SVertex_from_SVertex(Freestyle::SVertex &sv); +PyObject *BPy_ViewVertex_from_ViewVertex(Freestyle::ViewVertex &vv); +PyObject *BPy_NonTVertex_from_NonTVertex(Freestyle::NonTVertex &ntv); +PyObject *BPy_TVertex_from_TVertex(Freestyle::TVertex &tv); +PyObject *BPy_ViewEdge_from_ViewEdge(Freestyle::ViewEdge &ve); +PyObject *BPy_Chain_from_Chain(Freestyle::Chain &c); +PyObject *BPy_ViewShape_from_ViewShape(Freestyle::ViewShape &vs); + +PyObject *BPy_AdjacencyIterator_from_AdjacencyIterator(Freestyle::AdjacencyIterator &a_it); +PyObject *BPy_Interface0DIterator_from_Interface0DIterator(Freestyle::Interface0DIterator &if0D_it, bool reversed); -PyObject *BPy_CurvePointIterator_from_CurvePointIterator(CurveInternal::CurvePointIterator &cp_it); +PyObject *BPy_CurvePointIterator_from_CurvePointIterator( + Freestyle::CurveInternal::CurvePointIterator &cp_it); PyObject *BPy_StrokeVertexIterator_from_StrokeVertexIterator( - StrokeInternal::StrokeVertexIterator &sv_it, bool reversed); -PyObject *BPy_SVertexIterator_from_SVertexIterator(ViewEdgeInternal::SVertexIterator &sv_it); + Freestyle::StrokeInternal::StrokeVertexIterator &sv_it, bool reversed); +PyObject *BPy_SVertexIterator_from_SVertexIterator( + Freestyle::ViewEdgeInternal::SVertexIterator &sv_it); PyObject *BPy_orientedViewEdgeIterator_from_orientedViewEdgeIterator( - ViewVertexInternal::orientedViewEdgeIterator &ove_it, bool reversed); -PyObject *BPy_ViewEdgeIterator_from_ViewEdgeIterator(ViewEdgeInternal::ViewEdgeIterator &ve_it); -PyObject *BPy_ChainingIterator_from_ChainingIterator(ChainingIterator &c_it); -PyObject *BPy_ChainPredicateIterator_from_ChainPredicateIterator(ChainPredicateIterator &cp_it); -PyObject *BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator(ChainSilhouetteIterator &cs_it); + Freestyle::ViewVertexInternal::orientedViewEdgeIterator &ove_it, bool reversed); +PyObject *BPy_ViewEdgeIterator_from_ViewEdgeIterator( + Freestyle::ViewEdgeInternal::ViewEdgeIterator &ve_it); +PyObject *BPy_ChainingIterator_from_ChainingIterator(Freestyle::ChainingIterator &c_it); +PyObject *BPy_ChainPredicateIterator_from_ChainPredicateIterator( + Freestyle::ChainPredicateIterator &cp_it); +PyObject *BPy_ChainSilhouetteIterator_from_ChainSilhouetteIterator( + Freestyle::ChainSilhouetteIterator &cs_it); //============================== // Python => C++ //============================== bool bool_from_PyBool(PyObject *b); -IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj); -Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj); -Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj); -bool Vec2f_ptr_from_PyObject(PyObject *obj, Vec2f &vec); -bool Vec3f_ptr_from_PyObject(PyObject *obj, Vec3f &vec); -bool Vec3r_ptr_from_PyObject(PyObject *obj, Vec3r &vec); -bool Vec2f_ptr_from_Vector(PyObject *obj, Vec2f &vec); -bool Vec3f_ptr_from_Vector(PyObject *obj, Vec3f &vec); -bool Vec3r_ptr_from_Vector(PyObject *obj, Vec3r &vec); -bool Vec3f_ptr_from_Color(PyObject *obj, Vec3f &vec); -bool Vec3r_ptr_from_Color(PyObject *obj, Vec3r &vec); -bool Vec2f_ptr_from_PyList(PyObject *obj, Vec2f &vec); -bool Vec3f_ptr_from_PyList(PyObject *obj, Vec3f &vec); -bool Vec3r_ptr_from_PyList(PyObject *obj, Vec3r &vec); -bool Vec2f_ptr_from_PyTuple(PyObject *obj, Vec2f &vec); -bool Vec3f_ptr_from_PyTuple(PyObject *obj, Vec3f &vec); -bool Vec3r_ptr_from_PyTuple(PyObject *obj, Vec3r &vec); +Freestyle::IntegrationType IntegrationType_from_BPy_IntegrationType(PyObject *obj); +Freestyle::Stroke::MediumType MediumType_from_BPy_MediumType(PyObject *obj); +Freestyle::Nature::EdgeNature EdgeNature_from_BPy_Nature(PyObject *obj); +bool Vec2f_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec2f &vec); +bool Vec3f_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec3f &vec); +bool Vec3r_ptr_from_PyObject(PyObject *obj, Freestyle::Geometry::Vec3r &vec); +bool Vec2f_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec2f &vec); +bool Vec3f_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec3f &vec); +bool Vec3r_ptr_from_Vector(PyObject *obj, Freestyle::Geometry::Vec3r &vec); +bool Vec3f_ptr_from_Color(PyObject *obj, Freestyle::Geometry::Vec3f &vec); +bool Vec3r_ptr_from_Color(PyObject *obj, Freestyle::Geometry::Vec3r &vec); +bool Vec2f_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec2f &vec); +bool Vec3f_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec3f &vec); +bool Vec3r_ptr_from_PyList(PyObject *obj, Freestyle::Geometry::Vec3r &vec); +bool Vec2f_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec2f &vec); +bool Vec3f_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec3f &vec); +bool Vec3r_ptr_from_PyTuple(PyObject *obj, Freestyle::Geometry::Vec3r &vec); bool float_array_from_PyObject(PyObject *obj, float *v, int n); diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp index 2aa08ec3ab5..e3e6ba5ab83 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.cpp @@ -28,6 +28,8 @@ extern "C" { #include "BLI_hash_mm2a.h" +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h index 13a116d7ef2..084fcef9a62 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsMaterial.h +++ b/source/blender/freestyle/intern/python/BPy_FrsMaterial.h @@ -26,8 +26,6 @@ extern "C" { #include "../scene_graph/FrsMaterial.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject FrsMaterial_Type; /*---------------------------Python BPy_FrsMaterial structure definition----------*/ typedef struct { - PyObject_HEAD FrsMaterial *m; + PyObject_HEAD Freestyle::FrsMaterial *m; } BPy_FrsMaterial; /*---------------------------Python BPy_FrsMaterial visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp index 943a9ca0e64..73e2abc8688 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_FrsNoise.h b/source/blender/freestyle/intern/python/BPy_FrsNoise.h index 09bcc82ae94..0f8f2d3242c 100644 --- a/source/blender/freestyle/intern/python/BPy_FrsNoise.h +++ b/source/blender/freestyle/intern/python/BPy_FrsNoise.h @@ -27,8 +27,6 @@ extern "C" { #include "../geometry/Noise.h" #include "../system/PseudoNoise.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,8 +39,8 @@ extern PyTypeObject FrsNoise_Type; /*---------------------------Python BPy_FrsNoise structure definition----------*/ typedef struct { - PyObject_HEAD Noise *n; - PseudoNoise *pn; + PyObject_HEAD Freestyle::Noise *n; + Freestyle::PseudoNoise *pn; } BPy_FrsNoise; /*---------------------------Python BPy_FrsNoise visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_Id.cpp b/source/blender/freestyle/intern/python/BPy_Id.cpp index 323e76fe249..5f9824db773 100644 --- a/source/blender/freestyle/intern/python/BPy_Id.cpp +++ b/source/blender/freestyle/intern/python/BPy_Id.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_Id.h b/source/blender/freestyle/intern/python/BPy_Id.h index f5952297c66..51a70a391b1 100644 --- a/source/blender/freestyle/intern/python/BPy_Id.h +++ b/source/blender/freestyle/intern/python/BPy_Id.h @@ -26,12 +26,8 @@ extern "C" { #include <iostream> -using namespace std; - #include "../system/Id.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -44,7 +40,7 @@ extern PyTypeObject Id_Type; /*---------------------------Python BPy_Id structure definition----------*/ typedef struct { - PyObject_HEAD Id *id; + PyObject_HEAD Freestyle::Id *id; } BPy_Id; /*---------------------------Python BPy_Id visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp index 25f3c54ea7d..15f3f936b14 100644 --- a/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------ MODULE FUNCTIONS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_IntegrationType.h b/source/blender/freestyle/intern/python/BPy_IntegrationType.h index be815c6c95a..9176a504b24 100644 --- a/source/blender/freestyle/intern/python/BPy_IntegrationType.h +++ b/source/blender/freestyle/intern/python/BPy_IntegrationType.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Interface1D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp index 3d0c57d5509..a1456a9491f 100644 --- a/source/blender/freestyle/intern/python/BPy_Interface0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_Interface0D.cpp @@ -34,6 +34,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_Interface0D.h b/source/blender/freestyle/intern/python/BPy_Interface0D.h index 7e41a8888e1..9734378f446 100644 --- a/source/blender/freestyle/intern/python/BPy_Interface0D.h +++ b/source/blender/freestyle/intern/python/BPy_Interface0D.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Interface0D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject Interface0D_Type; /*---------------------------Python BPy_Interface0D structure definition----------*/ typedef struct { - PyObject_HEAD Interface0D *if0D; + PyObject_HEAD Freestyle::Interface0D *if0D; bool borrowed; /* true if *if0D is a borrowed object */ } BPy_Interface0D; diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp index 8a4a6eb61db..2fe56eb952d 100644 --- a/source/blender/freestyle/intern/python/BPy_Interface1D.cpp +++ b/source/blender/freestyle/intern/python/BPy_Interface1D.cpp @@ -35,6 +35,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_Interface1D.h b/source/blender/freestyle/intern/python/BPy_Interface1D.h index 20a4af0b4d0..4ed562c24f7 100644 --- a/source/blender/freestyle/intern/python/BPy_Interface1D.h +++ b/source/blender/freestyle/intern/python/BPy_Interface1D.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Interface1D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject Interface1D_Type; /*---------------------------Python BPy_Interface1D structure definition----------*/ typedef struct { - PyObject_HEAD Interface1D *if1D; + PyObject_HEAD Freestyle::Interface1D *if1D; bool borrowed; /* true if *if1D is a borrowed object */ } BPy_Interface1D; diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.cpp b/source/blender/freestyle/intern/python/BPy_Iterator.cpp index bee30aa9e8c..5346c4a8dc0 100644 --- a/source/blender/freestyle/intern/python/BPy_Iterator.cpp +++ b/source/blender/freestyle/intern/python/BPy_Iterator.cpp @@ -36,6 +36,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_Iterator.h b/source/blender/freestyle/intern/python/BPy_Iterator.h index 5d1e8422976..7094384140f 100644 --- a/source/blender/freestyle/intern/python/BPy_Iterator.h +++ b/source/blender/freestyle/intern/python/BPy_Iterator.h @@ -26,8 +26,6 @@ extern "C" { #include "../system/Iterator.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -40,7 +38,7 @@ extern PyTypeObject Iterator_Type; /*---------------------------Python BPy_Iterator structure definition----------*/ typedef struct { - PyObject_HEAD Iterator *it; + PyObject_HEAD Freestyle::Iterator *it; } BPy_Iterator; /*---------------------------Python BPy_Iterator visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.cpp b/source/blender/freestyle/intern/python/BPy_MediumType.cpp index 547f46839b8..35f9dc17070 100644 --- a/source/blender/freestyle/intern/python/BPy_MediumType.cpp +++ b/source/blender/freestyle/intern/python/BPy_MediumType.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*-----------------------BPy_MediumType type definition ------------------------------*/ diff --git a/source/blender/freestyle/intern/python/BPy_MediumType.h b/source/blender/freestyle/intern/python/BPy_MediumType.h index 854f826291e..e34edc45f42 100644 --- a/source/blender/freestyle/intern/python/BPy_MediumType.h +++ b/source/blender/freestyle/intern/python/BPy_MediumType.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Stroke.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_Nature.cpp b/source/blender/freestyle/intern/python/BPy_Nature.cpp index b0a620803d1..304364b60eb 100644 --- a/source/blender/freestyle/intern/python/BPy_Nature.cpp +++ b/source/blender/freestyle/intern/python/BPy_Nature.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// static PyObject *BPy_Nature_and(PyObject *a, PyObject *b); diff --git a/source/blender/freestyle/intern/python/BPy_Nature.h b/source/blender/freestyle/intern/python/BPy_Nature.h index 48d15c8e796..a105db22b2a 100644 --- a/source/blender/freestyle/intern/python/BPy_Nature.h +++ b/source/blender/freestyle/intern/python/BPy_Nature.h @@ -26,8 +26,6 @@ extern "C" { #include "../winged_edge/Nature.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_Operators.cpp b/source/blender/freestyle/intern/python/BPy_Operators.cpp index 5fd02e4a9dd..5dbf18c24a7 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.cpp +++ b/source/blender/freestyle/intern/python/BPy_Operators.cpp @@ -36,6 +36,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- @@ -260,8 +262,8 @@ PyDoc_STRVAR(Operators_sequential_split_doc, "\n" " .. tip::\n" "\n" - " By specifiying a starting and stopping predicate allows\n" - " the chains to overlapp rather than chains partitioning.\n" + " By specifying a starting and stopping predicate allows\n" + " the chains to overlap rather than chains partitioning.\n" "\n" " :arg starting_pred: The predicate on a point that expresses the\n" " starting condition. Each time this condition is verified, a new chain begins\n" diff --git a/source/blender/freestyle/intern/python/BPy_Operators.h b/source/blender/freestyle/intern/python/BPy_Operators.h index 3b060d63f3c..9ed6bc2305d 100644 --- a/source/blender/freestyle/intern/python/BPy_Operators.h +++ b/source/blender/freestyle/intern/python/BPy_Operators.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Operators.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_SShape.cpp b/source/blender/freestyle/intern/python/BPy_SShape.cpp index ed83e76559f..bb1b07a8c4c 100644 --- a/source/blender/freestyle/intern/python/BPy_SShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_SShape.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_SShape.h b/source/blender/freestyle/intern/python/BPy_SShape.h index 9741a10f69e..a6fb090a537 100644 --- a/source/blender/freestyle/intern/python/BPy_SShape.h +++ b/source/blender/freestyle/intern/python/BPy_SShape.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Silhouette.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -40,7 +38,7 @@ extern PyTypeObject SShape_Type; /*---------------------------Python BPy_SShape structure definition----------*/ typedef struct { - PyObject_HEAD SShape *ss; + PyObject_HEAD Freestyle::SShape *ss; bool borrowed; /* true if *ss is a borrowed object */ } BPy_SShape; diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp index 8f706f56f7d..c95abae3645 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h index 9068eb4c7a3..9c0a7368dcb 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h +++ b/source/blender/freestyle/intern/python/BPy_StrokeAttribute.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Stroke.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject StrokeAttribute_Type; /*---------------------------Python BPy_StrokeAttribute structure definition----------*/ typedef struct { - PyObject_HEAD StrokeAttribute *sa; + PyObject_HEAD Freestyle::StrokeAttribute *sa; bool borrowed; /* true if *sa is a borrowed reference */ } BPy_StrokeAttribute; diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp index b55da256c22..01f8ec18022 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp +++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.cpp @@ -46,6 +46,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_StrokeShader.h b/source/blender/freestyle/intern/python/BPy_StrokeShader.h index 04fff8e8052..74c5df52312 100644 --- a/source/blender/freestyle/intern/python/BPy_StrokeShader.h +++ b/source/blender/freestyle/intern/python/BPy_StrokeShader.h @@ -26,12 +26,8 @@ extern "C" { #include "../system/FreestyleConfig.h" -using namespace std; - #include "../stroke/StrokeShader.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -45,7 +41,7 @@ extern PyTypeObject StrokeShader_Type; /*---------------------------Python BPy_StrokeShader structure definition----------*/ typedef struct { - PyObject_HEAD StrokeShader *ss; + PyObject_HEAD Freestyle::StrokeShader *ss; } BPy_StrokeShader; /*---------------------------Python BPy_StrokeShader visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp index 78c93ddce31..de426183b6a 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.cpp @@ -35,6 +35,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h index 1319cabe94a..ef3021faf48 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction0D.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Functions0D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp index 365850b748c..591f69b23df 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.cpp @@ -33,6 +33,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h index 331c3b4aaa1..4613d58c2b7 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h +++ b/source/blender/freestyle/intern/python/BPy_UnaryFunction1D.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/Functions1D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp index e3076d4615f..3c3b0fe82e3 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h index 2460b1f028b..3d45c2fc701 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate0D.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Predicates0D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject UnaryPredicate0D_Type; /*---------------------------Python BPy_UnaryPredicate0D structure definition----------*/ typedef struct { - PyObject_HEAD UnaryPredicate0D *up0D; + PyObject_HEAD Freestyle::UnaryPredicate0D *up0D; } BPy_UnaryPredicate0D; /*---------------------------Python BPy_UnaryPredicate0D visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp index 4b5269a1434..26087d1a6ef 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.cpp @@ -38,6 +38,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h index 8fad7f94caf..0139ed8af77 100644 --- a/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h +++ b/source/blender/freestyle/intern/python/BPy_UnaryPredicate1D.h @@ -26,8 +26,6 @@ extern "C" { #include "../stroke/Predicates1D.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -41,7 +39,7 @@ extern PyTypeObject UnaryPredicate1D_Type; /*---------------------------Python BPy_UnaryPredicate1D structure definition----------*/ typedef struct { - PyObject_HEAD UnaryPredicate1D *up1D; + PyObject_HEAD Freestyle::UnaryPredicate1D *up1D; } BPy_UnaryPredicate1D; /*---------------------------Python BPy_UnaryPredicate1D visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp index 8565a95fc1a..24925edecf9 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewMap.cpp +++ b/source/blender/freestyle/intern/python/BPy_ViewMap.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_ViewMap.h b/source/blender/freestyle/intern/python/BPy_ViewMap.h index 59738b6dce9..2222b327dc2 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewMap.h +++ b/source/blender/freestyle/intern/python/BPy_ViewMap.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/ViewMap.h" -using namespace Freestyle; - #ifdef __cplusplus extern "C" { #endif @@ -40,7 +38,7 @@ extern PyTypeObject ViewMap_Type; /*---------------------------Python BPy_ViewMap structure definition----------*/ typedef struct { - PyObject_HEAD ViewMap *vm; + PyObject_HEAD Freestyle::ViewMap *vm; } BPy_ViewMap; /*---------------------------Python BPy_ViewMap visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp index 6c8551867fd..d6964d4d6ec 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewShape.cpp +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/BPy_ViewShape.h b/source/blender/freestyle/intern/python/BPy_ViewShape.h index bd51fd0d5cb..8401c4378f0 100644 --- a/source/blender/freestyle/intern/python/BPy_ViewShape.h +++ b/source/blender/freestyle/intern/python/BPy_ViewShape.h @@ -26,8 +26,6 @@ extern "C" { #include "../view_map/ViewMap.h" -using namespace Freestyle; - #include "BPy_SShape.h" #ifdef __cplusplus @@ -42,7 +40,7 @@ extern PyTypeObject ViewShape_Type; /*---------------------------Python BPy_ViewShape structure definition----------*/ typedef struct { - PyObject_HEAD ViewShape *vs; + PyObject_HEAD Freestyle::ViewShape *vs; bool borrowed; /* true if *vs a borrowed object */ BPy_SShape *py_ss; } BPy_ViewShape; diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp index e284f28cd0b..4299cfae214 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_FalseBP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp index 2c84f69dd6e..fb057022290 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_Length2DBP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp index ab79ae4e209..96e35bd305b 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_SameShapeIdBP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp index 47c3c6b53aa..eb53cfc5b0e 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_TrueBP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp index 9d69b1c902c..9522a8da4f7 100644 --- a/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp +++ b/source/blender/freestyle/intern/python/BinaryPredicate1D/BPy_ViewMapGradientNormBP1D.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Director.cpp b/source/blender/freestyle/intern/python/Director.cpp index ff1d63f5f58..4dd3f732be9 100644 --- a/source/blender/freestyle/intern/python/Director.cpp +++ b/source/blender/freestyle/intern/python/Director.cpp @@ -56,6 +56,8 @@ #include "UnaryFunction1D/BPy_UnaryFunction1DVec3f.h" #include "UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h" +using namespace Freestyle; + // BinaryPredicate0D: __call__ int Director_BPy_BinaryPredicate0D___call__(BinaryPredicate0D *bp0D, Interface0D &i1, diff --git a/source/blender/freestyle/intern/python/Director.h b/source/blender/freestyle/intern/python/Director.h index 468150524f1..0894911fe14 100644 --- a/source/blender/freestyle/intern/python/Director.h +++ b/source/blender/freestyle/intern/python/Director.h @@ -34,31 +34,34 @@ class Stroke; class StrokeShader; } // namespace Freestyle -using namespace Freestyle; - // BinaryPredicate0D: __call__ -int Director_BPy_BinaryPredicate0D___call__(BinaryPredicate0D *bp0D, - Interface0D &i1, - Interface0D &i2); +int Director_BPy_BinaryPredicate0D___call__(Freestyle::BinaryPredicate0D *bp0D, + Freestyle::Interface0D &i1, + Freestyle::Interface0D &i2); // BinaryPredicate1D: __call__ -int Director_BPy_BinaryPredicate1D___call__(BinaryPredicate1D *bp1D, - Interface1D &i1, - Interface1D &i2); +int Director_BPy_BinaryPredicate1D___call__(Freestyle::BinaryPredicate1D *bp1D, + Freestyle::Interface1D &i1, + Freestyle::Interface1D &i2); // UnaryFunction{0D,1D}: __call__ -int Director_BPy_UnaryFunction0D___call__(void *uf0D, void *py_uf0D, Interface0DIterator &if0D_it); -int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Interface1D &if1D); +int Director_BPy_UnaryFunction0D___call__(void *uf0D, + void *py_uf0D, + Freestyle::Interface0DIterator &if0D_it); +int Director_BPy_UnaryFunction1D___call__(void *uf1D, void *py_uf1D, Freestyle::Interface1D &if1D); // UnaryPredicate0D: __call__ -int Director_BPy_UnaryPredicate0D___call__(UnaryPredicate0D *up0D, Interface0DIterator &if0D_it); +int Director_BPy_UnaryPredicate0D___call__(Freestyle::UnaryPredicate0D *up0D, + Freestyle::Interface0DIterator &if0D_it); // UnaryPredicate1D: __call__ -int Director_BPy_UnaryPredicate1D___call__(UnaryPredicate1D *up1D, Interface1D &if1D); +int Director_BPy_UnaryPredicate1D___call__(Freestyle::UnaryPredicate1D *up1D, + Freestyle::Interface1D &if1D); // StrokeShader: shade -int Director_BPy_StrokeShader_shade(StrokeShader *ss, Stroke &s); +int Director_BPy_StrokeShader_shade(Freestyle::StrokeShader *ss, Freestyle::Stroke &s); // ChainingIterator: init, traverse -int Director_BPy_ChainingIterator_init(ChainingIterator *c_it); -int Director_BPy_ChainingIterator_traverse(ChainingIterator *c_it, AdjacencyIterator &a_it); +int Director_BPy_ChainingIterator_init(Freestyle::ChainingIterator *c_it); +int Director_BPy_ChainingIterator_traverse(Freestyle::ChainingIterator *c_it, + Freestyle::AdjacencyIterator &a_it); diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp index f70f70275df..57639b6161b 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------CurvePoint methods----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h index 6a550085817..0def155d22b 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_CurvePoint.h @@ -37,7 +37,7 @@ extern PyTypeObject CurvePoint_Type; /*---------------------------Python BPy_CurvePoint structure definition----------*/ typedef struct { BPy_Interface0D py_if0D; - CurvePoint *cp; + Freestyle::CurvePoint *cp; } BPy_CurvePoint; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp index b245ecd81f1..63a9ead910e 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------SVertex methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h index 8d24576a98f..d2fa48d17d8 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_SVertex.h @@ -37,7 +37,7 @@ extern PyTypeObject SVertex_Type; /*---------------------------Python BPy_SVertex structure definition----------*/ typedef struct { BPy_Interface0D py_if0D; - SVertex *sv; + Freestyle::SVertex *sv; } BPy_SVertex; /*---------------------------Python BPy_SVertex visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp index 696b3022e85..98fb460c3e4 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------ViewVertex methods----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h index cb9815fb3d4..b5881dcafb5 100644 --- a/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h +++ b/source/blender/freestyle/intern/python/Interface0D/BPy_ViewVertex.h @@ -37,7 +37,7 @@ extern PyTypeObject ViewVertex_Type; /*---------------------------Python BPy_ViewVertex structure definition----------*/ typedef struct { BPy_Interface0D py_if0D; - ViewVertex *vv; + Freestyle::ViewVertex *vv; } BPy_ViewVertex; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp index 5e63e190356..da8cd9d2395 100644 --- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h index 44da0ed212a..d635a8541db 100644 --- a/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h +++ b/source/blender/freestyle/intern/python/Interface0D/CurvePoint/BPy_StrokeVertex.h @@ -38,7 +38,7 @@ extern PyTypeObject StrokeVertex_Type; /*---------------------------Python BPy_StrokeVertex structure definition----------*/ typedef struct { BPy_CurvePoint py_cp; - StrokeVertex *sv; + Freestyle::StrokeVertex *sv; } BPy_StrokeVertex; /*---------------------------Python BPy_StrokeVertex visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp index ed10f3e0af5..90522ba7f9f 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------NonTVertex methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h index 43f2c2b4a5c..6d84533aa6b 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_NonTVertex.h @@ -37,7 +37,7 @@ extern PyTypeObject NonTVertex_Type; /*---------------------------Python BPy_NonTVertex structure definition----------*/ typedef struct { BPy_ViewVertex py_vv; - NonTVertex *ntv; + Freestyle::NonTVertex *ntv; } BPy_NonTVertex; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp index 596eec7a4e5..5f90f0fa7a9 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------TVertex methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h index 253934bb4e7..009ba24d1e8 100644 --- a/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h +++ b/source/blender/freestyle/intern/python/Interface0D/ViewVertex/BPy_TVertex.h @@ -37,7 +37,7 @@ extern PyTypeObject TVertex_Type; /*---------------------------Python BPy_TVertex structure definition----------*/ typedef struct { BPy_ViewVertex py_vv; - TVertex *tv; + Freestyle::TVertex *tv; } BPy_TVertex; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp index 0438abfd38c..2d019e2a979 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------FEdge methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h index 25b1bc99860..3c259d77a44 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FEdge.h @@ -37,7 +37,7 @@ extern PyTypeObject FEdge_Type; /*---------------------------Python BPy_FEdge structure definition----------*/ typedef struct { BPy_Interface1D py_if1D; - FEdge *fe; + Freestyle::FEdge *fe; } BPy_FEdge; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp index d77a8007b1a..6a7d4aef08f 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------CurvePoint methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h index 9bdc3919a38..be3e98edefe 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_FrsCurve.h @@ -37,7 +37,7 @@ extern PyTypeObject FrsCurve_Type; /*---------------------------Python BPy_FrsCurve structure definition----------*/ typedef struct { BPy_Interface1D py_if1D; - Curve *c; + Freestyle::Curve *c; } BPy_FrsCurve; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp index 90cc3e4f1ab..a5792d4bc5a 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.cpp @@ -31,6 +31,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------Stroke methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h index 33c6aa70f91..eb919b4a376 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_Stroke.h @@ -37,7 +37,7 @@ extern PyTypeObject Stroke_Type; /*---------------------------Python BPy_Stroke structure definition----------*/ typedef struct { BPy_Interface1D py_if1D; - Stroke *s; + Freestyle::Stroke *s; } BPy_Stroke; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp index c416d860c77..bfd093f694e 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp @@ -32,6 +32,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------ViewEdge methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h index 519081cedbd..ffcdb46cff6 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.h @@ -37,7 +37,7 @@ extern PyTypeObject ViewEdge_Type; /*---------------------------Python BPy_ViewEdge structure definition----------*/ typedef struct { BPy_Interface1D py_if1D; - ViewEdge *ve; + Freestyle::ViewEdge *ve; } BPy_ViewEdge; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp index dcf6c149b7d..bbcbe98df3a 100644 --- a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------Chain methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h index 73da253688c..279a9cdc945 100644 --- a/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h +++ b/source/blender/freestyle/intern/python/Interface1D/Curve/BPy_Chain.h @@ -37,7 +37,7 @@ extern PyTypeObject Chain_Type; /*---------------------------Python BPy_Chain structure definition----------*/ typedef struct { BPy_FrsCurve py_c; - Chain *c; + Freestyle::Chain *c; } BPy_Chain; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp index 454a2bb1c0f..f0aec671953 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------FEdgeSharp methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h index 2b8b09a5990..c3d0298bc5c 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSharp.h @@ -37,7 +37,7 @@ extern PyTypeObject FEdgeSharp_Type; /*---------------------------Python BPy_FEdgeSharp structure definition----------*/ typedef struct { BPy_FEdge py_fe; - FEdgeSharp *fes; + Freestyle::FEdgeSharp *fes; } BPy_FEdgeSharp; /*---------------------------Python BPy_FEdgeSharp visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp index c0d56ec949c..e6461dd6e8a 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// /*----------------------FEdgeSmooth methods ----------------------------*/ diff --git a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h index 97497281310..d8ddd6c573f 100644 --- a/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h +++ b/source/blender/freestyle/intern/python/Interface1D/FEdge/BPy_FEdgeSmooth.h @@ -38,7 +38,7 @@ extern PyTypeObject FEdgeSmooth_Type; /*---------------------------Python BPy_FEdgeSmooth structure definition----------*/ typedef struct { BPy_FEdge py_fe; - FEdgeSmooth *fes; + Freestyle::FEdgeSmooth *fes; } BPy_FEdgeSmooth; /*---------------------------Python BPy_FEdgeSmooth visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp index 9f5f8d07e26..d548396b229 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h index e5332e0d180..1de73dad015 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_AdjacencyIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject AdjacencyIterator_Type; /*---------------------------Python BPy_AdjacencyIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - AdjacencyIterator *a_it; + Freestyle::AdjacencyIterator *a_it; bool at_start; } BPy_AdjacencyIterator; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp index e4cd1cd073b..fe2fa32b184 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h index ece8018d285..ae6f7307e3c 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainPredicateIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject ChainPredicateIterator_Type; /*---------------------------Python BPy_ChainPredicateIterator structure definition----------*/ typedef struct { BPy_ChainingIterator py_c_it; - ChainPredicateIterator *cp_it; + Freestyle::ChainPredicateIterator *cp_it; PyObject *upred; PyObject *bpred; } BPy_ChainPredicateIterator; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp index 9aa8984f4af..ac73b231dd0 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h index f91d0fb2585..7eb5ca8d70c 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainSilhouetteIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject ChainSilhouetteIterator_Type; /*---------------------------Python BPy_ChainSilhouetteIterator structure definition----------*/ typedef struct { BPy_ChainingIterator py_c_it; - ChainSilhouetteIterator *cs_it; + Freestyle::ChainSilhouetteIterator *cs_it; } BPy_ChainSilhouetteIterator; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp index f2441fa9d18..c464d30f92e 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h index e950824764c..54fd6e08f05 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ChainingIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject ChainingIterator_Type; /*---------------------------Python BPy_ChainingIterator structure definition----------*/ typedef struct { BPy_ViewEdgeIterator py_ve_it; - ChainingIterator *c_it; + Freestyle::ChainingIterator *c_it; } BPy_ChainingIterator; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp index ff710e931d4..bd7ed9a48da 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h index db36bf386ec..2de21178e95 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_CurvePointIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject CurvePointIterator_Type; /*---------------------------Python BPy_CurvePointIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - CurveInternal::CurvePointIterator *cp_it; + Freestyle::CurveInternal::CurvePointIterator *cp_it; } BPy_CurvePointIterator; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp index d0de53fa424..6afa9d25df7 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h index 663193bedee..82e44218634 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_Interface0DIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject Interface0DIterator_Type; /*---------------------------Python BPy_Interface0DIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - Interface0DIterator *if0D_it; + Freestyle::Interface0DIterator *if0D_it; bool reversed; bool at_start; } BPy_Interface0DIterator; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp index c0db79858b7..48452f341a5 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h index a34dc7a63c5..c7b18db8e48 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_SVertexIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject SVertexIterator_Type; /*---------------------------Python BPy_SVertexIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - ViewEdgeInternal::SVertexIterator *sv_it; + Freestyle::ViewEdgeInternal::SVertexIterator *sv_it; } BPy_SVertexIterator; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp index ceb0d2a7546..fdcb4d34c70 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h index 629471a664c..d7ad3d99a54 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_StrokeVertexIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject StrokeVertexIterator_Type; /*---------------------------Python BPy_StrokeVertexIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - StrokeInternal::StrokeVertexIterator *sv_it; + Freestyle::StrokeInternal::StrokeVertexIterator *sv_it; bool reversed; /* attribute to make next() work correctly */ bool at_start; diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp index e01bbe928ce..3cc462a8294 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h index 7169a13f328..782f20c8884 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_ViewEdgeIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject ViewEdgeIterator_Type; /*---------------------------Python BPy_ViewEdgeIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - ViewEdgeInternal::ViewEdgeIterator *ve_it; + Freestyle::ViewEdgeInternal::ViewEdgeIterator *ve_it; } BPy_ViewEdgeIterator; /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp index 735746e33be..924045c9702 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h index 7a13f6d2c72..c6b1a123324 100644 --- a/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h +++ b/source/blender/freestyle/intern/python/Iterator/BPy_orientedViewEdgeIterator.h @@ -38,7 +38,7 @@ extern PyTypeObject orientedViewEdgeIterator_Type; /*---------------------------Python BPy_orientedViewEdgeIterator structure definition----------*/ typedef struct { BPy_Iterator py_it; - ViewVertexInternal::orientedViewEdgeIterator *ove_it; + Freestyle::ViewVertexInternal::orientedViewEdgeIterator *ove_it; bool reversed; bool at_start; } BPy_orientedViewEdgeIterator; diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp index c3b98d12918..6b3a20dbd9b 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BackboneStretcherShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp index 50fc9938a87..fd9b3951c6b 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BezierCurveShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp index e1198266a98..756a6e46c0d 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_BlenderTextureShader.cpp @@ -28,6 +28,8 @@ extern "C" { #include "../../../../python/generic/py_capi_utils.h" +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp index e8790df2dd0..a2540e53425 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_CalligraphicShader.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp index 8fb6e26d8d7..7792fad3a68 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ColorNoiseShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp index 2b108226e90..364f2ad72c2 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantColorShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp index 0174107f27f..6ffcfec4f69 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstantThicknessShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp index b5c200c17b1..11153b9dfc5 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ConstrainedIncreasingThicknessShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp index d1c3219b079..d6619934c16 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_GuidingLinesShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp index 7d1efebe71f..9f9c6e540dc 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingColorShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp index f13930bd4b3..f91e5deacf7 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_IncreasingThicknessShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp index 48c63554f06..d087f6065b5 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_PolygonalizationShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp index 5f0a0bfb305..ed456230682 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SamplingShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp index 3d30fb4e11b..de9e67a93b2 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SmoothingShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp index 876dd5f2f63..b975c1bb703 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_SpatialNoiseShader.cpp @@ -27,6 +27,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp index bd70d41717b..2c8451da43d 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_StrokeTextureStepShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp index fd7f5fabe77..cbbaaf2f82b 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_ThicknessNoiseShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp index ed575b12b8d..b52e10d21c7 100644 --- a/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp +++ b/source/blender/freestyle/intern/python/StrokeShader/BPy_TipRemoverShader.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp index 5ce96212031..eec01c1ebb6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.cpp @@ -38,6 +38,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h index 60ebc646d74..abfc2609523 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DDouble.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction0DDouble_Type; /*---------------------------Python BPy_UnaryFunction0DDouble structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<double> *uf0D_double; + Freestyle::UnaryFunction0D<double> *uf0D_double; } BPy_UnaryFunction0DDouble; /*---------------------------Python BPy_UnaryFunction0DDouble visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp index 8c988d55c91..6126ff571e6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h index 9ce4b3bfd0b..83abc003393 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DEdgeNature.h @@ -38,7 +38,7 @@ extern PyTypeObject UnaryFunction0DEdgeNature_Type; /*---------------------------Python BPy_UnaryFunction0DEdgeNature structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<Nature::EdgeNature> *uf0D_edgenature; + Freestyle::UnaryFunction0D<Freestyle::Nature::EdgeNature> *uf0D_edgenature; } BPy_UnaryFunction0DEdgeNature; /*---------------------------Python BPy_UnaryFunction0DEdgeNature visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp index 25b19e84b60..6b843817197 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.cpp @@ -34,6 +34,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h index fd221201d99..a4c401f3dcd 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DFloat.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction0DFloat_Type; /*---------------------------Python BPy_UnaryFunction0DFloat structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<float> *uf0D_float; + Freestyle::UnaryFunction0D<float> *uf0D_float; } BPy_UnaryFunction0DFloat; /*---------------------------Python BPy_UnaryFunction0DFloat visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp index b2426cab572..74f4ac9d392 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h index 14e5d48ce43..b13c976f0ac 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DId.h @@ -38,7 +38,7 @@ extern PyTypeObject UnaryFunction0DId_Type; /*---------------------------Python BPy_UnaryFunction0DId structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<Id> *uf0D_id; + Freestyle::UnaryFunction0D<Freestyle::Id> *uf0D_id; } BPy_UnaryFunction0DId; /*---------------------------Python BPy_UnaryFunction0DId visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp index 77f89265ba4..382dfdbd72d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h index bbd53c409eb..72054713a66 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DMaterial.h @@ -38,7 +38,7 @@ extern PyTypeObject UnaryFunction0DMaterial_Type; /*---------------------------Python BPy_UnaryFunction0DMaterial structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<FrsMaterial> *uf0D_material; + Freestyle::UnaryFunction0D<Freestyle::FrsMaterial> *uf0D_material; } BPy_UnaryFunction0DMaterial; /*---------------------------Python BPy_UnaryFunction0DMaterial visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp index 52f990502ef..87241708d9c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h index 1a466ffc673..2958d10994c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DUnsigned.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction0DUnsigned_Type; /*---------------------------Python BPy_UnaryFunction0DUnsigned structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<unsigned int> *uf0D_unsigned; + Freestyle::UnaryFunction0D<unsigned int> *uf0D_unsigned; } BPy_UnaryFunction0DUnsigned; /*---------------------------Python BPy_UnaryFunction0DUnsigned visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp index 45e1144cd32..b1451a89854 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h index 6c3d5fc85cc..2e570adbaee 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec2f.h @@ -23,7 +23,6 @@ #include "../BPy_UnaryFunction0D.h" #include "../../geometry/Geom.h" -using namespace Geometry; #ifdef __cplusplus extern "C" { @@ -39,7 +38,7 @@ extern PyTypeObject UnaryFunction0DVec2f_Type; /*---------------------------Python BPy_UnaryFunction0DVec2f structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<Vec2f> *uf0D_vec2f; + Freestyle::UnaryFunction0D<Freestyle::Geometry::Vec2f> *uf0D_vec2f; } BPy_UnaryFunction0DVec2f; /*---------------------------Python BPy_UnaryFunction0DVec2f visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp index 18eeae86dd7..65b5f56f61c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h index 4be9b170311..6334988a0ef 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVec3f.h @@ -23,7 +23,6 @@ #include "../BPy_UnaryFunction0D.h" #include "../../geometry/Geom.h" -using namespace Geometry; #ifdef __cplusplus extern "C" { @@ -39,7 +38,7 @@ extern PyTypeObject UnaryFunction0DVec3f_Type; /*---------------------------Python BPy_UnaryFunction0DVec3f structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<Vec3f> *uf0D_vec3f; + Freestyle::UnaryFunction0D<Freestyle::Geometry::Vec3f> *uf0D_vec3f; } BPy_UnaryFunction0DVec3f; /*---------------------------Python BPy_UnaryFunction0DVec3f visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp index 28c4425b2a4..0c0c4930245 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.cpp @@ -29,6 +29,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h index 2a36ae21002..4e49374273f 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DVectorViewShape.h @@ -40,7 +40,7 @@ extern PyTypeObject UnaryFunction0DVectorViewShape_Type; * definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<std::vector<ViewShape *>> *uf0D_vectorviewshape; + Freestyle::UnaryFunction0D<std::vector<Freestyle::ViewShape *>> *uf0D_vectorviewshape; } BPy_UnaryFunction0DVectorViewShape; /*---------------------------Python BPy_UnaryFunction0DVectorViewShape visible diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp index 75773aaa8d0..d5122b27b35 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h index 8a8dcdceb1f..7a3c27a30c1 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/BPy_UnaryFunction0DViewShape.h @@ -38,7 +38,7 @@ extern PyTypeObject UnaryFunction0DViewShape_Type; /*---------------------------Python BPy_UnaryFunction0DViewShape structure definition----------*/ typedef struct { BPy_UnaryFunction0D py_uf0D; - UnaryFunction0D<ViewShape *> *uf0D_viewshape; + Freestyle::UnaryFunction0D<Freestyle::ViewShape *> *uf0D_viewshape; } BPy_UnaryFunction0DViewShape; /*---------------------------Python BPy_UnaryFunction0DViewShape visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp index b59e72e23d2..384d633fb2d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Id/BPy_ShapeIdF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp index 9f7f2b234f7..2c76f6f303a 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp index 1cd1a4ab8ac..6de53794228 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Nature_EdgeNature/BPy_CurveNatureF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp index 60cfed83713..5baf1ba448e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_Normal2DF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp index 063f1651486..864e8573043 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec2f/BPy_VertexOrientation2DF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp index b0188cd0244..b2cc62f6904 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Vec3f/BPy_VertexOrientation3DF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp index ba890477782..2a9b521907d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetOccludeeF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp index 531020dc32a..e5e50dfcd4c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_ViewShape/BPy_GetShapeF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp index cb36e388306..71dda2e2c32 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_Curvature2DAngleF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp index ca306a55d1e..0bf7f0e7fa4 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_DensityF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp index 6a688212239..0c4abc60981 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedXF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp index 8efaaf1b699..a87e64ee2ce 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedYF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp index e13c990685f..52e0021d3b0 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetProjectedZF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp index 43cbb433bdd..98422fb45f3 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetXF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp index 24bfe3be985..f60115a4240 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetYF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp index 84a985a134d..822c3256fd9 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_GetZF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp index 247473dcb41..06d759f0737 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_LocalAverageDepthF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp index e82b5f1c557..656749dfdff 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp index b4760d10b2c..e547ebacf7e 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetCurvilinearAbscissaF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp index d4c735e3572..8afeaed8518 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetParameterF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp index 6d5f1ed80c3..d9ab0edb53c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_GetViewMapGradientNormF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp index bbf2aee5204..125d0b8212d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadCompleteViewMapPixelF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp index 54401153d37..ed0782edb22 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadMapPixelF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp index 88ca0579870..f1dadedf183 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_float/BPy_ReadSteerableViewMapPixelF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp index d6e00988e68..aca638ab972 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_unsigned_int/BPy_QuantitativeInvisibilityF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp index ddff11d7916..8fe266c4f19 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_vector_ViewShape/BPy_GetOccludersF0D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp index 57b2d61d5c1..ad20dc79d71 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.cpp @@ -43,6 +43,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h index 1fb42a18337..a57e42ce528 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DDouble.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction1DDouble_Type; /*---------------------------Python BPy_UnaryFunction1DDouble structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<double> *uf1D_double; + Freestyle::UnaryFunction1D<double> *uf1D_double; } BPy_UnaryFunction1DDouble; /*---------------------------Python BPy_UnaryFunction1DDouble visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp index a987dbb67f5..44937b3ebcc 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h index 886eb469d51..4227cc47efa 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DEdgeNature.h @@ -38,7 +38,7 @@ extern PyTypeObject UnaryFunction1DEdgeNature_Type; /*---------------------------Python BPy_UnaryFunction1DEdgeNature structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<Nature::EdgeNature> *uf1D_edgenature; + Freestyle::UnaryFunction1D<Freestyle::Nature::EdgeNature> *uf1D_edgenature; } BPy_UnaryFunction1DEdgeNature; /*---------------------------Python BPy_UnaryFunction1DEdgeNature visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp index 66499c68c65..2fc4cd4f2cb 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h index 8b977c9c96a..8be928eba77 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DFloat.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction1DFloat_Type; /*---------------------------Python BPy_UnaryFunction1DFloat structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<float> *uf1D_float; + Freestyle::UnaryFunction1D<float> *uf1D_float; } BPy_UnaryFunction1DFloat; /*---------------------------Python BPy_UnaryFunction1DFloat visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp index 54c5c786367..d5211d66d16 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h index 9149275b610..30fe050c2ad 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DUnsigned.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction1DUnsigned_Type; /*---------------------------Python BPy_UnaryFunction1DUnsigned structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<unsigned int> *uf1D_unsigned; + Freestyle::UnaryFunction1D<unsigned int> *uf1D_unsigned; } BPy_UnaryFunction1DUnsigned; /*---------------------------Python BPy_UnaryFunction1DUnsigned visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp index 8b23163fc95..684c9e189fe 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.cpp @@ -31,6 +31,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h index b55f9af7c4d..2decb723a33 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec2f.h @@ -23,7 +23,6 @@ #include "../BPy_UnaryFunction1D.h" #include "../../geometry/Geom.h" -using namespace Geometry; #ifdef __cplusplus extern "C" { @@ -39,7 +38,7 @@ extern PyTypeObject UnaryFunction1DVec2f_Type; /*---------------------------Python BPy_UnaryFunction1DVec2f structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<Vec2f> *uf1D_vec2f; + Freestyle::UnaryFunction1D<Freestyle::Geometry::Vec2f> *uf1D_vec2f; } BPy_UnaryFunction1DVec2f; /*---------------------------Python BPy_UnaryFunction1DVec2f visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp index 9b6a2445588..c45c61fd9ac 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.cpp @@ -30,6 +30,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h index 9e4342979e4..9e7a899a371 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVec3f.h @@ -23,7 +23,6 @@ #include "../BPy_UnaryFunction1D.h" #include "../../geometry/Geom.h" -using namespace Geometry; #ifdef __cplusplus extern "C" { @@ -39,7 +38,7 @@ extern PyTypeObject UnaryFunction1DVec3f_Type; /*---------------------------Python BPy_UnaryFunction1DVec3f structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<Vec3f> *uf1D_vec3f; + Freestyle::UnaryFunction1D<Freestyle::Geometry::Vec3f> *uf1D_vec3f; } BPy_UnaryFunction1DVec3f; /*---------------------------Python BPy_UnaryFunction1DVec3f visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp index c95595dc953..da8855a3a19 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.cpp @@ -32,6 +32,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h index bfbcf5e451d..a8dfee7f9aa 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVectorViewShape.h @@ -40,7 +40,7 @@ extern PyTypeObject UnaryFunction1DVectorViewShape_Type; * definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D<std::vector<ViewShape *>> *uf1D_vectorviewshape; + Freestyle::UnaryFunction1D<std::vector<Freestyle::ViewShape *>> *uf1D_vectorviewshape; } BPy_UnaryFunction1DVectorViewShape; /*---------------------------Python BPy_UnaryFunction1DVectorViewShape visible diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp index b258b0b27f7..5cfd12c42ff 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.cpp @@ -32,6 +32,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //-------------------MODULE INITIALIZATION-------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h index 3a821bc2083..520ccc29c99 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/BPy_UnaryFunction1DVoid.h @@ -36,7 +36,7 @@ extern PyTypeObject UnaryFunction1DVoid_Type; /*---------------------------Python BPy_UnaryFunction1DVoid structure definition----------*/ typedef struct { BPy_UnaryFunction1D py_uf1D; - UnaryFunction1D_void *uf1D_void; + Freestyle::UnaryFunction1D_void *uf1D_void; } BPy_UnaryFunction1DVoid; /*---------------------------Python BPy_UnaryFunction1DVoid visible prototypes-----------*/ diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp index 205820d9a92..e203016aee5 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Nature_EdgeNature/BPy_CurveNatureF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp index d22a1ec99ef..620a74ddad1 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Normal2DF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp index f66bd4c668f..1d21f627305 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec2f/BPy_Orientation2DF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp index 2f408d45b74..60d6eeeef92 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_Vec3f/BPy_Orientation3DF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp index 13455eb3a4c..ce0b9c0f231 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_Curvature2DAngleF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp index fcf2bebc161..0190201ce37 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_DensityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp index 5c352c670c1..d9c9b7af7a2 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetCompleteViewMapDensityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp index 45c6a1b0fb7..2c5854a72e6 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetDirectionalViewMapDensityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp index 0c7276a13ec..6f00bc0f844 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedXF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp index 1f1c01a5344..b9b43c13b88 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedYF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp index cfa06f9d8fd..f0b9fd192b0 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetProjectedZF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp index 985e10f2b83..ef59d19aba4 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetSteerableViewMapDensityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp index 441ea2f5833..70b1a2cae2c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetViewMapGradientNormF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp index 716cfbfe37a..51c04ba82b3 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetXF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp index 693c2453db2..f18d3cb647c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetYF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp index e9030625b10..4d5d3f18604 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_GetZF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp index 4ae2cd054e2..a2f233e6f6d 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_LocalAverageDepthF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp index 9feb07552ca..6d9bff89d81 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp index 400b5a95fcf..280f44e2e0c 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_unsigned_int/BPy_QuantitativeInvisibilityF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp index 7637153017f..4d7697d4078 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludeeF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp index d532268b294..aae7a2597b1 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetOccludersF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp index dd1492e940e..703e2e50955 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_vector_ViewShape/BPy_GetShapeF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp index c3750734efc..a3b5bb8fe05 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_ChainingTimeStampF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp index 85738684e44..23d254dd843 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_IncrementChainingTimeStampF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp index 1f577820da4..cf94195cb01 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_void/BPy_TimeStampF1D.cpp @@ -28,6 +28,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp index 227aca2b5c6..f11a4d8c939 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_FalseUP0D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp index 5f5c756b28d..018f44e4f07 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate0D/BPy_TrueUP0D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp index b3f9c225931..7c6b7b809f1 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ContourUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp index f865fe5013d..0025b28137a 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_DensityLowerThanUP1D.cpp @@ -26,6 +26,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp index 154b44ff81a..34354349dfc 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToChainingTimeStampUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp index 2bb9dbaf484..c9e8c80c3ce 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_EqualToTimeStampUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp index 7b9923d7b6c..3cc9a21c050 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ExternalContourUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp index ec1a02e13aa..58efd78619e 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_FalseUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp index b9a76f91c21..cca81e6bc6e 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_QuantitativeInvisibilityUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp index 68f0ea7a913..a2eac6b41fe 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_ShapeUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp index 362bcc4cea8..79b0fce790a 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_TrueUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp index 9329e3a7628..965945a1f79 100644 --- a/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryPredicate1D/BPy_WithinImageBoundaryUP1D.cpp @@ -24,6 +24,8 @@ extern "C" { #endif +using namespace Freestyle; + /////////////////////////////////////////////////////////////////////////////////////////// //------------------------INSTANCE METHODS ---------------------------------- diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index 1c959c43481..47a2e98418a 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -228,7 +228,7 @@ class ViewMap { */ ViewVertex *InsertViewVertex(SVertex *iVertex, vector<ViewEdge *> &newViewEdges); - /* connects a FEdge to the graph trough a SVertex */ + /* connects a FEdge to the graph through a SVertex */ // FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex); /* Clean temporary FEdges created by chaining */ @@ -1085,13 +1085,13 @@ class ViewEdge : public Interface1D { return __B; } - /*! Returns the first FEdge that constitues this ViewEdge. */ + /*! Returns the first FEdge that constitutes this ViewEdge. */ inline FEdge *fedgeA() { return _FEdgeA; } - /*! Returns the last FEdge that constitues this ViewEdge. */ + /*! Returns the last FEdge that constitutes this ViewEdge. */ inline FEdge *fedgeB() { return _FEdgeB; diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index 0ee491a071c..1984aceb51c 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -19,7 +19,7 @@ * and: * OGF/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000-2003 Bruno Levy - * Contact: Bruno Levy levy@loria.fr + * Contact: Bruno Levy <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h index d73674d02cd..0eefc57c3a2 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.h +++ b/source/blender/freestyle/intern/winged_edge/Curvature.h @@ -19,7 +19,7 @@ * and: * OGF/Graphite: Geometry and Graphics Programming Library + Utilities * Copyright (C) 2000-2003 Bruno Levy - * Contact: Bruno Levy levy@loria.fr + * Contact: Bruno Levy <levy@loria.fr> * ISA Project * LORIA, INRIA Lorraine, * Campus Scientifique, BP 239 diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh index 5a7dfadf537..a854e63288d 100644 --- a/source/blender/functions/FN_cpp_type.hh +++ b/source/blender/functions/FN_cpp_type.hh @@ -929,4 +929,9 @@ inline std::unique_ptr<const CPPType> create_cpp_type(StringRef name, const T &d static std::unique_ptr<const CPPType> cpp_type = blender::fn::create_cpp_type<TYPE_NAME>( \ STRINGIFY(IDENTIFIER), default_value); \ return *cpp_type; \ + } \ + /* Support using `CPPType::get<const T>()`. Otherwise the caller would have to remove const. */ \ + template<> const blender::fn::CPPType &blender::fn::CPPType::get<const TYPE_NAME>() \ + { \ + return blender::fn::CPPType::get<TYPE_NAME>(); \ } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index e2f4d34ff40..f80ad60eb07 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -110,11 +110,11 @@ static bool dependsOnTime(GpencilModifierData *md) return (mmd->flag & GP_NOISE_USE_RANDOM) != 0; } -static float *noise_table(int len, int seed) +static float *noise_table(int len, int offset, int seed) { float *table = MEM_callocN(sizeof(float) * len, __func__); for (int i = 0; i < len; i++) { - table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + 1)); + table[i] = BLI_hash_int_01(BLI_hash_int_2d(seed, i + offset + 1)); } return table; } @@ -172,11 +172,19 @@ static void deformStroke(GpencilModifierData *md, /* Sanitize as it can create out of bound reads. */ float noise_scale = clamp_f(mmd->noise_scale, 0.0f, 1.0f); - int len = ceilf(gps->totpoints * noise_scale) + 1; - float *noise_table_position = (mmd->factor > 0.0f) ? noise_table(len, seed + 2) : NULL; - float *noise_table_strength = (mmd->factor_strength > 0.0f) ? noise_table(len, seed + 3) : NULL; - float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? noise_table(len, seed) : NULL; - float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? noise_table(len, seed + 4) : NULL; + int len = ceilf(gps->totpoints * noise_scale) + 2; + float *noise_table_position = (mmd->factor > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 2) : + NULL; + float *noise_table_strength = (mmd->factor_strength > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 3) : + NULL; + float *noise_table_thickness = (mmd->factor_thickness > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed) : + NULL; + float *noise_table_uvs = (mmd->factor_uvs > 0.0f) ? + noise_table(len, (int)floor(mmd->noise_offset), seed + 4) : + NULL; /* Calculate stroke normal. */ if (gps->totpoints > 2) { @@ -225,24 +233,27 @@ static void deformStroke(GpencilModifierData *md, cross_v3_v3v3(vec2, vec1, normal); normalize_v3(vec2); - float noise = table_sample(noise_table_position, i * noise_scale); + float noise = table_sample(noise_table_position, + i * noise_scale + fractf(mmd->noise_offset)); madd_v3_v3fl(&pt->x, vec2, (noise * 2.0f - 1.0f) * weight * mmd->factor * 0.1f); } if (mmd->factor_thickness > 0.0f) { - float noise = table_sample(noise_table_thickness, i * noise_scale); + float noise = table_sample(noise_table_thickness, + i * noise_scale + fractf(mmd->noise_offset)); pt->pressure *= max_ff(1.0f + (noise * 2.0f - 1.0f) * weight * mmd->factor_thickness, 0.0f); CLAMP_MIN(pt->pressure, GPENCIL_STRENGTH_MIN); } if (mmd->factor_strength > 0.0f) { - float noise = table_sample(noise_table_strength, i * noise_scale); + float noise = table_sample(noise_table_strength, + i * noise_scale + fractf(mmd->noise_offset)); pt->strength *= max_ff(1.0f - noise * weight * mmd->factor_strength, 0.0f); CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } if (mmd->factor_uvs > 0.0f) { - float noise = table_sample(noise_table_uvs, i * noise_scale); + float noise = table_sample(noise_table_uvs, i * noise_scale + fractf(mmd->noise_offset)); pt->uv_rot += (noise * 2.0f - 1.0f) * weight * mmd->factor_uvs * M_PI_2; CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); } @@ -292,6 +303,8 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiItemR(col, ptr, "factor_thickness", 0, IFACE_("Thickness"), ICON_NONE); uiItemR(col, ptr, "factor_uvs", 0, IFACE_("UV"), ICON_NONE); uiItemR(col, ptr, "noise_scale", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "noise_offset", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "seed", 0, NULL, ICON_NONE); gpencil_modifier_panel_end(layout, ptr); } @@ -316,7 +329,6 @@ static void random_panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetActive(layout, RNA_boolean_get(ptr, "random")); uiItemR(layout, ptr, "step", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "seed", 0, NULL, ICON_NONE); } static void mask_panel_draw(const bContext *UNUSED(C), Panel *panel) diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 85981ac8043..018e192bf37 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -84,7 +84,7 @@ typedef struct GPUBatch { GPUVertBuf *inst[GPU_BATCH_INST_VBO_MAX_LEN]; /** NULL if element list not needed */ GPUIndexBuf *elem; - /** Bookeeping. */ + /** Bookkeeping. */ eGPUBatchFlag flag; /** Type of geometry to draw. */ GPUPrimType prim_type; @@ -128,7 +128,7 @@ void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, eGPUShaderConfig sh_cfg); /* Will only work after setting the batch program. */ -/* TODO(fclem): Theses needs to be replaced by GPU_shader_uniform_* with explicit shader. */ +/* TODO(fclem): These need to be replaced by GPU_shader_uniform_* with explicit shader. */ #define GPU_batch_uniform_1i(batch, name, x) GPU_shader_uniform_1i((batch)->shader, name, x); #define GPU_batch_uniform_1b(batch, name, x) GPU_shader_uniform_1b((batch)->shader, name, x); #define GPU_batch_uniform_1f(batch, name, x) GPU_shader_uniform_1f((batch)->shader, name, x); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index c0f91756bf6..8c6592adf6d 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -20,7 +20,7 @@ /** \file * \ingroup gpu * - * GPU Framebuffer + * GPU Frame-buffer * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice * multiple FBO's may be created. * - actual FBO creation & config is deferred until GPU_framebuffer_bind or @@ -79,7 +79,7 @@ GPUFrameBuffer *GPU_framebuffer_back_get(void); } \ } while (0) -/* Framebuffer setup : You need to call GPU_framebuffer_bind for these +/* Frame-buffer setup: You need to call #GPU_framebuffer_bind for these * to be effective. */ void GPU_framebuffer_texture_attach_ex(GPUFrameBuffer *gpu_fb, GPUAttachment attachment, int slot); @@ -154,7 +154,7 @@ void GPU_framebuffer_texture_layer_attach( void GPU_framebuffer_texture_cubeface_attach( GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip); -/* Framebuffer operations */ +/* Frame-buffer operations. */ void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h); void GPU_framebuffer_viewport_get(GPUFrameBuffer *fb, int r_viewport[4]); diff --git a/source/blender/gpu/GPU_index_buffer.h b/source/blender/gpu/GPU_index_buffer.h index 0c71dd539a6..76aab3c196b 100644 --- a/source/blender/gpu/GPU_index_buffer.h +++ b/source/blender/gpu/GPU_index_buffer.h @@ -70,7 +70,7 @@ void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem); GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *); void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *); -/* Create a subrange of an existing indexbuffer. */ +/* Create a sub-range of an existing index-buffer. */ GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uint length); void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem, GPUIndexBuf *elem_src, diff --git a/source/blender/gpu/GPU_platform.h b/source/blender/gpu/GPU_platform.h index bb7e1d58041..c457b829bf7 100644 --- a/source/blender/gpu/GPU_platform.h +++ b/source/blender/gpu/GPU_platform.h @@ -34,6 +34,7 @@ typedef enum eGPUDeviceType { GPU_DEVICE_ATI = (1 << 1), GPU_DEVICE_INTEL = (1 << 2), GPU_DEVICE_INTEL_UHD = (1 << 3), + GPU_DEVICE_APPLE = (1 << 3), GPU_DEVICE_SOFTWARE = (1 << 4), GPU_DEVICE_UNKNOWN = (1 << 5), GPU_DEVICE_ANY = (0xff), diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 55716b584c3..9824c7016dc 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -29,7 +29,7 @@ extern "C" { struct GPUVertBuf; -/** Opaque type hidding blender::gpu::Shader */ +/** Opaque type hiding #blender::gpu::Shader */ typedef struct GPUShader GPUShader; typedef enum eGPUShaderTFBType { diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index f5a1ccbc40b..0687f271670 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -46,7 +46,7 @@ ENUM_OPERATORS(eGPUBarrier, GPU_BARRIER_TEXTURE_FETCH) /** * Defines the fixed pipeline blending equation. * SRC is the output color from the shader. - * DST is the color from the framebuffer. + * DST is the color from the frame-buffer. * The blending equation is : * (SRC * A) + (DST * B). * The blend mode will modify the A and B parameters. @@ -64,7 +64,7 @@ typedef enum eGPUBlend { * NOTE: Does not modify alpha. */ GPU_BLEND_INVERT, /** Order independent transparency. - * NOTE: Cannot be used as is. Needs special setup (framebuffer, shader ...). */ + * NOTE: Cannot be used as is. Needs special setup (frame-buffer, shader ...). */ GPU_BLEND_OIT, /** Special blend to add color under and multiply dst color by src alpha. */ GPU_BLEND_BACKGROUND, diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 91119bd05a1..da2d2639440 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -77,12 +77,12 @@ void GPU_samplers_update(void); */ /* Wrapper to supported OpenGL/Vulkan texture internal storage - * If you need a type just uncomment it. Be aware that some formats - * are not supported by renderbuffers. All of the following formats + * If you need a type just un-comment it. Be aware that some formats + * are not supported by render-buffers. All of the following formats * are part of the OpenGL 3.3 core * specification. */ typedef enum eGPUTextureFormat { - /* Formats texture & renderbuffer */ + /* Formats texture & render-buffer. */ GPU_RGBA8UI, GPU_RGBA8I, GPU_RGBA8, diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index eeaebd3fae5..aae58de533b 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -34,7 +34,7 @@ typedef enum { GPU_VERTBUF_INVALID = 0, /** Was init with a vertex format. */ GPU_VERTBUF_INIT = (1 << 0), - /** Data has been touched and need to be reuploaded. */ + /** Data has been touched and need to be re-uploaded. */ GPU_VERTBUF_DATA_DIRTY = (1 << 1), /** The buffer has been created inside GPU memory. */ GPU_VERTBUF_DATA_UPLOADED = (1 << 2), diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 84da95f6fee..a2072e504fd 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -109,7 +109,7 @@ static GPUPass *gpu_pass_cache_resolve_collision(GPUPass *pass, uint32_t hash) { BLI_spin_lock(&pass_cache_spin); - /* Collision, need to strcmp the whole shader. */ + /* Collision, need to `strcmp` the whole shader. */ for (; pass && (pass->hash == hash); pass = pass->next) { if ((defs != NULL) && (!STREQ(pass->defines, defs))) { /* Pass */ } diff --git a/source/blender/gpu/intern/gpu_context_private.hh b/source/blender/gpu/intern/gpu_context_private.hh index ffa7a38faa6..82753b44c51 100644 --- a/source/blender/gpu/intern/gpu_context_private.hh +++ b/source/blender/gpu/intern/gpu_context_private.hh @@ -93,7 +93,7 @@ class Context { bool is_active_on_thread(void); }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUContext *wrap(Context *ctx) { return reinterpret_cast<GPUContext *>(ctx); diff --git a/source/blender/gpu/intern/gpu_drawlist_private.hh b/source/blender/gpu/intern/gpu_drawlist_private.hh index 98603299d62..393307e6ee5 100644 --- a/source/blender/gpu/intern/gpu_drawlist_private.hh +++ b/source/blender/gpu/intern/gpu_drawlist_private.hh @@ -42,7 +42,7 @@ class DrawList { virtual void submit() = 0; }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUDrawList *wrap(DrawList *vert) { return reinterpret_cast<GPUDrawList *>(vert); diff --git a/source/blender/gpu/intern/gpu_framebuffer.cc b/source/blender/gpu/intern/gpu_framebuffer.cc index d5d7994a154..2e183f52eea 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.cc +++ b/source/blender/gpu/intern/gpu_framebuffer.cc @@ -359,7 +359,7 @@ void GPU_framebuffer_viewport_reset(GPUFrameBuffer *gpu_fb) unwrap(gpu_fb)->viewport_reset(); } -/* ---------- Framebuffer Operations ----------- */ +/* ---------- Frame-buffer Operations ----------- */ void GPU_framebuffer_clear(GPUFrameBuffer *gpu_fb, eGPUFrameBufferBits buffers, diff --git a/source/blender/gpu/intern/gpu_framebuffer_private.hh b/source/blender/gpu/intern/gpu_framebuffer_private.hh index 7afa56bfe3d..d63d72cf4f7 100644 --- a/source/blender/gpu/intern/gpu_framebuffer_private.hh +++ b/source/blender/gpu/intern/gpu_framebuffer_private.hh @@ -20,12 +20,7 @@ /** \file * \ingroup gpu * - * GPU Framebuffer - * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice - * multiple FBO's may be created. - * - actual FBO creation & config is deferred until GPU_framebuffer_bind or - * GPU_framebuffer_check_valid to allow creation & config while another - * opengl context is bound (since FBOs are not shared between ogl contexts). + * Private frame buffer API. */ #pragma once @@ -210,7 +205,7 @@ class FrameBuffer { }; }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUFrameBuffer *wrap(FrameBuffer *vert) { return reinterpret_cast<GPUFrameBuffer *>(vert); diff --git a/source/blender/gpu/intern/gpu_immediate_private.hh b/source/blender/gpu/intern/gpu_immediate_private.hh index 9fcbe2bdc0b..98399897ea9 100644 --- a/source/blender/gpu/intern/gpu_immediate_private.hh +++ b/source/blender/gpu/intern/gpu_immediate_private.hh @@ -34,7 +34,7 @@ namespace blender::gpu { class Immediate { public: - /** Pointer to the mapped buffer data for the currect vertex. */ + /** Pointer to the mapped buffer data for the current vertex. */ uchar *vertex_data = NULL; /** Current vertex index. */ uint vertex_idx = 0; @@ -49,10 +49,10 @@ class Immediate { GPUPrimType prim_type = GPU_PRIM_NONE; GPUVertFormat vertex_format = {}; GPUShader *shader = NULL; - /** Enforce strict vertex count (disabled when using immBeginAtMost). */ + /** Enforce strict vertex count (disabled when using #immBeginAtMost). */ bool strict_vertex_len = true; - /** Batch in construction when using immBeginBatch. */ + /** Batch in construction when using #immBeginBatch. */ GPUBatch *batch = NULL; /** Wide Line workaround. */ @@ -61,7 +61,7 @@ class Immediate { GPUShader *prev_shader = NULL; /** Builtin shader index. Used to test if the workaround can be done. */ eGPUBuiltinShader builtin_shader_bound = GPU_SHADER_TEXT; - /** Uniform color: Kept here to update the wideline shader just before immBegin. */ + /** Uniform color: Kept here to update the wide-line shader just before #immBegin. */ float uniform_color[4]; public: diff --git a/source/blender/gpu/intern/gpu_index_buffer_private.hh b/source/blender/gpu/intern/gpu_index_buffer_private.hh index 7054360d07f..2405db8664a 100644 --- a/source/blender/gpu/intern/gpu_index_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_index_buffer_private.hh @@ -57,7 +57,7 @@ class IndexBuf { uint32_t index_len_ = 0; /** Base index: Added to all indices after fetching. Allows index compression. */ uint32_t index_base_ = 0; - /** Bookeeping. */ + /** Bookkeeping. */ bool is_init_ = false; /** Is this object only a reference to a subrange of another IndexBuf. */ bool is_subrange_ = false; @@ -96,7 +96,7 @@ class IndexBuf { inline uint index_range(uint *r_min, uint *r_max); }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUIndexBuf *wrap(IndexBuf *indexbuf) { return reinterpret_cast<GPUIndexBuf *>(indexbuf); diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 08da49c3475..bf91a5bbb4d 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -132,7 +132,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType case GPU_NODE_LINK_ATTR: input->source = GPU_SOURCE_ATTR; input->attr = link->attr; - /* Failsafe handling if the same attribute is used with different datatypes for + /* Fail-safe handling if the same attribute is used with different data-types for * some reason (only really makes sense with float/vec2/vec3/vec4 though). This * can happen if mixing the generic Attribute node with specialized ones. */ CLAMP_MIN(input->attr->gputype, type); diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 66748b4146a..6cda7888712 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -269,7 +269,7 @@ typedef struct GPUPickState { ListBase bufs; } cache; - /* Pickign methods */ + /* Picking methods. */ union { /* GPU_SELECT_PICK_ALL */ struct { diff --git a/source/blender/gpu/intern/gpu_shader.cc b/source/blender/gpu/intern/gpu_shader.cc index d47ad5e0100..97673e92bcf 100644 --- a/source/blender/gpu/intern/gpu_shader.cc +++ b/source/blender/gpu/intern/gpu_shader.cc @@ -106,7 +106,7 @@ void Shader::print_log(Span<const char *> sources, char *log, const char *stage, error_line = error_char = -1; if (log_line[0] >= '0' && log_line[0] <= '9') { error_line = (int)strtol(log_line, &error_line_number_end, 10); - /* Try to fetch the error caracter (not always available). */ + /* Try to fetch the error character (not always available). */ if (ELEM(error_line_number_end[0], '(', ':') && error_line_number_end[1] != ' ') { error_char = (int)strtol(error_line_number_end + 1, &log_line, 10); } diff --git a/source/blender/gpu/intern/gpu_shader_interface.hh b/source/blender/gpu/intern/gpu_shader_interface.hh index 62513ffb8a7..942be84caae 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.hh +++ b/source/blender/gpu/intern/gpu_shader_interface.hh @@ -41,7 +41,7 @@ typedef struct ShaderInput { uint32_t name_offset; uint32_t name_hash; int32_t location; - /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */ + /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attributes. */ int32_t binding; } ShaderInput; @@ -226,7 +226,7 @@ inline const ShaderInput *ShaderInterface::input_lookup(const ShaderInput *const for (int i = inputs_len - 1; i >= 0; i--) { if (inputs[i].name_hash == name_hash) { if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) { - /* Hash colision resolve. */ + /* Hash collision resolve. */ for (; i >= 0 && inputs[i].name_hash == name_hash; i--) { if (STREQ(name, name_buffer_ + inputs[i].name_offset)) { return inputs + i; /* not found */ diff --git a/source/blender/gpu/intern/gpu_shader_private.hh b/source/blender/gpu/intern/gpu_shader_private.hh index 85427372559..d9327bbc0f4 100644 --- a/source/blender/gpu/intern/gpu_shader_private.hh +++ b/source/blender/gpu/intern/gpu_shader_private.hh @@ -76,7 +76,7 @@ class Shader { void print_log(Span<const char *> sources, char *log, const char *stage, const bool error); }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUShader *wrap(Shader *vert) { return reinterpret_cast<GPUShader *>(vert); diff --git a/source/blender/gpu/intern/gpu_state.cc b/source/blender/gpu/intern/gpu_state.cc index e158601a25c..782d25747bb 100644 --- a/source/blender/gpu/intern/gpu_state.cc +++ b/source/blender/gpu/intern/gpu_state.cc @@ -165,6 +165,11 @@ void GPU_depth_range(float near, float far) copy_v2_fl2(state.depth_range, near, far); } +/** + * \note By convention, this is set as needed and not reset back to 1.0. + * This means code that draws lines must always set the line width beforehand, + * but is not expected to restore it's previous value. + */ void GPU_line_width(float width) { width = max_ff(1.0f, width * PIXELSIZE); diff --git a/source/blender/gpu/intern/gpu_state_private.hh b/source/blender/gpu/intern/gpu_state_private.hh index cda1b591bb1..b79350a6506 100644 --- a/source/blender/gpu/intern/gpu_state_private.hh +++ b/source/blender/gpu/intern/gpu_state_private.hh @@ -101,16 +101,16 @@ union GPUStateMutable { /** Positive if using program point size. */ /* TODO(fclem): should be passed as uniform to all shaders. */ float point_size; - /** Not supported on every platform. Prefer using wideline shader. */ + /** Not supported on every platform. Prefer using wide-line shader. */ float line_width; /** Mutable stencil states. */ uint8_t stencil_write_mask; uint8_t stencil_compare_mask; uint8_t stencil_reference; uint8_t _pad0; - /* IMPORTANT: ensure x64 stuct alignment. */ + /* IMPORTANT: ensure x64 struct alignment. */ }; - /* Here to allow fast bitwise ops. */ + /* Here to allow fast bit-wise ops. */ uint64_t data[9]; }; diff --git a/source/blender/gpu/intern/gpu_texture_private.hh b/source/blender/gpu/intern/gpu_texture_private.hh index 4197d5c55fc..400a36559da 100644 --- a/source/blender/gpu/intern/gpu_texture_private.hh +++ b/source/blender/gpu/intern/gpu_texture_private.hh @@ -83,11 +83,11 @@ class Texture { protected: /* ---- Texture format (immutable after init). ---- */ - /** Width & Height & Depth. For cubemap arrays, d is number of facelayers. */ + /** Width & Height & Depth. For cube-map arrays, d is number of face-layers. */ int w_, h_, d_; /** Internal data format. */ eGPUTextureFormat format_; - /** Format caracteristics. */ + /** Format characteristics. */ eGPUTextureFormatFlag format_flag_; /** Texture type. */ eGPUTextureType type_; @@ -101,7 +101,7 @@ class Texture { /** For debugging */ char name_[DEBUG_NAME_LEN]; - /** Framebuffer references to update on deletion. */ + /** Frame-buffer references to update on deletion. */ GPUAttachmentType fb_attachment_[GPU_TEX_MAX_FBO_ATTACHED]; FrameBuffer *fb_[GPU_TEX_MAX_FBO_ATTACHED]; @@ -245,7 +245,7 @@ class Texture { virtual bool init_internal(GPUVertBuf *vbo) = 0; }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUTexture *wrap(Texture *vert) { return reinterpret_cast<GPUTexture *>(vert); diff --git a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh index 826bdd9f8d5..e8fc1343eaf 100644 --- a/source/blender/gpu/intern/gpu_uniform_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_uniform_buffer_private.hh @@ -65,7 +65,7 @@ class UniformBuf { } }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUUniformBuf *wrap(UniformBuf *vert) { return reinterpret_cast<GPUUniformBuf *>(vert); diff --git a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh index da8b02c5c66..67a09f6f83c 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer_private.hh +++ b/source/blender/gpu/intern/gpu_vertex_buffer_private.hh @@ -62,7 +62,7 @@ class VertBuf { void init(const GPUVertFormat *format, GPUUsageType usage); void clear(void); - /* Data manament */ + /* Data management. */ void allocate(uint vert_len); void resize(uint vert_len); void upload(void); @@ -105,7 +105,7 @@ class VertBuf { virtual void duplicate_data(VertBuf *dst) = 0; }; -/* Syntacting suggar. */ +/* Syntactic sugar. */ static inline GPUVertBuf *wrap(VertBuf *vert) { return reinterpret_cast<GPUVertBuf *>(vert); diff --git a/source/blender/gpu/intern/gpu_vertex_format.cc b/source/blender/gpu/intern/gpu_vertex_format.cc index 014c70033fc..8498da11507 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.cc +++ b/source/blender/gpu/intern/gpu_vertex_format.cc @@ -105,7 +105,7 @@ uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len) static uchar copy_attr_name(GPUVertFormat *format, const char *name) { - /* strncpy does 110% of what we need; let's do exactly 100% */ + /* `strncpy` does 110% of what we need; let's do exactly 100% */ uchar name_offset = format->name_offset; char *name_copy = format->names + name_offset; uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - name_offset; @@ -162,7 +162,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format, assert(comp_len != 8 && comp_len != 12 && comp_len != 16); } #endif - format->name_len++; /* multiname support */ + format->name_len++; /* Multi-name support. */ const uint attr_id = format->attr_len++; GPUVertAttr *attr = &format->attrs[attr_id]; @@ -186,7 +186,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias) assert(format->name_len < GPU_VERT_FORMAT_MAX_NAMES); /* there's room for more */ assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); #endif - format->name_len++; /* multiname support */ + format->name_len++; /* Multi-name support. */ attr->names[attr->name_len++] = copy_attr_name(format, alias); } @@ -200,7 +200,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias) * * WARNING: this function creates a lot of aliases/attributes, make sure to keep the attribute * name short to avoid overflowing the name-buffer. - * */ + */ void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count) { /* Sanity check. Maximum can be upgraded if needed. */ diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 205ba1d06d6..c118145ebd6 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -86,10 +86,10 @@ struct GPUViewport { int size[2]; int flag; - /* Set the active view (for stereoscoptic viewport rendering). */ + /* Set the active view (for stereoscopic viewport rendering). */ int active_view; - /* If engine_handles mismatch we free all ViewportEngineData in this viewport. */ + /* If engine_handles mismatch we free all #ViewportEngineData in this viewport. */ struct { void *handle; ViewportEngineData *data; @@ -589,7 +589,7 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, /* Restore. */ view_settings->curve_mapping = tmp_curve_mapping; viewport->view_settings.curve_mapping = tmp_curve_mapping_vp; - /* Only copy curvemapping if needed. Avoid uneeded OCIO cache miss. */ + /* Only copy curve-mapping if needed. Avoid unneeded OCIO cache miss. */ if (tmp_curve_mapping && viewport->view_settings.curve_mapping == NULL) { BKE_color_managed_view_settings_free(&viewport->view_settings); viewport->view_settings.curve_mapping = BKE_curvemapping_copy(tmp_curve_mapping); @@ -820,7 +820,7 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, const float w = (float)GPU_texture_width(color); const float h = (float)GPU_texture_height(color); - /* We allow rects with min/max swapped, but we also need coorectly assigned coordinates. */ + /* We allow rects with min/max swapped, but we also need correctly assigned coordinates. */ rcti sanitized_rect = *rect; BLI_rcti_sanitize(&sanitized_rect); @@ -974,7 +974,7 @@ static void gpu_viewport_passes_free(PassList *psl, int psl_len) memset(psl->passes, 0, sizeof(*psl->passes) * psl_len); } -/* Must be executed inside Drawmanager Opengl Context. */ +/* Must be executed inside Draw-manager OpenGL Context. */ void GPU_viewport_free(GPUViewport *viewport) { gpu_viewport_engines_data_free(viewport); diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 1d76b07c966..ef7788194a1 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -96,6 +96,11 @@ void GLBackend::platform_init() GPG.device = GPU_DEVICE_SOFTWARE; GPG.driver = GPU_DRIVER_SOFTWARE; } + else if (strstr(vendor, "Apple")) { + /* Apple Silicon. */ + GPG.device = GPU_DEVICE_APPLE; + GPG.driver = GPU_DRIVER_OFFICIAL; + } else if (strstr(renderer, "Apple Software Renderer")) { GPG.device = GPU_DEVICE_SOFTWARE; GPG.driver = GPU_DRIVER_SOFTWARE; @@ -244,15 +249,16 @@ static void detect_workarounds() if (!GLEW_VERSION_4_0) { GLContext::base_instance_support = false; } - /* The renderers include: - * Mobility Radeon HD 5000; - * Radeon HD 7500M; - * Radeon HD 7570M; - * Radeon HD 7600M; - * And many others... */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || - strstr(version, "4.5.13422"))) { + strstr(version, "4.5.13422") || strstr(version, "4.5.13467"))) { + /* The renderers include: + * Radeon HD 5000; + * Radeon HD 7500M; + * Radeon HD 7570M; + * Radeon HD 7600M; + * Radeon R5 Graphics; + * And others... */ GLContext::unused_fb_slot_workaround = true; GCaps.mip_render_workaround = true; GCaps.shader_image_load_store_support = false; @@ -302,7 +308,7 @@ static void detect_workarounds() if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && !GLEW_VERSION_4_5) { GLContext::copy_image_support = false; } - /* Special fix for theses specific GPUs. + /* Special fix for these specific GPUs. * Without this workaround, blender crashes on startup. (see T72098) */ if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) && (strstr(renderer, "HD Graphics 620") || strstr(renderer, "HD Graphics 630"))) { @@ -361,14 +367,14 @@ static void detect_workarounds() } } - /* Some Intel drivers have issues with using mips as framebuffer targets if - * GL_TEXTURE_MAX_LEVEL is higher than the target mip. + /* Some Intel drivers have issues with using mips as frame-buffer targets if + * GL_TEXTURE_MAX_LEVEL is higher than the target MIP. * Only check at the end after all other workarounds because this uses the drawing code. * Also after device/driver flags to avoid the check that causes pre GCN Radeon to crash. */ if (GCaps.mip_render_workaround == false) { GCaps.mip_render_workaround = detect_mip_render_workaround(); } - /* Disable multidraw if the base instance cannot be read. */ + /* Disable multi-draw if the base instance cannot be read. */ if (GLContext::shader_draw_parameters_support == false) { GLContext::multi_draw_indirect_support = false; } diff --git a/source/blender/gpu/opengl/gl_batch.hh b/source/blender/gpu/opengl/gl_batch.hh index 0fadde7a70d..218b9ffe4b7 100644 --- a/source/blender/gpu/opengl/gl_batch.hh +++ b/source/blender/gpu/opengl/gl_batch.hh @@ -52,9 +52,9 @@ class GLVaoCache { GLContext *context_ = NULL; /** Last interface this batch was drawn with. */ GLShaderInterface *interface_ = NULL; - /** Cached vao for the last interface. */ + /** Cached VAO for the last interface. */ GLuint vao_id_ = 0; - /** Used whend arb_base_instance is not supported. */ + /** Used when arb_base_instance is not supported. */ GLuint vao_base_instance_ = 0; int base_instance_ = 0; diff --git a/source/blender/gpu/opengl/gl_context.cc b/source/blender/gpu/opengl/gl_context.cc index d766e6f0828..6c9c6e10774 100644 --- a/source/blender/gpu/opengl/gl_context.cc +++ b/source/blender/gpu/opengl/gl_context.cc @@ -108,7 +108,7 @@ GLContext::~GLContext() BLI_assert(orphaned_vertarrays_.is_empty()); /* For now don't allow GPUFrameBuffers to be reuse in another context. */ BLI_assert(framebuffers_.is_empty()); - /* Delete vaos so the batch can be reused in another context. */ + /* Delete VAO's so the batch can be reused in another context. */ for (GLVaoCache *cache : vao_caches_) { cache->clear(); } @@ -312,7 +312,7 @@ void GLContext::memory_statistics_get(int *r_total_mem, int *r_free_mem) { /* TODO(merwin): use Apple's platform API to get this info. */ if (GLEW_NVX_gpu_memory_info) { - /* Teturned value in Kb. */ + /* Returned value in Kb. */ glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, r_total_mem); glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, r_free_mem); } diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh index 66a3fdd3355..0222adaba25 100644 --- a/source/blender/gpu/opengl/gl_context.hh +++ b/source/blender/gpu/opengl/gl_context.hh @@ -43,7 +43,7 @@ class GLVaoCache; class GLSharedOrphanLists { public: - /** Mutex for the bellow structures. */ + /** Mutex for the below structures. */ std::mutex lists_mutex; /** Buffers and textures are shared across context. Any context can free them. */ Vector<GLuint> textures; @@ -87,17 +87,17 @@ class GLContext : public Context { private: /** - * GPUBatch & GPUFramebuffer have references to the context they are from, in the case the + * #GPUBatch & #GPUFramebuffer have references to the context they are from, in the case the * context is destroyed, we need to remove any reference to it. */ Set<GLVaoCache *> vao_caches_; Set<GPUFrameBuffer *> framebuffers_; - /** Mutex for the bellow structures. */ + /** Mutex for the below structures. */ std::mutex lists_mutex_; /** VertexArrays and framebuffers are not shared across context. */ Vector<GLuint> orphaned_vertarrays_; Vector<GLuint> orphaned_framebuffers_; - /** GLBackend onws this data. */ + /** #GLBackend owns this data. */ GLSharedOrphanLists &shared_orphan_list_; public: diff --git a/source/blender/gpu/opengl/gl_debug.cc b/source/blender/gpu/opengl/gl_debug.cc index 0914c117241..ac42a950945 100644 --- a/source/blender/gpu/opengl/gl_debug.cc +++ b/source/blender/gpu/opengl/gl_debug.cc @@ -363,7 +363,7 @@ namespace blender::gpu { void GLContext::debug_group_begin(const char *name, int index) { if ((G.debug & G_DEBUG_GPU) && (GLEW_VERSION_4_3 || GLEW_KHR_debug)) { - /* Add 10 to avoid conlision with other indices from other possible callback layers. */ + /* Add 10 to avoid collision with other indices from other possible callback layers. */ index += 10; glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, index, -1, name); } diff --git a/source/blender/gpu/opengl/gl_framebuffer.cc b/source/blender/gpu/opengl/gl_framebuffer.cc index cbb332388dc..aea19295311 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.cc +++ b/source/blender/gpu/opengl/gl_framebuffer.cc @@ -142,13 +142,13 @@ bool GLFrameBuffer::check(char err_out[256]) #undef FORMAT_STATUS - const char *format = "GPUFrameBuffer: frame-buffer status %s\n"; + const char *format = "GPUFrameBuffer: %s status %s\n"; if (err_out) { - BLI_snprintf(err_out, 256, format, err); + BLI_snprintf(err_out, 256, format, this->name_, err); } else { - fprintf(stderr, format, err); + fprintf(stderr, format, this->name_, err); } return false; diff --git a/source/blender/gpu/opengl/gl_framebuffer.hh b/source/blender/gpu/opengl/gl_framebuffer.hh index 95e67f5973c..7b2c73d7042 100644 --- a/source/blender/gpu/opengl/gl_framebuffer.hh +++ b/source/blender/gpu/opengl/gl_framebuffer.hh @@ -20,7 +20,7 @@ /** \file * \ingroup gpu * - * Encapsulation of Framebuffer states (attached textures, viewport, scissors). + * Encapsulation of Frame-buffer states (attached textures, viewport, scissors). */ #pragma once @@ -45,22 +45,22 @@ class GLFrameBuffer : public FrameBuffer { private: /** OpenGL handle. */ GLuint fbo_id_ = 0; - /** Context the handle is from. Framebuffers are not shared accros contexts. */ + /** Context the handle is from. Frame-buffers are not shared across contexts. */ GLContext *context_ = NULL; /** State Manager of the same contexts. */ GLStateManager *state_manager_ = NULL; /** Copy of the GL state. Contains ONLY color attachments enums for slot binding. */ GLenum gl_attachments_[GPU_FB_MAX_COLOR_ATTACHMENT]; - /** Internal framebuffers are immutable. */ + /** Internal frame-buffers are immutable. */ bool immutable_; - /** True is the framebuffer has its first color target using the GPU_SRGB8_A8 format. */ + /** True is the frame-buffer has its first color target using the GPU_SRGB8_A8 format. */ bool srgb_; - /** True is the framebuffer has been bound using the GL_FRAMEBUFFER_SRGB feature. */ + /** True is the frame-buffer has been bound using the GL_FRAMEBUFFER_SRGB feature. */ bool enabled_srgb_ = false; public: /** - * Create a conventional framebuffer to attach texture to. + * Create a conventional frame-buffer to attach texture to. */ GLFrameBuffer(const char *name); diff --git a/source/blender/gpu/opengl/gl_primitive.hh b/source/blender/gpu/opengl/gl_primitive.hh index 7cd0654bc2c..05a15017c66 100644 --- a/source/blender/gpu/opengl/gl_primitive.hh +++ b/source/blender/gpu/opengl/gl_primitive.hh @@ -20,7 +20,7 @@ /** \file * \ingroup gpu * - * Encapsulation of Framebuffer states (attached textures, viewport, scissors). + * Encapsulation of Frame-buffer states (attached textures, viewport, scissors). */ #pragma once diff --git a/source/blender/gpu/opengl/gl_shader_interface.cc b/source/blender/gpu/opengl/gl_shader_interface.cc index 9533639b133..5870c645bf4 100644 --- a/source/blender/gpu/opengl/gl_shader_interface.cc +++ b/source/blender/gpu/opengl/gl_shader_interface.cc @@ -51,7 +51,7 @@ static inline int sampler_binding(int32_t program, int32_t uniform_location, int *sampler_len) { - /* Identify sampler uniforms and asign sampler units to them. */ + /* Identify sampler uniforms and assign sampler units to them. */ GLint type; glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); @@ -106,7 +106,7 @@ static inline int image_binding(int32_t program, int32_t uniform_location, int *image_len) { - /* Identify image uniforms and asign image units to them. */ + /* Identify image uniforms and assign image units to them. */ GLint type; glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type); @@ -133,7 +133,7 @@ static inline int image_binding(int32_t program, GLShaderInterface::GLShaderInterface(GLuint program) { - /* Necessary to make glUniform works. */ + /* Necessary to make #glUniform works. */ glUseProgram(program); GLint max_attr_name_len = 0, attr_len = 0; diff --git a/source/blender/gpu/opengl/gl_state.hh b/source/blender/gpu/opengl/gl_state.hh index 643e46acc2d..651c3c22afa 100644 --- a/source/blender/gpu/opengl/gl_state.hh +++ b/source/blender/gpu/opengl/gl_state.hh @@ -42,7 +42,7 @@ class GLTexture; */ class GLStateManager : public StateManager { public: - /** Anothter reference to the active framebuffer. */ + /** Another reference to the active frame-buffer. */ GLFrameBuffer *active_fb = nullptr; private: diff --git a/source/blender/gpu/opengl/gl_texture.cc b/source/blender/gpu/opengl/gl_texture.cc index 2e8d9dd6e1c..ef38e964c7b 100644 --- a/source/blender/gpu/opengl/gl_texture.cc +++ b/source/blender/gpu/opengl/gl_texture.cc @@ -32,7 +32,7 @@ #include "gl_backend.hh" #include "gl_debug.hh" #include "gl_state.hh" -#include "gpu_vertex_buffer_private.hh" /* TODO shoud be gl_vertex_buffer.hh */ +#include "gpu_vertex_buffer_private.hh" /* TODO should be `gl_vertex_buffer.hh` */ #include "gl_texture.hh" diff --git a/source/blender/gpu/opengl/gl_texture.hh b/source/blender/gpu/opengl/gl_texture.hh index e686a7defca..65a211e12a3 100644 --- a/source/blender/gpu/opengl/gl_texture.hh +++ b/source/blender/gpu/opengl/gl_texture.hh @@ -1,4 +1,3 @@ - /* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -20,13 +19,6 @@ /** \file * \ingroup gpu - * - * GPU Framebuffer - * - this is a wrapper for an OpenGL framebuffer object (FBO). in practice - * multiple FBO's may be created. - * - actual FBO creation & config is deferred until GPU_framebuffer_bind or - * GPU_framebuffer_check_valid to allow creation & config while another - * opengl context is bound (since FBOs are not shared between ogl contexts). */ #pragma once diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl index fb512a1f00e..81e0965fad3 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl @@ -57,7 +57,7 @@ in float dummy; vec2 do_widget(void) { - /* Offset to avoid loosing pixels (mimics conservative rasterization). */ + /* Offset to avoid losing pixels (mimics conservative rasterization). */ const vec2 ofs = vec2(0.5, -0.5); lineWidth = abs(rect.x - recti.x); vec2 emboss_ofs = vec2(0.0, -lineWidth); diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 3f444172499..eb31b0e9f87 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -1878,7 +1878,7 @@ static void execute_scene(struct Depsgraph *depsgraph, /*--------------------------------------------------- * plugin interface - * */ + */ void itasc_initialize_tree(struct Depsgraph *depsgraph, struct Scene *scene, Object *ob, diff --git a/source/blender/imbuf/IMB_metadata.h b/source/blender/imbuf/IMB_metadata.h index 501bf9dfba1..652ce913ee5 100644 --- a/source/blender/imbuf/IMB_metadata.h +++ b/source/blender/imbuf/IMB_metadata.h @@ -35,7 +35,7 @@ struct anim; * The metadata is a list of key/value pairs (both char *) that can me * saved in the header of several image formats. * Apart from some common keys like - * 'Software' and 'Description' (png standard) we'll use keys within the + * 'Software' and 'Description' (PNG standard) we'll use keys within the * Blender namespace, so should be called 'Blender::StampInfo' or 'Blender::FrameNum' * etc... * diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h index 08aa1936a6f..c92d764a104 100644 --- a/source/blender/imbuf/intern/IMB_allocimbuf.h +++ b/source/blender/imbuf/intern/IMB_allocimbuf.h @@ -32,7 +32,7 @@ struct ImBuf; void imb_refcounter_lock_init(void); void imb_refcounter_lock_exit(void); -#ifdef WIN32 +#ifndef WIN32 void imb_mmap_lock_init(void); void imb_mmap_lock_exit(void); void imb_mmap_lock(void); diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c index 8dfb3ada7d6..90c863878ff 100644 --- a/source/blender/imbuf/intern/allocimbuf.c +++ b/source/blender/imbuf/intern/allocimbuf.c @@ -53,7 +53,7 @@ void imb_refcounter_lock_exit(void) BLI_spin_end(&refcounter_spin); } -#ifdef WIN32 +#ifndef WIN32 static SpinLock mmap_spin; void imb_mmap_lock_init(void) @@ -197,7 +197,7 @@ void IMB_freezbuffloatImBuf(ImBuf *ibuf) ibuf->mall &= ~IB_zbuffloat; } -/** Free all pixel data (assosiated with image size). */ +/** Free all pixel data (associated with image size). */ void imb_freerectImbuf_all(ImBuf *ibuf) { imb_freerectImBuf(ibuf); diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index c40e65b1c5c..3a7570cd320 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -1050,7 +1050,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ int64_t pts_to_search = 0; double frame_rate; double pts_time_base; - long long st_time; + int64_t st_time; struct anim_index *tc_index = 0; AVStream *v_st; int new_frame_index = 0; /* To quiet gcc barking... */ @@ -1121,7 +1121,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ ffmpeg_decode_video_frame_scan(anim, pts_to_search); } else if (position != anim->curposition + 1) { - long long pos; + int64_t pos; int ret; if (tc_index) { @@ -1145,7 +1145,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ } } else { - pos = (long long)(position - anim->preseek) * AV_TIME_BASE / frame_rate; + pos = (int64_t)(position - anim->preseek) * AV_TIME_BASE / frame_rate; av_log(anim->pFormatCtx, AV_LOG_DEBUG, diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index 00fa0111d1c..3b1b970fb3c 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -400,7 +400,7 @@ void ColorBlock::boundsRangeAlpha(Color32 *start, Color32 *end) const #endif #if 0 -/** Sort colors by abosolute value in their 16 bit representation. */ +/** Sort colors by absolute value in their 16 bit representation. */ void ColorBlock::sortColorsByAbsoluteValue() { /* Dummy selection sort. */ diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 0271c7964b8..9c3d73bbb0d 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -25,7 +25,7 @@ * Original license from NVIDIA follows. */ -// This code is in the public domain -- castanyo@yahoo.es +// This code is in the public domain -- <castanyo@yahoo.es> #pragma once diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index cce264624ce..343c8cd8f64 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -425,7 +425,7 @@ static int check_pixel_assigned( * * When a mask is given, only effect pixels with a mask value of 1, * defined as #BAKE_MASK_MARGIN in rendercore.c - * */ + */ void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter) { const int width = ibuf->x; diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index f8029c08bad..7ada0130059 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -115,7 +115,7 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in return; } - /* gcc warns these could be uninitialized, but its ok. */ + /* GCC warns these could be uninitialized, but its ok. */ pixel_from_buffer(out, &outI, &outF, xout, yout); bicubic_interpolation_color(in, outI, outF, u, v); diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index fb8c361d94b..cf27557d043 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -476,7 +476,7 @@ static ImBuf *imb_load_jp2_stream(opj_stream_t *stream, r = image->comps[0].data; a = (use_alpha) ? image->comps[1].data : NULL; - /* grayscale 12bits+ */ + /* Gray-scale 12bits+ */ if (use_alpha) { a = image->comps[1].data; PIXEL_LOOPER_BEGIN (rect_float) { @@ -500,7 +500,7 @@ static ImBuf *imb_load_jp2_stream(opj_stream_t *stream, g = image->comps[1].data; b = image->comps[2].data; - /* rgb or rgba 12bits+ */ + /* RGB or RGBA 12bits+ */ if (use_alpha) { a = image->comps[3].data; PIXEL_LOOPER_BEGIN (rect_float) { @@ -551,7 +551,7 @@ static ImBuf *imb_load_jp2_stream(opj_stream_t *stream, g = image->comps[1].data; b = image->comps[2].data; - /* 8bit rgb or rgba */ + /* 8bit RGB or RGBA */ if (use_alpha) { a = image->comps[3].data; PIXEL_LOOPER_BEGIN (rect_uchar) { diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 979e7703e81..2a9cb9af891 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -1108,7 +1108,7 @@ void IMB_exr_write_channels(void *handle) const size_t num_pixels = ((size_t)data->width) * data->height; half *rect_half = nullptr, *current_rect_half = nullptr; - /* We allocate teporary storage for half pixels for all the channels at once. */ + /* We allocate temporary storage for half pixels for all the channels at once. */ if (data->num_half_channels != 0) { rect_half = (half *)MEM_mallocN(sizeof(half) * data->num_half_channels * num_pixels, __func__); @@ -1235,7 +1235,7 @@ void IMB_exr_read_channels(void *handle) Header header = in.header(); Box2i dw = header.dataWindow(); - /* Insert all matching channel into framebuffer. */ + /* Insert all matching channel into frame-buffer. */ FrameBuffer frameBuffer; ExrChannel *echan; diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index f0daa4543e1..50210650f05 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -23,13 +23,13 @@ */ #ifdef _WIN32 -# include "mmap_win.h" # include <io.h> # include <stddef.h> # include <sys/types.h> #endif #include "BLI_fileops.h" +#include "BLI_mmap.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -186,20 +186,19 @@ ImBuf *IMB_loadifffile( size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "%s: couldn't get mapping %s\n", __func__, descr); return NULL; } + mem = BLI_mmap_get_pointer(mmap_file); + ibuf = IMB_ibImageFromMemory(mem, size, flags, colorspace, descr); imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "%s: couldn't unmap file %s\n", __func__, descr); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); return ibuf; @@ -292,14 +291,15 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int size = BLI_file_descriptor_size(file); imb_mmap_lock(); - mem = mmap(NULL, size, PROT_READ, MAP_SHARED, file, 0); + BLI_mmap_file *mmap_file = BLI_mmap_open(file); imb_mmap_unlock(); - - if (mem == (unsigned char *)-1) { + if (mmap_file == NULL) { fprintf(stderr, "Couldn't get memory mapping for %s\n", ibuf->cachename); return; } + mem = BLI_mmap_get_pointer(mmap_file); + const ImFileType *type = IMB_file_type_from_ibuf(ibuf); if (type != NULL) { if (type->load_tile != NULL) { @@ -308,9 +308,7 @@ static void imb_loadtilefile(ImBuf *ibuf, int file, int tx, int ty, unsigned int } imb_mmap_lock(); - if (munmap(mem, size)) { - fprintf(stderr, "Couldn't unmap memory for %s.\n", ibuf->cachename); - } + BLI_mmap_free(mmap_file); imb_mmap_unlock(); } diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index a9833623250..d7cefbbd077 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -713,7 +713,7 @@ ImBuf *imb_loadtarga(const unsigned char *mem, return ibuf; } - if (!ELEM(tga.imgtyp, 1, 9)) { /* happens sometimes (beuh) */ + if (!ELEM(tga.imgtyp, 1, 9)) { /* happens sometimes (ugh) */ if (cmap) { MEM_freeN(cmap); cmap = NULL; diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index 038c9950968..0d2080b5f0a 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -63,7 +63,7 @@ * because 'near' is disabled through BLI_windstuff */ # include "BLI_winstuff.h" # include "utfconv.h" -# include <direct.h> /* chdir */ +# include <direct.h> /* #chdir */ # include <shlobj.h> #endif diff --git a/source/blender/imbuf/intern/thumbs_blend.c b/source/blender/imbuf/intern/thumbs_blend.c index 486db07597f..0d1fa354b3e 100644 --- a/source/blender/imbuf/intern/thumbs_blend.c +++ b/source/blender/imbuf/intern/thumbs_blend.c @@ -57,7 +57,7 @@ ImBuf *IMB_thumb_load_blend(const char *blen_path, const char *blen_group, const /* Note: we should handle all previews for a same group at once, would avoid reopening * `.blend` file for each and every ID. However, this adds some complexity, * so keep it for later. */ - names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, &nnames); + names = BLO_blendhandle_get_datablock_names(libfiledata, idcode, false, &nnames); previews = BLO_blendhandle_get_previews(libfiledata, idcode, &nprevs); BLO_blendhandle_close(libfiledata); diff --git a/source/blender/imbuf/intern/tiff.c b/source/blender/imbuf/intern/tiff.c index 587d6ad9e7e..2fb14e40d9d 100644 --- a/source/blender/imbuf/intern/tiff.c +++ b/source/blender/imbuf/intern/tiff.c @@ -512,7 +512,7 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image) } if (success) { - /* Code seems to be not needed for 16 bits tif, on PPC G5 OSX (ton) */ + /* Code seems to be not needed for 16 bits TIFF, on PPC G5 OSX (ton) */ if (bitspersample < 16) { if (ENDIAN_ORDER == B_ENDIAN) { IMB_convert_rgba_to_abgr(tmpibuf); @@ -806,7 +806,7 @@ bool imb_savetiff(ImBuf *ibuf, const char *filepath, int flags) /* open TIFF file for writing */ if (flags & IB_mem) { - /* bork at the creation of a TIFF in memory */ + /* Failed to allocate TIFF in memory. */ fprintf(stderr, "imb_savetiff: creation of in-memory TIFF files is " "not yet supported.\n"); diff --git a/source/blender/io/alembic/exporter/abc_archive.cc b/source/blender/io/alembic/exporter/abc_archive.cc index 68ad2089a3e..90a4baf97bc 100644 --- a/source/blender/io/alembic/exporter/abc_archive.cc +++ b/source/blender/io/alembic/exporter/abc_archive.cc @@ -112,7 +112,7 @@ static OArchive *create_archive(std::ofstream *abc_ostream, * * If 'time_relative' is true, samples are returned as time (in seconds) from params.frame_start. * If 'time_relative' is false, samples are returned as fractional frames from 0. - * */ + */ static void get_shutter_samples(double scene_fps, const AlembicExportParams ¶ms, int nr_of_samples, diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.h b/source/blender/io/alembic/exporter/abc_writer_mesh.h index fdf2d3cc1e3..ed4fb4e4514 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.h +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.h @@ -32,7 +32,7 @@ namespace blender::io::alembic { /* Writer for Alembic geometry. Does not assume the object is a mesh object. */ class ABCGenericMeshWriter : public ABCAbstractWriter { private: - /* Either polymesh or subd is used, depending on is_subd_. + /* Either poly-mesh or subdivision-surface is used, depending on is_subd_. * References to the schema must be kept, or Alembic will not properly write. */ Alembic::AbcGeom::OPolyMesh abc_poly_mesh_; Alembic::AbcGeom::OPolyMeshSchema abc_poly_mesh_schema_; diff --git a/source/blender/io/alembic/exporter/abc_writer_transform.cc b/source/blender/io/alembic/exporter/abc_writer_transform.cc index 7fe9fd933c5..eff042d036d 100644 --- a/source/blender/io/alembic/exporter/abc_writer_transform.cc +++ b/source/blender/io/alembic/exporter/abc_writer_transform.cc @@ -94,7 +94,7 @@ void ABCTransformWriter::do_write(HierarchyContext &context) scale_mat[3][3] = args_.export_params->global_scale; /* also scale translation */ mul_m4_m4m4(parent_relative_matrix, parent_relative_matrix, scale_mat); parent_relative_matrix[3][3] /= - args_.export_params->global_scale; /* normalise the homogeneous component */ + args_.export_params->global_scale; /* Normalize the homogeneous component. */ } XformSample xform_sample; diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 0b9636ffb70..8133f615080 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -521,7 +521,7 @@ static bool has_animated_geom_params(const ICompoundProperty arbGeomParams) return false; } -/* Specialisation of has_animations() as defined in abc_reader_object.h. */ +/* Specialization of #has_animations() as defined in abc_reader_object.h. */ template<> bool has_animations(Alembic::AbcGeom::IPolyMeshSchema &schema, ImportSettings *settings) { if (settings->is_sequence || !schema.isConstant()) { diff --git a/source/blender/io/alembic/intern/abc_util.cc b/source/blender/io/alembic/intern/abc_util.cc index aa7beb37dc5..3d3ba0347c5 100644 --- a/source/blender/io/alembic/intern/abc_util.cc +++ b/source/blender/io/alembic/intern/abc_util.cc @@ -135,7 +135,7 @@ bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string return prop.getPropertyHeader(name) != nullptr; } -typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t; +using index_time_pair_t = std::pair<Alembic::AbcCoreAbstract::index_t, float>; float get_weight_and_index(float time, const Alembic::AbcCoreAbstract::TimeSamplingPtr &time_sampling, diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp index 9f54bf2aa28..49f28325257 100644 --- a/source/blender/io/collada/AnimationImporter.cpp +++ b/source/blender/io/collada/AnimationImporter.cpp @@ -120,12 +120,12 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) COLLADAFW::FloatOrDoubleArray &intan = curve->getInTangentValues(); COLLADAFW::FloatOrDoubleArray &outtan = curve->getOutTangentValues(); - /* intangent */ + /* In-tangent. */ unsigned int index = 2 * (j * dim + i); bez.vec[0][0] = bc_get_float_value(intan, index) * fps; bez.vec[0][1] = bc_get_float_value(intan, index + 1); - /* outtangent */ + /* Out-tangent. */ bez.vec[2][0] = bc_get_float_value(outtan, index) * fps; bez.vec[2][1] = bc_get_float_value(outtan, index + 1); if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER) { diff --git a/source/blender/io/collada/ArmatureExporter.cpp b/source/blender/io/collada/ArmatureExporter.cpp index 9bf1a4ae830..28f5f9d40bc 100644 --- a/source/blender/io/collada/ArmatureExporter.cpp +++ b/source/blender/io/collada/ArmatureExporter.cpp @@ -197,7 +197,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, add_bone_transform(ob_arm, bone, node); - /* Write nodes of childobjects, remove written objects from list */ + /* Write nodes of child-objects, remove written objects from list. */ std::vector<Object *>::iterator iter = child_objects.begin(); while (iter != child_objects.end()) { @@ -219,7 +219,7 @@ void ArmatureExporter::add_bone_node(Bone *bone, * single matrix the tweak must be applied * to the result. */ if (export_settings.get_open_sim()) { - /* Tweak objects parentinverse to match compatibility. */ + /* Tweak objects parent-inverse to match compatibility. */ float temp[4][4]; copy_m4_m4(temp, bone->arm_mat); diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 7eef5c3f5fb..5c3d6be589a 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -1108,7 +1108,7 @@ BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, } if (!has_connect && this->import_settings->auto_connect) { - /* auto connect only whyen parent has exactly one child*/ + /* Auto connect only when parent has exactly one child. */ connect_type = sibcount == 1; } diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h index 27856dd55f4..a1597cd47be 100644 --- a/source/blender/io/collada/BCAnimationCurve.h +++ b/source/blender/io/collada/BCAnimationCurve.h @@ -133,7 +133,7 @@ class BCAnimationCurve { void get_frames(BCFrames &frames) const; - /* Curve edit functions create a copy of the underlaying FCurve */ + /* Curve edit functions create a copy of the underlying #FCurve. */ FCurve *get_edit_fcurve(); bool add_value_from_rna(const int frame); bool add_value_from_matrix(const BCSample &sample, const int frame); diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index a6ee0b8bee6..b2a9027380e 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -536,7 +536,7 @@ const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob) const return &sample->get_matrix(); } -/* Get the matrix for the given Bone, returns Unity when the Objewct is not sampled */ +/* Get the matrix for the given Bone, returns Unity when the Object is not sampled. */ const BCMatrix *BCSampleFrame::get_sample_matrix(Object *ob, Bone *bone) const { BCSampleMap::const_iterator it = sampleMap.find(ob); diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 10c1a90576c..259bf901091 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -275,15 +275,15 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = nullptr, Object *parob = nullptr) { - /* The split in T29246, rootmap must point at actual root when + /* The split in T29246, root_map must point at actual root when * calculating bones in apply_curves_as_matrix. - actual root is the root node. * This has to do with inverse bind poses being world space - * (the sources for skinned bones' restposes) and the way - * non-skinning nodes have their "restpose" recursively calculated. + * (the sources for skinned bones' rest-poses) and the way + * non-skinning nodes have their "rest-pose" recursively calculated. * XXX TODO: design issue, how to support unrelated joints taking * part in skinning. */ if (par) { // && par->getType() == COLLADAFW::Node::JOINT) { - /* par is root if there's no corresp. key in root_map */ + /* If par is root if there's no corresponding key in root_map. */ if (root_map.find(par->getUniqueId()) == root_map.end()) { root_map[node->getUniqueId()] = node; } @@ -942,7 +942,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) case CAM_PERSP: default: { double x = camera->getXFov().getValue(); - /* x is in degrees, cam->lens is in millimiters */ + /* X is in degrees, cam->lens is in millimeters. */ cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x); } break; } @@ -955,7 +955,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) case CAM_PERSP: default: { double yfov = camera->getYFov().getValue(); - /* yfov is in degrees, cam->lens is in millimiters */ + /* yfov is in degrees, cam->lens is in millimeters. */ cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x); } break; } diff --git a/source/blender/io/collada/DocumentImporter.h b/source/blender/io/collada/DocumentImporter.h index a23e983940e..a6ed014a33c 100644 --- a/source/blender/io/collada/DocumentImporter.h +++ b/source/blender/io/collada/DocumentImporter.h @@ -125,7 +125,7 @@ class DocumentImporter : COLLADAFW::IWriter { /** Add element and data for UniqueId */ bool addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags); - /** Get an extisting ExtraTags for uid */ + /** Get an existing #ExtraTags for uid */ ExtraTags *getExtraTags(const COLLADAFW::UniqueId &uid); bool is_armature(COLLADAFW::Node *node); diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 2934ea1caa6..172f9a468b4 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -693,7 +693,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) set_poly_indices(mpoly, mloop, loop_index, triangle_vertex_indices, 3); if (mp_has_normals) { /* vertex normals, same implementation as for the triangles */ - /* the same for vertces normals */ + /* The same for vertices normals. */ unsigned int vertex_normal_indices[3] = { first_normal, normal_indices[1], normal_indices[2]}; if (!is_flat_face(vertex_normal_indices, nor, 3)) { diff --git a/source/blender/io/common/IO_dupli_persistent_id.hh b/source/blender/io/common/IO_dupli_persistent_id.hh index 6fabafd9d51..afc539636ac 100644 --- a/source/blender/io/common/IO_dupli_persistent_id.hh +++ b/source/blender/io/common/IO_dupli_persistent_id.hh @@ -41,7 +41,7 @@ class PersistentID { PersistentID(); explicit PersistentID(const DupliObject *dupli_ob); - /* Return true iff the persistent IDs are the same, ignoring the first digit. */ + /* Return true if the persistent IDs are the same, ignoring the first digit. */ bool is_from_same_instancer_as(const PersistentID &other) const; /* Construct the persistent ID of this instance's instancer. */ diff --git a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc index eaa4d2fdde7..a33d636500f 100644 --- a/source/blender/io/common/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc @@ -400,7 +400,7 @@ static bool remove_weak_subtrees(const HierarchyContext *context, void AbstractHierarchyIterator::export_graph_prune() { - /* Take a copy of the map so that we can modify while recursing. */ + /* Take a copy of the map so that we can modify while recusing. */ ExportGraph unpruned_export_graph = export_graph_; remove_weak_subtrees(HierarchyContext::root(), export_graph_, unpruned_export_graph); } diff --git a/source/blender/io/common/intern/object_identifier_test.cc b/source/blender/io/common/intern/object_identifier_test.cc index 30e1e43d076..8d0800ce2cb 100644 --- a/source/blender/io/common/intern/object_identifier_test.cc +++ b/source/blender/io/common/intern/object_identifier_test.cc @@ -129,7 +129,7 @@ TEST_F(ObjectIdentifierOrderTest, duplicated_objects) EXPECT_FALSE(id_different_dupli_b < id_dupli_b); } -TEST_F(ObjectIdentifierOrderTest, behaviour_as_map_keys) +TEST_F(ObjectIdentifierOrderTest, behavior_as_map_keys) { ObjectIdentifier id_root = ObjectIdentifier::for_graph_root(); ObjectIdentifier id_another_root = ObjectIdentifier::for_graph_root(); diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt index 79b15c60b94..6ea30f48a13 100644 --- a/source/blender/io/usd/CMakeLists.txt +++ b/source/blender/io/usd/CMakeLists.txt @@ -30,6 +30,9 @@ if(WIN32) endif() add_definitions(-DPXR_STATIC) +# USD headers use deprecated TBB headers, silence warning. +add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1) + set(INC . ../common diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 263ce2203e9..00d0d4e3626 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -24,6 +24,7 @@ #pragma once +#include "DNA_ID_enums.h" #include "DNA_defs.h" #include "DNA_listBase.h" @@ -193,6 +194,10 @@ enum { IDOVERRIDE_LIBRARY_FLAG_MANDATORY = 1 << 0, /** User cannot change that override operation. */ IDOVERRIDE_LIBRARY_FLAG_LOCKED = 1 << 1, + + /** For overrides of ID pointers: this override still matches (follows) the hierarchy of the + * reference linked data. */ + IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE = 1 << 8, }; /** A single overridden property, contain all operations on this one. */ @@ -254,7 +259,7 @@ typedef struct IDOverrideLibrary { /** * ID is the first thing included in all serializable types. It * provides a common handle to place all data in double-linked lists. - * */ + */ /* 2 characters for ID code and 64 for actual name */ #define MAX_ID_NAME 66 @@ -363,13 +368,6 @@ typedef struct Library { short versionfile, subversionfile; } Library; -enum eIconSizes { - ICON_SIZE_ICON = 0, - ICON_SIZE_PREVIEW = 1, - - NUM_ICON_SIZES, -}; - /* for PreviewImage->flag */ enum ePreviewImage_Flag { PRV_CHANGED = (1 << 0), @@ -407,87 +405,6 @@ typedef struct PreviewImage { BLI_assert((prv)->tag & PRV_TAG_DEFFERED), \ (void *)((prv) + 1)) -/** - * Defines for working with IDs. - * - * The tags represent types! This is a dirty way of enabling RTTI. The - * sig_byte end endian defines aren't really used much. - */ - -#ifdef __BIG_ENDIAN__ -/* big endian */ -# define MAKE_ID2(c, d) ((c) << 8 | (d)) -#else -/* little endian */ -# define MAKE_ID2(c, d) ((d) << 8 | (c)) -#endif - -/** - * ID from database. - * - * Written to #BHead.code (for file IO) - * and the first 2 bytes of #ID.name (for runtime checks, see #GS macro). - */ -typedef enum ID_Type { - ID_SCE = MAKE_ID2('S', 'C'), /* Scene */ - ID_LI = MAKE_ID2('L', 'I'), /* Library */ - ID_OB = MAKE_ID2('O', 'B'), /* Object */ - ID_ME = MAKE_ID2('M', 'E'), /* Mesh */ - ID_CU = MAKE_ID2('C', 'U'), /* Curve */ - ID_MB = MAKE_ID2('M', 'B'), /* MetaBall */ - ID_MA = MAKE_ID2('M', 'A'), /* Material */ - ID_TE = MAKE_ID2('T', 'E'), /* Tex (Texture) */ - ID_IM = MAKE_ID2('I', 'M'), /* Image */ - ID_LT = MAKE_ID2('L', 'T'), /* Lattice */ - ID_LA = MAKE_ID2('L', 'A'), /* Light */ - ID_CA = MAKE_ID2('C', 'A'), /* Camera */ - ID_IP = MAKE_ID2('I', 'P'), /* Ipo (depreciated, replaced by FCurves) */ - ID_KE = MAKE_ID2('K', 'E'), /* Key (shape key) */ - ID_WO = MAKE_ID2('W', 'O'), /* World */ - ID_SCR = MAKE_ID2('S', 'R'), /* Screen */ - ID_VF = MAKE_ID2('V', 'F'), /* VFont (Vector Font) */ - ID_TXT = MAKE_ID2('T', 'X'), /* Text */ - ID_SPK = MAKE_ID2('S', 'K'), /* Speaker */ - ID_SO = MAKE_ID2('S', 'O'), /* Sound */ - ID_GR = MAKE_ID2('G', 'R'), /* Group */ - ID_AR = MAKE_ID2('A', 'R'), /* bArmature */ - ID_AC = MAKE_ID2('A', 'C'), /* bAction */ - ID_NT = MAKE_ID2('N', 'T'), /* bNodeTree */ - ID_BR = MAKE_ID2('B', 'R'), /* Brush */ - ID_PA = MAKE_ID2('P', 'A'), /* ParticleSettings */ - ID_GD = MAKE_ID2('G', 'D'), /* bGPdata, (Grease Pencil) */ - ID_WM = MAKE_ID2('W', 'M'), /* WindowManager */ - ID_MC = MAKE_ID2('M', 'C'), /* MovieClip */ - ID_MSK = MAKE_ID2('M', 'S'), /* Mask */ - ID_LS = MAKE_ID2('L', 'S'), /* FreestyleLineStyle */ - ID_PAL = MAKE_ID2('P', 'L'), /* Palette */ - ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */ - ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */ - ID_WS = MAKE_ID2('W', 'S'), /* WorkSpace */ - ID_LP = MAKE_ID2('L', 'P'), /* LightProbe */ - ID_HA = MAKE_ID2('H', 'A'), /* Hair */ - ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */ - ID_VO = MAKE_ID2('V', 'O'), /* Volume */ - ID_SIM = MAKE_ID2('S', 'I'), /* Simulation (currently unused) */ -} ID_Type; - -/* Only used as 'placeholder' in .blend files for directly linked data-blocks. */ -#define ID_LINK_PLACEHOLDER MAKE_ID2('I', 'D') /* (internal use only) */ - -/* Deprecated. */ -#define ID_SCRN MAKE_ID2('S', 'N') - -/* NOTE! Fake IDs, needed for g.sipo->blocktype or outliner */ -#define ID_SEQ MAKE_ID2('S', 'Q') -/* constraint */ -#define ID_CO MAKE_ID2('C', 'O') -/* pose (action channel, used to be ID_AC in code, so we keep code for backwards compat) */ -#define ID_PO MAKE_ID2('A', 'C') -/* used in outliner... */ -#define ID_NLA MAKE_ID2('N', 'L') -/* fluidsim Ipo */ -#define ID_FLUIDSIM MAKE_ID2('F', 'S') - #define ID_FAKE_USERS(id) ((((const ID *)id)->flag & LIB_FAKEUSER) ? 1 : 0) #define ID_REAL_USERS(id) (((const ID *)id)->us - ID_FAKE_USERS(id)) #define ID_EXTRA_USERS(id) (((const ID *)id)->tag & LIB_TAG_EXTRAUSER ? 1 : 0) @@ -510,6 +427,10 @@ typedef enum ID_Type { (ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0 && \ (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) +/* NOTE: The three checks below do not take into account whether given ID is linked or not (when + * chaining overrides over several libraries). User must ensure the ID is not linked itself + * currently. */ +/* TODO: add `_EDITABLE` versions of those macros (that would check if ID is linked or not)? */ #define ID_IS_OVERRIDE_LIBRARY_REAL(_id) \ (((const ID *)(_id))->override_library != NULL && \ ((const ID *)(_id))->override_library->reference != NULL) @@ -685,7 +606,7 @@ typedef enum IDRecalcFlag { * redraw update in that case. */ /* Selection of the ID itself or its components (for example, vertices) did - * change, and all the drawing data is to eb updated. */ + * change, and all the drawing data is to be updated. */ ID_RECALC_SELECT = (1 << 9), /* Flags on the base did change, and is to be copied onto all the copies of * corresponding objects. */ diff --git a/source/blender/makesdna/DNA_ID_enums.h b/source/blender/makesdna/DNA_ID_enums.h new file mode 100644 index 00000000000..04cbf51dd62 --- /dev/null +++ b/source/blender/makesdna/DNA_ID_enums.h @@ -0,0 +1,118 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup DNA + * \brief Enumerations for `DNA_ID.h`. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum eIconSizes { + ICON_SIZE_ICON = 0, + ICON_SIZE_PREVIEW = 1, + + NUM_ICON_SIZES, +}; + +/** + * Defines for working with IDs. + * + * The tags represent types! This is a dirty way of enabling RTTI. The + * sig_byte end endian defines aren't really used much. + */ + +#ifdef __BIG_ENDIAN__ +/* big endian */ +# define MAKE_ID2(c, d) ((c) << 8 | (d)) +#else +/* little endian */ +# define MAKE_ID2(c, d) ((d) << 8 | (c)) +#endif + +/** + * ID from database. + * + * Written to #BHead.code (for file IO) + * and the first 2 bytes of #ID.name (for runtime checks, see #GS macro). + */ +typedef enum ID_Type { + ID_SCE = MAKE_ID2('S', 'C'), /* Scene */ + ID_LI = MAKE_ID2('L', 'I'), /* Library */ + ID_OB = MAKE_ID2('O', 'B'), /* Object */ + ID_ME = MAKE_ID2('M', 'E'), /* Mesh */ + ID_CU = MAKE_ID2('C', 'U'), /* Curve */ + ID_MB = MAKE_ID2('M', 'B'), /* MetaBall */ + ID_MA = MAKE_ID2('M', 'A'), /* Material */ + ID_TE = MAKE_ID2('T', 'E'), /* Tex (Texture) */ + ID_IM = MAKE_ID2('I', 'M'), /* Image */ + ID_LT = MAKE_ID2('L', 'T'), /* Lattice */ + ID_LA = MAKE_ID2('L', 'A'), /* Light */ + ID_CA = MAKE_ID2('C', 'A'), /* Camera */ + ID_IP = MAKE_ID2('I', 'P'), /* Ipo (depreciated, replaced by FCurves) */ + ID_KE = MAKE_ID2('K', 'E'), /* Key (shape key) */ + ID_WO = MAKE_ID2('W', 'O'), /* World */ + ID_SCR = MAKE_ID2('S', 'R'), /* Screen */ + ID_VF = MAKE_ID2('V', 'F'), /* VFont (Vector Font) */ + ID_TXT = MAKE_ID2('T', 'X'), /* Text */ + ID_SPK = MAKE_ID2('S', 'K'), /* Speaker */ + ID_SO = MAKE_ID2('S', 'O'), /* Sound */ + ID_GR = MAKE_ID2('G', 'R'), /* Collection */ + ID_AR = MAKE_ID2('A', 'R'), /* bArmature */ + ID_AC = MAKE_ID2('A', 'C'), /* bAction */ + ID_NT = MAKE_ID2('N', 'T'), /* bNodeTree */ + ID_BR = MAKE_ID2('B', 'R'), /* Brush */ + ID_PA = MAKE_ID2('P', 'A'), /* ParticleSettings */ + ID_GD = MAKE_ID2('G', 'D'), /* bGPdata, (Grease Pencil) */ + ID_WM = MAKE_ID2('W', 'M'), /* WindowManager */ + ID_MC = MAKE_ID2('M', 'C'), /* MovieClip */ + ID_MSK = MAKE_ID2('M', 'S'), /* Mask */ + ID_LS = MAKE_ID2('L', 'S'), /* FreestyleLineStyle */ + ID_PAL = MAKE_ID2('P', 'L'), /* Palette */ + ID_PC = MAKE_ID2('P', 'C'), /* PaintCurve */ + ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */ + ID_WS = MAKE_ID2('W', 'S'), /* WorkSpace */ + ID_LP = MAKE_ID2('L', 'P'), /* LightProbe */ + ID_HA = MAKE_ID2('H', 'A'), /* Hair */ + ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */ + ID_VO = MAKE_ID2('V', 'O'), /* Volume */ + ID_SIM = MAKE_ID2('S', 'I'), /* Simulation (geometry node groups) */ +} ID_Type; + +/* Only used as 'placeholder' in .blend files for directly linked data-blocks. */ +#define ID_LINK_PLACEHOLDER MAKE_ID2('I', 'D') /* (internal use only) */ + +/* Deprecated. */ +#define ID_SCRN MAKE_ID2('S', 'N') + +/* NOTE: Fake IDs, needed for `g.sipo->blocktype` or outliner. */ +#define ID_SEQ MAKE_ID2('S', 'Q') +/* constraint */ +#define ID_CO MAKE_ID2('C', 'O') +/* pose (action channel, used to be ID_AC in code, so we keep code for backwards compatible). */ +#define ID_PO MAKE_ID2('A', 'C') +/* used in outliner... */ +#define ID_NLA MAKE_ID2('N', 'L') +/* fluidsim Ipo */ +#define ID_FLUIDSIM MAKE_ID2('F', 'S') + +#ifdef __cplusplus +} +#endif diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 790a7a36288..96245e3b067 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -676,6 +676,8 @@ typedef struct bAction { */ int idroot; char _pad[4]; + + PreviewImage *preview; } bAction; /* Flags for the action */ diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index 1eafa655195..c66618c0acd 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -438,9 +438,10 @@ typedef enum eDriverVar_Types { /** 'final' transform for object/bones */ DVAR_TYPE_TRANSFORM_CHAN, - /** Maximum number of variable types. + /** + * Maximum number of variable types. * - * \note This must always be th last item in this list, + * \note This must always be the last item in this list, * so add new types above this line. */ MAX_DVAR_TYPES, diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h index f12934c9104..093a1a00ece 100644 --- a/source/blender/makesdna/DNA_brush_enums.h +++ b/source/blender/makesdna/DNA_brush_enums.h @@ -75,6 +75,10 @@ typedef enum eGPDbrush_Flag { GP_BRUSH_USE_STRENGTH_PRESSURE = (1 << 1), /* brush use pressure for alpha factor */ GP_BRUSH_USE_JITTER_PRESSURE = (1 << 2), + /* Disable automatic zoom for filling. */ + GP_BRUSH_FILL_FIT_DISABLE = (1 << 3), + /* Show extend fill help lines. */ + GP_BRUSH_FILL_SHOW_EXTENDLINES = (1 << 4), /* fill hide transparent */ GP_BRUSH_FILL_HIDE = (1 << 6), /* show fill help lines */ diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 4b020019062..a11e7d77c67 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -50,7 +50,8 @@ typedef struct BrushClone { typedef struct BrushGpencilSettings { /** Amount of smoothing to apply to newly created strokes. */ float draw_smoothfac; - char _pad2[4]; + /** Fill zoom factor */ + float fill_factor; /** Amount of alpha strength to apply to newly created strokes. */ float draw_strength; /** Amount of jitter to apply to newly created strokes. */ @@ -75,8 +76,8 @@ typedef struct BrushGpencilSettings { float fill_threshold; /** Number of pixel to consider the leak is too small (x 2). */ short fill_leak; - /** Fill zoom factor */ - short fill_factor; + char _pad2[2]; + int flag2; /** Number of simplify steps. */ @@ -130,6 +131,10 @@ typedef struct BrushGpencilSettings { /** Randomness for Value. */ float random_value; + /** Factor to extend stroke extremes using fill tool. */ + float fill_extend_fac; + char _pad3[4]; + struct CurveMapping *curve_sensitivity; struct CurveMapping *curve_strength; struct CurveMapping *curve_jitter; @@ -286,7 +291,7 @@ typedef struct Brush { int curve_preset; - /* Maximun distance to search fake neighbors from a vertex. */ + /* Maximum distance to search fake neighbors from a vertex. */ float disconnected_distance_max; int deform_target; diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 467174c4f32..1eff7be3f15 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -166,7 +166,7 @@ typedef struct ClothSimSettings { /** Mechanical damping of shear springs. */ float shear_damp; - /** The maximum lenght an internal spring can have during creation. */ + /** The maximum length an internal spring can have during creation. */ float internal_spring_max_length; /** How much the interal spring can diverge from the vertex normal during creation. */ float internal_spring_max_diversion; diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index c8e09225432..e3dcd283efa 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -242,10 +242,12 @@ typedef struct DynamicPaintBrushSettings { /** For fast RNA access. */ struct DynamicPaintModifierData *pmd; - /* NOTE: Storing the particle system pointer here is very weak, as it prevents modfiers' data + /** + * \note Storing the particle system pointer here is very weak, as it prevents modifiers' data * copying to be self-sufficient (extra external code needs to ensure the pointer remains valid * when the modifier data is copied from one object to another). See e.g. - * `BKE_object_copy_particlesystems` or `BKE_object_copy_modifier`. */ + * `BKE_object_copy_particlesystems` or `BKE_object_copy_modifier`. + */ struct ParticleSystem *psys; int flags; diff --git a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h index fdb77bfd196..399bf6f0a6d 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_defaults.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_defaults.h @@ -152,6 +152,7 @@ .factor_thickness = 0.0f, \ .factor_uvs = 0.0f, \ .noise_scale = 0.0f, \ + .noise_offset = 0.0f, \ .step = 4, \ .layer_pass = 0, \ .seed = 1, \ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index 9ac40495887..b2d62e0a5f6 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -107,6 +107,8 @@ typedef struct NoiseGpencilModifierData { float factor_uvs; /** Noise Frequency scaling */ float noise_scale; + float noise_offset; + char _pad[4]; /** How many frames before recalculate randoms. */ int step; /** Custom index for passes. */ @@ -180,7 +182,7 @@ typedef struct ThickGpencilModifierData { int flag; /** Relative thickness factor. */ float thickness_fac; - /** Absolute thickness overide. */ + /** Absolute thickness override. */ int thickness; /** Custom index for passes. */ int layer_pass; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 949b0bb5bf5..e02757c1249 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -45,6 +45,9 @@ struct MDeformVert; #define GP_DEFAULT_CURVE_ERROR 0.1f #define GP_DEFAULT_CURVE_EDIT_CORNER_ANGLE M_PI_2 +#define GPENCIL_MIN_FILL_FAC 0.05f +#define GPENCIL_MAX_FILL_FAC 5.0f + /* ***************************************** */ /* GP Stroke Points */ @@ -512,6 +515,11 @@ typedef struct bGPDlayer { int act_mask; char _pad2[4]; + /** Layer transforms. */ + float location[3], rotation[3], scale[3]; + float layer_mat[4][4], layer_invmat[4][4]; + char _pad3[4]; + bGPDlayer_Runtime runtime; } bGPDlayer; @@ -574,7 +582,9 @@ typedef struct bGPdata_Runtime { /** Temp stroke used for drawing. */ struct bGPDstroke *sbuffer_gps; - char _pad[2]; + /** Animation playing flag. */ + short playing; + /** Material index of the stroke. */ short matid; @@ -802,8 +812,9 @@ typedef enum eGP_DrawMode { /* Check if 'multiedit sessions' is enabled */ #define GPENCIL_MULTIEDIT_SESSIONS_ON(gpd) \ ((gpd) && \ - ((gpd)->flag & (GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | \ - GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE)) && \ + ((gpd)->flag & \ + (GP_DATA_STROKE_PAINTMODE | GP_DATA_STROKE_EDITMODE | GP_DATA_STROKE_SCULPTMODE | \ + GP_DATA_STROKE_WEIGHTMODE | GP_DATA_STROKE_VERTEXMODE)) && \ ((gpd)->flag & GP_DATA_STROKE_MULTIEDIT)) #define GPENCIL_CURVE_EDIT_SESSIONS_ON(gpd) \ @@ -840,6 +851,8 @@ typedef enum eGP_DrawMode { ((flag & (GP_VERTEX_MASK_SELECTMODE_POINT | GP_VERTEX_MASK_SELECTMODE_STROKE | \ GP_VERTEX_MASK_SELECTMODE_SEGMENT))) +#define GPENCIL_PLAY_ON(gpd) ((gpd) && ((gpd)->runtime.playing == 1)) + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 780115a31be..05be31262a6 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -271,6 +271,9 @@ typedef struct MIntProperty { typedef struct MStringProperty { char s[255], s_len; } MStringProperty; +typedef struct MBoolProperty { + uint8_t b; +} MBoolProperty; /** \} */ @@ -414,7 +417,6 @@ typedef struct OrigSpaceLoop { typedef struct FreestyleEdge { char flag; - char _pad[3]; } FreestyleEdge; /** #FreestyleEdge.flag */ @@ -424,7 +426,6 @@ enum { typedef struct FreestyleFace { char flag; - char _pad[3]; } FreestyleFace; /** #FreestyleFace.flag */ diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 8601dcf76ac..9335c360363 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -236,7 +236,7 @@ .flag = 0, \ } -/* Defines are scattered accross too many files, they need to be moved to DNA. */ +/* Defines are scattered across too many files, they need to be moved to DNA. */ #if 0 #define _DNA_DEFAULT_DataTransferModifierData \ { \ @@ -440,7 +440,7 @@ .renderlvl = 0, \ .totlvl = 0, \ .flags = eMultiresModifierFlag_UseCrease | eMultiresModifierFlag_ControlEdges, \ - .uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS, \ + .uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES, \ .quality = 4, \ .boundary_smooth = SUBSURF_BOUNDARY_SMOOTH_ALL, \ } @@ -622,7 +622,7 @@ .levels = 1, \ .renderLevels = 2, \ .flags = eSubsurfModifierFlag_UseCrease | eSubsurfModifierFlag_ControlEdges, \ - .uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS, \ + .uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES, \ .quality = 3, \ .boundary_smooth = SUBSURF_BOUNDARY_SMOOTH_ALL, \ .emCache = NULL, \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 3de4299e0bd..29421430e5d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -984,10 +984,12 @@ enum { typedef struct ParticleSystemModifierData { ModifierData modifier; - /* NOTE: Storing the particle system pointer here is very weak, as it prevents modfiers' data + /** + * \note Storing the particle system pointer here is very weak, as it prevents modifiers' data * copying to be self-sufficient (extra external code needs to ensure the pointer remains valid * when the modifier data is copied from one object to another). See e.g. - * `BKE_object_copy_particlesystems` or `BKE_object_copy_modifier`. */ + * `BKE_object_copy_particlesystems` or `BKE_object_copy_modifier`. + */ struct ParticleSystem *psys; /** Final Mesh - its topology may differ from orig mesh. */ struct Mesh *mesh_final; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 7d18ff3ed58..43c5fa81651 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -118,7 +118,9 @@ typedef struct bNodeSocket { /* XXX deprecated, kept for forward compatibility */ short stack_type DNA_DEPRECATED; char display_shape; - char _pad[3]; + char _pad[1]; + /* Runtime-only cache of the number of input links, for multi-input sockets. */ + short total_inputs; /** Custom dynamic defined label, MAX_NAME. */ char label[64]; @@ -200,6 +202,8 @@ typedef enum eNodeSocketFlag { SOCK_NO_INTERNAL_LINK = (1 << 9), /** Draw socket in a more compact form. */ SOCK_COMPACT = (1 << 10), + /** Make the input socket accept multiple incoming links in the UI. */ + SOCK_MULTI_INPUT = (1 << 11), } eNodeSocketFlag; /* limit data in bNode to what we want to see saved? */ @@ -389,13 +393,15 @@ typedef struct bNodeLink { bNodeSocket *fromsock, *tosock; int flag; - char _pad[4]; + /* A runtime storage for automatically sorted links to multi-input sockets. */ + int multi_input_socket_index; } bNodeLink; /* link->flag */ #define NODE_LINKFLAG_HILITE (1 << 0) /* link has been successfully validated */ #define NODE_LINK_VALID (1 << 1) -#define NODE_LINK_TEST (1 << 2) /* free test flag, undefined */ +#define NODE_LINK_TEST (1 << 2) /* free test flag, undefined */ +#define NODE_LINK_TEMP_HIGHLIGHT (1 << 3) /* Link is highlighted for picking. */ /* tree->edit_quality/tree->render_quality */ #define NTREE_QUALITY_HIGH 0 @@ -549,7 +555,6 @@ typedef struct bNodeSocketValueFloat { typedef struct bNodeSocketValueBoolean { char value; - char _pad[3]; } bNodeSocketValueBoolean; typedef struct bNodeSocketValueVector { @@ -829,7 +834,6 @@ typedef struct NodeColorspill { typedef struct NodeDilateErode { char falloff; - char _pad[7]; } NodeDilateErode; typedef struct NodeMask { @@ -838,7 +842,6 @@ typedef struct NodeMask { typedef struct NodeSetAlpha { char mode; - char _pad[7]; } NodeSetAlpha; typedef struct NodeTexBase { @@ -995,7 +998,6 @@ typedef struct NodeTrackPosData { typedef struct NodeTranslateData { char wrap_axis; char relative; - char _pad[6]; } NodeTranslateData; typedef struct NodePlaneTrackDeformData { @@ -1074,7 +1076,6 @@ typedef struct NodeCryptomatte { typedef struct NodeDenoise { char hdr; - char _pad[7]; } NodeDenoise; typedef struct NodeAttributeCompare { @@ -1089,14 +1090,13 @@ typedef struct NodeAttributeCompare { } NodeAttributeCompare; typedef struct NodeAttributeMath { - /* e.g. NODE_MATH_ADD. */ + /* NodeMathOperation. */ uint8_t operation; /* GeometryNodeAttributeInputMode */ uint8_t input_type_a; uint8_t input_type_b; - - char _pad[5]; + uint8_t input_type_c; } NodeAttributeMath; typedef struct NodeAttributeMix { @@ -1117,8 +1117,6 @@ typedef struct NodeAttributeVectorMath { uint8_t input_type_a; uint8_t input_type_b; uint8_t input_type_c; - - char _pad[4]; } NodeAttributeVectorMath; typedef struct NodeAttributeColorRamp { @@ -1145,35 +1143,72 @@ typedef struct NodeGeometryRotatePoints { typedef struct NodeGeometryAlignRotationToVector { /* GeometryNodeAlignRotationToVectorAxis */ uint8_t axis; + /* GeometryNodeAlignRotationToVectorPivotAxis */ + uint8_t pivot_axis; /* GeometryNodeAttributeInputMode */ uint8_t input_type_factor; uint8_t input_type_vector; - - char _pad[5]; } NodeGeometryAlignRotationToVector; typedef struct NodeGeometryPointScale { /* GeometryNodeAttributeInputMode */ uint8_t input_type; - - char _pad[7]; } NodeGeometryPointScale; typedef struct NodeGeometryPointTranslate { /* GeometryNodeAttributeInputMode */ uint8_t input_type; - - char _pad[7]; } NodeGeometryPointTranslate; typedef struct NodeGeometryObjectInfo { /* GeometryNodeTransformSpace. */ uint8_t transform_space; - - char _pad[7]; } NodeGeometryObjectInfo; +typedef struct NodeGeometryPointInstance { + /* GeometryNodePointInstanceType. */ + uint8_t instance_type; + /* GeometryNodePointInstanceFlag. */ + uint8_t flag; +} NodeGeometryPointInstance; + +typedef struct NodeGeometryPointsToVolume { + /* GeometryNodePointsToVolumeResolutionMode */ + uint8_t resolution_mode; + /* GeometryNodeAttributeInputMode */ + uint8_t input_type_radius; +} NodeGeometryPointsToVolume; + +typedef struct NodeGeometryCollectionInfo { + /* GeometryNodeTransformSpace. */ + uint8_t transform_space; +} NodeGeometryCollectionInfo; + +typedef struct NodeGeometryAttributeProximity { + /* GeometryNodeAttributeProximityTargetGeometryElement. */ + uint8_t target_geometry_element; +} NodeGeometryAttributeProximity; + +typedef struct NodeGeometryVolumeToMesh { + /* VolumeToMeshResolutionMode */ + uint8_t resolution_mode; +} NodeGeometryVolumeToMesh; + +typedef struct NodeAttributeCombineXYZ { + /* GeometryNodeAttributeInputMode. */ + uint8_t input_type_x; + uint8_t input_type_y; + uint8_t input_type_z; + + char _pad[1]; +} NodeAttributeCombineXYZ; + +typedef struct NodeAttributeSeparateXYZ { + /* GeometryNodeAttributeInputMode. */ + uint8_t input_type; +} NodeAttributeSeparateXYZ; + /* script node mode */ #define NODE_SCRIPT_INTERNAL 0 #define NODE_SCRIPT_EXTERNAL 1 @@ -1369,7 +1404,7 @@ enum { #define SHD_MATH_CLAMP 1 /* Math node operations. */ -enum { +typedef enum NodeMathOperation { NODE_MATH_ADD = 0, NODE_MATH_SUBTRACT = 1, NODE_MATH_MULTIPLY = 2, @@ -1410,7 +1445,7 @@ enum { NODE_MATH_PINGPONG = 37, NODE_MATH_SMOOTH_MIN = 38, NODE_MATH_SMOOTH_MAX = 39, -}; +} NodeMathOperation; /* Vector Math node operations. */ typedef enum NodeVectorMathOperation { @@ -1561,6 +1596,12 @@ typedef enum NodeShaderOutputTarget { /* Geometry Nodes */ +typedef enum GeometryNodeAttributeProximityTargetGeometryElement { + GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS = 0, + GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES = 1, + GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES = 2, +} GeometryNodeAttributeProximityTargetGeometryElement; + /* Boolean Node */ typedef enum GeometryNodeBooleanOperation { GEO_NODE_BOOLEAN_INTERSECT = 0, @@ -1586,6 +1627,10 @@ typedef enum GeometryNodePointInstanceType { GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION = 1, } GeometryNodePointInstanceType; +typedef enum GeometryNodePointInstanceFlag { + GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION = (1 << 0), +} GeometryNodePointInstanceFlag; + typedef enum GeometryNodeAttributeInputMode { GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE = 0, GEO_NODE_ATTRIBUTE_INPUT_FLOAT = 1, @@ -1615,11 +1660,23 @@ typedef enum GeometryNodeAlignRotationToVectorAxis { GEO_NODE_ALIGN_ROTATION_TO_VECTOR_AXIS_Z = 2, } GeometryNodeAlignRotationToVectorAxis; +typedef enum GeometryNodeAlignRotationToVectorPivotAxis { + GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO = 0, + GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_X = 1, + GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Y = 2, + GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Z = 3, +} GeometryNodeAlignRotationToVectorPivotAxis; + typedef enum GeometryNodeTransformSpace { GEO_NODE_TRANSFORM_SPACE_ORIGINAL = 0, GEO_NODE_TRANSFORM_SPACE_RELATIVE = 1, } GeometryNodeTransformSpace; +typedef enum GeometryNodePointsToVolumeResolutionMode { + GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT = 0, + GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE = 1, +} GeometryNodePointsToVolumeResolutionMode; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h index 8a8a40a5069..16129768b60 100644 --- a/source/blender/makesdna/DNA_outliner_types.h +++ b/source/blender/makesdna/DNA_outliner_types.h @@ -72,53 +72,55 @@ enum { }; /** #TreeStoreElem.types */ -#define TSE_NLA 1 /* NO ID */ -#define TSE_NLA_ACTION 2 -#define TSE_DEFGROUP_BASE 3 -#define TSE_DEFGROUP 4 -#define TSE_BONE 5 -#define TSE_EBONE 6 -#define TSE_CONSTRAINT_BASE 7 -#define TSE_CONSTRAINT 8 -#define TSE_MODIFIER_BASE 9 -#define TSE_MODIFIER 10 -#define TSE_LINKED_OB 11 -/* #define TSE_SCRIPT_BASE 12 */ /* UNUSED */ -#define TSE_POSE_BASE 13 -#define TSE_POSE_CHANNEL 14 -#define TSE_ANIM_DATA 15 -#define TSE_DRIVER_BASE 16 /* NO ID */ -/* #define TSE_DRIVER 17 */ /* UNUSED */ +typedef enum eTreeStoreElemType { + TSE_NLA = 1, /* NO ID */ + TSE_NLA_ACTION = 2, + TSE_DEFGROUP_BASE = 3, + TSE_DEFGROUP = 4, + TSE_BONE = 5, + TSE_EBONE = 6, + TSE_CONSTRAINT_BASE = 7, + TSE_CONSTRAINT = 8, + TSE_MODIFIER_BASE = 9, + TSE_MODIFIER = 10, + TSE_LINKED_OB = 11, + /* TSE_SCRIPT_BASE = 12, */ /* UNUSED */ + TSE_POSE_BASE = 13, + TSE_POSE_CHANNEL = 14, + TSE_ANIM_DATA = 15, + TSE_DRIVER_BASE = 16, /* NO ID */ + /* TSE_DRIVER = 17, */ /* UNUSED */ -#define TSE_PROXY 18 -#define TSE_R_LAYER_BASE 19 -#define TSE_R_LAYER 20 -/* #define TSE_R_PASS 21 */ /* UNUSED */ -#define TSE_LINKED_MAT 22 -/* NOTE, is used for light group */ -#define TSE_LINKED_LAMP 23 -#define TSE_POSEGRP_BASE 24 -#define TSE_POSEGRP 25 -#define TSE_SEQUENCE 26 /* NO ID */ -#define TSE_SEQ_STRIP 27 /* NO ID */ -#define TSE_SEQUENCE_DUP 28 /* NO ID */ -#define TSE_LINKED_PSYS 29 -#define TSE_RNA_STRUCT 30 /* NO ID */ -#define TSE_RNA_PROPERTY 31 /* NO ID */ -#define TSE_RNA_ARRAY_ELEM 32 /* NO ID */ -#define TSE_NLA_TRACK 33 /* NO ID */ -#define TSE_KEYMAP 34 /* NO ID */ -#define TSE_KEYMAP_ITEM 35 /* NO ID */ -#define TSE_ID_BASE 36 /* NO ID */ -#define TSE_GP_LAYER 37 /* NO ID */ -#define TSE_LAYER_COLLECTION 38 -#define TSE_SCENE_COLLECTION_BASE 39 -#define TSE_VIEW_COLLECTION_BASE 40 -#define TSE_SCENE_OBJECTS_BASE 41 -#define TSE_GPENCIL_EFFECT_BASE 42 -#define TSE_GPENCIL_EFFECT 43 -#define TSE_LIBRARY_OVERRIDE_BASE 44 -#define TSE_LIBRARY_OVERRIDE 45 + TSE_PROXY = 18, + TSE_R_LAYER_BASE = 19, + TSE_R_LAYER = 20, + /* TSE_R_PASS = 21, */ /* UNUSED */ + /* TSE_LINKED_MAT = 22, */ + /* NOTE, is used for light group */ + /* TSE_LINKED_LAMP = 23, */ + TSE_POSEGRP_BASE = 24, + TSE_POSEGRP = 25, + TSE_SEQUENCE = 26, /* NO ID */ + TSE_SEQ_STRIP = 27, /* NO ID */ + TSE_SEQUENCE_DUP = 28, /* NO ID */ + TSE_LINKED_PSYS = 29, + TSE_RNA_STRUCT = 30, /* NO ID */ + TSE_RNA_PROPERTY = 31, /* NO ID */ + TSE_RNA_ARRAY_ELEM = 32, /* NO ID */ + TSE_NLA_TRACK = 33, /* NO ID */ + /* TSE_KEYMAP = 34, */ /* UNUSED */ + /* TSE_KEYMAP_ITEM = 35, */ /* UNUSED */ + TSE_ID_BASE = 36, /* NO ID */ + TSE_GP_LAYER = 37, /* NO ID */ + TSE_LAYER_COLLECTION = 38, + TSE_SCENE_COLLECTION_BASE = 39, + TSE_VIEW_COLLECTION_BASE = 40, + TSE_SCENE_OBJECTS_BASE = 41, + TSE_GPENCIL_EFFECT_BASE = 42, + TSE_GPENCIL_EFFECT = 43, + TSE_LIBRARY_OVERRIDE_BASE = 44, + TSE_LIBRARY_OVERRIDE = 45, +} eTreeStoreElemType; /** Check whether given #TreeStoreElem should have a real ID in #TreeStoreElem.id member. */ #define TSE_IS_REAL_ID(_tse) \ @@ -132,8 +134,6 @@ enum { TSE_RNA_STRUCT, \ TSE_RNA_PROPERTY, \ TSE_RNA_ARRAY_ELEM, \ - TSE_KEYMAP, \ - TSE_KEYMAP_ITEM, \ TSE_ID_BASE, \ TSE_GP_LAYER)) diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 03f5d3f8d47..51f8b58da62 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -63,6 +63,9 @@ struct wmTimer; /* Defined in `buttons_intern.h`. */ typedef struct SpaceProperties_Runtime SpaceProperties_Runtime; +/* Defined in `node_intern.h`. */ +typedef struct SpaceNode_Runtime SpaceNode_Runtime; + /* -------------------------------------------------------------------- */ /** \name SpaceLink (Base) * \{ */ @@ -1084,6 +1087,8 @@ typedef struct FileDirEntry { struct FileDirEntry *next, *prev; int uuid[4]; + /* Name needs freeing if FILE_ENTRY_NAME_FREE is set. Otherwise this is a direct pointer to a + * name buffer. */ char *name; char *description; @@ -1162,6 +1167,7 @@ enum { /* FileDirEntry.flags */ enum { FILE_ENTRY_INVALID_PREVIEW = 1 << 0, /* The preview for this entry could not be generated. */ + FILE_ENTRY_NAME_FREE = 1 << 1, }; /** \} */ @@ -1518,19 +1524,17 @@ typedef struct SpaceNode { /** Context, no need to save in file? well... pinning... */ struct ID *id, *from; - /** Menunr: browse id block in header. */ + short flag; - char _pad1[2]; - /** Internal state variables. */ - float aspect; - char _pad2[4]; + + /** Direction for offsetting nodes on insertion. */ + char insert_ofs_dir; + char _pad1; /** Offset for drawing the backdrop. */ float xof, yof; /** Zoom for backdrop. */ float zoom; - /** Mouse pos for drawing socketless link and adding nodes. */ - float cursor[2]; /** * XXX nodetree pointer info is all in the path stack now, @@ -1541,33 +1545,25 @@ typedef struct SpaceNode { */ ListBase treepath; - struct bNodeTree *nodetree, *edittree; + /* The tree farthest down in the group heirarchy. */ + struct bNodeTree *edittree; + + struct bNodeTree *nodetree; /* tree type for the current node tree */ char tree_idname[64]; /** Treetype: as same nodetree->type. */ int treetype DNA_DEPRECATED; - char _pad3[4]; /** Texfrom object, world or brush. */ short texfrom; /** Shader from object or world. */ short shaderfrom; - /** Currently on 0/1, for auto compo. */ - short recalc; - - /** Direction for offsetting nodes on insertion. */ - char insert_ofs_dir; - char _pad4; - - /** Temporary data for modal linking operator. */ - ListBase linkdrag; - /* XXX hack for translate_attach op-macros to pass data from transform op to insert_offset op */ - /** Temporary data for node insert offset (in UI called Auto-offset). */ - struct NodeInsertOfsData *iofsd; /** Grease-pencil data. */ struct bGPdata *gpd; + + SpaceNode_Runtime *runtime; } SpaceNode; /* SpaceNode.flag */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index 5b6b706c83c..f08aee317a3 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -141,7 +141,7 @@ typedef struct MovieTrackingTrack { /** Count of markers in track. */ int markersnr; /** Most recently used marker. */ - int last_marker; + int _pad; /** Markers in track. */ MovieTrackingMarker *markers; @@ -251,8 +251,6 @@ typedef struct MovieTrackingPlaneTrack { } MovieTrackingPlaneTrack; typedef struct MovieTrackingSettings { - int flag; - /* ** default tracker settings */ /** Model of the motion for this track. */ short default_motion_model; @@ -309,8 +307,6 @@ typedef struct MovieTrackingSettings { /* set object scale */ /** Distance between two bundles used for object scaling. */ float object_distance; - - char _pad3[4]; } MovieTrackingSettings; typedef struct MovieTrackingStabilization { @@ -526,12 +522,6 @@ typedef enum eTrackFrameMatch { TRACK_MATCH_PREVIOS_FRAME = 1, } eTrackFrameMatch; -/* MovieTrackingSettings->flag */ -enum { - TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED = (1 << 0), - TRACKING_SETTINGS_SHOW_EXTRA_EXPANDED = (1 << 1), -}; - /* MovieTrackingSettings->motion_flag */ enum { TRACKING_MOTION_TRIPOD = (1 << 0), diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index f620602f051..0e31ec3494e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -762,8 +762,12 @@ typedef struct UserDef { char _pad13[4]; struct SolidLight light_param[4]; float light_ambient[3]; - char _pad3[4]; - short gizmo_flag, gizmo_size; + char gizmo_flag; + /** Generic gizmo size. */ + char gizmo_size; + /** Navigate gizmo size. */ + char gizmo_size_navigate_v3d; + char _pad3[5]; short edit_studio_light; short lookdev_sphere_size; short vbotimeout, vbocollectrate; @@ -1009,8 +1013,11 @@ typedef enum ePathCompare_Flag { /** #UserDef.viewzoom */ typedef enum eViewZoom_Style { - USER_ZOOM_CONT = 0, + /** Update zoom continuously with a timer while dragging the cursor. */ + USER_ZOOM_CONTINUE = 0, + /** Map changes in distance from the view center to zoom. */ USER_ZOOM_SCALE = 1, + /** Map horizontal/vertical motion to zoom. */ USER_ZOOM_DOLLY = 2, } eViewZoom_Style; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index f07af2c14a0..a3aaf3ee937 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -215,7 +215,7 @@ enum { (WM_OUTLINER_SYNC_SELECT_FROM_OBJECT | WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE | \ WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE | WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE) -#define WM_KEYCONFIG_STR_DEFAULT "blender" +#define WM_KEYCONFIG_STR_DEFAULT "Blender" /* IME is win32 only! */ #if !defined(WIN32) && !defined(DNA_DEPRECATED) diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index eb7779213fd..db34cf83fa9 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -48,12 +48,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c ) -if(WIN32 AND NOT UNIX) - list(APPEND SRC - ../../../../intern/guardedalloc/intern/mmap_win.c - ) -endif() - # SRC_DNA_INC is defined in the parent dir add_cc_flags_custom_test(makesdna) diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 54d2bc88d16..7624649bf78 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -397,13 +397,11 @@ static int add_type(const char *str, int size) } /** - * * Because of the weird way of tokenizing, we have to 'cast' function * pointers to ... (*f)(), whatever the original signature. In fact, * we add name and type at the same time... There are two special * cases, unfortunately. These are explicitly checked. - * - * */ + */ static int add_name(const char *str) { char buf[255]; /* stupid limit, change it :) */ @@ -479,17 +477,16 @@ static int add_name(const char *str) } /* - * Put )(void) at the end? Maybe )(). Should check this with - * old sdna. Actually, sometimes )(), sometimes )(void...) + * Put `)(void)` at the end? Maybe `)()`. Should check this with + * old `sdna`. Actually, sometimes `)()`, sometimes `)(void...)` * Alas.. such is the nature of brain-damage :( * - * Sorted it out: always do )(), except for headdraw and - * windraw, part of ScrArea. This is important, because some + * Sorted it out: always do )(), except for `headdraw` and + * `windraw`, part of #ScrArea. This is important, because some * linkers will treat different fp's differently when called * !!! This has to do with interference in byte-alignment and - * the way args are pushed on the stack. - * - * */ + * the way arguments are pushed on the stack. + */ buf[i] = 0; DEBUG_PRINTF(3, "Name before chomping: %s\n", buf); if ((strncmp(buf, "(*headdraw", 10) == 0) || (strncmp(buf, "(*windraw", 9) == 0)) { @@ -1077,7 +1074,7 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char } } - if (size_native % 4) { + if (size_native % 4 && !ELEM(size_native, 1, 2)) { fprintf(stderr, "Sizeerror 4 in struct: %s (add %d bytes)\n", types[structtype], diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 35b174f0da8..eaa2675573c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -91,6 +91,7 @@ extern StructRNA RNA_BoidSettings; extern StructRNA RNA_BoidState; extern StructRNA RNA_Bone; extern StructRNA RNA_BoneGroup; +extern StructRNA RNA_BoolAttribute; extern StructRNA RNA_BoolProperty; extern StructRNA RNA_BooleanModifier; extern StructRNA RNA_Brush; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 72cdaecb2c3..94cfd8464ae 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -189,7 +189,6 @@ set(SRC ../../../../intern/guardedalloc/intern/mallocn.c ../../../../intern/guardedalloc/intern/mallocn_guarded_impl.c ../../../../intern/guardedalloc/intern/mallocn_lockfree_impl.c - ../../../../intern/guardedalloc/intern/mmap_win.c # Needed for defaults. ../../../../release/datafiles/userdef/userdef_default.c diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index e9e00ff6f71..bec3db10905 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4758,8 +4758,14 @@ static const char *cpp_classes = "class CollectionIterator {\n" "public:\n" " CollectionIterator() : iter(), t(iter.ptr), init(false) { iter.valid = false; }\n" + " CollectionIterator(const PointerRNA &ptr) : CollectionIterator() { this->begin(ptr); }\n" " ~CollectionIterator(void) { if (init) Tend(&iter); };\n" "\n" + " CollectionIterator(const CollectionIterator &other) = delete;\n" + " CollectionIterator(CollectionIterator &&other) = delete;\n" + " CollectionIterator &operator=(const CollectionIterator &other) = delete;\n" + " CollectionIterator &operator=(CollectionIterator &&other) = delete;\n" + "\n" " operator bool(void)\n" " { return iter.valid != 0; }\n" " const CollectionIterator<T, Tbegin, Tnext, Tend>& operator++() { Tnext(&iter); t = " @@ -4777,9 +4783,6 @@ static const char *cpp_classes = "true; }\n" "\n" "private:\n" - " const CollectionIterator<T, Tbegin, Tnext, Tend>& operator = " - "(const CollectionIterator<T, Tbegin, Tnext, Tend>& /*copy*/) {}\n" - "" " CollectionPropertyIterator iter;\n" " T t;\n" " bool init;\n" @@ -4794,6 +4797,8 @@ static const char *cpp_classes = "\n" " void begin(CollectionIterator<T, Tbegin, Tnext, Tend>& iter)\n" " { iter.begin(ptr); }\n" + " CollectionIterator<T, Tbegin, Tnext, Tend> begin()\n" + " { return CollectionIterator<T, Tbegin, Tnext, Tend>(ptr); }\n" " CollectionIterator<T, Tbegin, Tnext, Tend> end()\n" " { return CollectionIterator<T, Tbegin, Tnext, Tend>(); } /* test */ \n" "" diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index ae23e0b9109..d8c91cb2923 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3704,7 +3704,7 @@ void RNA_property_pointer_set(PointerRNA *ptr, } } else { - /* Assigning to an IDProperty desguised as RNA one. */ + /* Assigning to an IDProperty disguised as RNA one. */ if (ptr_value.type != NULL && !RNA_struct_is_a(ptr_value.type, &RNA_ID)) { BKE_reportf(reports, RPT_ERROR, @@ -3741,7 +3741,7 @@ void RNA_property_pointer_set(PointerRNA *ptr, pprop->set(ptr, ptr_value, reports); } } - /* IDProperty desguised as RNA property (and not yet defined in ptr). */ + /* IDProperty disguised as RNA property (and not yet defined in ptr). */ else if (prop->flag & PROP_EDITABLE) { IDPropertyTemplate val = {0}; IDProperty *group; @@ -6174,7 +6174,7 @@ char *RNA_path_full_property_py_ex( } else { if (use_fallback) { - /* fuzzy fallback. be explicit in our ignoranc. */ + /* Fuzzy fallback. Be explicit in our ignorance. */ data_path = RNA_property_identifier(prop); data_delim = " ... "; } diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index 1e7f5e841ba..d6305388cf9 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -42,6 +42,7 @@ #include "BKE_armature.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_lib_override.h" #include "BKE_main.h" @@ -133,7 +134,7 @@ bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop) /* Special handling for insertions of constraints or modifiers... */ /* TODO Note We may want to add a more generic system to RNA * (like a special property in struct of items) - * if we get more overrideable collections, + * if we get more overridable collections, * for now we can live with those special-cases handling I think. */ if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) { bConstraint *con = ptr->data; @@ -1178,6 +1179,17 @@ void RNA_struct_override_apply(Main *bmain, #endif } } + + /* Some cases (like point caches) may require additional post-processing. */ + if (RNA_struct_is_a(ptr_dst->type, &RNA_ID)) { + ID *id_dst = ptr_dst->data; + ID *id_src = ptr_src->data; + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id_dst); + if (id_type->lib_override_apply_post != NULL) { + id_type->lib_override_apply_post(id_dst, id_src); + } + } + #ifdef DEBUG_OVERRIDE_TIMEIT TIMEIT_END_AVERAGED(RNA_struct_override_apply); #endif diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index 06215e16965..8e95388fe2b 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -61,7 +61,7 @@ static void rna_AnimViz_path_start_frame_set(PointerRNA *ptr, int value) { bAnimVizSettings *data = (bAnimVizSettings *)ptr->data; - /* XXX: watchit! Path Start > MAXFRAME/2 could be a problem... */ + /* XXX: Watch it! Path Start > MAXFRAME/2 could be a problem. */ data->path_sf = value; FRAMENUMBER_MIN_CLAMP(data->path_sf); diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c index 7cd6e375a82..21b26b51e0a 100644 --- a/source/blender/makesrna/intern/rna_attribute.c +++ b/source/blender/makesrna/intern/rna_attribute.c @@ -169,6 +169,9 @@ static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRN case CD_PROP_STRING: struct_size = sizeof(MStringProperty); break; + case CD_PROP_BOOL: + struct_size = sizeof(MBoolProperty); + break; default: struct_size = 0; length = 0; @@ -299,6 +302,9 @@ PointerRNA rna_AttributeGroup_iterator_get(CollectionPropertyIterator *iter) case CD_PROP_STRING: type = &RNA_StringAttribute; break; + case CD_PROP_BOOL: + type = &RNA_BoolAttribute; + break; default: return PointerRNA_NULL; } @@ -555,6 +561,34 @@ static void rna_def_attribute_string(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Attribute_update_data"); } +static void rna_def_attribute_bool(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "BoolAttribute", "Attribute"); + RNA_def_struct_sdna(srna, "CustomDataLayer"); + RNA_def_struct_ui_text(srna, "Bool Attribute", "Bool geometry attribute"); + + prop = RNA_def_property(srna, "data", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "BoolAttributeValue"); + RNA_def_property_collection_funcs(prop, + "rna_Attribute_data_begin", + "rna_iterator_array_next", + "rna_iterator_array_end", + "rna_iterator_array_get", + "rna_Attribute_data_length", + NULL, + NULL, + NULL); + + srna = RNA_def_struct(brna, "BoolAttributeValue", NULL); + RNA_def_struct_sdna(srna, "MBoolProperty"); + RNA_def_struct_ui_text(srna, "Bool Attribute Value", "Bool value in geometry attribute"); + prop = RNA_def_property(srna, "value", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "b", 0x01); +} + static void rna_def_attribute(BlenderRNA *brna) { PropertyRNA *prop; @@ -592,6 +626,7 @@ static void rna_def_attribute(BlenderRNA *brna) rna_def_attribute_byte_color(brna); rna_def_attribute_int(brna); rna_def_attribute_string(brna); + rna_def_attribute_bool(brna); } /* Mesh/PointCloud/Hair.attributes */ diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2af6c04147c..3dcc9471906 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1304,7 +1304,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - /* Randomnes factor for pressure */ + /* Randomness factor for pressure */ prop = RNA_def_property(srna, "random_pressure", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "draw_random_press"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1313,7 +1313,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - /* Randomnes factor for strength */ + /* Randomness factor for strength */ prop = RNA_def_property(srna, "random_strength", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "draw_random_strength"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1446,7 +1446,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); - /* fill threshold for transparence */ + /* Fill threshold for transparency. */ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fill_threshold"); RNA_def_property_range(prop, 0.0f, 1.0f); @@ -1464,13 +1464,13 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); /* fill factor size */ - prop = RNA_def_property(srna, "fill_factor", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "fill_factor"); - RNA_def_property_range(prop, 1, 8); + prop = RNA_def_property(srna, "fill_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fill_factor"); + RNA_def_property_range(prop, GPENCIL_MIN_FILL_FAC, GPENCIL_MAX_FILL_FAC); RNA_def_property_ui_text( prop, - "Resolution", - "Multiplier for fill resolution, higher resolution is more accurate but slower"); + "Precision", + "Factor for fill boundary accuracy, higher values are more accurate but slower"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); @@ -1608,6 +1608,15 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Value", "Random factor to modify original value"); RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + /* Factor to extend stroke extremes in Fill tool. */ + prop = RNA_def_property(srna, "extend_stroke_factor", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "fill_extend_fac"); + RNA_def_property_range(prop, 0.0f, 10.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text( + prop, "Stroke Extension", "Strokes end extension for closing gaps, use zero to disable"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + /* Flags */ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_PRESSURE); @@ -1827,6 +1836,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Lines", "Show help lines for filling to see boundaries"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "show_fill_extend", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_FILL_SHOW_EXTENDLINES); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_ui_text(prop, "Show Extend Lines", "Show help lines for stroke extension"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "show_fill", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_BRUSH_FILL_HIDE); RNA_def_property_boolean_default(prop, true); @@ -1834,6 +1849,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) prop, "Show Fill", "Show transparent lines to use as boundary for filling"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "use_fill_limit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_FILL_FIT_DISABLE); + RNA_def_property_boolean_default(prop, true); + RNA_def_property_ui_text(prop, "Limit to Viewport", "Fill only visible areas in viewport"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "use_default_eraser", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_DEFAULT_ERASER); RNA_def_property_boolean_default(prop, true); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 4f5828311d8..843cb326be2 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -3032,7 +3032,7 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) prop, "Use Original Scale", "Apply volume preservation over the original scaling"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - /* volume presevation for "volumetric" scale mode */ + /* Volume preservation for "volumetric" scale mode. */ prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.0, 100.0f); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index cec6a50d170..df3bd0cca29 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -1298,7 +1298,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_, dcont = rna_find_container_def(cont); - /* XXX - toto, detect supertype collisions */ + /* TODO: detect super-type collisions. */ if (rna_findlink(&dcont->properties, identifier)) { CLOG_ERROR(&LOG, "duplicate identifier \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier); DefRNA.error = true; @@ -4111,6 +4111,16 @@ PropertyRNA *RNA_def_float_percentage(StructOrFunctionRNA *cont_, ASSERT_SOFT_HARD_LIMITS; +#ifdef DEBUG + /* Properties with PROP_PERCENTAGE should use a range like 0 to 100, unlike PROP_FACTOR. */ + if (hardmax < 2.0f) { + CLOG_WARN(&LOG, + "Percentage property with incorrect range: %s.%s", + CONTAINER_RNA_ID(cont), + identifier); + } +#endif + prop = RNA_def_property(cont, identifier, PROP_FLOAT, PROP_PERCENTAGE); RNA_def_property_float_default(prop, default_value); if (hardmin != hardmax) { diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index cbb642577e1..aab81b2bd1f 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -684,7 +684,7 @@ static void rna_def_depsgraph(BlenderRNA *brna) "This invalidates all references to evaluated data-blocks from this dependency graph."); RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); - /* Queries for original datablockls (the ones depsgraph is built for). */ + /* Queries for original data-blocks (the ones depsgraph is built for). */ prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "Scene"); @@ -699,7 +699,7 @@ static void rna_def_depsgraph(BlenderRNA *brna) RNA_def_property_ui_text( prop, "View Layer", "Original view layer dependency graph is built for"); - /* Queries for evaluated datablockls (the ones depsgraph is evaluating). */ + /* Queries for evaluated data-blocks (the ones depsgraph is evaluating). */ func = RNA_def_function(srna, "id_eval_get", "rna_Depsgraph_id_eval_get"); parm = RNA_def_pointer( diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index 7c4762aa3a3..83df997b3d4 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -625,7 +625,7 @@ static void rna_def_canvas_surface(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DPAINT_OUT1); RNA_def_property_ui_text(prop, "Use Output", "Save this output layer"); - /* output for secondary sufrace data */ + /* Output for secondary surface data. */ prop = RNA_def_property(srna, "output_name_b", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "output_name2"); RNA_def_property_ui_text(prop, "Output Name", "Name used to save output from this surface"); diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 3ea98d610f4..a34c3c7b536 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1964,7 +1964,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Tension", - "Surface tension of liquid (higher value results in greater hydrophobic behaviour)"); + "Surface tension of liquid (higher value results in greater hydrophobic behavior)"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_datacache_reset"); prop = RNA_def_property(srna, "viscosity_base", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 81e20003d8f..5437c93ef61 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -168,6 +168,7 @@ static const EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = { # include "BKE_action.h" # include "BKE_animsys.h" +# include "BKE_deform.h" # include "BKE_gpencil.h" # include "BKE_gpencil_curve.h" # include "BKE_gpencil_geom.h" @@ -182,6 +183,16 @@ static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } +static void rna_GpencilLayerMatrix_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bGPDlayer *gpl = (bGPDlayer *)ptr->data; + + loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale); + invert_m4_m4(gpl->layer_invmat, gpl->layer_mat); + + rna_GPencil_update(bmain, scene, ptr); +} + static void rna_GPencil_curve_edit_mode_toggle(Main *bmain, Scene *scene, PointerRNA *ptr) { ToolSettings *ts = scene->toolsettings; @@ -806,6 +817,74 @@ static void rna_GPencil_stroke_point_pop(ID *id, WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); } +static void rna_GPencil_stroke_point_update(ID *id, bGPDstroke *stroke) +{ + bGPdata *gpd = (bGPdata *)id; + + /* Calc geometry data. */ + if (stroke) { + BKE_gpencil_stroke_geometry_update(gpd, stroke); + + DEG_id_tag_update(&gpd->id, + ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + + WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL); + } +} + +static float rna_GPencilStrokePoints_weight_get(bGPDstroke *stroke, + ReportList *reports, + int vertex_group_index, + int point_index) +{ + MDeformVert *dvert = stroke->dvert; + if (dvert == NULL) { + BKE_report(reports, RPT_ERROR, "Groups: No groups for this stroke"); + return -1.0f; + } + + if (dvert->totweight <= vertex_group_index || vertex_group_index < 0) { + BKE_report(reports, RPT_ERROR, "Groups: index out of range"); + return -1.0f; + } + + if (stroke->totpoints <= point_index || point_index < 0) { + BKE_report(reports, RPT_ERROR, "GPencilStrokePoints: index out of range"); + return -1.0f; + } + + MDeformVert *pt_dvert = stroke->dvert + point_index; + MDeformWeight *dw = BKE_defvert_find_index(pt_dvert, vertex_group_index); + if (dw) { + return dw->weight; + } + + return -1.0f; +} + +static void rna_GPencilStrokePoints_weight_set( + bGPDstroke *stroke, ReportList *reports, int vertex_group_index, int point_index, float weight) +{ + BKE_gpencil_dvert_ensure(stroke); + + MDeformVert *dvert = stroke->dvert; + if (dvert == NULL) { + BKE_report(reports, RPT_ERROR, "Groups: No groups for this stroke"); + return; + } + + if (stroke->totpoints <= point_index || point_index < 0) { + BKE_report(reports, RPT_ERROR, "GPencilStrokePoints: index out of range"); + return; + } + + MDeformVert *pt_dvert = stroke->dvert + point_index; + MDeformWeight *dw = BKE_defvert_ensure_index(pt_dvert, vertex_group_index); + if (dw) { + dw->weight = weight; + } +} + static bGPDstroke *rna_GPencil_stroke_new(bGPDframe *frame) { bGPDstroke *stroke = BKE_gpencil_stroke_new(0, 0, 1.0f); @@ -940,7 +1019,7 @@ static void rna_GPencil_frame_remove(bGPDlayer *layer, ReportList *reports, Poin static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src) { - bGPDframe *frame = BKE_gpencil_frame_duplicate(src); + bGPDframe *frame = BKE_gpencil_frame_duplicate(src, true); while (BKE_gpencil_layer_frame_find(layer, frame->framenum)) { frame->framenum++; @@ -1044,21 +1123,6 @@ static void rna_GPencil_clear(bGPdata *gpd) WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } -static void rna_GpencilVertex_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -{ - bGPDstroke *gps = ptr->data; - - if (gps->dvert) { - MDeformVert *dvert = gps->dvert; - - rna_iterator_array_begin( - iter, (void *)dvert->dw, sizeof(MDeformWeight), dvert->totweight, 0, NULL); - } - else { - rna_iterator_array_begin(iter, NULL, 0, 0, 0, NULL); - } -} - static char *rna_GreasePencilGrid_path(PointerRNA *UNUSED(ptr)) { return BLI_strdup("grid"); @@ -1264,6 +1328,58 @@ static void rna_def_gpencil_stroke_points_api(BlenderRNA *brna, PropertyRNA *cpr RNA_def_function_ui_description(func, "Remove a grease pencil stroke point"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); RNA_def_int(func, "index", -1, INT_MIN, INT_MAX, "Index", "point index", INT_MIN, INT_MAX); + + func = RNA_def_function(srna, "update", "rna_GPencil_stroke_point_update"); + RNA_def_function_ui_description(func, "Recalculate internal triangulation data"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID); + + func = RNA_def_function(srna, "weight_get", "rna_GPencilStrokePoints_weight_get"); + RNA_def_function_ui_description(func, "Get vertex group point weight"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_int(func, + "vertex_group_index", + 0, + 0, + INT_MAX, + "Vertex Group Index", + "Index of Vertex Group in the array of groups", + 0, + INT_MAX); + RNA_def_int(func, + "point_index", + 0, + 0, + INT_MAX, + "Point Index", + "Index of the Point in the array", + 0, + INT_MAX); + parm = RNA_def_float( + func, "weight", 0, -FLT_MAX, FLT_MAX, "Weight", "Point Weight", -FLT_MAX, FLT_MAX); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "weight_set", "rna_GPencilStrokePoints_weight_set"); + RNA_def_function_ui_description(func, "Set vertex group point weight"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_int(func, + "vertex_group_index", + 0, + 0, + INT_MAX, + "Vertex Group Index", + "Index of Vertex Group in the array of groups", + 0, + INT_MAX); + RNA_def_int(func, + "point_index", + 0, + 0, + INT_MAX, + "Point Index", + "Index of the Point in the array", + 0, + INT_MAX); + RNA_def_float(func, "weight", 0, -FLT_MAX, FLT_MAX, "Weight", "Point Weight", -FLT_MAX, FLT_MAX); } /* This information is read only and it can be used by add-ons */ @@ -1491,21 +1607,6 @@ static void rna_def_gpencil_stroke(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Stroke Points", "Stroke data points"); rna_def_gpencil_stroke_points_api(brna, prop); - /* vertex groups */ - prop = RNA_def_property(srna, "groups", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, - "rna_GpencilVertex_groups_begin", - "rna_iterator_array_next", - "rna_iterator_array_end", - "rna_iterator_array_get", - NULL, - NULL, - NULL, - NULL); - RNA_def_property_struct_type(prop, "GpencilVertexGroupElement"); - RNA_def_property_ui_text( - prop, "Groups", "Weights for the vertex groups this vertex is member of"); - /* Triangles */ prop = RNA_def_property(srna, "triangles", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "triangles", "tot_triangles"); @@ -2012,6 +2113,45 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Blend Mode", "Blend mode"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); + /* Layer transforms. */ + prop = RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_float_sdna(prop, NULL, "location"); + RNA_def_property_ui_text(prop, "Location", "Values for change location"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_EULER); + RNA_def_property_float_sdna(prop, NULL, "rotation"); + RNA_def_property_ui_text(prop, "Rotation", "Values for changes in rotation"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ); + RNA_def_property_float_sdna(prop, NULL, "scale"); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "Scale", "Values for changes in scale"); + RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); + RNA_def_property_update(prop, 0, "rna_GpencilLayerMatrix_update"); + + /* Layer matrix. */ + prop = RNA_def_property(srna, "matrix_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_mat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Matrix Layer", "Local Layer transformation matrix"); + + /* Layer inverse matrix. */ + prop = RNA_def_property(srna, "matrix_inverse_layer", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "layer_invmat"); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON); + RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text( + prop, "Matrix Layer Inverse", "Local Layer transformation inverse matrix"); + /* Flags */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_HIDE); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 89eb989a442..71d5a53adb2 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -489,7 +489,7 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "seed", PROP_INT, PROP_UNSIGNED); - RNA_def_property_ui_text(prop, "Seed", "Random seed"); + RNA_def_property_ui_text(prop, "Noise Seed", "Random seed"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "noise_scale", PROP_FLOAT, PROP_FACTOR); @@ -498,6 +498,13 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Noise Scale", "Scale the noise frequency"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "noise_offset", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "noise_offset"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3); + RNA_def_property_ui_text(prop, "Noise Offset", "Offset the noise along the strokes"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "use_custom_curve", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_CUSTOM_CURVE); RNA_def_property_ui_text( diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index 25472ce9520..319aeb69a2b 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -132,12 +132,12 @@ static void rna_Lattice_update_size(Main *bmain, Scene *scene, PointerRNA *ptr) Object *ob; int newu, newv, neww; - /* we don't modify the actual pnts, but go through opnts instead */ + /* We don't modify the actual `pnts`, but go through `opnts` instead. */ newu = (lt->opntsu > 0) ? lt->opntsu : lt->pntsu; newv = (lt->opntsv > 0) ? lt->opntsv : lt->pntsv; neww = (lt->opntsw > 0) ? lt->opntsw : lt->pntsw; - /* BKE_lattice_resize needs an object, any object will have the same result */ + /* #BKE_lattice_resize needs an object, any object will have the same result */ for (ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->data == lt) { BKE_lattice_resize(lt, newu, newv, neww, ob); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index d162917ea0c..f92a2932f06 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -288,7 +288,7 @@ void RNA_api_mesh(StructRNA *srna) "Define custom split normals of this mesh " "(use zero-vectors to keep auto ones)"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); RNA_def_property_multi_array(parm, 2, normals_array_dim); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); @@ -301,7 +301,7 @@ void RNA_api_mesh(StructRNA *srna) "Define custom split normals of this mesh, from vertices' normals " "(use zero-vectors to keep auto ones)"); RNA_def_function_flag(func, FUNC_USE_REPORTS); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_float_array(func, "normals", 1, NULL, -1.0f, 1.0f, "", "Normals", 0.0f, 0.0f); RNA_def_property_multi_array(parm, 2, normals_array_dim); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index e02e47745b0..7209d17735a 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -681,7 +681,7 @@ static void rna_Modifier_is_active_set(PointerRNA *ptr, bool value) ModifierData *md = ptr->data; if (value) { - /* Disable the active flag of all other modif-iers. */ + /* Disable the active flag of all other modifiers. */ for (ModifierData *prev_md = md->prev; prev_md != NULL; prev_md = prev_md->prev) { prev_md->flag &= ~eModifierFlag_Active; } @@ -1632,33 +1632,35 @@ static IDProperty *rna_NodesModifier_properties(PointerRNA *ptr, bool create) static void rna_def_property_subdivision_common(StructRNA *srna) { static const EnumPropertyItem prop_uv_smooth_items[] = { - {SUBSURF_UV_SMOOTH_NONE, "NONE", 0, "None", "UVs are not smoothed, boundaries are kept sharp"}, - {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS, - "PRESERVE_CORNERS", - 0, - "Keep Corners", - "UVs are smoothed, corners on discontinuous boundary are kept sharp"}, -# if 0 - {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_AND_JUNCTIONS, - "PRESERVE_CORNERS_AND_JUNCTIONS", - 0, - "Smooth, keep corners+junctions", - "UVs are smoothed, corners on discontinuous boundary and " - "junctions of 3 or more regions are kept sharp"}, - {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_JUNCTIONS_AND_CONCAVE, - "PRESERVE_CORNERS_JUNCTIONS_AND_CONCAVE", - 0, - "Smooth, keep corners+junctions+concave", - "UVs are smoothed, corners on discontinuous boundary, " - "junctions of 3 or more regions and darts and concave corners are kept sharp"}, - {SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES, - "PRESERVE_BOUNDARIES", - 0, - "Smooth, keep corners", - "UVs are smoothed, boundaries are kept sharp"}, -# endif - {SUBSURF_UV_SMOOTH_ALL, "PRESERVE_BOUNDARIES", 0, "All", "UVs and boundaries are smoothed"}, - {0, NULL, 0, NULL, NULL}, + {SUBSURF_UV_SMOOTH_NONE, + "NONE", + 0, + "None", + "UVs are not smoothed, boundaries are kept sharp"}, + {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS, + "PRESERVE_CORNERS", + 0, + "Keep Corners", + "UVs are smoothed, corners on discontinuous boundary are kept sharp"}, + {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_AND_JUNCTIONS, + "PRESERVE_CORNERS_AND_JUNCTIONS", + 0, + "Keep Corners, Junctions", + "UVs are smoothed, corners on discontinuous boundary and " + "junctions of 3 or more regions are kept sharp"}, + {SUBSURF_UV_SMOOTH_PRESERVE_CORNERS_JUNCTIONS_AND_CONCAVE, + "PRESERVE_CORNERS_JUNCTIONS_AND_CONCAVE", + 0, + "Keep Corners, Junctions, Concave", + "UVs are smoothed, corners on discontinuous boundary, " + "junctions of 3 or more regions and darts and concave corners are kept sharp"}, + {SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES, + "PRESERVE_BOUNDARIES", + 0, + "Keep boundaries", + "UVs are smoothed, boundaries are kept sharp"}, + {SUBSURF_UV_SMOOTH_ALL, "SMOOTH_ALL", 0, "All", "UVs and boundaries are smoothed"}, + {0, NULL, 0, NULL, NULL}, }; static const EnumPropertyItem prop_boundary_smooth_items[] = { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index f9b5041b1cf..610edb0e37c 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -29,6 +29,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -1964,22 +1965,6 @@ static const EnumPropertyItem *rna_GeometryNodeAttributeFill_domain_itemf( return itemf_function_check(rna_enum_attribute_domain_items, attribute_fill_domain_supported); } -static bool attribute_math_operation_supported(const EnumPropertyItem *item) -{ - return ELEM(item->value, - NODE_MATH_ADD, - NODE_MATH_SUBTRACT, - NODE_MATH_MULTIPLY, - NODE_MATH_DIVIDE) && - (item->identifier[0] != '\0'); -} -static const EnumPropertyItem *rna_GeometryNodeAttributeMath_operation_itemf( - bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) -{ - *r_free = true; - return itemf_function_check(rna_enum_node_math_items, attribute_math_operation_supported); -} - /** * This bit of ugly code makes sure the float / attribute option shows up instead of * vector / attribute if the node uses an operation that uses a float for input B. @@ -4741,9 +4726,10 @@ static void def_sh_tex_sky(StructRNA *srna) RNA_def_property_float_default(prop, 0.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); - prop = RNA_def_property(srna, "altitude", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "altitude", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_ui_text(prop, "Altitude", "Height from sea level"); - RNA_def_property_range(prop, 0.0f, 60.0f); + RNA_def_property_range(prop, 0.0f, 60000.0f); + RNA_def_property_ui_range(prop, 0.0f, 60000.0f, 10, 1); RNA_def_property_float_default(prop, 0.0f); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); @@ -5395,7 +5381,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna) func = RNA_def_function(srna, "calc_point_density", "rna_ShaderNodePointDensity_density_calc"); RNA_def_function_ui_description(func, "Calculate point density"); RNA_def_pointer(func, "depsgraph", "Depsgraph", "", ""); - /* TODO, See how array size of 0 works, this shouldnt be used. */ + /* TODO, See how array size of 0 works, this shouldn't be used. */ parm = RNA_def_float_array(func, "rgba_values", 1, NULL, 0, 0, "", "RGBA Values", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, 0); RNA_def_function_output(func, parm); @@ -8563,10 +8549,9 @@ static void def_geo_attribute_math(StructRNA *srna) prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "operation"); RNA_def_property_enum_items(prop, rna_enum_node_math_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_GeometryNodeAttributeMath_operation_itemf"); RNA_def_property_enum_default(prop, NODE_MATH_ADD); RNA_def_property_ui_text(prop, "Operation", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); prop = RNA_def_property(srna, "input_type_a", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_a"); @@ -8579,6 +8564,12 @@ static void def_geo_attribute_math(StructRNA *srna) RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); RNA_def_property_ui_text(prop, "Input Type B", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_c", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "input_type_c"); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); + RNA_def_property_ui_text(prop, "Input Type C", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } static void def_geo_attribute_vector_math(StructRNA *srna) @@ -8632,16 +8623,17 @@ static void def_geo_point_instance(StructRNA *srna) }; PropertyRNA *prop; + RNA_def_struct_sdna_from(srna, "NodeGeometryPointInstance", "storage"); prop = RNA_def_property(srna, "instance_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_sdna(prop, NULL, "instance_type"); RNA_def_property_enum_items(prop, instance_type_items); RNA_def_property_enum_default(prop, GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); RNA_def_property_ui_text(prop, "Instance Type", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); prop = RNA_def_property(srna, "use_whole_collection", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", 1); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION); RNA_def_property_ui_text(prop, "Whole Collection", "Instance entire collection on each point"); RNA_def_property_update(prop, 0, "rna_Node_socket_update"); } @@ -8682,7 +8674,7 @@ static void def_geo_attribute_attribute_compare(StructRNA *srna) prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items); - RNA_def_property_enum_default(prop, NODE_MATH_ADD); + RNA_def_property_enum_default(prop, NODE_FLOAT_COMPARE_GREATER_THAN); RNA_def_property_ui_text(prop, "Operation", ""); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); @@ -8802,6 +8794,30 @@ static void def_geo_align_rotation_to_vector(StructRNA *srna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem pivot_axis_items[] = { + {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO, + "AUTO", + ICON_NONE, + "Auto", + "Automatically detect the best rotation axis to rotate towards the vector"}, + {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_X, + "X", + ICON_NONE, + "X", + "Rotate around the local X axis"}, + {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Y, + "Y", + ICON_NONE, + "Y", + "Rotate around the local Y axis"}, + {GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_Z, + "Z", + ICON_NONE, + "Z", + "Rotate around the local Z axis"}, + {0, NULL, 0, NULL, NULL}, + }; + PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "NodeGeometryAlignRotationToVector", "storage"); @@ -8811,6 +8827,11 @@ static void def_geo_align_rotation_to_vector(StructRNA *srna) RNA_def_property_ui_text(prop, "Axis", "Axis to align to the vector"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + prop = RNA_def_property(srna, "pivot_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, pivot_axis_items); + RNA_def_property_ui_text(prop, "Pivot Axis", "Axis to rotate around"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + prop = RNA_def_property(srna, "input_type_factor", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); RNA_def_property_ui_text(prop, "Input Type Factor", ""); @@ -8846,6 +8867,19 @@ static void def_geo_point_translate(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_attribute_sample_texture(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "id"); + RNA_def_property_struct_type(prop, "Texture"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Texture", "Texture to sample values from"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations"); +} + static void def_geo_object_info(StructRNA *srna) { PropertyRNA *prop; @@ -8876,6 +8910,161 @@ static void def_geo_object_info(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_geo_points_to_volume(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem resolution_mode_items[] = { + {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT, + "VOXEL_AMOUNT", + 0, + "Amount", + "Specify the approximate number of voxels along the diagonal"}, + {GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE, + "VOXEL_SIZE", + 0, + "Size", + "Specify the voxel side length"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryPointsToVolume", "storage"); + + prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, resolution_mode_items); + RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_radius", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); + RNA_def_property_ui_text(prop, "Radius Input Type", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_geo_collection_info(StructRNA *srna) +{ + PropertyRNA *prop; + + static const EnumPropertyItem rna_node_geometry_collection_info_transform_space_items[] = { + {GEO_NODE_TRANSFORM_SPACE_ORIGINAL, + "ORIGINAL", + 0, + "Original", + "Output the geometry relative to the collection offset"}, + {GEO_NODE_TRANSFORM_SPACE_RELATIVE, + "RELATIVE", + 0, + "Relative", + "Bring the input collection geometry into the modified object, maintaining the relative " + "position between the objects in the scene."}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryCollectionInfo", "storage"); + + prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_collection_info_transform_space_items); + RNA_def_property_ui_text(prop, "Transform Space", "The transformation of the geometry output"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + +static void def_geo_attribute_proximity(StructRNA *srna) +{ + static const EnumPropertyItem target_geometry_element[] = { + {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS, + "POINTS", + ICON_NONE, + "Points", + "Calculate proximity to the target's points (usually faster than the other two modes)"}, + {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES, + "EDGES", + ICON_NONE, + "Edges", + "Calculate proximity to the target's edges"}, + {GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES, + "FACES", + ICON_NONE, + "Faces", + "Calculate proximity to the target's faces"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeGeometryAttributeProximity", "storage"); + + prop = RNA_def_property(srna, "target_geometry_element", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, target_geometry_element); + RNA_def_property_enum_default(prop, GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES); + RNA_def_property_ui_text( + prop, "Target Geometry", "Element of the target geometry to calculate the distance from"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_geo_volume_to_mesh(StructRNA *srna) +{ + PropertyRNA *prop; + + static EnumPropertyItem resolution_mode_items[] = { + {VOLUME_TO_MESH_RESOLUTION_MODE_GRID, + "GRID", + 0, + "Grid", + "Use resolution of the volume grid"}, + {VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT, + "VOXEL_AMOUNT", + 0, + "Voxel Amount", + "Desired number of voxels along one axis"}, + {VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE, + "VOXEL_SIZE", + 0, + "Voxel Size", + "Desired voxel side length"}, + {0, NULL, 0, NULL, NULL}, + }; + + RNA_def_struct_sdna_from(srna, "NodeGeometryVolumeToMesh", "storage"); + + prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, resolution_mode_items); + RNA_def_property_ui_text(prop, "Resolution Mode", "How the voxel size is specified"); +} + +static void def_geo_attribute_combine_xyz(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeAttributeCombineXYZ", "storage"); + + prop = RNA_def_property(srna, "input_type_x", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); + RNA_def_property_ui_text(prop, "Input Type X", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_y", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); + RNA_def_property_ui_text(prop, "Input Type Y", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); + + prop = RNA_def_property(srna, "input_type_z", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_float); + RNA_def_property_ui_text(prop, "Input Type Z", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + +static void def_geo_attribute_separate_xyz(StructRNA *srna) +{ + PropertyRNA *prop; + + RNA_def_struct_sdna_from(srna, "NodeAttributeSeparateXYZ", "storage"); + + prop = RNA_def_property(srna, "input_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_node_geometry_attribute_input_type_items_vector); + RNA_def_property_ui_text(prop, "Input Type", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index faa20e642cf..1eb5ed3977a 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -85,16 +85,16 @@ const EnumPropertyItem rna_enum_object_mode_items[] = { ICON_GREASEPENCIL, "Draw", "Paint Grease Pencil Strokes"}, - {OB_MODE_VERTEX_GPENCIL, - "VERTEX_GPENCIL", - ICON_VPAINT_HLT, - "Vertex Paint", - "Grease Pencil Vertex Paint Strokes"}, {OB_MODE_WEIGHT_GPENCIL, "WEIGHT_GPENCIL", ICON_WPAINT_HLT, "Weight Paint", "Grease Pencil Weight Paint Strokes"}, + {OB_MODE_VERTEX_GPENCIL, + "VERTEX_GPENCIL", + ICON_VPAINT_HLT, + "Vertex Paint", + "Grease Pencil Vertex Paint Strokes"}, {0, NULL, 0, NULL, NULL}, }; @@ -1304,11 +1304,13 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value) if (value) { ob->matbits[index] = 1; - /* ob->colbits |= (1 << index); */ /* DEPRECATED */ + /* DEPRECATED */ + // ob->colbits |= (1 << index); } else { ob->matbits[index] = 0; - /* ob->colbits &= ~(1 << index); */ /* DEPRECATED */ + /* DEPRECATED */ + // ob->colbits &= ~(1 << index); } } @@ -2120,7 +2122,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) func = RNA_def_function(srna, "add", "rna_VertexGroup_vertex_add"); RNA_def_function_ui_description(func, "Add vertices to the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); parm = RNA_def_float(func, "weight", 0, 0.0f, 1.0f, "", "Vertex weight", 0.0f, 1.0f); @@ -2131,7 +2133,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) func = RNA_def_function(srna, "remove", "rna_VertexGroup_vertex_remove"); RNA_def_function_ui_description(func, "Remove a vertex from the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); @@ -2178,14 +2180,14 @@ static void rna_def_face_map(BlenderRNA *brna) func = RNA_def_function(srna, "add", "rna_FaceMap_face_add"); RNA_def_function_ui_description(func, "Add vertices to the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove"); RNA_def_function_ui_description(func, "Remove a vertex from the group"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID); - /* TODO, see how array size of 0 works, this shouldnt be used */ + /* TODO, see how array size of 0 works, this shouldn't be used */ parm = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0); RNA_def_parameter_flags(parm, PROP_DYNAMIC, PARM_REQUIRED); } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 3126f3e11f4..0c2860c05e7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -848,6 +848,14 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Use Eevee Viewport", "Uses Eevee for viewport shading in LookDev shading mode"); + prop = RNA_def_property(srna, "bl_use_custom_freestyle", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_CUSTOM_FREESTYLE); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text( + prop, + "Use Custom Freestyle", + "Handles freestyle rendering on its own, instead of delegating it to EEVEE"); + prop = RNA_def_property(srna, "bl_use_gpu_context", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_GPU_CONTEXT); RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index c929e3ab1aa..b0a942cd39e 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1279,12 +1279,22 @@ static int rna_property_override_diff_propptr(Main *bmain, 0); if (is_id) { - /* For now, once we deal with nodetrees we'll want to get rid of that one. */ - // BLI_assert(no_ownership); + /* Owned IDs (the ones we want to actually compare in depth, instead of just comparing pointer + * values) should be always properly tagged as 'virtual' overrides. */ + ID *id = propptr_a->owner_id; + if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) { + id = propptr_b->owner_id; + if (id != NULL && !ID_IS_OVERRIDE_LIBRARY(id)) { + id = NULL; + } + } + + BLI_assert(no_ownership || id == NULL || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(id)); + UNUSED_VARS_NDEBUG(id); } if (override) { - if (no_ownership /* || is_id */ || is_null || is_type_diff || !is_valid_for_diffing) { + if (no_ownership || is_null || is_type_diff || !is_valid_for_diffing) { /* In case this pointer prop does not own its data (or one is NULL), do not compare structs! * This is a quite safe path to infinite loop, among other nasty issues. * Instead, just compare pointers themselves. */ @@ -1304,9 +1314,9 @@ static int rna_property_override_diff_propptr(Main *bmain, BLI_assert(op->rna_prop_type == property_type); } + IDOverrideLibraryPropertyOperation *opop = NULL; if (created || rna_itemname_a != NULL || rna_itemname_b != NULL || rna_itemindex_a != -1 || rna_itemindex_b != -1) { - IDOverrideLibraryPropertyOperation *opop; opop = BKE_lib_override_library_property_operation_get(op, IDOVERRIDE_LIBRARY_OP_REPLACE, rna_itemname_b, @@ -1327,6 +1337,38 @@ static int rna_property_override_diff_propptr(Main *bmain, else { BKE_lib_override_library_operations_tag(op, IDOVERRIDE_LIBRARY_TAG_UNUSED, false); } + + if (is_id && no_ownership) { + if (opop == NULL) { + opop = BKE_lib_override_library_property_operation_find(op, + rna_itemname_b, + rna_itemname_a, + rna_itemindex_b, + rna_itemindex_a, + true, + NULL); + BLI_assert(opop != NULL); + } + + BLI_assert(propptr_a->data == propptr_a->owner_id); + BLI_assert(propptr_b->data == propptr_b->owner_id); + ID *id_a = propptr_a->data; + ID *id_b = propptr_b->data; + if (ELEM(NULL, id_a, id_b)) { + /* In case one of the pointer is NULL and not the other, we consider that the + * override is not matching its reference anymore. */ + opop->flag &= ~IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; + } + else if (id_a->override_library != NULL && id_a->override_library->reference == id_b) { + opop->flag |= IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; + } + else if (id_b->override_library != NULL && id_b->override_library->reference == id_a) { + opop->flag |= IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; + } + else { + opop->flag &= ~IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; + } + } } } @@ -1429,8 +1471,8 @@ static int rna_property_override_diff_propptr(Main *bmain, } } else { - /* We could also use is_diff_pointer, but then we potentially lose the gt/lt info - - * and don't think performances are critical here for now anyway... */ + /* We could also use is_diff_pointer, but then we potentially lose the greater-than/less-than + * info - and don't think performances are critical here for now anyway. */ return !RNA_struct_equals(bmain, propptr_a, propptr_b, mode); } } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index af31f16f4e0..58a89b7ffdc 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1495,7 +1495,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_exr_codec_itemf(bContext int i = 1, totitem = 0; if (imf->depth == 16) { - return rna_enum_exr_codec_items; /* All compression types are defined for halfs */ + return rna_enum_exr_codec_items; /* All compression types are defined for half-float. */ } for (i = 0; i < R_IMF_EXR_CODEC_MAX; i++) { @@ -2102,7 +2102,7 @@ static char *rna_TransformOrientationSlot_path(PointerRNA *ptr) } } - /* Should not happen, but in case, just return defqult path. */ + /* Should not happen, but in case, just return default path. */ BLI_assert(0); return BLI_strdup("transform_orientation_slots[0]"); } @@ -7712,7 +7712,7 @@ void RNA_def_scene(BlenderRNA *brna) prop, "Preview Range End Frame", "Alternative end frame for UI playback"); RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL); - /* Subframe for moblur debug. */ + /* Sub-frame for motion-blur debug. */ prop = RNA_def_property(srna, "show_subframe", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_SHOW_SUBFRAME); diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index 08387077cea..4481555b931 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -896,7 +896,7 @@ static void rna_def_gp_paint(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_GpPaint_path"); RNA_def_struct_ui_text(srna, "Grease Pencil Paint", ""); - /* Use vertex color (main swith). */ + /* Use vertex color (main switch). */ prop = RNA_def_property(srna, "color_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_paint_mode); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 251845ee5b0..c56ddeb9053 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -439,7 +439,7 @@ const EnumPropertyItem rna_enum_clip_editor_mode_items[] = { {0, NULL, 0, NULL, NULL}, }; -/* Actually populated dynamically trough a function, +/* Actually populated dynamically through a function, * but helps for context-less access (e.g. doc, i18n...). */ static const EnumPropertyItem buttons_context_items[] = { {BCONTEXT_TOOL, "TOOL", ICON_TOOL_SETTINGS, "Tool", "Active Tool and Workspace settings"}, @@ -2279,6 +2279,20 @@ static bool rna_SpaceNodeEditor_tree_type_poll(void *Cv, bNodeTreeType *type) } } +static void rna_SpaceNodeEditor_cursor_location_get(PointerRNA *ptr, float value[2]) +{ + const SpaceNode *snode = (SpaceNode *)ptr->data; + + ED_node_cursor_location_get(snode, value); +} + +static void rna_SpaceNodeEditor_cursor_location_set(PointerRNA *ptr, const float value[2]) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + + ED_node_cursor_location_set(snode, value); +} + const EnumPropertyItem *RNA_enum_node_tree_types_itemf_impl(bContext *C, bool *r_free) { return rna_node_tree_type_itemf(C, rna_SpaceNodeEditor_tree_type_poll, r_free); @@ -2346,9 +2360,13 @@ static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, { ARegion *region = CTX_wm_region(C); - UI_view2d_region_to_view(®ion->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); - snode->cursor[0] /= UI_DPI_FAC; - snode->cursor[1] /= UI_DPI_FAC; + float cursor_location[2]; + + UI_view2d_region_to_view(®ion->v2d, x, y, &cursor_location[0], &cursor_location[1]); + cursor_location[0] /= UI_DPI_FAC; + cursor_location[1] /= UI_DPI_FAC; + + ED_node_cursor_location_set(snode, cursor_location); } static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, @@ -2460,7 +2478,7 @@ static void rna_FileSelectPrams_filter_glob_set(PointerRNA *ptr, const char *val BLI_strncpy(params->filter_glob, value, sizeof(params->filter_glob)); - /* Remove stupi things like last group being a wildcard-only one... */ + /* Remove stupid things like last group being a wildcard-only one. */ BLI_path_extension_glob_validate(params->filter_glob); } @@ -4640,7 +4658,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) } } - /* Heper for drawing the icon. */ + /* Helper for drawing the icon. */ prop = RNA_def_property(srna, "icon_from_show_object_viewport", PROP_INT, PROP_NONE); RNA_def_property_int_funcs( prop, "rna_SpaceView3D_icon_from_show_object_viewport_get", NULL, NULL); @@ -5684,13 +5702,13 @@ static void rna_def_space_graph(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Pivot Point", "Pivot center for rotation/scaling"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - /* dopesheet */ + /* Dope-sheet. */ prop = RNA_def_property(srna, "dopesheet", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "DopeSheet"); RNA_def_property_pointer_sdna(prop, NULL, "ads"); RNA_def_property_ui_text(prop, "Dope Sheet", "Settings for filtering animation data"); - /* autosnap */ + /* Auto-snap. */ prop = RNA_def_property(srna, "auto_snap", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "autosnap"); RNA_def_property_enum_items(prop, autosnap_items); @@ -5698,14 +5716,14 @@ static void rna_def_space_graph(BlenderRNA *brna) prop, "Auto Snap", "Automatic time snapping settings for transformations"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - /* readonly state info */ + /* Read-only state info. */ prop = RNA_def_property(srna, "has_ghost_curves", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_SpaceGraphEditor_has_ghost_curves_get", NULL); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text( prop, "Has Ghost Curves", "Graph Editor instance has some ghost curves stored"); - /* nromalize curves */ + /* Normalize curves. */ prop = RNA_def_property(srna, "use_normalization", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_NORMALIZE); RNA_def_property_ui_text(prop, @@ -6818,11 +6836,13 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_enum_items(prop, backdrop_channels_items); RNA_def_property_ui_text(prop, "Display Channels", "Channels of the image to draw"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); - /* the mx/my "cursor" in the node editor is used only by operators to store the mouse position */ prop = RNA_def_property(srna, "cursor_location", PROP_FLOAT, PROP_XYZ); RNA_def_property_array(prop, 2); - RNA_def_property_float_sdna(prop, NULL, "cursor"); + RNA_def_property_float_funcs(prop, + "rna_SpaceNodeEditor_cursor_location_get", + "rna_SpaceNodeEditor_cursor_location_set", + NULL); RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 1870c660efd..bcf75fb284f 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -976,22 +976,6 @@ static void rna_def_trackingSettings(BlenderRNA *brna) RNA_def_property_enum_items(prop, cleanup_items); RNA_def_property_ui_text(prop, "Action", "Cleanup action to execute"); - /* ** default tracker settings ** */ - prop = RNA_def_property(srna, "show_default_expanded", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SETTINGS_SHOW_DEFAULT_EXPANDED); - RNA_def_property_ui_text( - prop, "Show Expanded", "Show default options expanded in the user interface"); - RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); - - /* ** extra tracker settings ** */ - prop = RNA_def_property(srna, "show_extra_expanded", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", TRACKING_SETTINGS_SHOW_EXTRA_EXPANDED); - RNA_def_property_ui_text( - prop, "Show Expanded", "Show extra options expanded in the user interface"); - RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1); - /* solver settings */ prop = RNA_def_property(srna, "use_tripod_solver", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index cfcd9aff759..1d3a7750c39 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -649,7 +649,7 @@ static StructRNA *rna_UIList_register(Main *bmain, uiList dummyuilist = {NULL}; PointerRNA dummyul_ptr; int have_function[3]; - size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */ + size_t over_alloc = 0; /* Warning, if this becomes a mess, we better do another allocation. */ /* setup dummy menu & menu type to store static properties in */ dummyuilist.type = &dummyult; @@ -669,7 +669,7 @@ static StructRNA *rna_UIList_register(Main *bmain, return NULL; } - /* check if we have registered this uilist type before, and remove it */ + /* Check if we have registered this UI-list type before, and remove it. */ ult = WM_uilisttype_find(dummyult.idname, true); if (ult && ult->rna_ext.srna) { rna_UIList_unregister(bmain, ult->rna_ext.srna); @@ -904,7 +904,7 @@ static StructRNA *rna_Menu_register(Main *bmain, Menu dummymenu = {NULL}; PointerRNA dummymtr; int have_function[2]; - size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */ + size_t over_alloc = 0; /* Warning, if this becomes a mess, we better do another allocation. */ size_t description_size = 0; char _menu_descr[RNA_DYN_DESCR_MAX]; diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 447f5b4210b..f128719db19 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -595,7 +595,7 @@ static const char *rna_ui_get_enum_name(bContext *C, const char *identifier) { PropertyRNA *prop = NULL; - const EnumPropertyItem *items = NULL, *item; + const EnumPropertyItem *items = NULL; bool free; const char *name = ""; @@ -609,11 +609,9 @@ static const char *rna_ui_get_enum_name(bContext *C, RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free); if (items) { - for (item = items; item->identifier; item++) { - if (item->identifier[0] && STREQ(item->identifier, identifier)) { - name = item->name; - break; - } + const int index = RNA_enum_from_identifier(items, identifier); + if (index != -1) { + name = items[index].name; } if (free) { MEM_freeN((void *)items); @@ -629,7 +627,7 @@ static const char *rna_ui_get_enum_description(bContext *C, const char *identifier) { PropertyRNA *prop = NULL; - const EnumPropertyItem *items = NULL, *item; + const EnumPropertyItem *items = NULL; bool free; const char *desc = ""; @@ -643,11 +641,9 @@ static const char *rna_ui_get_enum_description(bContext *C, RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free); if (items) { - for (item = items; item->identifier; item++) { - if (item->identifier[0] && STREQ(item->identifier, identifier)) { - desc = item->description; - break; - } + const int index = RNA_enum_from_identifier(items, identifier); + if (index != -1) { + desc = items[index].description; } if (free) { MEM_freeN((void *)items); @@ -663,7 +659,7 @@ static int rna_ui_get_enum_icon(bContext *C, const char *identifier) { PropertyRNA *prop = NULL; - const EnumPropertyItem *items = NULL, *item; + const EnumPropertyItem *items = NULL; bool free; int icon = ICON_NONE; @@ -677,11 +673,9 @@ static int rna_ui_get_enum_icon(bContext *C, RNA_property_enum_items(C, ptr, prop, &items, NULL, &free); if (items) { - for (item = items; item->identifier; item++) { - if (item->identifier[0] && STREQ(item->identifier, identifier)) { - icon = item->icon; - break; - } + const int index = RNA_enum_from_identifier(items, identifier); + if (index != -1) { + icon = items[index].icon; } if (free) { MEM_freeN((void *)items); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 8a836eb7376..269a242f074 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -243,7 +243,7 @@ void rna_userdef_is_dirty_update(Main *UNUSED(bmain), rna_userdef_is_dirty_update_impl(); } -/** Take care not to use this if we expet 'is_dirty' to be tagged. */ +/** Take care not to use this if we expect 'is_dirty' to be tagged. */ static void rna_userdef_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr)) @@ -863,7 +863,7 @@ static StructRNA *rna_AddonPref_register(Main *bmain, PointerRNA dummy_ptr; // int have_function[1]; - /* setup dummy addon-pref & addon-pref type to store static properties in */ + /* Setup dummy add-on preference and it's type to store static properties in. */ RNA_pointer_create(NULL, &RNA_AddonPreferences, &dummy_addon, &dummy_ptr); /* validate the python class */ @@ -881,13 +881,13 @@ static StructRNA *rna_AddonPref_register(Main *bmain, return NULL; } - /* check if we have registered this addon-pref type before, and remove it */ + /* Check if we have registered this add-on preference type before, and remove it. */ apt = BKE_addon_pref_type_find(dummy_addon.module, true); if (apt && apt->rna_ext.srna) { rna_AddonPref_unregister(bmain, apt->rna_ext.srna); } - /* create a new addon-pref type */ + /* Create a new add-on preference type. */ apt = MEM_mallocN(sizeof(bAddonPrefType), "addonpreftype"); memcpy(apt, &dummy_apt, sizeof(dummy_apt)); BKE_addon_pref_type_add(apt); @@ -4762,6 +4762,11 @@ static void rna_def_userdef_view(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Gizmo Size", "Diameter of the gizmo"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + prop = RNA_def_property(srna, "gizmo_size_navigate_v3d", PROP_INT, PROP_PIXEL); + RNA_def_property_range(prop, 30, 200); + RNA_def_property_ui_text(prop, "Navigate Gizmo Size", "The Navigate Gizmo size"); + RNA_def_property_update(prop, 0, "rna_userdef_gizmo_update"); + /* Lookdev */ prop = RNA_def_property(srna, "lookdev_sphere_size", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "lookdev_sphere_size"); @@ -5649,7 +5654,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) }; static const EnumPropertyItem view_zoom_styles[] = { - {USER_ZOOM_CONT, + {USER_ZOOM_CONTINUE, "CONTINUE", 0, "Continue", @@ -5734,10 +5739,11 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop = RNA_def_property(srna, "use_mouse_continuous", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_CONTINUOUS_MOUSE); - RNA_def_property_ui_text(prop, - "Continuous Grab", - "Allow moving the mouse outside the view on some manipulations " - "(transform, ui control drag)"); + RNA_def_property_ui_text( + prop, + "Continuous Grab", + "Let the mouse wrap around the view boundaries so mouse movements are not limited by the " + "screen size (used by transform, dragging of UI controls, etc.)"); prop = RNA_def_property(srna, "use_drag_immediately", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_RELEASECONFIRM); diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c index a98a52c2252..214a32372dd 100644 --- a/source/blender/makesrna/intern/rna_vfont.c +++ b/source/blender/makesrna/intern/rna_vfont.c @@ -37,7 +37,7 @@ # include "WM_api.h" -/* matching fnction in rna_ID.c */ +/* Matching function in rna_ID.c */ static int rna_VectorFont_filepath_editable(PointerRNA *ptr, const char **UNUSED(r_info)) { VFont *vfont = (VFont *)ptr->owner_id; diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index 3ebcb09a65d..6b96562b3f8 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -72,6 +72,12 @@ const EnumPropertyItem rna_enum_window_cursor_items[] = { # include "WM_types.h" +/* Needed since RNA doesn't use `const` in function signatures. */ +static bool rna_KeyMapItem_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2) +{ + return WM_keymap_item_compare(k1, k2); +} + static void rna_KeyMapItem_to_string(wmKeyMapItem *kmi, bool compact, char *result) { WM_keymap_item_to_string(kmi, compact, result, UI_MAX_SHORTCUT_STR); @@ -156,7 +162,7 @@ static void rna_gizmo_group_type_unlink_delayed(ReportList *reports, const char } } -/* placeholder data for final implementation of a true progressbar */ +/* Placeholder data for final implementation of a true progress-bar. */ static struct wmStaticProgress { float min; float max; @@ -1103,7 +1109,7 @@ void RNA_api_keymapitem(StructRNA *srna) FunctionRNA *func; PropertyRNA *parm; - func = RNA_def_function(srna, "compare", "WM_keymap_item_compare"); + func = RNA_def_function(srna, "compare", "rna_KeyMapItem_compare"); parm = RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_boolean(func, "result", 0, "Comparison result", ""); diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c index 00d832e2eef..e61482c91e2 100644 --- a/source/blender/makesrna/intern/rna_wm_gizmo.c +++ b/source/blender/makesrna/intern/rna_wm_gizmo.c @@ -260,7 +260,7 @@ static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr) wmWindowManager *wm = (wmWindowManager *)ptr->owner_id; # endif - /* We could try workaruond this lookup, but not trivial. */ + /* We could try workaround this lookup, but not trivial. */ for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) { IDProperty *properties = ptr->data; LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { @@ -1089,7 +1089,7 @@ static void rna_def_gizmo(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); parm = RNA_def_pointer(func, "event", "Event", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); - /* TODO, shuold be a enum-flag */ + /* TODO, should be a enum-flag */ parm = RNA_def_enum_flag(func, "tweak", tweak_actions, 0, "Tweak", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_enum_flag( diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 3a7addcba94..c19782df44b 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -185,7 +185,7 @@ endif() if(WITH_OPENVDB) list(APPEND INC - ../../../intern/openvdb + ../../../intern/openvdb ) list(APPEND INC_SYS ${OPENVDB_INCLUDE_DIRS} diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 412d6b87d82..b48bf722526 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -68,7 +68,8 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(amd, DNA_struct_default_get(ArrayModifierData), modifier); - /* Open the first subpanel by default, it corresspnds to Relative offset which is enabled too. */ + /* Open the first sub-panel by default, + * it corresponds to Relative offset which is enabled too. */ md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1; } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 04b68a7a800..e72e0279263 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -222,7 +222,7 @@ static void deformVerts(ModifierData *md, } } - /* happens on file load (ONLY when i decomment changes in readfile.c) */ + /* Happens on file load (ONLY when I un-comment changes in readfile.c) */ if (!collmd->bvhtree) { collmd->bvhtree = bvhtree_build_from_mvert( collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft); diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 15c4e8af6ce..001c7d8d098 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -423,11 +423,11 @@ static void calc_tangent_ortho(float ts[3][3]) cross_v3_v3v3(ts[1], ts[2], v_tan_a); mul_v3_fl(ts[1], dot_v3v3(ts[1], v_tan_b) < 0.0f ? -1.0f : 1.0f); - /* orthognalise tangent */ + /* Orthogonalize tangent. */ mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], v_tan_a)); sub_v3_v3v3(ts[0], v_tan_a, t_vec_a); - /* orthognalise bitangent */ + /* Orthogonalize bi-tangent. */ mul_v3_v3fl(t_vec_a, ts[2], dot_v3v3(ts[2], ts[1])); mul_v3_v3fl(t_vec_b, ts[0], dot_v3v3(ts[0], ts[1]) / dot_v3v3(v_tan_a, v_tan_a)); sub_v3_v3(ts[1], t_vec_a); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index f3d6cf49dd6..23bfe76a5c3 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -215,24 +215,27 @@ static bool isDisabled(const struct Scene *UNUSED(scene), class GeometryNodesEvaluator { private: blender::LinearAllocator<> allocator_; - Map<const DInputSocket *, GMutablePointer> value_by_input_; + Map<std::pair<const DInputSocket *, const DOutputSocket *>, GMutablePointer> value_by_input_; Vector<const DInputSocket *> group_outputs_; blender::nodes::MultiFunctionByNode &mf_by_node_; const blender::nodes::DataTypeConversions &conversions_; const PersistentDataHandleMap &handle_map_; const Object *self_object_; + Depsgraph *depsgraph_; public: GeometryNodesEvaluator(const Map<const DOutputSocket *, GMutablePointer> &group_input_data, Vector<const DInputSocket *> group_outputs, blender::nodes::MultiFunctionByNode &mf_by_node, const PersistentDataHandleMap &handle_map, - const Object *self_object) + const Object *self_object, + Depsgraph *depsgraph) : group_outputs_(std::move(group_outputs)), mf_by_node_(mf_by_node), conversions_(blender::nodes::get_implicit_type_conversions()), handle_map_(handle_map), - self_object_(self_object) + self_object_(self_object), + depsgraph_(depsgraph) { for (auto item : group_input_data.items()) { this->forward_to_inputs(*item.key, item.value); @@ -243,8 +246,8 @@ class GeometryNodesEvaluator { { Vector<GMutablePointer> results; for (const DInputSocket *group_output : group_outputs_) { - GMutablePointer result = this->get_input_value(*group_output); - results.append(result); + Vector<GMutablePointer> result = this->get_input_values(*group_output); + results.append(result[0]); } for (GMutablePointer value : value_by_input_.values()) { value.destruct(); @@ -253,32 +256,53 @@ class GeometryNodesEvaluator { } private: - GMutablePointer get_input_value(const DInputSocket &socket_to_compute) + Vector<GMutablePointer> get_input_values(const DInputSocket &socket_to_compute) { - std::optional<GMutablePointer> value = value_by_input_.pop_try(&socket_to_compute); - if (value.has_value()) { - /* This input has been computed before, return it directly. */ - return *value; - } Span<const DOutputSocket *> from_sockets = socket_to_compute.linked_sockets(); Span<const DGroupInput *> from_group_inputs = socket_to_compute.linked_group_inputs(); const int total_inputs = from_sockets.size() + from_group_inputs.size(); - BLI_assert(total_inputs <= 1); if (total_inputs == 0) { /* The input is not connected, use the value from the socket itself. */ - return get_unlinked_input_value(socket_to_compute); + return {get_unlinked_input_value(socket_to_compute)}; } + if (from_group_inputs.size() == 1) { - /* The input gets its value from the input of a group that is not further connected. */ - return get_unlinked_input_value(socket_to_compute); + return {get_unlinked_input_value(socket_to_compute)}; + } + + /* Multi-input sockets contain a vector of inputs. */ + if (socket_to_compute.is_multi_input_socket()) { + Vector<GMutablePointer> values; + for (const DOutputSocket *from_socket : from_sockets) { + const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair( + &socket_to_compute, from_socket); + std::optional<GMutablePointer> value = value_by_input_.pop_try(key); + if (value.has_value()) { + values.append(*value); + } + else { + this->compute_output_and_forward(*from_socket); + GMutablePointer value = value_by_input_.pop(key); + values.append(value); + } + } + return values; } - /* Compute the socket now. */ const DOutputSocket &from_socket = *from_sockets[0]; + const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair( + &socket_to_compute, &from_socket); + std::optional<GMutablePointer> value = value_by_input_.pop_try(key); + if (value.has_value()) { + /* This input has been computed before, return it directly. */ + return {*value}; + } + + /* Compute the socket now. */ this->compute_output_and_forward(from_socket); - return value_by_input_.pop(&socket_to_compute); + return {value_by_input_.pop(key)}; } void compute_output_and_forward(const DOutputSocket &socket_to_compute) @@ -299,14 +323,21 @@ class GeometryNodesEvaluator { GValueMap<StringRef> node_inputs_map{allocator_}; for (const DInputSocket *input_socket : node.inputs()) { if (input_socket->is_available()) { - GMutablePointer value = this->get_input_value(*input_socket); - node_inputs_map.add_new_direct(input_socket->identifier(), value); + Vector<GMutablePointer> values = this->get_input_values(*input_socket); + for (int i = 0; i < values.size(); ++i) { + /* Values from Multi Input Sockets are stored in input map with the format + * <identifier>[<index>]. */ + blender::StringRefNull key = allocator_.copy_string( + input_socket->identifier() + (i > 0 ? ("[" + std::to_string(i)) + "]" : "")); + node_inputs_map.add_new_direct(key, std::move(values[i])); + } } } /* Execute the node. */ GValueMap<StringRef> node_outputs_map{allocator_}; - GeoNodeExecParams params{bnode, node_inputs_map, node_outputs_map, handle_map_, self_object_}; + GeoNodeExecParams params{ + bnode, node_inputs_map, node_outputs_map, handle_map_, self_object_, depsgraph_}; this->execute_node(node, params); /* Forward computed outputs to linked input sockets. */ @@ -389,13 +420,15 @@ class GeometryNodesEvaluator { void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward) { + /* For all sockets that are linked with the from_socket push the value to their node. */ Span<const DInputSocket *> to_sockets_all = from_socket.linked_sockets(); const CPPType &from_type = *value_to_forward.type(); - Vector<const DInputSocket *> to_sockets_same_type; for (const DInputSocket *to_socket : to_sockets_all) { const CPPType &to_type = *blender::nodes::socket_cpp_type_get(*to_socket->typeinfo()); + const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair( + to_socket, &from_socket); if (from_type == to_type) { to_sockets_same_type.append(to_socket); } @@ -407,7 +440,7 @@ class GeometryNodesEvaluator { else { to_type.copy_to_uninitialized(to_type.default_value(), buffer); } - value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + add_value_to_input_socket(key, GMutablePointer{to_type, buffer}); } } @@ -418,23 +451,35 @@ class GeometryNodesEvaluator { else if (to_sockets_same_type.size() == 1) { /* This value is only used on one input socket, no need to copy it. */ const DInputSocket *to_socket = to_sockets_same_type[0]; - value_by_input_.add_new(to_socket, value_to_forward); + const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair( + to_socket, &from_socket); + + add_value_to_input_socket(key, value_to_forward); } else { /* Multiple inputs use the value, make a copy for every input except for one. */ const DInputSocket *first_to_socket = to_sockets_same_type[0]; Span<const DInputSocket *> other_to_sockets = to_sockets_same_type.as_span().drop_front(1); const CPPType &type = *value_to_forward.type(); - - value_by_input_.add_new(first_to_socket, value_to_forward); + const std::pair<const DInputSocket *, const DOutputSocket *> first_key = std::make_pair( + first_to_socket, &from_socket); + add_value_to_input_socket(first_key, value_to_forward); for (const DInputSocket *to_socket : other_to_sockets) { + const std::pair<const DInputSocket *, const DOutputSocket *> key = std::make_pair( + to_socket, &from_socket); void *buffer = allocator_.allocate(type.size(), type.alignment()); type.copy_to_uninitialized(value_to_forward.get(), buffer); - value_by_input_.add_new(to_socket, GMutablePointer{type, buffer}); + add_value_to_input_socket(key, GMutablePointer{type, buffer}); } } } + void add_value_to_input_socket(const std::pair<const DInputSocket *, const DOutputSocket *> key, + GMutablePointer value) + { + value_by_input_.add_new(key, value); + } + GMutablePointer get_unlinked_input_value(const DInputSocket &socket) { bNodeSocket *bsocket; @@ -473,7 +518,7 @@ class GeometryNodesEvaluator { * TODO(Hans): Codify this with some sort of table or refactor IDProperty use in RNA_access.c. */ struct SocketPropertyType { - /* Create the actual propery used to store the data for the modifier. */ + /* Create the actual property used to store the data for the modifier. */ IDProperty *(*create_prop)(const bNodeSocket &socket, const char *name); /* Reused to build the "soft_min" property too. */ IDProperty *(*create_min_ui_prop)(const bNodeSocket &socket, const char *name); @@ -926,7 +971,7 @@ static GeometrySet compute_geometry(const DerivedNodeTree &tree, group_outputs.append(&socket_to_compute); GeometryNodesEvaluator evaluator{ - group_inputs, group_outputs, mf_by_node, handle_map, ctx->object}; + group_inputs, group_outputs, mf_by_node, handle_map, ctx->object, ctx->depsgraph}; Vector<GMutablePointer> results = evaluator.execute(); BLI_assert(results.size() == 1); GMutablePointer result = results[0]; diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index ba370b401f3..84360caa345 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -486,9 +486,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * /* * Normal Calculation (for face flipping) * Sort edge verts for correct face flipping - * NOT REALLY NEEDED but face flipping is nice. - * - * */ + * NOT REALLY NEEDED but face flipping is nice. */ /* Notice! * @@ -780,7 +778,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * * use edge connectivity work this out */ if (SV_IS_VALID(vc->v[0])) { if (SV_IS_VALID(vc->v[1])) { - /* 2 edges connedted */ + /* 2 edges connected. */ /* make 2 connecting vert locations relative to the middle vert */ sub_v3_v3v3(tmp_vec1, mvert_new[vc->v[0]].co, mvert_new[i].co); sub_v3_v3v3(tmp_vec2, mvert_new[vc->v[1]].co, mvert_new[i].co); diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index e41e70864dc..ea31bdc6e31 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -256,7 +256,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, smd->limit[0] = min_ff(smd->limit[0], smd->limit[1]); /* Upper limit >= than lower limit */ - /* Calculate matrixs do convert between coordinate spaces */ + /* Calculate matrix to convert between coordinate spaces. */ if (smd->origin != NULL) { transf = &tmp_transf; BLI_SPACE_TRANSFORM_SETUP(transf, ob, smd->origin); @@ -314,7 +314,7 @@ static void SimpleDeformModifier_do(SimpleDeformModifierData *smd, simpleDeform_callback = simpleDeform_stretch; break; default: - return; /* No simpledeform mode? */ + return; /* No simple-deform mode? */ } if (smd->mode == MOD_SIMPLEDEFORM_MODE_BEND) { diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index f62980ec4fd..0f8503eddde 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -2434,9 +2434,9 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, vm[orig_mloop[loopstart + j].v]); BLI_assert(flip || vm[orig_medge[new_edge->old_edge].v1] == vm[orig_mloop[loopstart + j].v]); - /* The vert thats in the current loop. */ + /* The vert that's in the current loop. */ const uint new_v1 = new_edge->link_edge_groups[flip]->new_vert; - /* The vert thats in the next loop. */ + /* The vert that's in the next loop. */ const uint new_v2 = new_edge->link_edge_groups[1 - flip]->new_vert; if (k == 0 || face_verts[k - 1] != new_v1) { face_loops[k] = loopstart + j; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 0fad78683eb..99011c5e351 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -104,7 +104,7 @@ typedef struct SDefBindCalcData { * needed once when running bind, so optimizing this structure isn't a priority. */ typedef struct SDefBindPoly { - /** Coordinates copied directly from the modifiers inptut. */ + /** Coordinates copied directly from the modifiers input. */ float (*coords)[3]; /** Coordinates projected into 2D space using `normal`. */ float (*coords_v2)[2]; @@ -114,7 +114,12 @@ typedef struct SDefBindPoly { float weight_dist_proj; float weight_dist; float weight; + /** Distances from the centroid to edges flanking the corner vertex, used to penalize + * small or long and narrow faces in favor of bigger and more square ones. */ float scales[2]; + /** Distance weight from the corner vertex to the chord line, used to penalize + * cases with the three consecutive vertices being nearly in line. */ + float scale_mid; /** Center of `coords` */ float centroid[3]; /** Center of `coords_v2` */ @@ -123,15 +128,18 @@ typedef struct SDefBindPoly { * The calculated normal of coords (could be shared between faces). */ float normal[3]; + /** Vectors pointing from the centroid to the midpoints of the two edges + * flanking the corner vertex. */ float cent_edgemid_vecs_v2[2][2]; - /** - * The unsigned angle of this face-corner in `[0.0 .. PI]` range, - * where a small value is a thin corner. PI is a straight line. - * Take care dividing by this value as it can approach zero. - */ + /** Angle between the cent_edgemid_vecs_v2 vectors. */ float edgemid_angle; + /** Angles between the centroid-to-point and cent_edgemid_vecs_v2 vectors. + * Positive values measured towards the corner; clamped non-negative. */ float point_edgemid_angles[2]; + /** Angles between the centroid-to-corner and cent_edgemid_vecs_v2 vectors. */ float corner_edgemid_angles[2]; + /** Weight of the bind mode based on the corner and two adjacent vertices, + * versus the one based on the centroid and the dominant edge. */ float dominant_angle_weight; /** Index of the input polygon. */ uint index; @@ -414,13 +422,14 @@ BLI_INLINE uint nearestVert(SDefBindCalcData *const data, const float point_co[3 BLI_INLINE int isPolyValid(const float coords[][2], const uint nr) { - float prev_co[2]; + float prev_co[2], prev_prev_co[2]; float curr_vec[2], prev_vec[2]; if (!is_poly_convex_v2(coords, nr)) { return MOD_SDEF_BIND_RESULT_CONCAVE_ERR; } + copy_v2_v2(prev_prev_co, coords[nr - 2]); copy_v2_v2(prev_co, coords[nr - 1]); sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]); normalize_v2(prev_vec); @@ -428,15 +437,23 @@ BLI_INLINE int isPolyValid(const float coords[][2], const uint nr) for (int i = 0; i < nr; i++) { sub_v2_v2v2(curr_vec, coords[i], prev_co); + /* Check overlap between directly adjacent vertices. */ const float curr_len = normalize_v2(curr_vec); if (curr_len < FLT_EPSILON) { return MOD_SDEF_BIND_RESULT_OVERLAP_ERR; } + /* Check overlap between vertices skipping one. */ + if (len_squared_v2v2(prev_prev_co, coords[i]) < FLT_EPSILON * FLT_EPSILON) { + return MOD_SDEF_BIND_RESULT_OVERLAP_ERR; + } + + /* Check for adjacent parallel edges. */ if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) { return MOD_SDEF_BIND_RESULT_CONCAVE_ERR; } + copy_v2_v2(prev_prev_co, prev_co); copy_v2_v2(prev_co, coords[i]); copy_v2_v2(prev_vec, curr_vec); } @@ -460,9 +477,9 @@ static void freeBindData(SDefBindWeightData *const bwdata) MEM_freeN(bwdata); } -BLI_INLINE float computeAngularWeight(const float point_angle) +BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle) { - return sinf(point_angle * M_PI_2); + return sinf(min_ff(point_angle / edgemid_angle, 1) * M_PI_2); } BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, @@ -603,33 +620,51 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, avg_point_dist += bpoly->weight_dist; - /* Compute centroid to mid-edge vectors */ - mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0], - bpoly->coords_v2[bpoly->edge_vert_inds[0]], - bpoly->coords_v2[bpoly->corner_ind]); + /* Common vertex coordinates. */ + const float *const vert0_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[0]]; + const float *const vert1_v2 = bpoly->coords_v2[bpoly->edge_vert_inds[1]]; + const float *const corner_v2 = bpoly->coords_v2[bpoly->corner_ind]; - mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1], - bpoly->coords_v2[bpoly->edge_vert_inds[1]], - bpoly->coords_v2[bpoly->corner_ind]); + /* Compute centroid to mid-edge vectors */ + mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0], vert0_v2, corner_v2); + mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1], vert1_v2, corner_v2); sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2); sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2); - /* Compute poly scales with respect to mid-edges, and normalize the vectors */ - bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]); - bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]); + normalize_v2(bpoly->cent_edgemid_vecs_v2[0]); + normalize_v2(bpoly->cent_edgemid_vecs_v2[1]); - /* Compute the required polygon angles */ + /* Compute poly scales with respect to the two edges. */ + bpoly->scales[0] = dist_to_line_v2(bpoly->centroid_v2, vert0_v2, corner_v2); + bpoly->scales[1] = dist_to_line_v2(bpoly->centroid_v2, vert1_v2, corner_v2); + + /* Compute the angle between the edge mid vectors. */ bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->cent_edgemid_vecs_v2[1]); - sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2); + /* Compute the angles between the corner and the edge mid vectors. The angles + * are computed signed in order to correctly clamp point_edgemid_angles later. */ + float corner_angles[2]; + + sub_v2_v2v2(tmp_vec_v2, corner_v2, bpoly->centroid_v2); normalize_v2(tmp_vec_v2); - bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2, - bpoly->cent_edgemid_vecs_v2[0]); - bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2, - bpoly->cent_edgemid_vecs_v2[1]); + corner_angles[0] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]); + corner_angles[1] = angle_signed_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]); + + bpoly->corner_edgemid_angles[0] = fabsf(corner_angles[0]); + bpoly->corner_edgemid_angles[1] = fabsf(corner_angles[1]); + + /* Verify that the computed values are valid (the polygon isn't somehow + * degenerate despite having passed isPolyValid). */ + if (bpoly->scales[0] < FLT_EPSILON || bpoly->scales[1] < FLT_EPSILON || + bpoly->edgemid_angle < FLT_EPSILON || bpoly->corner_edgemid_angles[0] < FLT_EPSILON || + bpoly->corner_edgemid_angles[1] < FLT_EPSILON) { + freeBindData(bwdata); + data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + return NULL; + } /* Check for infinite weights, and compute angular data otherwise. */ if (bpoly->weight_dist < FLT_EPSILON) { @@ -640,15 +675,54 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ; } else { - float cent_point_vec[2]; + /* Compute angles between the point and the edge mid vectors. */ + float cent_point_vec[2], point_angles[2]; sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2); normalize_v2(cent_point_vec); - bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec, - bpoly->cent_edgemid_vecs_v2[0]); - bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec, - bpoly->cent_edgemid_vecs_v2[1]); + point_angles[0] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]) * + signf(corner_angles[0]); + point_angles[1] = angle_signed_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]) * + signf(corner_angles[1]); + + if (point_angles[0] <= 0 && point_angles[1] <= 0) { + /* If the point is outside the corner formed by the edge mid vectors, + * choose to clamp the closest side and flip the other. */ + if (point_angles[0] < point_angles[1]) { + point_angles[0] = bpoly->edgemid_angle - point_angles[1]; + } + else { + point_angles[1] = bpoly->edgemid_angle - point_angles[0]; + } + } + + bpoly->point_edgemid_angles[0] = max_ff(0, point_angles[0]); + bpoly->point_edgemid_angles[1] = max_ff(0, point_angles[1]); + + /* Compute the distance scale for the corner. The base value is the orthogonal + * distance from the corner to the chord, scaled by sqrt(2) to preserve the old + * values in case of a square grid. This doesn't use the centroid because the + * LOOPTRI method only uses these three vertices. */ + bpoly->scale_mid = area_tri_v2(vert0_v2, corner_v2, vert1_v2) / + len_v2v2(vert0_v2, vert1_v2) * sqrtf(2); + + if (bpoly->inside) { + /* When inside, interpolate to centroid-based scale close to the center. */ + float min_dist = min_ff(bpoly->scales[0], bpoly->scales[1]); + + bpoly->scale_mid = interpf(bpoly->scale_mid, + (bpoly->scales[0] + bpoly->scales[1]) / 2, + min_ff(bpoly->weight_dist_proj / min_dist, 1)); + } + + /* Verify that the additional computed values are valid. */ + if (bpoly->scale_mid < FLT_EPSILON || + bpoly->point_edgemid_angles[0] + bpoly->point_edgemid_angles[1] < FLT_EPSILON) { + freeBindData(bwdata); + data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + return NULL; + } } } } @@ -688,12 +762,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, /* Compute angular weight component */ if (epolys->num == 1) { - ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]); + ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], + bpolys[0]->edgemid_angle); bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0]; } else if (epolys->num == 2) { - ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]); - ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]]); + ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], + bpolys[0]->edgemid_angle); + ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]], + bpolys[1]->edgemid_angle); bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1]; bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1]; @@ -731,6 +808,13 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, bpoly->dominant_angle_weight = corner_angle_weights[1]; } + /* Check for invalid weights just in case computations fail. */ + if (bpoly->dominant_angle_weight < 0 || bpoly->dominant_angle_weight > 1) { + freeBindData(bwdata); + data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR; + return NULL; + } + bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2); /* Compute quadratic angular scale interpolation weight */ @@ -748,10 +832,15 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data, inv_sqr *= inv_sqr; scale_weight = sqr / (sqr + inv_sqr); + BLI_assert(scale_weight >= 0 && scale_weight <= 1); + /* Compute interpolated scale (no longer need the individual scales, * so simply storing the result over the scale in index zero) */ - bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) + - bpoly->scales[!bpoly->dominant_edge] * scale_weight; + bpoly->scales[0] = interpf(bpoly->scale_mid, + interpf(bpoly->scales[!bpoly->dominant_edge], + bpoly->scales[bpoly->dominant_edge], + scale_weight), + bpoly->dominant_angle_weight); /* Scale the point distance weights, and introduce falloff */ bpoly->weight_dist_proj /= bpoly->scales[0]; diff --git a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc index 941bc8409f7..41ed7ae983a 100644 --- a/source/blender/modifiers/intern/MOD_volume_to_mesh.cc +++ b/source/blender/modifiers/intern/MOD_volume_to_mesh.cc @@ -24,6 +24,7 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_volume.h" +#include "BKE_volume_to_mesh.hh" #include "MOD_modifiertypes.h" #include "MOD_ui_common.h" @@ -128,139 +129,6 @@ static void panelRegister(ARegionType *region_type) modifier_panel_register(region_type, eModifierType_VolumeToMesh, panel_draw); } -#ifdef WITH_OPENVDB - -struct VolumeToMeshOp { - const openvdb::GridBase &base_grid; - VolumeToMeshModifierData &vmmd; - const ModifierEvalContext &ctx; - std::vector<openvdb::Vec3s> verts; - std::vector<openvdb::Vec3I> tris; - std::vector<openvdb::Vec4I> quads; - - template<typename GridType> bool operator()() - { - if constexpr (std::is_scalar_v<typename GridType::ValueType>) { - this->generate_mesh_data<GridType>(); - return true; - } - else { - return false; - } - } - - template<typename GridType> void generate_mesh_data() - { - /* Make a new transform from the index space into the mesh object space. */ - openvdb::math::Transform::Ptr transform = this->base_grid.transform().copy(); - transform->postMult(openvdb::Mat4d((float *)vmmd.object->obmat)); - openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx.object->imat); - /* `imat` had floating point issues and wasn't affine. */ - imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); - transform->postMult(imat); - - /* Create a new grid with a different transform. The underlying tree is shared. */ - typename GridType::ConstPtr grid = openvdb::gridConstPtrCast<GridType>( - this->base_grid.copyGridReplacingTransform(transform)); - - if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_GRID) { - this->grid_to_mesh(*grid); - return; - } - - const float resolution_factor = this->compute_resolution_factor(*grid); - typename GridType::Ptr temp_grid = this->create_grid_with_changed_resolution( - *grid, resolution_factor); - this->grid_to_mesh(*temp_grid); - } - - template<typename GridType> - typename GridType::Ptr create_grid_with_changed_resolution(const GridType &old_grid, - const float resolution_factor) - { - BLI_assert(resolution_factor > 0.0f); - - openvdb::Mat4R xform; - xform.setToScale(openvdb::Vec3d(resolution_factor)); - openvdb::tools::GridTransformer transformer{xform}; - - typename GridType::Ptr new_grid = GridType::create(); - transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid); - new_grid->transform() = old_grid.transform(); - new_grid->transform().preScale(1.0f / resolution_factor); - return new_grid; - } - - float compute_resolution_factor(const openvdb::GridBase &grid) const - { - const openvdb::Vec3s voxel_size{grid.voxelSize()}; - const float current_voxel_size = std::max({voxel_size[0], voxel_size[1], voxel_size[2]}); - const float desired_voxel_size = this->compute_desired_voxel_size(grid); - return current_voxel_size / desired_voxel_size; - } - - float compute_desired_voxel_size(const openvdb::GridBase &grid) const - { - if (this->vmmd.resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { - return this->vmmd.voxel_size; - } - const openvdb::CoordBBox coord_bbox = base_grid.evalActiveVoxelBoundingBox(); - const openvdb::BBoxd bbox = grid.transform().indexToWorld(coord_bbox); - const float max_extent = bbox.extents()[bbox.maxExtent()]; - const float voxel_size = max_extent / this->vmmd.voxel_amount; - return voxel_size; - } - - template<typename GridType> void grid_to_mesh(const GridType &grid) - { - openvdb::tools::volumeToMesh( - grid, this->verts, this->tris, this->quads, this->vmmd.threshold, this->vmmd.adaptivity); - } -}; - -static Mesh *new_mesh_from_openvdb_data(Span<openvdb::Vec3s> verts, - Span<openvdb::Vec3I> tris, - Span<openvdb::Vec4I> quads) -{ - const int tot_loops = 3 * tris.size() + 4 * quads.size(); - const int tot_polys = tris.size() + quads.size(); - - Mesh *mesh = BKE_mesh_new_nomain(verts.size(), 0, 0, tot_loops, tot_polys); - - /* Write vertices. */ - for (const int i : verts.index_range()) { - const blender::float3 co = blender::float3(verts[i].asV()); - copy_v3_v3(mesh->mvert[i].co, co); - } - - /* Write triangles. */ - for (const int i : tris.index_range()) { - mesh->mpoly[i].loopstart = 3 * i; - mesh->mpoly[i].totloop = 3; - for (int j = 0; j < 3; j++) { - /* Reverse vertex order to get correct normals. */ - mesh->mloop[3 * i + j].v = tris[i][2 - j]; - } - } - - /* Write quads. */ - const int poly_offset = tris.size(); - const int loop_offset = tris.size() * 3; - for (const int i : quads.index_range()) { - mesh->mpoly[poly_offset + i].loopstart = loop_offset + 4 * i; - mesh->mpoly[poly_offset + i].totloop = 4; - for (int j = 0; j < 4; j++) { - /* Reverse vertex order to get correct normals. */ - mesh->mloop[loop_offset + 4 * i + j].v = quads[i][3 - j]; - } - } - - BKE_mesh_calc_edges(mesh, false, false); - BKE_mesh_calc_normals(mesh); - return mesh; -} -#endif - static Mesh *create_empty_mesh(const Mesh *input_mesh) { Mesh *new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0); @@ -296,16 +164,35 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * return create_empty_mesh(input_mesh); } - const openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); + const openvdb::GridBase::ConstPtr local_grid = BKE_volume_grid_openvdb_for_read(volume, + volume_grid); + + openvdb::math::Transform::Ptr transform = local_grid->transform().copy(); + transform->postMult(openvdb::Mat4d(((float *)vmmd->object->obmat))); + openvdb::Mat4d imat = openvdb::Mat4d((float *)ctx->object->imat); + /* `imat` had floating point issues and wasn't affine. */ + imat.setCol(3, openvdb::Vec4d(0, 0, 0, 1)); + transform->postMult(imat); + + /* Create a temporary transformed grid. The underlying tree is shared. */ + openvdb::GridBase::ConstPtr transformed_grid = local_grid->copyGridReplacingTransform(transform); + + blender::bke::VolumeToMeshResolution resolution; + resolution.mode = (VolumeToMeshResolutionMode)vmmd->resolution_mode; + if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT) { + resolution.settings.voxel_amount = vmmd->voxel_amount; + } + if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + resolution.settings.voxel_size = vmmd->voxel_size; + } - const VolumeGridType grid_type = BKE_volume_grid_type(volume_grid); - VolumeToMeshOp to_mesh_op{*grid, *vmmd, *ctx}; - if (!BKE_volume_grid_type_operation(grid_type, to_mesh_op)) { - BKE_modifier_set_error(ctx->object, md, "Expected a scalar grid"); + Mesh *mesh = blender::bke::volume_to_mesh( + *transformed_grid, resolution, vmmd->threshold, vmmd->adaptivity); + if (mesh == nullptr) { + BKE_modifier_set_error(ctx->object, md, "Could not generate mesh from grid"); return create_empty_mesh(input_mesh); } - Mesh *mesh = new_mesh_from_openvdb_data(to_mesh_op.verts, to_mesh_op.tris, to_mesh_op.quads); BKE_mesh_copy_settings(mesh, input_mesh); if (vmmd->flag & VOLUME_TO_MESH_USE_SMOOTH_SHADE) { BKE_mesh_smooth_flag_set(mesh, true); diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index ed4d658eb4f..64c240eb5fd 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -26,6 +26,7 @@ set(INC intern shader texture + ../editors/include ../blenkernel ../blenlib ../blentranslation @@ -142,15 +143,21 @@ set(SRC geometry/nodes/node_geo_align_rotation_to_vector.cc geometry/nodes/node_geo_attribute_color_ramp.cc + geometry/nodes/node_geo_attribute_combine_xyz.cc geometry/nodes/node_geo_attribute_compare.cc geometry/nodes/node_geo_attribute_fill.cc geometry/nodes/node_geo_attribute_math.cc geometry/nodes/node_geo_attribute_mix.cc + geometry/nodes/node_geo_attribute_sample_texture.cc + geometry/nodes/node_geo_attribute_proximity.cc geometry/nodes/node_geo_attribute_randomize.cc + geometry/nodes/node_geo_attribute_separate_xyz.cc geometry/nodes/node_geo_attribute_vector_math.cc geometry/nodes/node_geo_boolean.cc + geometry/nodes/node_geo_collection_info.cc geometry/nodes/node_geo_common.cc geometry/nodes/node_geo_edge_split.cc + geometry/nodes/node_geo_is_viewport.cc geometry/nodes/node_geo_join_geometry.cc geometry/nodes/node_geo_object_info.cc geometry/nodes/node_geo_point_distribute.cc @@ -159,9 +166,11 @@ set(SRC geometry/nodes/node_geo_point_scale.cc geometry/nodes/node_geo_point_separate.cc geometry/nodes/node_geo_point_translate.cc + geometry/nodes/node_geo_points_to_volume.cc geometry/nodes/node_geo_subdivision_surface.cc geometry/nodes/node_geo_transform.cc geometry/nodes/node_geo_triangulate.cc + geometry/nodes/node_geo_volume_to_mesh.cc geometry/node_geometry_exec.cc geometry/node_geometry_tree.cc geometry/node_geometry_util.cc @@ -347,6 +356,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) +endif() + if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() @@ -366,4 +379,11 @@ if(WITH_OPENSUBDIV) add_definitions(-DWITH_OPENSUBDIV) endif() +if(WITH_OPENVDB) + list(APPEND INC_SYS + ${OPENVDB_INCLUDE_DIRS} + ) + add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS}) +endif() + blender_add_lib(bf_nodes "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/nodes/NOD_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh index 4d594a77ebc..62affe43895 100644 --- a/source/blender/nodes/NOD_derived_node_tree.hh +++ b/source/blender/nodes/NOD_derived_node_tree.hh @@ -80,6 +80,7 @@ class DInputSocket : public DSocket { private: Vector<DOutputSocket *> linked_sockets_; Vector<DGroupInput *> linked_group_inputs_; + bool is_multi_input_socket_; friend DerivedNodeTree; @@ -90,6 +91,7 @@ class DInputSocket : public DSocket { Span<const DGroupInput *> linked_group_inputs() const; bool is_linked() const; + bool is_multi_input_socket() const; }; class DOutputSocket : public DSocket { @@ -362,6 +364,11 @@ inline bool DInputSocket::is_linked() const return linked_sockets_.size() > 0 || linked_group_inputs_.size() > 0; } +inline bool DInputSocket::is_multi_input_socket() const +{ + return is_multi_input_socket_; +} + /* -------------------------------------------------------------------- * DOutputSocket inline methods. */ diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h index 75dd8f89bc8..b5279f7d914 100644 --- a/source/blender/nodes/NOD_function.h +++ b/source/blender/nodes/NOD_function.h @@ -21,13 +21,13 @@ extern "C" { #endif void register_node_type_fn_boolean_math(void); +void register_node_type_fn_combine_strings(void); void register_node_type_fn_float_compare(void); -void register_node_type_fn_switch(void); void register_node_type_fn_group_instance_id(void); -void register_node_type_fn_combine_strings(void); +void register_node_type_fn_input_vector(void); void register_node_type_fn_object_transforms(void); void register_node_type_fn_random_float(void); -void register_node_type_fn_input_vector(void); +void register_node_type_fn_switch(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index 523d0cfa24d..8980855fd51 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -26,27 +26,35 @@ void register_node_tree_type_geo(void); void register_node_type_geo_group(void); +void register_node_type_geo_align_rotation_to_vector(void); +void register_node_type_geo_attribute_color_ramp(void); +void register_node_type_geo_attribute_combine_xyz(void); +void register_node_type_geo_attribute_compare(void); void register_node_type_geo_attribute_fill(void); +void register_node_type_geo_attribute_math(void); +void register_node_type_geo_attribute_mix(void); +void register_node_type_geo_attribute_proximity(void); +void register_node_type_geo_attribute_randomize(void); +void register_node_type_geo_attribute_separate_xyz(void); void register_node_type_geo_attribute_vector_math(void); void register_node_type_geo_boolean(void); +void register_node_type_geo_collection_info(void); void register_node_type_geo_edge_split(void); -void register_node_type_geo_transform(void); -void register_node_type_geo_subdivision_surface(void); -void register_node_type_geo_triangulate(void); +void register_node_type_geo_is_viewport(void); +void register_node_type_geo_join_geometry(void); +void register_node_type_geo_object_info(void); void register_node_type_geo_point_distribute(void); void register_node_type_geo_point_instance(void); -void register_node_type_geo_object_info(void); -void register_node_type_geo_attribute_randomize(void); -void register_node_type_geo_attribute_math(void); -void register_node_type_geo_join_geometry(void); -void register_node_type_geo_point_separate(void); +void register_node_type_geo_point_rotate(void); void register_node_type_geo_point_scale(void); +void register_node_type_geo_point_separate(void); void register_node_type_geo_point_translate(void); -void register_node_type_geo_attribute_compare(void); -void register_node_type_geo_attribute_mix(void); -void register_node_type_geo_attribute_color_ramp(void); -void register_node_type_geo_point_rotate(void); -void register_node_type_geo_align_rotation_to_vector(void); +void register_node_type_geo_points_to_volume(void); +void register_node_type_geo_sample_texture(void); +void register_node_type_geo_subdivision_surface(void); +void register_node_type_geo_transform(void); +void register_node_type_geo_triangulate(void); +void register_node_type_geo_volume_to_mesh(void); #ifdef __cplusplus } diff --git a/source/blender/nodes/NOD_geometry_exec.hh b/source/blender/nodes/NOD_geometry_exec.hh index f278d6b4107..91d46e3951f 100644 --- a/source/blender/nodes/NOD_geometry_exec.hh +++ b/source/blender/nodes/NOD_geometry_exec.hh @@ -24,12 +24,16 @@ #include "DNA_node_types.h" +struct Depsgraph; + namespace blender::nodes { using bke::BooleanReadAttribute; using bke::BooleanWriteAttribute; using bke::Color4fReadAttribute; using bke::Color4fWriteAttribute; +using bke::Float2ReadAttribute; +using bke::Float2WriteAttribute; using bke::Float3ReadAttribute; using bke::Float3WriteAttribute; using bke::FloatReadAttribute; @@ -54,18 +58,21 @@ class GeoNodeExecParams { GValueMap<StringRef> &output_values_; const PersistentDataHandleMap &handle_map_; const Object *self_object_; + Depsgraph *depsgraph_; public: GeoNodeExecParams(const bNode &node, GValueMap<StringRef> &input_values, GValueMap<StringRef> &output_values, const PersistentDataHandleMap &handle_map, - const Object *self_object) + const Object *self_object, + Depsgraph *depsgraph) : node_(node), input_values_(input_values), output_values_(output_values), handle_map_(handle_map), - self_object_(self_object) + self_object_(self_object), + depsgraph_(depsgraph) { } @@ -97,6 +104,25 @@ class GeoNodeExecParams { } /** + * Get input as vector for multi input socket with the given identifier. + * + * This method can only be called once for each identifier. + */ + template<typename T> Vector<T> extract_multi_input(StringRef identifier) + { + Vector<T> values; + values.append(input_values_.extract<T>(identifier)); + int i = 1; + std::string sub_identifier = identifier + "[1]"; + while (input_values_.contains(sub_identifier)) { + values.append(input_values_.extract<T>(sub_identifier)); + i++; + sub_identifier = identifier + "[" + std::to_string(i) + "]"; + } + return values; + } + + /** * Get the input value for the input socket with the given identifier. * * This makes a copy of the value, which is fine for most types but should be avoided for @@ -163,6 +189,11 @@ class GeoNodeExecParams { return self_object_; } + Depsgraph *depsgraph() const + { + return depsgraph_; + } + /** * Creates a read-only attribute based on node inputs. The method automatically detects which * input with the given name is available. diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index e91b385a87e..15f078cebf2 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -289,6 +289,14 @@ DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_VECTOR_MATH, def_geo_attribute_vector_m DefNode(GeometryNode, GEO_NODE_ALIGN_ROTATION_TO_VECTOR, def_geo_align_rotation_to_vector, "ALIGN_ROTATION_TO_VECTOR", AlignRotationToVector, "Align Rotation to Vector", "") DefNode(GeometryNode, GEO_NODE_POINT_SCALE, def_geo_point_scale, "POINT_SCALE", PointScale, "Point Scale", "") DefNode(GeometryNode, GEO_NODE_POINT_TRANSLATE, def_geo_point_translate, "POINT_TRANSLATE", PointTranslate, "Point Translate", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE, def_geo_attribute_sample_texture, "ATTRIBUTE_SAMPLE_TEXTURE", AttributeSampleTexture, "Attribute Sample Texture", "") +DefNode(GeometryNode, GEO_NODE_POINTS_TO_VOLUME, def_geo_points_to_volume, "POINTS_TO_VOLUME", PointsToVolume, "Points to Volume", "") +DefNode(GeometryNode, GEO_NODE_COLLECTION_INFO, def_geo_collection_info, "COLLECTION_INFO", CollectionInfo, "Collection Info", "") +DefNode(GeometryNode, GEO_NODE_IS_VIEWPORT, 0, "IS_VIEWPORT", IsViewport, "Is Viewport", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_PROXIMITY, def_geo_attribute_proximity, "ATTRIBUTE_PROXIMITY", AttributeProximity, "Attribute Proximity", "") +DefNode(GeometryNode, GEO_NODE_VOLUME_TO_MESH, def_geo_volume_to_mesh, "VOLUME_TO_MESH", VolumeToMesh, "Volume to Mesh", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_COMBINE_XYZ, def_geo_attribute_combine_xyz, "ATTRIBUTE_COMBINE_XYZ", AttributeCombineXYZ, "Attribute Combine XYZ", "") +DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_SEPARATE_XYZ, def_geo_attribute_separate_xyz, "ATTRIBUTE_SEPARATE_XYZ", AttributeSeparateXYZ, "Attribute Separate XYZ", "") /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc index 9148cef7805..7a83ff8e016 100644 --- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc +++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc @@ -19,6 +19,9 @@ #include "RNA_enum_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_function_util.hh" static bNodeSocketTemplate fn_node_boolean_math_in[] = { @@ -32,6 +35,11 @@ static bNodeSocketTemplate fn_node_boolean_math_out[] = { {-1, ""}, }; +static void fn_node_boolean_math_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); +} + static void node_boolean_math_update(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1); @@ -86,5 +94,6 @@ void register_node_type_fn_boolean_math() node_type_label(&ntype, node_boolean_math_label); node_type_update(&ntype, node_boolean_math_update); ntype.expand_in_mf_network = node_boolean_expand_in_mf_network; + ntype.draw_buttons = fn_node_boolean_math_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc index 93c79a48571..6c8df8f2ea0 100644 --- a/source/blender/nodes/function/nodes/node_fn_float_compare.cc +++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc @@ -21,6 +21,9 @@ #include "RNA_enum_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_function_util.hh" static bNodeSocketTemplate fn_node_float_compare_in[] = { @@ -35,6 +38,11 @@ static bNodeSocketTemplate fn_node_float_compare_out[] = { {-1, ""}, }; +static void geo_node_float_compare_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); +} + static void node_float_compare_update(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sockEpsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 2); @@ -105,5 +113,6 @@ void register_node_type_fn_float_compare() node_type_label(&ntype, node_float_compare_label); node_type_update(&ntype, node_float_compare_update); ntype.expand_in_mf_network = node_float_compare_expand_in_mf_network; + ntype.draw_buttons = geo_node_float_compare_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/function/nodes/node_fn_input_vector.cc b/source/blender/nodes/function/nodes/node_fn_input_vector.cc index c2707f6307a..2cd4eb1d9df 100644 --- a/source/blender/nodes/function/nodes/node_fn_input_vector.cc +++ b/source/blender/nodes/function/nodes/node_fn_input_vector.cc @@ -18,11 +18,20 @@ #include "BLI_hash.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate fn_node_input_vector_out[] = { {SOCK_VECTOR, N_("Vector")}, {-1, ""}, }; +static void fn_node_input_vector_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayout *col = uiLayoutColumn(layout, true); + uiItemR(col, ptr, "vector", UI_ITEM_R_EXPAND, "", ICON_NONE); +} + static void fn_node_vector_input_expand_in_mf_network( blender::nodes::NodeMFNetworkBuilder &builder) { @@ -50,6 +59,6 @@ void register_node_type_fn_input_vector() node_type_storage( &ntype, "NodeInputVector", node_free_standard_storage, node_copy_standard_storage); ntype.expand_in_mf_network = fn_node_vector_input_expand_in_mf_network; - + ntype.draw_buttons = fn_node_input_vector_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/function/nodes/node_fn_switch.cc b/source/blender/nodes/function/nodes/node_fn_switch.cc index 281ddb05c76..5187decbbe5 100644 --- a/source/blender/nodes/function/nodes/node_fn_switch.cc +++ b/source/blender/nodes/function/nodes/node_fn_switch.cc @@ -15,8 +15,17 @@ */ #include "BLI_listbase.h" + +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_function_util.hh" +static void fn_node_switch_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); +} + static bNodeSocketTemplate fn_node_switch_in[] = { {SOCK_BOOLEAN, N_("Switch")}, @@ -72,5 +81,6 @@ void register_node_type_fn_switch() fn_node_type_base(&ntype, FN_NODE_SWITCH, "Switch", 0, 0); node_type_socket_templates(&ntype, fn_node_switch_in, fn_node_switch_out); node_type_update(&ntype, fn_node_switch_update); + ntype.draw_buttons = fn_node_switch_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc index 53af6073793..daaccf4450b 100644 --- a/source/blender/nodes/geometry/node_geometry_util.cc +++ b/source/blender/nodes/geometry/node_geometry_util.cc @@ -54,6 +54,8 @@ static int attribute_data_type_complexity(const CustomDataType data_type) return 1; case CD_PROP_FLOAT: return 2; + case CD_PROP_FLOAT2: + return 3; case CD_PROP_FLOAT3: return 4; case CD_PROP_COLOR: diff --git a/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc b/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc index eac77b25bd6..e592bd0bda8 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc @@ -18,6 +18,9 @@ #include "BLI_math_rotation.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_align_rotation_to_vector_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Factor")}, @@ -32,32 +35,25 @@ static bNodeSocketTemplate geo_node_align_rotation_to_vector_out[] = { {-1, ""}, }; -namespace blender::nodes { - -static void align_rotations_on_component(GeometryComponent &component, - const GeoNodeExecParams ¶ms) +static void geo_node_align_rotation_to_vector_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) { - const bNode &node = params.node(); - const NodeGeometryAlignRotationToVector &storage = *(const NodeGeometryAlignRotationToVector *) - node.storage; - - OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output( - "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); - if (!rotation_attribute) { - return; - } - MutableSpan<float3> rotations = rotation_attribute->get_span<float3>(); - - FloatReadAttribute factors = params.get_input_attribute<float>( - "Factor", component, ATTR_DOMAIN_POINT, 1.0f); - Float3ReadAttribute vectors = params.get_input_attribute<float3>( - "Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1}); + uiItemR(layout, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "pivot_axis", 0, IFACE_("Pivot"), ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "input_type_factor", 0, IFACE_("Factor"), ICON_NONE); + uiItemR(col, ptr, "input_type_vector", 0, IFACE_("Vector"), ICON_NONE); +} - float3 main_axis{0, 0, 0}; - main_axis[storage.axis] = 1; +namespace blender::nodes { - const int domain_size = component.attribute_domain_size(ATTR_DOMAIN_POINT); - for (const int i : IndexRange(domain_size)) { +static void align_rotations_auto_pivot(const Float3ReadAttribute &vectors, + const FloatReadAttribute &factors, + const float3 local_main_axis, + MutableSpan<float3> rotations) +{ + for (const int i : IndexRange(vectors.size())) { const float3 vector = vectors[i]; if (is_zero_v3(vector)) { continue; @@ -66,7 +62,7 @@ static void align_rotations_on_component(GeometryComponent &component, float old_rotation[3][3]; eul_to_mat3(old_rotation, rotations[i]); float3 old_axis; - mul_v3_m3v3(old_axis, old_rotation, main_axis); + mul_v3_m3v3(old_axis, old_rotation, local_main_axis); const float3 new_axis = vector.normalized(); const float3 rotation_axis = float3::cross_high_precision(old_axis, new_axis); @@ -84,6 +80,81 @@ static void align_rotations_on_component(GeometryComponent &component, rotations[i] = new_rotation; } +} + +static void align_rotations_fixed_pivot(const Float3ReadAttribute &vectors, + const FloatReadAttribute &factors, + const float3 local_main_axis, + const float3 local_pivot_axis, + MutableSpan<float3> rotations) +{ + if (local_main_axis == local_pivot_axis) { + /* Can't compute any meaningful rotation angle in this case. */ + return; + } + + for (const int i : IndexRange(vectors.size())) { + const float3 vector = vectors[i]; + if (is_zero_v3(vector)) { + continue; + } + + float old_rotation[3][3]; + eul_to_mat3(old_rotation, rotations[i]); + float3 old_axis; + mul_v3_m3v3(old_axis, old_rotation, local_main_axis); + float3 pivot_axis; + mul_v3_m3v3(pivot_axis, old_rotation, local_pivot_axis); + + float full_angle = angle_signed_on_axis_v3v3_v3(vector, old_axis, pivot_axis); + if (full_angle > M_PI) { + /* Make sure the point is rotated as little as possible. */ + full_angle -= 2.0f * M_PI; + } + const float angle = factors[i] * full_angle; + + float rotation[3][3]; + axis_angle_to_mat3(rotation, pivot_axis, angle); + + float new_rotation_matrix[3][3]; + mul_m3_m3m3(new_rotation_matrix, rotation, old_rotation); + + float3 new_rotation; + mat3_to_eul(new_rotation, new_rotation_matrix); + + rotations[i] = new_rotation; + } +} + +static void align_rotations_on_component(GeometryComponent &component, + const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + const NodeGeometryAlignRotationToVector &storage = *(const NodeGeometryAlignRotationToVector *) + node.storage; + + OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output( + "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + if (!rotation_attribute) { + return; + } + MutableSpan<float3> rotations = rotation_attribute->get_span<float3>(); + + FloatReadAttribute factors = params.get_input_attribute<float>( + "Factor", component, ATTR_DOMAIN_POINT, 1.0f); + Float3ReadAttribute vectors = params.get_input_attribute<float3>( + "Vector", component, ATTR_DOMAIN_POINT, {0, 0, 1}); + + float3 local_main_axis{0, 0, 0}; + local_main_axis[storage.axis] = 1; + if (storage.pivot_axis == GEO_NODE_ALIGN_ROTATION_TO_VECTOR_PIVOT_AXIS_AUTO) { + align_rotations_auto_pivot(vectors, factors, local_main_axis, rotations); + } + else { + float3 local_pivot_axis{0, 0, 0}; + local_pivot_axis[storage.pivot_axis - 1] = 1; + align_rotations_fixed_pivot(vectors, factors, local_main_axis, local_pivot_axis, rotations); + } rotation_attribute.apply_span_and_save(); } @@ -145,5 +216,6 @@ void register_node_type_geo_align_rotation_to_vector() node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_align_rotation_to_vector_exec; + ntype.draw_buttons = geo_node_align_rotation_to_vector_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc index 9b0900e19ab..179e418214c 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc @@ -18,6 +18,9 @@ #include "BKE_colorband.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_attribute_color_ramp_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Attribute")}, @@ -30,6 +33,13 @@ static bNodeSocketTemplate geo_node_attribute_color_ramp_out[] = { {-1, ""}, }; +static void geo_node_attribute_color_ramp_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiTemplateColorRamp(layout, ptr, "color_ramp", 0); +} + namespace blender::nodes { static void execute_on_component(const GeoNodeExecParams ¶ms, GeometryComponent &component) @@ -104,5 +114,6 @@ void register_node_type_geo_attribute_color_ramp() node_type_init(&ntype, blender::nodes::geo_node_attribute_color_ramp_init); node_type_size_preset(&ntype, NODE_SIZE_LARGE); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_color_ramp_exec; + ntype.draw_buttons = geo_node_attribute_color_ramp_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc new file mode 100644 index 00000000000..a231b4f9e92 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_combine_xyz.cc @@ -0,0 +1,135 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +static bNodeSocketTemplate geo_node_attribute_combine_xyz_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("X")}, + {SOCK_FLOAT, N_("X"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_STRING, N_("Y")}, + {SOCK_FLOAT, N_("Y"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_STRING, N_("Z")}, + {SOCK_FLOAT, N_("Z"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_combine_xyz_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_combine_xyz_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "input_type_x", 0, IFACE_("Type X"), ICON_NONE); + uiItemR(layout, ptr, "input_type_y", 0, IFACE_("Type Y"), ICON_NONE); + uiItemR(layout, ptr, "input_type_z", 0, IFACE_("Type Z"), ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_attribute_combine_xyz_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeAttributeCombineXYZ *data = (NodeAttributeCombineXYZ *)MEM_callocN( + sizeof(NodeAttributeCombineXYZ), __func__); + + data->input_type_x = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + data->input_type_y = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + data->input_type_z = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + node->storage = data; +} + +static void geo_node_attribute_combine_xyz_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeCombineXYZ *node_storage = (NodeAttributeCombineXYZ *)node->storage; + update_attribute_input_socket_availabilities( + *node, "X", (GeometryNodeAttributeInputMode)node_storage->input_type_x); + update_attribute_input_socket_availabilities( + *node, "Y", (GeometryNodeAttributeInputMode)node_storage->input_type_y); + update_attribute_input_socket_availabilities( + *node, "Z", (GeometryNodeAttributeInputMode)node_storage->input_type_z); +} + +static void combine_attributes(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const std::string result_name = params.get_input<std::string>("Result"); + /* The result domain is always point for now. */ + const AttributeDomain result_domain = ATTR_DOMAIN_POINT; + if (result_name.empty()) { + return; + } + + OutputAttributePtr attribute_result = component.attribute_try_get_for_output( + result_name, result_domain, CD_PROP_FLOAT3); + if (!attribute_result) { + return; + } + FloatReadAttribute attribute_x = params.get_input_attribute<float>( + "X", component, result_domain, 0.0f); + FloatReadAttribute attribute_y = params.get_input_attribute<float>( + "Y", component, result_domain, 0.0f); + FloatReadAttribute attribute_z = params.get_input_attribute<float>( + "Z", component, result_domain, 0.0f); + + MutableSpan<float3> results = attribute_result->get_span_for_write_only<float3>(); + for (const int i : results.index_range()) { + const float x = attribute_x[i]; + const float y = attribute_y[i]; + const float z = attribute_z[i]; + const float3 result = float3(x, y, z); + results[i] = result; + } + attribute_result.apply_span_and_save(); +} + +static void geo_node_attribute_combine_xyz_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + if (geometry_set.has<MeshComponent>()) { + combine_attributes(geometry_set.get_component_for_write<MeshComponent>(), params); + } + if (geometry_set.has<PointCloudComponent>()) { + combine_attributes(geometry_set.get_component_for_write<PointCloudComponent>(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_combine_xyz() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_COMBINE_XYZ, "Attribute Combine XYZ", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_combine_xyz_in, geo_node_attribute_combine_xyz_out); + node_type_init(&ntype, blender::nodes::geo_node_attribute_combine_xyz_init); + node_type_update(&ntype, blender::nodes::geo_node_attribute_combine_xyz_update); + node_type_storage( + &ntype, "NodeAttributeCombineXYZ", node_free_standard_storage, node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_combine_xyz_exec; + ntype.draw_buttons = geo_node_attribute_combine_xyz_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc index 20a2b2127c2..5e434a7f96d 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc @@ -26,6 +26,9 @@ #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "NOD_math_functions.hh" static bNodeSocketTemplate geo_node_attribute_compare_in[] = { @@ -48,10 +51,19 @@ static bNodeSocketTemplate geo_node_attribute_compare_out[] = { {-1, ""}, }; +static void geo_node_attribute_compare_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); + uiItemR(layout, ptr, "input_type_a", 0, IFACE_("Type A"), ICON_NONE); + uiItemR(layout, ptr, "input_type_b", 0, IFACE_("Type B"), ICON_NONE); +} + static void geo_node_attribute_compare_init(bNodeTree *UNUSED(tree), bNode *node) { NodeAttributeCompare *data = (NodeAttributeCompare *)MEM_callocN(sizeof(NodeAttributeCompare), - "attribute mix node"); + __func__); data->operation = NODE_FLOAT_COMPARE_GREATER_THAN; data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; @@ -327,6 +339,7 @@ void register_node_type_geo_attribute_compare() node_type_socket_templates( &ntype, geo_node_attribute_compare_in, geo_node_attribute_compare_out); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_compare_exec; + ntype.draw_buttons = geo_node_attribute_compare_layout; node_type_update(&ntype, blender::nodes::geo_node_attribute_compare_update); node_type_storage( &ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage); diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc index 9cec4070f89..92b47769d1f 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc @@ -21,6 +21,9 @@ #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_attribute_fill_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Attribute")}, @@ -36,6 +39,12 @@ static bNodeSocketTemplate geo_node_attribute_fill_out[] = { {-1, ""}, }; +static void geo_node_attribute_fill_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); + // uiItemR(layout, ptr, "domain", 0, "", ICON_NONE); +} + static void geo_node_attribute_fill_init(bNodeTree *UNUSED(tree), bNode *node) { node->custom1 = CD_PROP_FLOAT; @@ -131,5 +140,6 @@ void register_node_type_geo_attribute_fill() node_type_init(&ntype, geo_node_attribute_fill_init); node_type_update(&ntype, geo_node_attribute_fill_update); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_fill_exec; + ntype.draw_buttons = geo_node_attribute_fill_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc index f8ec9124db3..076f7a9ee28 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc @@ -26,6 +26,9 @@ #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "NOD_math_functions.hh" static bNodeSocketTemplate geo_node_attribute_math_in[] = { @@ -34,6 +37,8 @@ static bNodeSocketTemplate geo_node_attribute_math_in[] = { {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {SOCK_STRING, N_("B")}, {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_STRING, N_("C")}, + {SOCK_FLOAT, N_("C"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, {SOCK_STRING, N_("Result")}, {-1, ""}, }; @@ -43,14 +48,91 @@ static bNodeSocketTemplate geo_node_attribute_math_out[] = { {-1, ""}, }; +static bool operation_use_input_c(const NodeMathOperation operation) +{ + return ELEM(operation, + NODE_MATH_MULTIPLY_ADD, + NODE_MATH_SMOOTH_MIN, + NODE_MATH_SMOOTH_MAX, + NODE_MATH_WRAP, + NODE_MATH_COMPARE); +} + +static bool operation_use_input_b(const NodeMathOperation operation) +{ + switch (operation) { + case NODE_MATH_ADD: + case NODE_MATH_SUBTRACT: + case NODE_MATH_MULTIPLY: + case NODE_MATH_DIVIDE: + case NODE_MATH_POWER: + case NODE_MATH_LOGARITHM: + case NODE_MATH_MINIMUM: + case NODE_MATH_MAXIMUM: + case NODE_MATH_LESS_THAN: + case NODE_MATH_GREATER_THAN: + case NODE_MATH_MODULO: + case NODE_MATH_ARCTAN2: + case NODE_MATH_SNAP: + case NODE_MATH_WRAP: + case NODE_MATH_COMPARE: + case NODE_MATH_MULTIPLY_ADD: + case NODE_MATH_PINGPONG: + case NODE_MATH_SMOOTH_MIN: + case NODE_MATH_SMOOTH_MAX: + return true; + case NODE_MATH_SINE: + case NODE_MATH_COSINE: + case NODE_MATH_TANGENT: + case NODE_MATH_ARCSINE: + case NODE_MATH_ARCCOSINE: + case NODE_MATH_ARCTANGENT: + case NODE_MATH_ROUND: + case NODE_MATH_ABSOLUTE: + case NODE_MATH_FLOOR: + case NODE_MATH_CEIL: + case NODE_MATH_FRACTION: + case NODE_MATH_SQRT: + case NODE_MATH_INV_SQRT: + case NODE_MATH_SIGN: + case NODE_MATH_EXPONENT: + case NODE_MATH_RADIANS: + case NODE_MATH_DEGREES: + case NODE_MATH_SINH: + case NODE_MATH_COSH: + case NODE_MATH_TANH: + case NODE_MATH_TRUNC: + return false; + } + BLI_assert(false); + return false; +} + +static void geo_node_attribute_math_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage; + NodeMathOperation operation = (NodeMathOperation)node_storage->operation; + + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); + uiItemR(layout, ptr, "input_type_a", 0, IFACE_("Type A"), ICON_NONE); + + if (operation_use_input_b(operation)) { + uiItemR(layout, ptr, "input_type_b", 0, IFACE_("Type B"), ICON_NONE); + } + if (operation_use_input_c(operation)) { + uiItemR(layout, ptr, "input_type_c", 0, IFACE_("Type C"), ICON_NONE); + } +} + static void geo_node_attribute_math_init(bNodeTree *UNUSED(tree), bNode *node) { - NodeAttributeMath *data = (NodeAttributeMath *)MEM_callocN(sizeof(NodeAttributeMath), - "NodeAttributeMath"); + NodeAttributeMath *data = (NodeAttributeMath *)MEM_callocN(sizeof(NodeAttributeMath), __func__); data->operation = NODE_MATH_ADD; data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + data->input_type_c = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; node->storage = data; } @@ -58,38 +140,64 @@ namespace blender::nodes { static void geo_node_attribute_math_update(bNodeTree *UNUSED(ntree), bNode *node) { - NodeAttributeMath *node_storage = (NodeAttributeMath *)node->storage; + NodeAttributeMath &node_storage = *(NodeAttributeMath *)node->storage; + NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage.operation); update_attribute_input_socket_availabilities( - *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a); + *node, "A", (GeometryNodeAttributeInputMode)node_storage.input_type_a); update_attribute_input_socket_availabilities( - *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b); + *node, + "B", + (GeometryNodeAttributeInputMode)node_storage.input_type_b, + operation_use_input_b(operation)); + update_attribute_input_socket_availabilities( + *node, + "C", + (GeometryNodeAttributeInputMode)node_storage.input_type_c, + operation_use_input_c(operation)); } -static void do_math_operation(const FloatReadAttribute &input_a, - const FloatReadAttribute &input_b, - FloatWriteAttribute result, - const int operation) +static void do_math_operation(Span<float> span_a, + Span<float> span_b, + Span<float> span_c, + MutableSpan<float> span_result, + const NodeMathOperation operation) { - const int size = input_a.size(); - - Span<float> span_a = input_a.get_span(); - Span<float> span_b = input_b.get_span(); - MutableSpan<float> span_result = result.get_span_for_write_only(); + bool success = try_dispatch_float_math_fl_fl_fl_to_fl( + operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { + for (const int i : IndexRange(span_result.size())) { + span_result[i] = math_function(span_a[i], span_b[i], span_c[i]); + } + }); + BLI_assert(success); + UNUSED_VARS_NDEBUG(success); +} +static void do_math_operation(Span<float> span_a, + Span<float> span_b, + MutableSpan<float> span_result, + const NodeMathOperation operation) +{ bool success = try_dispatch_float_math_fl_fl_to_fl( operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { - for (const int i : IndexRange(size)) { - const float in1 = span_a[i]; - const float in2 = span_b[i]; - const float out = math_function(in1, in2); - span_result[i] = out; + for (const int i : IndexRange(span_result.size())) { + span_result[i] = math_function(span_a[i], span_b[i]); } }); + BLI_assert(success); + UNUSED_VARS_NDEBUG(success); +} - result.apply_span(); - - /* The operation is not supported by this node currently. */ +static void do_math_operation(Span<float> span_input, + MutableSpan<float> span_result, + const NodeMathOperation operation) +{ + bool success = try_dispatch_float_math_fl_to_fl( + operation, [&](auto math_function, const FloatMathOperationInfo &UNUSED(info)) { + for (const int i : IndexRange(span_result.size())) { + span_result[i] = math_function(span_input[i]); + } + }); BLI_assert(success); UNUSED_VARS_NDEBUG(success); } @@ -98,7 +206,7 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP { const bNode &node = params.node(); const NodeAttributeMath *node_storage = (const NodeAttributeMath *)node.storage; - const int operation = node_storage->operation; + const NodeMathOperation operation = static_cast<NodeMathOperation>(node_storage->operation); /* The result type of this node is always float. */ const CustomDataType result_type = CD_PROP_FLOAT; @@ -115,15 +223,44 @@ static void attribute_math_calc(GeometryComponent &component, const GeoNodeExecP ReadAttributePtr attribute_a = params.get_input_attribute( "A", component, result_domain, result_type, nullptr); - ReadAttributePtr attribute_b = params.get_input_attribute( - "B", component, result_domain, result_type, nullptr); - if (!attribute_a || !attribute_b) { - /* Attribute wasn't found. */ + if (!attribute_a) { return; } - do_math_operation(*attribute_a, *attribute_b, *attribute_result, operation); - attribute_result.save(); + /* Note that passing the data with `get_span<float>()` works + * because the attributes were accessed with #CD_PROP_FLOAT. */ + if (operation_use_input_b(operation)) { + ReadAttributePtr attribute_b = params.get_input_attribute( + "B", component, result_domain, result_type, nullptr); + if (!attribute_b) { + return; + } + if (operation_use_input_c(operation)) { + ReadAttributePtr attribute_c = params.get_input_attribute( + "C", component, result_domain, result_type, nullptr); + if (!attribute_c) { + return; + } + do_math_operation(attribute_a->get_span<float>(), + attribute_b->get_span<float>(), + attribute_c->get_span<float>(), + attribute_result->get_span_for_write_only<float>(), + operation); + } + else { + do_math_operation(attribute_a->get_span<float>(), + attribute_b->get_span<float>(), + attribute_result->get_span_for_write_only<float>(), + operation); + } + } + else { + do_math_operation(attribute_a->get_span<float>(), + attribute_result->get_span_for_write_only<float>(), + operation); + } + + attribute_result.apply_span_and_save(); } static void geo_node_attribute_math_exec(GeoNodeExecParams params) @@ -149,9 +286,10 @@ void register_node_type_geo_attribute_math() geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_MATH, "Attribute Math", NODE_CLASS_ATTRIBUTE, 0); node_type_socket_templates(&ntype, geo_node_attribute_math_in, geo_node_attribute_math_out); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_math_exec; + ntype.draw_buttons = geo_node_attribute_math_layout; node_type_update(&ntype, blender::nodes::geo_node_attribute_math_update); node_type_init(&ntype, geo_node_attribute_math_init); node_type_storage( - &ntype, "NodeAttributeCompare", node_free_standard_storage, node_copy_standard_storage); + &ntype, "NodeAttributeMath", node_free_standard_storage, node_copy_standard_storage); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc index 58d67145e75..976970d06b1 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc @@ -18,6 +18,9 @@ #include "DNA_material_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_attribute_mix_in[] = { @@ -41,6 +44,15 @@ static bNodeSocketTemplate geo_node_mix_attribute_out[] = { {-1, ""}, }; +static void geo_node_attribute_mix_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE); + uiLayout *col = uiLayoutColumn(layout, false); + uiItemR(col, ptr, "input_type_factor", 0, IFACE_("Factor"), ICON_NONE); + uiItemR(col, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE); + uiItemR(col, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE); +} + namespace blender::nodes { static void do_mix_operation_float(const int blend_mode, @@ -204,6 +216,7 @@ void register_node_type_geo_attribute_mix() node_type_socket_templates(&ntype, geo_node_attribute_mix_in, geo_node_mix_attribute_out); node_type_init(&ntype, blender::nodes::geo_node_attribute_mix_init); node_type_update(&ntype, blender::nodes::geo_node_attribute_mix_update); + ntype.draw_buttons = geo_node_attribute_mix_layout; node_type_storage( &ntype, "NodeAttributeMix", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_mix_exec; diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc new file mode 100644 index 00000000000..45f20ca553a --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc @@ -0,0 +1,235 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_kdopbvh.h" +#include "BLI_kdtree.h" +#include "BLI_task.hh" +#include "BLI_timeit.hh" + +#include "DNA_mesh_types.h" + +#include "BKE_bvhutils.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_attribute_proximity_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_GEOMETRY, N_("Target")}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_proximity_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_proximity_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "target_geometry_element", 0, "", ICON_NONE); +} + +static void geo_attribute_proximity_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryAttributeProximity *node_storage = (NodeGeometryAttributeProximity *)MEM_callocN( + sizeof(NodeGeometryAttributeProximity), __func__); + + node_storage->target_geometry_element = + GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES; + node->storage = node_storage; +} + +namespace blender::nodes { + +static void proximity_calc(MutableSpan<float> distance_span, + Span<float3> positions, + BVHTreeFromMesh &tree_data_mesh, + BVHTreeFromPointCloud &tree_data_pointcloud, + const bool bvh_mesh_success, + const bool bvh_pointcloud_success) +{ + /* The pointcloud loop uses the values already in the span, + * which is only set if the mesh BVH is used (because it's first). */ + if (!bvh_mesh_success) { + distance_span.fill(FLT_MAX); + } + + IndexRange range = positions.index_range(); + parallel_for(range, 512, [&](IndexRange range) { + BVHTreeNearest nearest; + + if (bvh_mesh_success) { + copy_v3_fl(nearest.co, FLT_MAX); + nearest.index = -1; + + for (int i : range) { + nearest.dist_sq = len_squared_v3v3(nearest.co, positions[i]); + BLI_bvhtree_find_nearest(tree_data_mesh.tree, + positions[i], + &nearest, + tree_data_mesh.nearest_callback, + &tree_data_mesh); + distance_span[i] = sqrtf(nearest.dist_sq); + } + } + + if (bvh_pointcloud_success) { + copy_v3_fl(nearest.co, FLT_MAX); + nearest.index = -1; + + for (int i : range) { + /* Use the distance to the last found point as upper bound to speedup the bvh lookup. */ + nearest.dist_sq = len_squared_v3v3(nearest.co, positions[i]); + BLI_bvhtree_find_nearest(tree_data_pointcloud.tree, + positions[i], + &nearest, + tree_data_pointcloud.nearest_callback, + &tree_data_pointcloud); + distance_span[i] = std::min(distance_span[i], sqrtf(nearest.dist_sq)); + } + } + }); +} + +static bool bvh_from_mesh(const Mesh *target_mesh, + int target_geometry_element, + BVHTreeFromMesh &r_tree_data_mesh) +{ + BVHCacheType bvh_type = BVHTREE_FROM_LOOPTRI; + switch (target_geometry_element) { + case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS: + bvh_type = BVHTREE_FROM_VERTS; + break; + case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_EDGES: + bvh_type = BVHTREE_FROM_EDGES; + break; + case GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_FACES: + bvh_type = BVHTREE_FROM_LOOPTRI; + break; + } + + /* This only updates a cache and can be considered to be logically const. */ + BKE_bvhtree_from_mesh_get(&r_tree_data_mesh, const_cast<Mesh *>(target_mesh), bvh_type, 2); + if (r_tree_data_mesh.tree == nullptr) { + return false; + } + return true; +} + +static bool bvh_from_pointcloud(const PointCloud *target_pointcloud, + BVHTreeFromPointCloud &r_tree_data_pointcloud) +{ + BKE_bvhtree_from_pointcloud_get(&r_tree_data_pointcloud, target_pointcloud, 2); + if (r_tree_data_pointcloud.tree == nullptr) { + return false; + } + return true; +} + +static void attribute_calc_proximity(GeometryComponent &component, + GeometrySet &geometry_set_target, + GeoNodeExecParams ¶ms) +{ + const std::string result_attribute_name = params.get_input<std::string>("Result"); + OutputAttributePtr distance_attribute = component.attribute_try_get_for_output( + result_attribute_name, ATTR_DOMAIN_POINT, CD_PROP_FLOAT); + + ReadAttributePtr position_attribute = component.attribute_try_get_for_read("position"); + BLI_assert(position_attribute->custom_data_type() == CD_PROP_FLOAT3); + + if (!distance_attribute || !position_attribute) { + return; + } + + const bNode &node = params.node(); + const NodeGeometryAttributeProximity &storage = *(const NodeGeometryAttributeProximity *) + node.storage; + + BVHTreeFromMesh tree_data_mesh; + BVHTreeFromPointCloud tree_data_pointcloud; + bool bvh_mesh_success = false; + bool bvh_pointcloud_success = false; + + if (geometry_set_target.has_mesh()) { + bvh_mesh_success = bvh_from_mesh( + geometry_set_target.get_mesh_for_read(), storage.target_geometry_element, tree_data_mesh); + } + + if (geometry_set_target.has_pointcloud() && + storage.target_geometry_element == + GEO_NODE_ATTRIBUTE_PROXIMITY_TARGET_GEOMETRY_ELEMENT_POINTS) { + bvh_pointcloud_success = bvh_from_pointcloud(geometry_set_target.get_pointcloud_for_read(), + tree_data_pointcloud); + } + + proximity_calc(distance_attribute->get_span_for_write_only<float>(), + position_attribute->get_span<float3>(), + tree_data_mesh, + tree_data_pointcloud, + bvh_mesh_success, + bvh_pointcloud_success); + + if (bvh_mesh_success) { + free_bvhtree_from_mesh(&tree_data_mesh); + } + if (bvh_pointcloud_success) { + free_bvhtree_from_pointcloud(&tree_data_pointcloud); + } + + distance_attribute.apply_span_and_save(); +} + +static void geo_node_attribute_proximity_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set_target = params.extract_input<GeometrySet>("Target"); + + if (geometry_set.has<MeshComponent>()) { + attribute_calc_proximity( + geometry_set.get_component_for_write<MeshComponent>(), geometry_set_target, params); + } + if (geometry_set.has<PointCloudComponent>()) { + attribute_calc_proximity( + geometry_set.get_component_for_write<PointCloudComponent>(), geometry_set_target, params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_proximity() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_PROXIMITY, "Attribute Proximity", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_proximity_in, geo_node_attribute_proximity_out); + node_type_init(&ntype, geo_attribute_proximity_init); + node_type_storage(&ntype, + "NodeGeometryAttributeProximity", + node_free_standard_storage, + node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_proximity_exec; + ntype.draw_buttons = geo_node_attribute_proximity_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc index 0e7bb25e659..f5765af83b3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc @@ -19,6 +19,9 @@ #include "BLI_hash.h" #include "BLI_rand.hh" +#include "UI_interface.h" +#include "UI_resources.h" + #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" @@ -38,6 +41,13 @@ static bNodeSocketTemplate geo_node_attribute_randomize_out[] = { {-1, ""}, }; +static void geo_node_attribute_random_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE); +} + static void geo_node_attribute_randomize_init(bNodeTree *UNUSED(tree), bNode *node) { node->custom1 = CD_PROP_FLOAT; @@ -50,8 +60,7 @@ static void geo_node_attribute_randomize_update(bNodeTree *UNUSED(ntree), bNode bNodeSocket *sock_min_float = sock_max_vector->next; bNodeSocket *sock_max_float = sock_min_float->next; - const int data_type = node->custom1; - + const CustomDataType data_type = static_cast<CustomDataType>(node->custom1); nodeSetSocketAvailability(sock_min_vector, data_type == CD_PROP_FLOAT3); nodeSetSocketAvailability(sock_max_vector, data_type == CD_PROP_FLOAT3); nodeSetSocketAvailability(sock_min_float, data_type == CD_PROP_FLOAT); @@ -86,8 +95,11 @@ static void randomize_attribute_bool(BooleanWriteAttribute attribute, attribute.apply_span(); } -static void randomize_attribute_float( - FloatWriteAttribute attribute, float min, float max, Span<uint32_t> hashes, const int seed) +static void randomize_attribute_float(FloatWriteAttribute attribute, + const float min, + const float max, + Span<uint32_t> hashes, + const int seed) { MutableSpan<float> attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { @@ -97,8 +109,11 @@ static void randomize_attribute_float( attribute.apply_span(); } -static void randomize_attribute_float3( - Float3WriteAttribute attribute, float3 min, float3 max, Span<uint32_t> hashes, const int seed) +static void randomize_attribute_float3(Float3WriteAttribute attribute, + const float3 min, + const float3 max, + Span<uint32_t> hashes, + const int seed) { MutableSpan<float3> attribute_span = attribute.get_span(); for (const int i : IndexRange(attribute.size())) { @@ -129,8 +144,7 @@ Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &compo } else { /* If there is no "id" attribute for per-point variation, just create it here. */ - RandomNumberGenerator rng; - rng.seed(0); + RandomNumberGenerator rng(0); for (const int i : hashes.index_range()) { hashes[i] = rng.get_uint32(); } @@ -211,5 +225,6 @@ void register_node_type_geo_attribute_randomize() node_type_init(&ntype, geo_node_attribute_randomize_init); node_type_update(&ntype, geo_node_attribute_randomize_update); ntype.geometry_node_execute = blender::nodes::geo_node_random_attribute_exec; + ntype.draw_buttons = geo_node_attribute_random_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc new file mode 100644 index 00000000000..b6a960e5617 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc @@ -0,0 +1,118 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "BLI_compiler_attrs.h" + +#include "DNA_texture_types.h" + +#include "BKE_texture.h" + +#include "RE_texture.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_attribute_sample_texture_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Mapping")}, + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_sample_texture_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_sample_texture_layout(uiLayout *layout, + bContext *C, + PointerRNA *ptr) +{ + uiTemplateID(layout, C, ptr, "texture", "texture.new", NULL, NULL, 0, ICON_NONE, NULL); +} + +namespace blender::nodes { + +static void execute_on_component(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const bNode &node = params.node(); + Tex *texture = reinterpret_cast<Tex *>(node.id); + const std::string result_attribute_name = params.get_input<std::string>("Result"); + + if (texture == nullptr) { + return; + } + + const std::string mapping_name = params.get_input<std::string>("Mapping"); + if (!component.attribute_exists(mapping_name)) { + return; + } + + OutputAttributePtr attribute_out = component.attribute_try_get_for_output( + result_attribute_name, ATTR_DOMAIN_POINT, CD_PROP_COLOR); + if (!attribute_out) { + return; + } + + Float3ReadAttribute mapping_attribute = component.attribute_get_for_read<float3>( + mapping_name, ATTR_DOMAIN_POINT, {0, 0, 0}); + + MutableSpan<Color4f> colors = attribute_out->get_span<Color4f>(); + for (const int i : IndexRange(mapping_attribute.size())) { + TexResult texture_result = {0}; + const float3 position = mapping_attribute[i]; + /* For legacy reasons we have to map [0, 1] to [-1, 1] to support uv mappings. */ + const float3 remapped_position = position * 2.0f - float3(1.0f); + BKE_texture_get_value(nullptr, texture, remapped_position, &texture_result, false); + colors[i] = {texture_result.tr, texture_result.tg, texture_result.tb, texture_result.ta}; + } + attribute_out.apply_span_and_save(); +} + +static void geo_node_attribute_sample_texture_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + if (geometry_set.has<MeshComponent>()) { + execute_on_component(geometry_set.get_component_for_write<MeshComponent>(), params); + } + if (geometry_set.has<PointCloudComponent>()) { + execute_on_component(geometry_set.get_component_for_write<PointCloudComponent>(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_sample_texture() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, + GEO_NODE_ATTRIBUTE_SAMPLE_TEXTURE, + "Attribute Sample Texture", + NODE_CLASS_ATTRIBUTE, + 0); + node_type_size_preset(&ntype, NODE_SIZE_LARGE); + node_type_socket_templates( + &ntype, geo_node_attribute_sample_texture_in, geo_node_attribute_sample_texture_out); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_sample_texture_exec; + ntype.draw_buttons = geo_node_attribute_sample_texture_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc new file mode 100644 index 00000000000..07941f7db79 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_separate_xyz.cc @@ -0,0 +1,148 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "DNA_material_types.h" + +#include "node_geometry_util.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +static bNodeSocketTemplate geo_node_attribute_separate_xyz_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Vector")}, + {SOCK_VECTOR, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -FLT_MAX, FLT_MAX}, + {SOCK_STRING, N_("Result X")}, + {SOCK_STRING, N_("Result Y")}, + {SOCK_STRING, N_("Result Z")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_attribute_separate_xyz_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_attribute_separate_xyz_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_attribute_separate_xyz_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeAttributeSeparateXYZ *data = (NodeAttributeSeparateXYZ *)MEM_callocN( + sizeof(NodeAttributeSeparateXYZ), __func__); + data->input_type = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; +} + +static void geo_node_attribute_separate_xyz_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeAttributeSeparateXYZ *node_storage = (NodeAttributeSeparateXYZ *)node->storage; + update_attribute_input_socket_availabilities( + *node, "Vector", (GeometryNodeAttributeInputMode)node_storage->input_type); +} + +static void extract_input(const int index, const Span<float3> &input, MutableSpan<float> result) +{ + for (const int i : result.index_range()) { + /* Get the component of the float3. (0: X, 1: Y, 2: Z). */ + const float component = input[i][index]; + result[i] = component; + } +} + +static void separate_attribute(GeometryComponent &component, const GeoNodeExecParams ¶ms) +{ + const std::string result_name_x = params.get_input<std::string>("Result X"); + const std::string result_name_y = params.get_input<std::string>("Result Y"); + const std::string result_name_z = params.get_input<std::string>("Result Z"); + /* The node is only for float3 to float conversions. */ + const CustomDataType input_type = CD_PROP_FLOAT3; + const CustomDataType result_type = CD_PROP_FLOAT; + /* The result domain is always point for now. */ + const AttributeDomain result_domain = ATTR_DOMAIN_POINT; + + /* No output to write to. */ + if (result_name_x.empty() && result_name_y.empty() && result_name_z.empty()) { + return; + } + + ReadAttributePtr attribute_input = params.get_input_attribute( + "Vector", component, result_domain, input_type, nullptr); + if (!attribute_input) { + return; + } + const Span<float3> input_span = attribute_input->get_span<float3>(); + + OutputAttributePtr attribute_result_x = component.attribute_try_get_for_output( + result_name_x, result_domain, result_type); + OutputAttributePtr attribute_result_y = component.attribute_try_get_for_output( + result_name_y, result_domain, result_type); + OutputAttributePtr attribute_result_z = component.attribute_try_get_for_output( + result_name_z, result_domain, result_type); + + /* Only extract the components for the outputs with a given attribute. */ + if (attribute_result_x) { + extract_input(0, input_span, attribute_result_x->get_span_for_write_only<float>()); + attribute_result_x.apply_span_and_save(); + } + if (attribute_result_y) { + extract_input(1, input_span, attribute_result_y->get_span_for_write_only<float>()); + attribute_result_y.apply_span_and_save(); + } + if (attribute_result_z) { + extract_input(2, input_span, attribute_result_z->get_span_for_write_only<float>()); + attribute_result_z.apply_span_and_save(); + } +} + +static void geo_node_attribute_separate_xyz_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); + + if (geometry_set.has<MeshComponent>()) { + separate_attribute(geometry_set.get_component_for_write<MeshComponent>(), params); + } + if (geometry_set.has<PointCloudComponent>()) { + separate_attribute(geometry_set.get_component_for_write<PointCloudComponent>(), params); + } + + params.set_output("Geometry", geometry_set); +} + +} // namespace blender::nodes + +void register_node_type_geo_attribute_separate_xyz() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_ATTRIBUTE_SEPARATE_XYZ, "Attribute Separate XYZ", NODE_CLASS_ATTRIBUTE, 0); + node_type_socket_templates( + &ntype, geo_node_attribute_separate_xyz_in, geo_node_attribute_separate_xyz_out); + node_type_init(&ntype, blender::nodes::geo_node_attribute_separate_xyz_init); + node_type_update(&ntype, blender::nodes::geo_node_attribute_separate_xyz_update); + node_type_storage( + &ntype, "NodeAttributeSeparateXYZ", node_free_standard_storage, node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_attribute_separate_xyz_exec; + ntype.draw_buttons = geo_node_attribute_separate_xyz_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc index 529906a35e7..62a291e8506 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc @@ -26,6 +26,9 @@ #include "DNA_mesh_types.h" #include "DNA_pointcloud_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "NOD_math_functions.hh" static bNodeSocketTemplate geo_node_attribute_vector_math_in[] = { @@ -46,25 +49,6 @@ static bNodeSocketTemplate geo_node_attribute_vector_math_out[] = { {-1, ""}, }; -static void geo_node_attribute_vector_math_init(bNodeTree *UNUSED(tree), bNode *node) -{ - NodeAttributeVectorMath *data = (NodeAttributeVectorMath *)MEM_callocN( - sizeof(NodeAttributeVectorMath), __func__); - - data->operation = NODE_VECTOR_MATH_ADD; - data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; - node->storage = data; -} - -static CustomDataType operation_get_read_type_b(const NodeVectorMathOperation operation) -{ - if (operation == NODE_VECTOR_MATH_SCALE) { - return CD_PROP_FLOAT; - } - return CD_PROP_FLOAT3; -} - static bool operation_use_input_b(const NodeVectorMathOperation operation) { return !ELEM(operation, @@ -84,6 +68,44 @@ static bool operation_use_input_c(const NodeVectorMathOperation operation) return operation == NODE_VECTOR_MATH_WRAP; } +static void geo_node_attribute_vector_math_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + bNode *node = (bNode *)ptr->data; + const NodeAttributeVectorMath &node_storage = *(NodeAttributeVectorMath *)node->storage; + const NodeVectorMathOperation operation = (const NodeVectorMathOperation)node_storage.operation; + + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); + uiItemR(layout, ptr, "input_type_a", 0, IFACE_("Type A"), ICON_NONE); + + if (operation_use_input_b(operation)) { + uiItemR(layout, ptr, "input_type_b", 0, IFACE_("Type B"), ICON_NONE); + } + if (operation_use_input_c(operation)) { + uiItemR(layout, ptr, "input_type_c", 0, IFACE_("Type C"), ICON_NONE); + } +} + +static CustomDataType operation_get_read_type_b(const NodeVectorMathOperation operation) +{ + if (operation == NODE_VECTOR_MATH_SCALE) { + return CD_PROP_FLOAT; + } + return CD_PROP_FLOAT3; +} + +static void geo_node_attribute_vector_math_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeAttributeVectorMath *data = (NodeAttributeVectorMath *)MEM_callocN( + sizeof(NodeAttributeVectorMath), __func__); + + data->operation = NODE_VECTOR_MATH_ADD; + data->input_type_a = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + data->input_type_b = GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE; + node->storage = data; +} + static CustomDataType operation_get_result_type(const NodeVectorMathOperation operation) { switch (operation) { @@ -419,6 +441,7 @@ void register_node_type_geo_attribute_vector_math() node_type_socket_templates( &ntype, geo_node_attribute_vector_math_in, geo_node_attribute_vector_math_out); ntype.geometry_node_execute = blender::nodes::geo_node_attribute_vector_math_exec; + ntype.draw_buttons = geo_node_attribute_vector_math_layout; node_type_update(&ntype, blender::nodes::geo_node_attribute_vector_math_update); node_type_init(&ntype, geo_node_attribute_vector_math_init); node_type_storage( diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc index 19178546e40..403b74b2fef 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc @@ -24,6 +24,9 @@ #include "RNA_enum_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "BKE_mesh.h" #include "bmesh.h" @@ -42,6 +45,11 @@ static bNodeSocketTemplate geo_node_boolean_out[] = { {-1, ""}, }; +static void geo_node_boolean_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); +} + static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) { return BM_elem_flag_test(f, BM_ELEM_DRAW) ? 1 : 0; @@ -147,6 +155,7 @@ void register_node_type_geo_boolean() geo_node_type_base(&ntype, GEO_NODE_BOOLEAN, "Boolean", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates(&ntype, geo_node_boolean_in, geo_node_boolean_out); + ntype.draw_buttons = geo_node_boolean_layout; ntype.geometry_node_execute = blender::nodes::geo_node_boolean_exec; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc new file mode 100644 index 00000000000..42ad434ffcd --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_collection_info.cc @@ -0,0 +1,108 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "BLI_math_matrix.h" + +#include "DNA_collection_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +static bNodeSocketTemplate geo_node_collection_info_in[] = { + {SOCK_COLLECTION, N_("Collection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_collection_info_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_collection_info_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "transform_space", 0, NULL, ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_collection_info_exec(GeoNodeExecParams params) +{ + bke::PersistentCollectionHandle collection_handle = + params.extract_input<bke::PersistentCollectionHandle>("Collection"); + Collection *collection = params.handle_map().lookup(collection_handle); + + GeometrySet geometry_set_out; + + if (collection == nullptr) { + params.set_output("Geometry", geometry_set_out); + return; + } + + const bNode &bnode = params.node(); + NodeGeometryCollectionInfo *node_storage = (NodeGeometryCollectionInfo *)bnode.storage; + const bool transform_space_relative = (node_storage->transform_space == + GEO_NODE_TRANSFORM_SPACE_RELATIVE); + + InstancedData instance; + instance.type = INSTANCE_DATA_TYPE_COLLECTION; + instance.data.collection = collection; + + InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>(); + + float transform_mat[4][4]; + unit_m4(transform_mat); + const Object *self_object = params.self_object(); + + if (transform_space_relative) { + copy_v3_v3(transform_mat[3], collection->instance_offset); + + mul_m4_m4_pre(transform_mat, self_object->imat); + + float3 self_loc; + copy_v3_v3(self_loc, self_object->obmat[3]); + } + instances.add_instance(instance, transform_mat, -1); + + params.set_output("Geometry", geometry_set_out); +} + +static void geo_node_collection_info_node_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCollectionInfo *data = (NodeGeometryCollectionInfo *)MEM_callocN( + sizeof(NodeGeometryCollectionInfo), __func__); + data->transform_space = GEO_NODE_TRANSFORM_SPACE_ORIGINAL; + node->storage = data; +} + +} // namespace blender::nodes + +void register_node_type_geo_collection_info() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_COLLECTION_INFO, "Collection Info", NODE_CLASS_INPUT, 0); + node_type_socket_templates(&ntype, geo_node_collection_info_in, geo_node_collection_info_out); + node_type_init(&ntype, blender::nodes::geo_node_collection_info_node_init); + node_type_storage(&ntype, + "NodeGeometryCollectionInfo", + node_free_standard_storage, + node_copy_standard_storage); + ntype.geometry_node_execute = blender::nodes::geo_node_collection_info_exec; + ntype.draw_buttons = geo_node_collection_info_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc b/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc new file mode 100644 index 00000000000..667beaa1722 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_is_viewport.cc @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "node_geometry_util.hh" + +#include "DEG_depsgraph_query.h" + +static bNodeSocketTemplate geo_node_is_viewport_out[] = { + {SOCK_BOOLEAN, N_("Is Viewport")}, + {-1, ""}, +}; + +namespace blender::nodes { + +static void geo_node_is_viewport_exec(GeoNodeExecParams params) +{ + const Depsgraph *depsgraph = params.depsgraph(); + const eEvaluationMode mode = DEG_get_mode(depsgraph); + const bool is_viewport = mode == DAG_EVAL_VIEWPORT; + + params.set_output("Is Viewport", is_viewport); +} + +} // namespace blender::nodes + +void register_node_type_geo_is_viewport() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_IS_VIEWPORT, "Is Viewport", NODE_CLASS_INPUT, 0); + node_type_socket_templates(&ntype, nullptr, geo_node_is_viewport_out); + ntype.geometry_node_execute = blender::nodes::geo_node_is_viewport_exec; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index 42402e23fa5..a56939a43c7 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -24,8 +24,16 @@ #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_join_geometry_in[] = { - {SOCK_GEOMETRY, N_("Geometry")}, - {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_GEOMETRY, + N_("Geometry"), + 0.0f, + 0.0f, + 0.0f, + 1.0f, + -1.0f, + 1.0f, + PROP_NONE, + SOCK_MULTI_INPUT}, {-1, ""}, }; @@ -138,17 +146,17 @@ static void determine_final_data_type_and_domain(Span<const GeometryComponent *> CustomDataType *r_type, AttributeDomain *r_domain) { + Vector<CustomDataType> data_types; for (const GeometryComponent *component : components) { ReadAttributePtr attribute = component->attribute_try_get_for_read(attribute_name); if (attribute) { - /* TODO: Use data type with most information. */ - *r_type = bke::cpp_type_to_custom_data_type(attribute->cpp_type()); + data_types.append(attribute->custom_data_type()); /* TODO: Use highest priority domain. */ *r_domain = attribute->domain(); - return; } } - BLI_assert(false); + + *r_type = attribute_data_type_highest_complexity(data_types); } static void fill_new_attribute(Span<const GeometryComponent *> src_components, @@ -243,12 +251,20 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo } } +static void join_components(Span<const VolumeComponent *> src_components, GeometrySet &result) +{ + /* Not yet supported. Joining volume grids with the same name requires resampling of at least one + * of the grids. The cell size of the resulting volume has to be determined somehow. */ + VolumeComponent &dst_component = result.get_component_for_write<VolumeComponent>(); + UNUSED_VARS(src_components, dst_component); +} + template<typename Component> -static void join_component_type(Span<const GeometrySet *> src_geometry_sets, GeometrySet &result) +static void join_component_type(Span<GeometrySet> src_geometry_sets, GeometrySet &result) { Vector<const Component *> components; - for (const GeometrySet *geometry_set : src_geometry_sets) { - const Component *component = geometry_set->get_component_for_read<Component>(); + for (const GeometrySet &geometry_set : src_geometry_sets) { + const Component *component = geometry_set.get_component_for_read<Component>(); if (component != nullptr && !component->is_empty()) { components.append(component); } @@ -266,15 +282,13 @@ static void join_component_type(Span<const GeometrySet *> src_geometry_sets, Geo static void geo_node_join_geometry_exec(GeoNodeExecParams params) { - GeometrySet geometry_set_a = params.extract_input<GeometrySet>("Geometry"); - GeometrySet geometry_set_b = params.extract_input<GeometrySet>("Geometry_001"); - GeometrySet geometry_set_result; + Vector<GeometrySet> geometry_sets = params.extract_multi_input<GeometrySet>("Geometry"); - std::array<const GeometrySet *, 2> src_geometry_sets = {&geometry_set_a, &geometry_set_b}; - - join_component_type<MeshComponent>(src_geometry_sets, geometry_set_result); - join_component_type<PointCloudComponent>(src_geometry_sets, geometry_set_result); - join_component_type<InstancesComponent>(src_geometry_sets, geometry_set_result); + GeometrySet geometry_set_result; + join_component_type<MeshComponent>(geometry_sets, geometry_set_result); + join_component_type<PointCloudComponent>(geometry_sets, geometry_set_result); + join_component_type<InstancesComponent>(geometry_sets, geometry_set_result); + join_component_type<VolumeComponent>(geometry_sets, geometry_set_result); params.set_output("Geometry", std::move(geometry_set_result)); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc index ab5e4f8964a..4e26977b85a 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_object_info.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_object_info.cc @@ -19,9 +19,13 @@ #include "BKE_mesh.h" #include "BKE_mesh_wrapper.h" #include "BKE_modifier.h" +#include "BKE_volume.h" #include "BLI_math_matrix.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_object_info_in[] = { {SOCK_OBJECT, N_("Object")}, {-1, ""}, @@ -35,6 +39,11 @@ static bNodeSocketTemplate geo_node_object_info_out[] = { {-1, ""}, }; +static void geo_node_object_info_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); +} + namespace blender::nodes { static void geo_node_object_info_exec(GeoNodeExecParams params) { @@ -86,6 +95,18 @@ static void geo_node_object_info_exec(GeoNodeExecParams params) mesh_component.copy_vertex_group_names_from_object(*object); } } + if (object->type == OB_VOLUME) { + InstancesComponent &instances = geometry_set.get_component_for_write<InstancesComponent>(); + + if (transform_space_relative) { + instances.add_instance(object, transform); + } + else { + float unit_transform[4][4]; + unit_m4(unit_transform); + instances.add_instance(object, unit_transform); + } + } } } @@ -115,5 +136,6 @@ void register_node_type_geo_object_info() node_type_storage( &ntype, "NodeGeometryObjectInfo", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_object_info_exec; + ntype.draw_buttons = geo_node_object_info_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc index 2f1aa276532..93abed7926e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc @@ -26,12 +26,16 @@ #include "DNA_meshdata_types.h" #include "DNA_pointcloud_types.h" +#include "BKE_attribute_math.hh" #include "BKE_bvhutils.h" #include "BKE_deform.h" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_pointcloud.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_point_distribute_in[] = { @@ -48,6 +52,13 @@ static bNodeSocketTemplate geo_node_point_distribute_out[] = { {-1, ""}, }; +static void geo_node_point_distribute_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "distribute_method", 0, "", ICON_NONE); +} + static void node_point_distribute_update(bNodeTree *UNUSED(ntree), bNode *node) { bNodeSocket *sock_min_dist = (bNodeSocket *)BLI_findlink(&node->inputs, 1); @@ -217,13 +228,141 @@ BLI_NOINLINE static void eliminate_points_based_on_mask(Span<bool> elimination_m } } -BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh, - Span<float3> bary_coords, - Span<int> looptri_indices, - MutableSpan<float3> r_normals, - MutableSpan<int> r_ids, - MutableSpan<float3> r_rotations) +template<typename T> +BLI_NOINLINE static void interpolate_attribute_point(const Mesh &mesh, + const Span<float3> bary_coords, + const Span<int> looptri_indices, + const Span<T> data_in, + MutableSpan<T> data_out) +{ + BLI_assert(data_in.size() == mesh.totvert); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); + + for (const int i : bary_coords.index_range()) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + + const int v0_index = mesh.mloop[looptri.tri[0]].v; + const int v1_index = mesh.mloop[looptri.tri[1]].v; + const int v2_index = mesh.mloop[looptri.tri[2]].v; + + const T &v0 = data_in[v0_index]; + const T &v1 = data_in[v1_index]; + const T &v2 = data_in[v2_index]; + + const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); + data_out[i] = interpolated_value; + } +} + +template<typename T> +BLI_NOINLINE static void interpolate_attribute_corner(const Mesh &mesh, + const Span<float3> bary_coords, + const Span<int> looptri_indices, + const Span<T> data_in, + MutableSpan<T> data_out) +{ + BLI_assert(data_in.size() == mesh.totloop); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); + + for (const int i : bary_coords.index_range()) { + const int looptri_index = looptri_indices[i]; + const MLoopTri &looptri = looptris[looptri_index]; + const float3 &bary_coord = bary_coords[i]; + + const int loop_index_0 = looptri.tri[0]; + const int loop_index_1 = looptri.tri[1]; + const int loop_index_2 = looptri.tri[2]; + + const T &v0 = data_in[loop_index_0]; + const T &v1 = data_in[loop_index_1]; + const T &v2 = data_in[loop_index_2]; + + const T interpolated_value = attribute_math::mix3(bary_coord, v0, v1, v2); + data_out[i] = interpolated_value; + } +} + +BLI_NOINLINE static void interpolate_attribute(const Mesh &mesh, + Span<float3> bary_coords, + Span<int> looptri_indices, + const StringRef attribute_name, + const ReadAttribute &attribute_in, + GeometryComponent &component) +{ + const CustomDataType data_type = attribute_in.custom_data_type(); + const AttributeDomain domain = attribute_in.domain(); + if (!ELEM(domain, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CORNER)) { + /* Not supported currently. */ + return; + } + + OutputAttributePtr attribute_out = component.attribute_try_get_for_output( + attribute_name, ATTR_DOMAIN_POINT, data_type); + if (!attribute_out) { + return; + } + + attribute_math::convert_to_static_type(data_type, [&](auto dummy) { + using T = decltype(dummy); + + Span data_in = attribute_in.get_span<T>(); + MutableSpan data_out = attribute_out->get_span_for_write_only<T>(); + + switch (domain) { + case ATTR_DOMAIN_POINT: { + interpolate_attribute_point<T>(mesh, bary_coords, looptri_indices, data_in, data_out); + break; + } + case ATTR_DOMAIN_CORNER: { + interpolate_attribute_corner<T>(mesh, bary_coords, looptri_indices, data_in, data_out); + break; + } + default: { + BLI_assert(false); + break; + } + } + }); + attribute_out.apply_span_and_save(); +} + +BLI_NOINLINE static void interpolate_existing_attributes(const MeshComponent &mesh_component, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) +{ + const Mesh &mesh = *mesh_component.get_for_read(); + + Set<std::string> attribute_names = mesh_component.attribute_names(); + for (StringRefNull attribute_name : attribute_names) { + if (ELEM(attribute_name, "position", "normal", "id")) { + continue; + } + + ReadAttributePtr attribute_in = mesh_component.attribute_try_get_for_read(attribute_name); + interpolate_attribute( + mesh, bary_coords, looptri_indices, attribute_name, *attribute_in, component); + } +} + +BLI_NOINLINE static void compute_special_attributes(const Mesh &mesh, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) { + OutputAttributePtr id_attribute = component.attribute_try_get_for_output( + "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); + OutputAttributePtr normal_attribute = component.attribute_try_get_for_output( + "normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + OutputAttributePtr rotation_attribute = component.attribute_try_get_for_output( + "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); + + MutableSpan<int> ids = id_attribute->get_span_for_write_only<int>(); + MutableSpan<float3> normals = normal_attribute->get_span_for_write_only<float3>(); + MutableSpan<float3> rotations = rotation_attribute->get_span_for_write_only<float3>(); + Span<MLoopTri> looptris = get_mesh_looptris(mesh); for (const int i : bary_coords.index_range()) { const int looptri_index = looptri_indices[i]; @@ -237,10 +376,24 @@ BLI_NOINLINE static void compute_remaining_point_data(const Mesh &mesh, const float3 v1_pos = mesh.mvert[v1_index].co; const float3 v2_pos = mesh.mvert[v2_index].co; - r_ids[i] = (int)(bary_coord.hash()) + looptri_index; - normal_tri_v3(r_normals[i], v0_pos, v1_pos, v2_pos); - r_rotations[i] = normal_to_euler_rotation(r_normals[i]); + ids[i] = (int)(bary_coord.hash()) + looptri_index; + normal_tri_v3(normals[i], v0_pos, v1_pos, v2_pos); + rotations[i] = normal_to_euler_rotation(normals[i]); } + + id_attribute.apply_span_and_save(); + normal_attribute.apply_span_and_save(); + rotation_attribute.apply_span_and_save(); +} + +BLI_NOINLINE static void add_remaining_point_attributes(const MeshComponent &mesh_component, + GeometryComponent &component, + Span<float3> bary_coords, + Span<int> looptri_indices) +{ + interpolate_existing_attributes(mesh_component, component, bary_coords, looptri_indices); + compute_special_attributes( + *mesh_component.get_for_read(), component, bary_coords, looptri_indices); } static void sample_mesh_surface_with_minimum_distance(const Mesh &mesh, @@ -315,11 +468,6 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) break; } const int tot_points = positions.size(); - Array<float3> normals(tot_points); - Array<int> stable_ids(tot_points); - Array<float3> rotations(tot_points); - compute_remaining_point_data( - *mesh_in, bary_coords, looptri_indices, normals, stable_ids, rotations); PointCloud *pointcloud = BKE_pointcloud_new_nomain(tot_points); memcpy(pointcloud->co, positions.data(), sizeof(float3) * tot_points); @@ -332,29 +480,7 @@ static void geo_node_point_distribute_exec(GeoNodeExecParams params) geometry_set_out.get_component_for_write<PointCloudComponent>(); point_component.replace(pointcloud); - { - OutputAttributePtr stable_id_attribute = point_component.attribute_try_get_for_output( - "id", ATTR_DOMAIN_POINT, CD_PROP_INT32); - MutableSpan<int> stable_ids_span = stable_id_attribute->get_span<int>(); - stable_ids_span.copy_from(stable_ids); - stable_id_attribute.apply_span_and_save(); - } - - { - OutputAttributePtr normals_attribute = point_component.attribute_try_get_for_output( - "normal", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); - MutableSpan<float3> normals_span = normals_attribute->get_span<float3>(); - normals_span.copy_from(normals); - normals_attribute.apply_span_and_save(); - } - - { - OutputAttributePtr rotations_attribute = point_component.attribute_try_get_for_output( - "rotation", ATTR_DOMAIN_POINT, CD_PROP_FLOAT3); - MutableSpan<float3> rotations_span = rotations_attribute->get_span<float3>(); - rotations_span.copy_from(rotations); - rotations_attribute.apply_span_and_save(); - } + add_remaining_point_attributes(mesh_component, point_component, bary_coords, looptri_indices); params.set_output("Geometry", std::move(geometry_set_out)); } @@ -369,5 +495,6 @@ void register_node_type_geo_point_distribute() node_type_socket_templates(&ntype, geo_node_point_distribute_in, geo_node_point_distribute_out); node_type_update(&ntype, node_point_distribute_update); ntype.geometry_node_execute = blender::nodes::geo_node_point_distribute_exec; + ntype.draw_buttons = geo_node_point_distribute_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index a96dc710427..1e7cf21f921 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -24,6 +24,9 @@ #include "BLI_hash.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_point_instance_in[] = { @@ -39,6 +42,14 @@ static bNodeSocketTemplate geo_node_point_instance_out[] = { {-1, ""}, }; +static void geo_node_point_instance_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "instance_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { + uiItemR(layout, ptr, "use_whole_collection", 0, NULL, ICON_NONE); + } +} + namespace blender::nodes { static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) @@ -47,8 +58,10 @@ static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) bNodeSocket *collection_socket = object_socket->next; bNodeSocket *seed_socket = collection_socket->next; - GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node->custom1; - const bool use_whole_collection = node->custom2 == 0; + NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node->storage; + GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node_storage->instance_type; + const bool use_whole_collection = (node_storage->flag & + GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION) != 0; nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); @@ -79,6 +92,8 @@ static void get_instanced_data__collection( MutableSpan<std::optional<InstancedData>> r_instances_data) { const bNode &node = params.node(); + NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage; + bke::PersistentCollectionHandle collection_handle = params.get_input<bke::PersistentCollectionHandle>("Collection"); Collection *collection = params.handle_map().lookup(collection_handle); @@ -86,7 +101,8 @@ static void get_instanced_data__collection( return; } - const bool use_whole_collection = node.custom2 == 0; + const bool use_whole_collection = (node_storage->flag & + GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION) != 0; if (use_whole_collection) { InstancedData instance; instance.type = INSTANCE_DATA_TYPE_COLLECTION; @@ -128,8 +144,9 @@ static Array<std::optional<InstancedData>> get_instanced_data(const GeoNodeExecP const int amount) { const bNode &node = params.node(); - const GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node.custom1; - + NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node.storage; + const GeometryNodePointInstanceType type = (GeometryNodePointInstanceType) + node_storage->instance_type; Array<std::optional<InstancedData>> instances_data(amount); switch (type) { @@ -189,6 +206,16 @@ static void geo_node_point_instance_exec(GeoNodeExecParams params) params.set_output("Geometry", std::move(geometry_set_out)); } + +static void geo_node_point_instance_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryPointInstance *data = (NodeGeometryPointInstance *)MEM_callocN( + sizeof(NodeGeometryPointInstance), __func__); + data->instance_type = GEO_NODE_POINT_INSTANCE_TYPE_OBJECT; + data->flag |= GEO_NODE_POINT_INSTANCE_WHOLE_COLLECTION; + node->storage = data; +} + } // namespace blender::nodes void register_node_type_geo_point_instance() @@ -197,6 +224,10 @@ void register_node_type_geo_point_instance() geo_node_type_base(&ntype, GEO_NODE_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates(&ntype, geo_node_point_instance_in, geo_node_point_instance_out); + node_type_init(&ntype, blender::nodes::geo_node_point_instance_init); + node_type_storage( + &ntype, "NodeGeometryPointInstance", node_free_standard_storage, node_copy_standard_storage); + ntype.draw_buttons = geo_node_point_instance_layout; node_type_update(&ntype, blender::nodes::geo_node_point_instance_update); ntype.geometry_node_execute = blender::nodes::geo_node_point_instance_exec; nodeRegisterType(&ntype); diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc index b1451dfb89e..3ca898bfd83 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc @@ -18,6 +18,9 @@ #include "BLI_math_rotation.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_point_rotate_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Axis")}, @@ -34,6 +37,23 @@ static bNodeSocketTemplate geo_node_point_rotate_out[] = { {-1, ""}, }; +static void geo_node_point_rotate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + NodeGeometryRotatePoints *storage = (NodeGeometryRotatePoints *)((bNode *)ptr->data)->storage; + + uiItemR(layout, ptr, "type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + uiLayout *col = uiLayoutColumn(layout, false); + if (storage->type == GEO_NODE_POINT_ROTATE_TYPE_AXIS_ANGLE) { + uiItemR(col, ptr, "input_type_axis", 0, IFACE_("Axis"), ICON_NONE); + uiItemR(col, ptr, "input_type_angle", 0, IFACE_("Angle"), ICON_NONE); + } + else { + uiItemR(col, ptr, "input_type_rotation", 0, IFACE_("Rotation"), ICON_NONE); + } +} + namespace blender::nodes { static void point_rotate__axis_angle__object_space(const int domain_size, @@ -202,5 +222,6 @@ void register_node_type_geo_point_rotate() node_type_storage( &ntype, "NodeGeometryRotatePoints", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_point_rotate_exec; + ntype.draw_buttons = geo_node_point_rotate_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc b/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc index 47fca93d2ab..78e23b783db 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_scale.cc @@ -18,6 +18,9 @@ #include "BKE_colorband.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_point_scale_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Factor")}, @@ -30,6 +33,11 @@ static bNodeSocketTemplate geo_node_point_scale_out[] = { {-1, ""}, }; +static void geo_node_point_scale_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); +} + namespace blender::nodes { static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component) @@ -96,5 +104,6 @@ void register_node_type_geo_point_scale() node_type_storage( &ntype, "NodeGeometryPointScale", node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_point_scale_exec; + ntype.draw_buttons = geo_node_point_scale_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_translate.cc b/source/blender/nodes/geometry/nodes/node_geo_point_translate.cc index 72176b11fdb..f7f369f5d66 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_translate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_translate.cc @@ -18,6 +18,9 @@ #include "BKE_colorband.h" +#include "UI_interface.h" +#include "UI_resources.h" + static bNodeSocketTemplate geo_node_point_translate_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_STRING, N_("Translation")}, @@ -30,6 +33,11 @@ static bNodeSocketTemplate geo_node_point_translate_out[] = { {-1, ""}, }; +static void geo_node_point_translate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "input_type", 0, IFACE_("Type"), ICON_NONE); +} + namespace blender::nodes { static void execute_on_component(GeoNodeExecParams params, GeometryComponent &component) @@ -97,5 +105,6 @@ void register_node_type_geo_point_translate() node_free_standard_storage, node_copy_standard_storage); ntype.geometry_node_execute = blender::nodes::geo_node_point_translate_exec; + ntype.draw_buttons = geo_node_point_translate_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc new file mode 100644 index 00000000000..428f129fb36 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_points_to_volume.cc @@ -0,0 +1,273 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +# include <openvdb/tools/LevelSetUtil.h> +# include <openvdb/tools/ParticlesToLevelSet.h> +#endif + +#include "node_geometry_util.hh" + +#include "BKE_lib_id.h" +#include "BKE_volume.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +static bNodeSocketTemplate geo_node_points_to_volume_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_FLOAT, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {SOCK_FLOAT, N_("Voxel Size"), 0.3f, 0.0f, 0.0f, 0.0f, 0.01f, FLT_MAX}, + {SOCK_FLOAT, N_("Voxel Amount"), 64.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {SOCK_STRING, N_("Radius")}, + {SOCK_FLOAT, N_("Radius"), 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_point_translate_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_points_to_volume_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); + uiItemR(layout, ptr, "input_type_radius", 0, IFACE_("Radius"), ICON_NONE); +} + +namespace blender::nodes { + +#ifdef WITH_OPENVDB +namespace { +/* Implements the interface required by #openvdb::tools::ParticlesToLevelSet. */ +struct ParticleList { + using PosType = openvdb::Vec3R; + + Span<float3> positions; + Span<float> radii; + + size_t size() const + { + return (size_t)positions.size(); + } + + void getPos(size_t n, openvdb::Vec3R &xyz) const + { + xyz = &positions[n].x; + } + + void getPosRad(size_t n, openvdb::Vec3R &xyz, openvdb::Real &radius) const + { + xyz = &positions[n].x; + radius = radii[n]; + } +}; +} // namespace + +static openvdb::FloatGrid::Ptr generate_volume_from_points(const Span<float3> positions, + const Span<float> radii, + const float density) +{ + /* Create a new grid that will be filled. #ParticlesToLevelSet requires the background value to + * be positive. It will be set to zero later on. */ + openvdb::FloatGrid::Ptr new_grid = openvdb::FloatGrid::create(1.0f); + + /* Create a narrow-band level set grid based on the positions and radii. */ + openvdb::tools::ParticlesToLevelSet op{*new_grid}; + /* Don't ignore particles based on their radius. */ + op.setRmin(0.0f); + op.setRmax(FLT_MAX); + ParticleList particles{positions, radii}; + op.rasterizeSpheres(particles); + op.finalize(); + + /* Convert the level set to a fog volume. This also sets the background value to zero. Inside the + * fog there will be a density of 1. */ + openvdb::tools::sdfToFogVolume(*new_grid); + + /* Take the desired density into account. */ + openvdb::tools::foreach (new_grid->beginValueOn(), + [&](const openvdb::FloatGrid::ValueOnIter &iter) { + iter.modifyValue([&](float &value) { value *= density; }); + }); + return new_grid; +} + +static float compute_voxel_size(const GeoNodeExecParams ¶ms, + Span<float3> positions, + const float radius) +{ + const NodeGeometryPointsToVolume &storage = + *(const NodeGeometryPointsToVolume *)params.node().storage; + + if (storage.resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE) { + return params.get_input<float>("Voxel Size"); + } + + if (positions.is_empty()) { + return 0.0f; + } + + float3 min, max; + INIT_MINMAX(min, max); + minmax_v3v3_v3_array(min, max, (float(*)[3])positions.data(), positions.size()); + + const float voxel_amount = params.get_input<float>("Voxel Amount"); + if (voxel_amount <= 1) { + return 0.0f; + } + + /* The voxel size adapts to the final size of the volume. */ + const float diagonal = float3::distance(min, max); + const float extended_diagonal = diagonal + 2.0f * radius; + const float voxel_size = extended_diagonal / voxel_amount; + return voxel_size; +} + +static void gather_point_data_from_component(const GeoNodeExecParams ¶ms, + const GeometryComponent &component, + Vector<float3> &r_positions, + Vector<float> &r_radii) +{ + Float3ReadAttribute positions = component.attribute_get_for_read<float3>( + "position", ATTR_DOMAIN_POINT, {0, 0, 0}); + FloatReadAttribute radii = params.get_input_attribute<float>( + "Radius", component, ATTR_DOMAIN_POINT, 0.0f); + + r_positions.extend(positions.get_span()); + r_radii.extend(radii.get_span()); +} + +static void convert_to_grid_index_space(const float voxel_size, + MutableSpan<float3> positions, + MutableSpan<float> radii) +{ + const float voxel_size_inv = 1.0f / voxel_size; + for (const int i : positions.index_range()) { + positions[i] *= voxel_size_inv; + /* Better align generated grid with source points. */ + positions[i] -= float3(0.5f); + radii[i] *= voxel_size_inv; + } +} + +static void initialize_volume_component_from_points(const GeometrySet &geometry_set_in, + GeometrySet &geometry_set_out, + const GeoNodeExecParams ¶ms) +{ + Vector<float3> positions; + Vector<float> radii; + + if (geometry_set_in.has<MeshComponent>()) { + gather_point_data_from_component( + params, *geometry_set_in.get_component_for_read<MeshComponent>(), positions, radii); + } + if (geometry_set_in.has<PointCloudComponent>()) { + gather_point_data_from_component( + params, *geometry_set_in.get_component_for_read<PointCloudComponent>(), positions, radii); + } + + const float max_radius = *std::max_element(radii.begin(), radii.end()); + const float voxel_size = compute_voxel_size(params, positions, max_radius); + if (voxel_size == 0.0f || positions.is_empty()) { + return; + } + + Volume *volume = (Volume *)BKE_id_new_nomain(ID_VO, nullptr); + BKE_volume_init_grids(volume); + + VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT); + openvdb::FloatGrid::Ptr density_grid = openvdb::gridPtrCast<openvdb::FloatGrid>( + BKE_volume_grid_openvdb_for_write(volume, c_density_grid, false)); + + const float density = params.get_input<float>("Density"); + convert_to_grid_index_space(voxel_size, positions, radii); + openvdb::FloatGrid::Ptr new_grid = generate_volume_from_points(positions, radii, density); + /* This merge is cheap, because the #density_grid is empty. */ + density_grid->merge(*new_grid); + density_grid->transform().postScale(voxel_size); + + VolumeComponent &volume_component = geometry_set_out.get_component_for_write<VolumeComponent>(); + volume_component.replace(volume); +} +#endif + +static void geo_node_points_to_volume_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set_out; + +#ifdef WITH_OPENVDB + initialize_volume_component_from_points(geometry_set_in, geometry_set_out, params); +#endif + + params.set_output("Geometry", std::move(geometry_set_out)); +} + +static void geo_node_points_to_volume_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)MEM_callocN( + sizeof(NodeGeometryPointsToVolume), __func__); + data->resolution_mode = GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT; + data->input_type_radius = GEO_NODE_ATTRIBUTE_INPUT_FLOAT; + node->storage = data; + + bNodeSocket *radius_attribute_socket = nodeFindSocket(node, SOCK_IN, "Radius"); + bNodeSocketValueString *radius_attribute_socket_value = + (bNodeSocketValueString *)radius_attribute_socket->default_value; + STRNCPY(radius_attribute_socket_value->value, "radius"); +} + +static void geo_node_points_to_volume_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryPointsToVolume *data = (NodeGeometryPointsToVolume *)node->storage; + bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); + bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); + nodeSetSocketAvailability(voxel_amount_socket, + data->resolution_mode == + GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_AMOUNT); + nodeSetSocketAvailability( + voxel_size_socket, data->resolution_mode == GEO_NODE_POINTS_TO_VOLUME_RESOLUTION_MODE_SIZE); + + update_attribute_input_socket_availabilities( + *node, "Radius", (GeometryNodeAttributeInputMode)data->input_type_radius); +} + +} // namespace blender::nodes + +void register_node_type_geo_points_to_volume() +{ + static bNodeType ntype; + + geo_node_type_base( + &ntype, GEO_NODE_POINTS_TO_VOLUME, "Points to Volume", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_points_to_volume_in, geo_node_point_translate_out); + node_type_storage(&ntype, + "NodeGeometryPointsToVolume", + node_free_standard_storage, + node_copy_standard_storage); + node_type_size(&ntype, 170, 120, 700); + node_type_init(&ntype, blender::nodes::geo_node_points_to_volume_init); + node_type_update(&ntype, blender::nodes::geo_node_points_to_volume_update); + ntype.geometry_node_execute = blender::nodes::geo_node_points_to_volume_exec; + ntype.draw_buttons = geo_node_points_to_volume_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc index 543859aef3f..99f7339a1cc 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc @@ -20,6 +20,9 @@ #include "BKE_subdiv.h" #include "BKE_subdiv_mesh.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_geometry_util.hh" static bNodeSocketTemplate geo_node_subdivision_surface_in[] = { @@ -36,6 +39,17 @@ static bNodeSocketTemplate geo_node_subdivision_surface_out[] = { {-1, ""}, }; +static void geo_node_subdivision_surface_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *UNUSED(ptr)) +{ +#ifndef WITH_OPENSUBDIV + uiItemL(layout, IFACE_("Disabled, built without OpenSubdiv"), ICON_ERROR); +#else + UNUSED_VARS(layout); +#endif +} + namespace blender::nodes { static void geo_node_subdivision_surface_exec(GeoNodeExecParams params) { @@ -112,5 +126,6 @@ void register_node_type_geo_subdivision_surface() node_type_socket_templates( &ntype, geo_node_subdivision_surface_in, geo_node_subdivision_surface_out); ntype.geometry_node_execute = blender::nodes::geo_node_subdivision_surface_exec; + ntype.draw_buttons = geo_node_subdivision_surface_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc index 1fcd1063993..539a7551be9 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc @@ -14,11 +14,19 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifdef WITH_OPENVDB +# include <openvdb/openvdb.h> +#endif + #include "BLI_math_matrix.h" #include "DNA_pointcloud_types.h" +#include "DNA_volume_types.h" #include "BKE_mesh.h" +#include "BKE_volume.h" + +#include "DEG_depsgraph_query.h" #include "node_geometry_util.hh" @@ -109,6 +117,43 @@ static void transform_instances(InstancesComponent &instances, } } +static void transform_volume(Volume *volume, + const float3 translation, + const float3 rotation, + const float3 scale, + GeoNodeExecParams ¶ms) +{ +#ifdef WITH_OPENVDB + /* Scaling an axis to zero is not supported for volumes. */ + const float3 limited_scale = { + (scale.x == 0.0f) ? FLT_EPSILON : scale.x, + (scale.y == 0.0f) ? FLT_EPSILON : scale.y, + (scale.z == 0.0f) ? FLT_EPSILON : scale.z, + }; + + Main *bmain = DEG_get_bmain(params.depsgraph()); + BKE_volume_load(volume, bmain); + + float matrix[4][4]; + loc_eul_size_to_mat4(matrix, translation, rotation, limited_scale); + + openvdb::Mat4s vdb_matrix; + memcpy(vdb_matrix.asPointer(), matrix, sizeof(float[4][4])); + openvdb::Mat4d vdb_matrix_d{vdb_matrix}; + + const int num_grids = BKE_volume_num_grids(volume); + for (const int i : IndexRange(num_grids)) { + VolumeGrid *volume_grid = BKE_volume_grid_get(volume, i); + + openvdb::GridBase::Ptr grid = BKE_volume_grid_openvdb_for_write(volume, volume_grid, false); + openvdb::math::Transform &grid_transform = grid->transform(); + grid_transform.postMult(vdb_matrix_d); + } +#else + UNUSED_VARS(volume, translation, rotation, scale, params); +#endif +} + static void geo_node_transform_exec(GeoNodeExecParams params) { GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); @@ -131,6 +176,11 @@ static void geo_node_transform_exec(GeoNodeExecParams params) transform_instances(instances, translation, rotation, scale); } + if (geometry_set.has_volume()) { + Volume *volume = geometry_set.get_volume_for_write(); + transform_volume(volume, translation, rotation, scale, params); + } + params.set_output("Geometry", std::move(geometry_set)); } } // namespace blender::nodes diff --git a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc index c224731ad9f..32fa32a9f13 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_triangulate.cc @@ -18,6 +18,9 @@ #include "RNA_enum_types.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "node_geometry_util.hh" extern "C" { @@ -39,6 +42,12 @@ static bNodeSocketTemplate geo_node_triangulate_out[] = { {-1, ""}, }; +static void geo_node_triangulate_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "quad_method", 0, "", ICON_NONE); + uiItemR(layout, ptr, "ngon_method", 0, "", ICON_NONE); +} + static void geo_triangulate_init(bNodeTree *UNUSED(ntree), bNode *node) { node->custom1 = GEO_NODE_TRIANGULATE_QUAD_SHORTEDGE; @@ -75,5 +84,6 @@ void register_node_type_geo_triangulate() node_type_socket_templates(&ntype, geo_node_triangulate_in, geo_node_triangulate_out); node_type_init(&ntype, geo_triangulate_init); ntype.geometry_node_execute = blender::nodes::geo_node_triangulate_exec; + ntype.draw_buttons = geo_node_triangulate_layout; nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc new file mode 100644 index 00000000000..54dccb613a1 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_volume_to_mesh.cc @@ -0,0 +1,171 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "DEG_depsgraph_query.h" +#ifdef WITH_OPENVDB +# include <openvdb/tools/GridTransformer.h> +# include <openvdb/tools/VolumeToMesh.h> +#endif + +#include "node_geometry_util.hh" + +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_volume.h" +#include "BKE_volume_to_mesh.hh" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +static bNodeSocketTemplate geo_node_volume_to_mesh_in[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {SOCK_STRING, N_("Grid")}, + {SOCK_FLOAT, N_("Voxel Size"), 0.3f, 0.0f, 0.0f, 0.0f, 0.01f, FLT_MAX}, + {SOCK_FLOAT, N_("Voxel Amount"), 64.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {SOCK_FLOAT, N_("Threshold"), 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {SOCK_FLOAT, N_("Adaptivity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_volume_to_mesh_out[] = { + {SOCK_GEOMETRY, N_("Geometry")}, + {-1, ""}, +}; + +static void geo_node_volume_to_mesh_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiLayoutSetPropSep(layout, true); + uiLayoutSetPropDecorate(layout, false); + uiItemR(layout, ptr, "resolution_mode", 0, IFACE_("Resolution"), ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_volume_to_mesh_init(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)MEM_callocN( + sizeof(NodeGeometryVolumeToMesh), __func__); + data->resolution_mode = VOLUME_TO_MESH_RESOLUTION_MODE_GRID; + + bNodeSocket *grid_socket = nodeFindSocket(node, SOCK_IN, "Grid"); + bNodeSocketValueString *grid_socket_value = (bNodeSocketValueString *)grid_socket->default_value; + STRNCPY(grid_socket_value->value, "density"); + + node->storage = data; +} + +static void geo_node_volume_to_mesh_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + NodeGeometryVolumeToMesh *data = (NodeGeometryVolumeToMesh *)node->storage; + + bNodeSocket *voxel_size_socket = nodeFindSocket(node, SOCK_IN, "Voxel Size"); + bNodeSocket *voxel_amount_socket = nodeFindSocket(node, SOCK_IN, "Voxel Amount"); + nodeSetSocketAvailability(voxel_amount_socket, + data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT); + nodeSetSocketAvailability(voxel_size_socket, + data->resolution_mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE); +} + +#ifdef WITH_OPENVDB + +static void create_mesh_from_volume(GeometrySet &geometry_set_in, + GeometrySet &geometry_set_out, + GeoNodeExecParams ¶ms) +{ + if (!geometry_set_in.has<VolumeComponent>()) { + return; + } + + const NodeGeometryVolumeToMesh &storage = + *(const NodeGeometryVolumeToMesh *)params.node().storage; + + bke::VolumeToMeshResolution resolution; + resolution.mode = (VolumeToMeshResolutionMode)storage.resolution_mode; + if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_AMOUNT) { + resolution.settings.voxel_amount = params.get_input<float>("Voxel Amount"); + if (resolution.settings.voxel_amount <= 0.0f) { + return; + } + } + else if (resolution.mode == VOLUME_TO_MESH_RESOLUTION_MODE_VOXEL_SIZE) { + resolution.settings.voxel_size = params.get_input<float>("Voxel Size"); + if (resolution.settings.voxel_size <= 0.0f) { + return; + } + } + + const VolumeComponent *component = geometry_set_in.get_component_for_read<VolumeComponent>(); + const Volume *volume = component->get_for_read(); + if (volume == nullptr) { + return; + } + + Main *bmain = DEG_get_bmain(params.depsgraph()); + BKE_volume_load(const_cast<Volume *>(volume), bmain); + + const std::string grid_name = params.get_input<std::string>("Grid"); + VolumeGrid *volume_grid = BKE_volume_grid_find(volume, grid_name.c_str()); + if (volume_grid == nullptr) { + return; + } + + float threshold = params.get_input<float>("Threshold"); + float adaptivity = params.get_input<float>("Adaptivity"); + + const openvdb::GridBase::ConstPtr grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid); + Mesh *mesh = bke::volume_to_mesh(*grid, resolution, threshold, adaptivity); + if (mesh == nullptr) { + return; + } + MeshComponent &dst_component = geometry_set_out.get_component_for_write<MeshComponent>(); + dst_component.replace(mesh); +} + +#endif /* WITH_OPENVDB */ + +static void geo_node_volume_to_mesh_exec(GeoNodeExecParams params) +{ + GeometrySet geometry_set_in = params.extract_input<GeometrySet>("Geometry"); + GeometrySet geometry_set_out; + +#ifdef WITH_OPENVDB + create_mesh_from_volume(geometry_set_in, geometry_set_out, params); +#endif + + params.set_output("Geometry", geometry_set_out); +} + +} // namespace blender::nodes + +void register_node_type_geo_volume_to_mesh() +{ + static bNodeType ntype; + + geo_node_type_base(&ntype, GEO_NODE_VOLUME_TO_MESH, "Volume to Mesh", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates(&ntype, geo_node_volume_to_mesh_in, geo_node_volume_to_mesh_out); + node_type_storage( + &ntype, "NodeGeometryVolumeToMesh", node_free_standard_storage, node_copy_standard_storage); + node_type_size(&ntype, 200, 120, 700); + node_type_init(&ntype, blender::nodes::geo_node_volume_to_mesh_init); + node_type_update(&ntype, blender::nodes::geo_node_volume_to_mesh_update); + ntype.geometry_node_execute = blender::nodes::geo_node_volume_to_mesh_exec; + ntype.draw_buttons = geo_node_volume_to_mesh_layout; + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc index c693047ff40..f5a0e14f18b 100644 --- a/source/blender/nodes/intern/derived_node_tree.cc +++ b/source/blender/nodes/intern/derived_node_tree.cc @@ -91,7 +91,7 @@ DNode &DerivedNodeTree::create_node(const NodeRef &node_ref, for (int i : node.inputs_.index_range()) { const InputSocketRef &socket_ref = node_ref.input(i); DInputSocket &socket = *node.inputs_[i]; - + socket.is_multi_input_socket_ = socket_ref.bsocket()->flag & SOCK_MULTI_INPUT; socket.id_ = UNINITIALIZED_ID; socket.node_ = &node; socket.socket_ref_ = &socket_ref; diff --git a/source/blender/nodes/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc index 2e4196af156..c2391667e86 100644 --- a/source/blender/nodes/intern/node_tree_multi_function.cc +++ b/source/blender/nodes/intern/node_tree_multi_function.cc @@ -19,6 +19,7 @@ #include "FN_multi_function_network_evaluation.hh" #include "BLI_color.hh" +#include "BLI_float2.hh" #include "BLI_float3.hh" namespace blender::nodes { @@ -191,27 +192,58 @@ static void add_implicit_conversion(DataTypeConversions &conversions, static DataTypeConversions create_implicit_conversions() { DataTypeConversions conversions; - add_implicit_conversion<float, int32_t>(conversions); + add_implicit_conversion<float, float2>(conversions); add_implicit_conversion<float, float3>(conversions); - add_implicit_conversion<int32_t, float>(conversions); + add_implicit_conversion<float, int32_t>(conversions); add_implicit_conversion<float, bool>(conversions); - add_implicit_conversion<bool, float>(conversions); - add_implicit_conversion<float3, float>( - conversions, "Vector Length", [](float3 a) { return a.length(); }); - add_implicit_conversion<int32_t, float3>( - conversions, "int32 to float3", [](int32_t a) { return float3((float)a); }); - add_implicit_conversion<float3, Color4f>( - conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); }); - add_implicit_conversion<Color4f, float3>( - conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); }); add_implicit_conversion<float, Color4f>( conversions, "float to Color4f", [](float a) { return Color4f(a, a, a, 1.0f); }); - add_implicit_conversion<Color4f, float>( - conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); + + add_implicit_conversion<float2, float3>( + conversions, "float2 to float3", [](float2 a) { return float3(a.x, a.y, 0.0f); }); + add_implicit_conversion<float2, float>( + conversions, "float2 to float", [](float2 a) { return a.length(); }); + add_implicit_conversion<float2, int32_t>( + conversions, "float2 to int32_t", [](float2 a) { return (int32_t)a.length(); }); + add_implicit_conversion<float2, bool>( + conversions, "float2 to bool", [](float2 a) { return a.length_squared() == 0.0f; }); + add_implicit_conversion<float2, Color4f>( + conversions, "float2 to Color4f", [](float2 a) { return Color4f(a.x, a.y, 0.0f, 1.0f); }); + add_implicit_conversion<float3, bool>( conversions, "float3 to boolean", [](float3 a) { return a.length_squared() == 0.0f; }); + add_implicit_conversion<float3, float>( + conversions, "Vector Length", [](float3 a) { return a.length(); }); + add_implicit_conversion<float3, int32_t>( + conversions, "float3 to int32_t", [](float3 a) { return (int)a.length(); }); + add_implicit_conversion<float3, float2>(conversions); + add_implicit_conversion<float3, Color4f>( + conversions, "float3 to Color4f", [](float3 a) { return Color4f(a.x, a.y, a.z, 1.0f); }); + + add_implicit_conversion<int32_t, bool>(conversions); + add_implicit_conversion<int32_t, float>(conversions); + add_implicit_conversion<int32_t, float2>( + conversions, "int32 to float2", [](int32_t a) { return float2((float)a); }); + add_implicit_conversion<int32_t, float3>( + conversions, "int32 to float3", [](int32_t a) { return float3((float)a); }); + + add_implicit_conversion<bool, float>(conversions); + add_implicit_conversion<bool, int32_t>(conversions); + add_implicit_conversion<bool, float2>( + conversions, "boolean to float2", [](bool a) { return (a) ? float2(1.0f) : float2(0.0f); }); add_implicit_conversion<bool, float3>( conversions, "boolean to float3", [](bool a) { return (a) ? float3(1.0f) : float3(0.0f); }); + add_implicit_conversion<bool, Color4f>(conversions, "boolean to Color4f", [](bool a) { + return (a) ? Color4f(1.0f, 1.0f, 1.0f, 1.0f) : Color4f(0.0f, 0.0f, 0.0f, 1.0f); + }); + + add_implicit_conversion<Color4f, float>( + conversions, "Color4f to float", [](Color4f a) { return rgb_to_grayscale(a); }); + add_implicit_conversion<Color4f, float2>( + conversions, "Color4f to float2", [](Color4f a) { return float2(a.r, a.g); }); + add_implicit_conversion<Color4f, float3>( + conversions, "Color4f to float3", [](Color4f a) { return float3(a.r, a.g, a.b); }); + return conversions; } diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index 9669dc6496b..c7c3ced4e56 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -281,25 +281,30 @@ static int node_count_links(bNodeTree *ntree, bNodeSocket *sock) return count; } -/* find an eligible socket for linking */ +/* Find an eligible socket for linking. */ static bNodeSocket *node_find_linkable_socket(bNodeTree *ntree, bNode *node, bNodeSocket *cur) { - /* link swapping: try to find a free slot with a matching name */ - bNodeSocket *first = cur->in_out == SOCK_IN ? node->inputs.first : node->outputs.first; bNodeSocket *sock; - sock = cur->next ? cur->next : first; /* wrap around the list end */ + /* Iterate over all sockets of the target node, to find one that matches the same socket type. + * The idea behind this is: When a user connects an input to a socket that is + * already linked (and if its not an Multi Input Socket), we try to find a replacement socket for + * the link that we try to overwrite and connect that previous link to the new socket. */ + sock = cur->next ? cur->next : first; /* Wrap around the list end. */ while (sock != cur) { if (!nodeSocketIsHidden(sock) && node_link_socket_match(sock, cur)) { - int link_count = node_count_links(ntree, sock); - /* take +1 into account since we would add a new link */ - if (link_count + 1 <= nodeSocketLinkLimit(sock)) { - return sock; /* found a valid free socket we can swap to */ - } + break; } + sock = sock->next ? sock->next : first; /* Wrap around the list end. */ + } - sock = sock->next ? sock->next : first; /* wrap around the list end */ + if (!nodeSocketIsHidden(sock) && node_link_socket_match(sock, cur)) { + int link_count = node_count_links(ntree, sock); + /* Take +1 into account since we would add a new link. */ + if (link_count + 1 <= nodeSocketLinkLimit(sock)) { + return sock; /* Found a valid free socket we can swap to. */ + } } return NULL; } @@ -309,7 +314,6 @@ void node_insert_link_default(bNodeTree *ntree, bNode *node, bNodeLink *link) bNodeSocket *sock = link->tosock; bNodeLink *tlink, *tlink_next; - /* inputs can have one link only, outputs can have unlimited links */ if (node != link->tonode) { return; } diff --git a/source/blender/nodes/texture/node_texture_util.c b/source/blender/nodes/texture/node_texture_util.c index 96a0be6babc..2091a8bf10e 100644 --- a/source/blender/nodes/texture/node_texture_util.c +++ b/source/blender/nodes/texture/node_texture_util.c @@ -146,7 +146,7 @@ void tex_output(bNode *node, } if (!out->data) { - /* Freed in tex_end_exec (node.c) */ + /* Freed in tex_end_exec (node.cc) */ dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate"); } else { diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 38122c45ef1..e9499818f64 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -293,7 +293,7 @@ static int bpy_bmesh_select_mode_set(BPy_BMesh *self, PyObject *value) return -1; } if (flag == 0) { - PyErr_SetString(PyExc_TypeError, "bm.select_mode: cant assignt an empty value"); + PyErr_SetString(PyExc_TypeError, "bm.select_mode: can't assign an empty value"); return -1; } @@ -1079,7 +1079,12 @@ PyDoc_STRVAR( " :arg cage: Get the mesh as a deformed cage.\n" " :type cage: boolean\n" " :arg face_normals: Calculate face normals.\n" - " :type face_normals: boolean\n"); + " :type face_normals: boolean\n" + "\n" + " .. deprecated:: 2.93\n" + "\n" + " The deform parameter is deprecated, assumed to be True, and will be removed in version " + "3.0.\n"); static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject *kw) { static const char *kwlist[] = {"object", "depsgraph", "deform", "cage", "face_normals", NULL}; @@ -1120,45 +1125,36 @@ static PyObject *bpy_bmesh_from_object(BPy_BMesh *self, PyObject *args, PyObject return NULL; } + if (use_deform == false) { + PyErr_WarnEx(PyExc_FutureWarning, + "from_object(...): the deform parameter is deprecated, assumed to be True, and " + "will be removed in version 3.0", + 1); + } + const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; scene_eval = DEG_get_evaluated_scene(depsgraph); ob_eval = DEG_get_evaluated_object(depsgraph, ob); bool need_free = false; /* Write the display mesh into the dummy mesh */ - if (use_deform) { - if (use_render) { - if (use_cage) { - PyErr_SetString(PyExc_ValueError, - "from_object(...): cage arg is unsupported when dependency graph " - "evaluation mode is RENDER"); - return NULL; - } - - me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true); - need_free = true; - } - else { - if (use_cage) { - me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks); - } - else { - me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks); - } - } - } - else { - /* !use_deform */ + if (use_render) { if (use_cage) { PyErr_SetString(PyExc_ValueError, - "from_object(...): cage arg is unsupported when deform=False"); + "from_object(...): cage arg is unsupported when dependency graph " + "evaluation mode is RENDER"); return NULL; } - if (use_render) { - me_eval = mesh_create_eval_no_deform_render(depsgraph, scene_eval, ob, &data_masks); + + me_eval = BKE_mesh_new_from_object(depsgraph, ob_eval, true); + need_free = true; + } + else { + if (use_cage) { + me_eval = mesh_get_eval_deform(depsgraph, scene_eval, ob_eval, &data_masks); } else { - me_eval = mesh_create_eval_no_deform(depsgraph, scene_eval, ob, &data_masks); + me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &data_masks); } } diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index d944cb435d0..ec6b8c54ac0 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -865,11 +865,11 @@ bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]) } /* restore MUST be called after this */ -void PyC_MainModule_Backup(PyObject **main_mod) +void PyC_MainModule_Backup(PyObject **r_main_mod) { PyObject *modules = PyImport_GetModuleDict(); - *main_mod = PyDict_GetItemString(modules, "__main__"); - Py_XINCREF(*main_mod); /* don't free */ + *r_main_mod = PyDict_GetItemString(modules, "__main__"); + Py_XINCREF(*r_main_mod); /* don't free */ } void PyC_MainModule_Restore(PyObject *main_mod) diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index f0875b82c3c..358123657c7 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -85,7 +85,7 @@ PyObject *PyC_DefaultNameSpace(const char *filename); void PyC_RunQuicky(const char *filepath, int n, ...); bool PyC_NameSpace_ImportArray(PyObject *py_dict, const char *imports[]); -void PyC_MainModule_Backup(PyObject **main_mod); +void PyC_MainModule_Backup(PyObject **r_main_mod); void PyC_MainModule_Restore(PyObject *main_mod); void PyC_SetHomePath(const char *py_path_bundle); diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c index 526b96f8584..b2603c75c3f 100644 --- a/source/blender/python/gpu/gpu_py_shader.c +++ b/source/blender/python/gpu/gpu_py_shader.c @@ -169,12 +169,12 @@ static PyObject *py_shader_uniform_block_from_name(BPyGPUShader *self, PyObject return PyLong_FromLong(uniform); } -static bool py_shader_uniform_vector_imp(PyObject *args, - int elem_size, - int *r_location, - int *r_length, - int *r_count, - Py_buffer *r_pybuffer) +static bool py_shader_uniform_vector_impl(PyObject *args, + int elem_size, + int *r_location, + int *r_length, + int *r_count, + Py_buffer *r_pybuffer) { PyObject *buffer; @@ -223,7 +223,7 @@ static PyObject *py_shader_uniform_vector_float(BPyGPUShader *self, PyObject *ar Py_buffer pybuffer; - if (!py_shader_uniform_vector_imp(args, sizeof(float), &location, &length, &count, &pybuffer)) { + if (!py_shader_uniform_vector_impl(args, sizeof(float), &location, &length, &count, &pybuffer)) { return NULL; } @@ -244,7 +244,7 @@ static PyObject *py_shader_uniform_vector_int(BPyGPUShader *self, PyObject *args Py_buffer pybuffer; - if (!py_shader_uniform_vector_imp(args, sizeof(int), &location, &length, &count, &pybuffer)) { + if (!py_shader_uniform_vector_impl(args, sizeof(int), &location, &length, &count, &pybuffer)) { return NULL; } @@ -570,9 +570,6 @@ PyDoc_STRVAR( " ``GL_ARB_texture_gather``, ``GL_ARB_texture_cube_map_array``\n" " and ``GL_ARB_shader_draw_parameters``.\n" "\n" - " To debug shaders, use the ``--debug-gpu-shaders`` command line option\n" - " to see full GLSL shader compilation and linking errors.\n" - "\n" " For drawing user interface elements and gizmos, use\n" " ``fragOutput = blender_srgb_to_framebuffer_space(fragOutput)``\n" " to transform the output sRGB colors to the frame-buffer color-space.\n" diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 02ab001dbf6..c7e195b586d 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -424,11 +424,6 @@ static PyGetSetDef bpy_app_getsets[] = { bpy_app_debug_set, bpy_app_debug_doc, (void *)G_DEBUG_SIMDATA}, - {"debug_gpumem", - bpy_app_debug_get, - bpy_app_debug_set, - bpy_app_debug_doc, - (void *)G_DEBUG_GPU_MEM}, {"debug_io", bpy_app_debug_get, bpy_app_debug_set, bpy_app_debug_doc, (void *)G_DEBUG_IO}, {"use_event_simulate", diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 1e81621246e..8ecee9b3f2e 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -286,7 +286,7 @@ void BPY_app_handlers_reset(const short do_all) } else { /* remove */ - /* PySequence_DelItem(ls, i); */ /* more obvious buw slower */ + /* PySequence_DelItem(ls, i); */ /* more obvious but slower */ PyList_SetSlice(ls, i, i + 1, NULL); } } diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 64e992bd76f..c4789407e4e 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -341,12 +341,20 @@ void BPY_python_start(bContext *C, int argc, const char **argv) } } - /* Without this the `sys.stdout` may be set to 'ascii' - * (it is on my system at least), where printing unicode values will raise - * an error, this is highly annoying, another stumbling block for developers, - * so use a more relaxed error handler and enforce utf-8 since the rest of - * Blender is utf-8 too - campbell */ - Py_SetStandardStreamEncoding("utf-8", "surrogateescape"); + /* Force `utf-8` on all platforms, since this is what's used for Blender's internal strings, + * providing consistent encoding behavior across all Blender installations. + * + * This also uses the `surrogateescape` error handler ensures any unexpected bytes are escaped + * instead of raising an error. + * + * Without this `sys.getfilesystemencoding()` and `sys.stdout` for example may be set to ASCII + * or some other encoding - where printing some `utf-8` values will raise an error. + * + * This can cause scripts to fail entirely on some systems. + * + * This assignment is the equivalent of enabling the `PYTHONUTF8` environment variable. + * See `PEP-540` for details on exactly what this changes. */ + Py_UTF8Mode = 1; /* Suppress error messages when calculating the module search path. * While harmless, it's noisy. */ diff --git a/source/blender/python/intern/bpy_interface_atexit.c b/source/blender/python/intern/bpy_interface_atexit.c index 8e5a6dc530b..03d51b2fd59 100644 --- a/source/blender/python/intern/bpy_interface_atexit.c +++ b/source/blender/python/intern/bpy_interface_atexit.c @@ -42,7 +42,7 @@ static PyObject *bpy_atexit(PyObject *UNUSED(self), PyObject *UNUSED(args), PyOb } static PyMethodDef meth_bpy_atexit = {"bpy_atexit", (PyCFunction)bpy_atexit, METH_NOARGS, NULL}; -static PyObject *func_bpy_atregister = NULL; /* borrowed referebce, atexit holds */ +static PyObject *func_bpy_atregister = NULL; /* borrowed reference, `atexit` holds. */ static void atexit_func_call(const char *func_name, PyObject *atexit_func_arg) { diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index c6f0fbd3a2b..39d1fba2dc9 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -173,7 +173,7 @@ static PyTypeObject bpy_lib_Type = { PyDoc_STRVAR( bpy_lib_load_doc, - ".. method:: load(filepath, link=False, relative=False)\n" + ".. method:: load(filepath, link=False, relative=False, assets_only=False)\n" "\n" " Returns a context manager which exposes 2 library objects on entering.\n" " Each object has attributes matching bpy.data which are lists of strings to be linked.\n" @@ -183,18 +183,28 @@ PyDoc_STRVAR( " :arg link: When False reference to the original file is lost.\n" " :type link: bool\n" " :arg relative: When True the path is stored relative to the open blend file.\n" - " :type relative: bool\n"); + " :type relative: bool\n" + " :arg assets_only: If True, only list data-blocks marked as assets.\n" + " :type assets_only: bool\n"); static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { Main *bmain = CTX_data_main(BPY_context_get()); BPy_Library *ret; const char *filename = NULL; - bool is_rel = false, is_link = false; - - static const char *_keywords[] = {"filepath", "link", "relative", NULL}; - static _PyArg_Parser _parser = {"s|O&O&:load", _keywords, 0}; - if (!_PyArg_ParseTupleAndKeywordsFast( - args, kw, &_parser, &filename, PyC_ParseBool, &is_link, PyC_ParseBool, &is_rel)) { + bool is_rel = false, is_link = false, use_assets_only = false; + + static const char *_keywords[] = {"filepath", "link", "relative", "assets_only", NULL}; + static _PyArg_Parser _parser = {"s|O&O&O&:load", _keywords, 0}; + if (!_PyArg_ParseTupleAndKeywordsFast(args, + kw, + &_parser, + &filename, + PyC_ParseBool, + &is_link, + PyC_ParseBool, + &is_rel, + PyC_ParseBool, + &use_assets_only)) { return NULL; } @@ -205,7 +215,8 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject * BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain)); ret->blo_handle = NULL; - ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0)); + ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0) | + (use_assets_only ? FILE_ASSETS_ONLY : 0)); ret->dict = _PyDict_NewPresized(MAX_LIBARRAY); @@ -218,7 +229,8 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) LinkNode *l, *names; int totnames; - names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); + names = BLO_blendhandle_get_datablock_names( + self->blo_handle, blocktype, (self->flag & FILE_ASSETS_ONLY) != 0, &totnames); list = PyList_New(totnames); if (names) { diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index a2125a5dff9..39ba8448795 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -605,7 +605,7 @@ static short pyrna_rotation_euler_order_get(PointerRNA *ptr, if (*r_prop_eul_order) { const short order = RNA_property_enum_get(ptr, *r_prop_eul_order); - /* Could be quat or axisangle. */ + /* Could be quaternion or axis-angle. */ if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { return order; } @@ -5051,7 +5051,7 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key { Py_ssize_t key_len_ssize_t; const char *key = _PyUnicode_AsStringAndSize(key_ob, &key_len_ssize_t); - const int key_len = (int)key_len_ssize_t; /* Comare with same type. */ + const int key_len = (int)key_len_ssize_t; /* Compare with same type. */ char name[256], *nameptr; int namelen; @@ -5094,7 +5094,7 @@ static bool foreach_attr_type(BPy_PropertyRNA *self, *r_attr_tot = 0; *r_attr_signed = false; - /* Note: this is fail with zero length lists, so don't let this get caled in that case. */ + /* NOTE: this is fail with zero length lists, so don't let this get called in that case. */ RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { prop = RNA_struct_find_property(&itemptr, attr); if (prop) { @@ -8737,15 +8737,17 @@ void pyrna_free_types(void) RNA_PROP_END; } -/* Note! MemLeak XXX +/** + * \warning memory leak! * * There is currently a bug where moving the registration of a Python class does - * not properly manage reference-counts from the Python class. As the srna owns + * not properly manage reference-counts from the Python class. As the `srna` owns * the Python class this should not be so tricky, but changing the references as * you'd expect when changing ownership crashes blender on exit so I had to comment out - * the decref. This is not so bad because the leak only happens when re-registering (hold F8) + * the #Py_DECREF. This is not so bad because the leak only happens when re-registering + * (continuously running `SCRIPT_OT_reload`). * - Should still be fixed - Campbell - * */ + */ PyDoc_STRVAR(pyrna_register_class_doc, ".. method:: register_class(cls)\n" "\n" diff --git a/source/blender/render/RE_engine.h b/source/blender/render/RE_engine.h index 1af40ac760b..c31a41f66d5 100644 --- a/source/blender/render/RE_engine.h +++ b/source/blender/render/RE_engine.h @@ -64,6 +64,7 @@ extern "C" { #define RE_USE_SPHERICAL_STEREO 128 #define RE_USE_STEREO_VIEWPORT 256 #define RE_USE_GPU_CONTEXT 512 +#define RE_USE_CUSTOM_FREESTYLE 1024 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 diff --git a/source/blender/render/RE_multires_bake.h b/source/blender/render/RE_multires_bake.h index fd200e85719..42ee2c57fbb 100644 --- a/source/blender/render/RE_multires_bake.h +++ b/source/blender/render/RE_multires_bake.h @@ -53,7 +53,7 @@ typedef struct MultiresBakeRender { int baked_objects, baked_faces; int raytrace_structure; /* Optimization structure to be used for AO baking */ - int octree_resolution; /* Reslution of octotree when using octotree optimization structure */ + int octree_resolution; /* Resolution of octree when using octree optimization structure */ int threads; /* Number of threads to be used for baking */ float user_scale; /* User scale used to scale displacement when baking derivative map. */ diff --git a/source/blender/render/RE_pipeline.h b/source/blender/render/RE_pipeline.h index 3e73ac77fc6..688709d55f3 100644 --- a/source/blender/render/RE_pipeline.h +++ b/source/blender/render/RE_pipeline.h @@ -252,13 +252,11 @@ void RE_ChangeModeFlag(struct Render *re, int flag, bool clear); struct Object *RE_GetCamera(struct Render *re); /* return camera override if set */ void RE_SetOverrideCamera(struct Render *re, struct Object *cam_ob); void RE_SetCamera(struct Render *re, struct Object *cam_ob); -void RE_SetWindow(struct Render *re, const rctf *viewplane, float clip_start, float clip_end); -void RE_SetOrtho(struct Render *re, const rctf *viewplane, float clip_start, float clip_end); /* get current view and window transform */ void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect); -/* set the render threads based on the command-line and autothreads setting */ +/* Set the render threads based on the command-line and auto-threads setting. */ void RE_init_threadcount(Render *re); bool RE_WriteRenderViewsImage(struct ReportList *reports, diff --git a/source/blender/render/intern/initrender.c b/source/blender/render/intern/initrender.c index fb7f7270c13..3494aa06833 100644 --- a/source/blender/render/intern/initrender.c +++ b/source/blender/render/intern/initrender.c @@ -172,28 +172,16 @@ struct Object *RE_GetCamera(Render *re) return BKE_camera_multiview_render(re->scene, camera, re->viewname); } -static void re_camera_params_get(Render *re, CameraParams *params) -{ - copy_m4_m4(re->winmat, params->winmat); - - re->clip_start = params->clip_start; - re->clip_end = params->clip_end; - - re->viewplane = params->viewplane; -} - void RE_SetOverrideCamera(Render *re, Object *cam_ob) { re->camera_override = cam_ob; } -static void re_camera_params_stereo3d(Render *re, CameraParams *params, Object *cam_ob) -{ - BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname); -} - -/* call this after InitState() */ -/* per render, there's one persistent viewplane. Parts will set their own viewplanes */ +/** + * Per render, there's one persistent view-plane. Parts will set their own view-planes. + * + * \note call this after #RE_InitState(). + */ void RE_SetCamera(Render *re, Object *cam_ob) { CameraParams params; @@ -201,14 +189,17 @@ void RE_SetCamera(Render *re, Object *cam_ob) /* setup parameters */ BKE_camera_params_init(¶ms); BKE_camera_params_from_object(¶ms, cam_ob); - re_camera_params_stereo3d(re, ¶ms, cam_ob); + BKE_camera_multiview_params(&re->r, ¶ms, cam_ob, re->viewname); /* compute matrix, viewplane, .. */ BKE_camera_params_compute_viewplane(¶ms, re->winx, re->winy, re->r.xasp, re->r.yasp); BKE_camera_params_compute_matrix(¶ms); /* extract results */ - re_camera_params_get(re, ¶ms); + copy_m4_m4(re->winmat, params.winmat); + re->clip_start = params.clip_start; + re->clip_end = params.clip_end; + re->viewplane = params.viewplane; } void RE_GetCameraWindow(struct Render *re, struct Object *camera, float r_winmat[4][4]) @@ -241,6 +232,19 @@ void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_modelmat BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_modelmat); } +void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect) +{ + *r_viewplane = re->viewplane; + + /* make disprect zero when no border render, is needed to detect changes in 3d view render */ + if (re->r.mode & R_BORDER) { + *r_disprect = re->disprect; + } + else { + BLI_rcti_init(r_disprect, 0, 0, 0, 0); + } +} + /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */ void RE_parts_free(Render *re) diff --git a/source/blender/render/intern/multires_bake.c b/source/blender/render/intern/multires_bake.c index a4f68419c67..1859886f563 100644 --- a/source/blender/render/intern/multires_bake.c +++ b/source/blender/render/intern/multires_bake.c @@ -768,7 +768,7 @@ static void *init_heights_data(MultiresBakeRender *bkr, Image *ima) if (ss_lvl > 0) { smd.levels = smd.renderLevels = ss_lvl; - smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS; + smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES; smd.quality = 3; height_data->ssdm = subsurf_make_derived_from_derived( diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 4628a5a132b..0a8b8f24614 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -983,53 +983,6 @@ void render_update_anim_renderdata(Render *re, RenderData *rd, ListBase *render_ BLI_duplicatelist(&re->r.views, &rd->views); } -void RE_SetWindow(Render *re, const rctf *viewplane, float clip_start, float clip_end) -{ - /* re->ok flag? */ - - re->viewplane = *viewplane; - re->clip_start = clip_start; - re->clip_end = clip_end; - - perspective_m4(re->winmat, - re->viewplane.xmin, - re->viewplane.xmax, - re->viewplane.ymin, - re->viewplane.ymax, - re->clip_start, - re->clip_end); -} - -void RE_SetOrtho(Render *re, const rctf *viewplane, float clip_start, float clip_end) -{ - /* re->ok flag? */ - - re->viewplane = *viewplane; - re->clip_start = clip_start; - re->clip_end = clip_end; - - orthographic_m4(re->winmat, - re->viewplane.xmin, - re->viewplane.xmax, - re->viewplane.ymin, - re->viewplane.ymax, - re->clip_start, - re->clip_end); -} - -void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect) -{ - *r_viewplane = re->viewplane; - - /* make disprect zero when no border render, is needed to detect changes in 3d view render */ - if (re->r.mode & R_BORDER) { - *r_disprect = re->disprect; - } - else { - BLI_rcti_init(r_disprect, 0, 0, 0, 0); - } -} - /* image and movie output has to move to either imbuf or kernel */ void RE_display_init_cb(Render *re, void *handle, void (*f)(void *handle, RenderResult *rr)) { @@ -2018,7 +1971,7 @@ void RE_RenderFrame(Render *re, if (write_still && !G.is_break) { if (BKE_imtype_is_movie(rd.im_format.imtype)) { /* operator checks this but in case its called from elsewhere */ - printf("Error: cant write single images with a movie format!\n"); + printf("Error: can't write single images with a movie format!\n"); } else { char name[FILE_MAX]; @@ -2055,12 +2008,39 @@ void RE_RenderFrame(Render *re, } #ifdef WITH_FREESTYLE + +/* Not freestyle specific, currently only used by free-style. */ +static void change_renderdata_engine(Render *re, const char *new_engine) +{ + if (!STREQ(re->r.engine, new_engine)) { + if (re->engine) { + RE_engine_free(re->engine); + re->engine = NULL; + } + BLI_strncpy(re->r.engine, new_engine, sizeof(re->r.engine)); + } +} + +static bool use_eevee_for_freestyle_render(Render *re) +{ + RenderEngineType *type = RE_engines_find(re->r.engine); + return !(type->flag & RE_USE_CUSTOM_FREESTYLE); +} + void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render) { re->result_ok = 0; if (render_init_from_main(re, &scene->r, bmain, scene, NULL, NULL, 0, 0)) { if (render) { + char scene_engine[32]; + BLI_strncpy(scene_engine, re->r.engine, sizeof(scene_engine)); + if (use_eevee_for_freestyle_render(re)) { + change_renderdata_engine(re, RE_engine_id_BLENDER_EEVEE); + } + do_render_3d(re); + + change_renderdata_engine(re, scene_engine); } } re->result_ok = 1; @@ -2357,7 +2337,7 @@ static int do_write_image_or_movie(Render *re, printf(" (Saving: %s)\n", name); fputc('\n', stdout); - fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */ + fflush(stdout); return ok; } @@ -2757,7 +2737,7 @@ void RE_init_threadcount(Render *re) void RE_layer_load_from_file( RenderLayer *layer, ReportList *reports, const char *filename, int x, int y) { - /* OCIO_TODO: assume layer was saved in defaule color space */ + /* OCIO_TODO: assume layer was saved in default color space */ ImBuf *ibuf = IMB_loadiffname(filename, IB_rect, NULL); RenderPass *rpass = NULL; diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index f135adc9f05..f73a200f3c6 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -443,7 +443,7 @@ RenderResult *render_result_new( } FOREACH_VIEW_LAYER_TO_RENDER_END; - /* previewrender doesn't do layers, so we make a default one */ + /* Preview-render doesn't do layers, so we make a default one. */ if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) { rl = MEM_callocN(sizeof(RenderLayer), "new render layer"); BLI_addtail(&rr->layers, rl); diff --git a/source/blender/render/intern/render_types.h b/source/blender/render/intern/render_types.h index 6be5fb4792c..7a4374dcf7c 100644 --- a/source/blender/render/intern/render_types.h +++ b/source/blender/render/intern/render_types.h @@ -103,7 +103,7 @@ struct Render { /* Camera transform, only used by Freestyle. */ float winmat[4][4]; - /* clippping */ + /* Clipping. */ float clip_start; float clip_end; diff --git a/source/blender/render/intern/texture_image.c b/source/blender/render/intern/texture_image.c index 5614318afbb..0299315beaf 100644 --- a/source/blender/render/intern/texture_image.c +++ b/source/blender/render/intern/texture_image.c @@ -630,7 +630,7 @@ static void boxsample(ImBuf *ibuf, const short imapextend) { /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 . - * Enlarge with antialiased edges of pixels. + * Enlarge with anti-aliased edges of pixels. * If variable 'imaprepeat' has been set, the * clipped-away parts are sampled as well. */ diff --git a/source/blender/render/intern/texture_procedural.c b/source/blender/render/intern/texture_procedural.c index a98f29a705d..b0ab20de10d 100644 --- a/source/blender/render/intern/texture_procedural.c +++ b/source/blender/render/intern/texture_procedural.c @@ -77,7 +77,7 @@ void RE_texture_rng_exit(void) /* ------------------------------------------------------------------------- */ -/* this allows colorbanded textures to control normals as well */ +/* This allows color-banded textures to control normals as well. */ static void tex_normal_derivate(const Tex *tex, TexResult *texres) { if (tex->flag & TEX_COLORBAND) { @@ -167,7 +167,7 @@ static int blend(const Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ /* ************************************************************************* */ -/* newnoise: all noisebased types now have different noisebases to choose from */ +/* newnoise: all noise-based types now have different noise-bases to choose from. */ static int clouds(const Tex *tex, const float texvec[3], TexResult *texres) { @@ -1059,7 +1059,7 @@ static void do_2d_mapping( dyt[2] *= 0.5f; } - /* if area, then reacalculate dxt[] and dyt[] */ + /* If area, then recalculate `dxt[]` and `dyt[]` */ if (areaflag) { fx = area[0]; fy = area[1]; diff --git a/source/blender/render/intern/zbuf.c b/source/blender/render/intern/zbuf.c index d74ab330dc2..33af3bbaf29 100644 --- a/source/blender/render/intern/zbuf.c +++ b/source/blender/render/intern/zbuf.c @@ -166,7 +166,7 @@ static void zbuf_add_to_span(ZSpan *zspan, const float v1[2], const float v2[2]) } for (y = my2; y >= my0; y--, xs0 += dx0) { - /* xs0 is the xcoord! */ + /* xs0 is the X-coordinate! */ span[y] = xs0; } } diff --git a/source/blender/sequencer/SEQ_render.h b/source/blender/sequencer/SEQ_render.h index 6f6d195126b..54584824da8 100644 --- a/source/blender/sequencer/SEQ_render.h +++ b/source/blender/sequencer/SEQ_render.h @@ -51,7 +51,7 @@ typedef struct SeqRenderData { bool is_proxy_render; bool is_prefetch_render; int view_id; - /* ID of task for asigning temp cache entries to particular task(thread, etc.) */ + /* ID of task for assigning temp cache entries to particular task(thread, etc.) */ eSeqTaskId task_id; /* special case for OpenGL render */ diff --git a/source/blender/sequencer/SEQ_select.h b/source/blender/sequencer/SEQ_select.h index 5a65f9c0d8c..abd56ef3af7 100644 --- a/source/blender/sequencer/SEQ_select.h +++ b/source/blender/sequencer/SEQ_select.h @@ -32,8 +32,8 @@ struct Sequence; struct Sequence *SEQ_select_active_get(struct Scene *scene); int SEQ_select_active_get_pair(struct Scene *scene, - struct Sequence **seq_act, - struct Sequence **seq_other); + struct Sequence **r_seq_act, + struct Sequence **r_seq_other); void SEQ_select_active_set(struct Scene *scene, struct Sequence *seq); #ifdef __cplusplus diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c index 344b5af26aa..290ee185865 100644 --- a/source/blender/sequencer/intern/image_cache.c +++ b/source/blender/sequencer/intern/image_cache.c @@ -166,7 +166,7 @@ typedef struct SeqCacheKey { float timeline_frame; /* Only for reference - used for freeing when cache is full. */ float cost; /* In short: render time(s) divided by playback frame duration(s) */ bool is_temp_cache; /* this cache entry will be freed before rendering next frame */ - /* ID of task for asigning temp cache entries to particular task(thread, etc.) */ + /* ID of task for assigning temp cache entries to particular task(thread, etc.) */ eSeqTaskId task_id; int type; } SeqCacheKey; @@ -824,16 +824,59 @@ static void seq_cache_valfree(void *val) BLI_mempool_free(item->cache_owner->items_pool, item); } -static void seq_cache_put_ex(SeqCache *cache, SeqCacheKey *key, ImBuf *ibuf) +static int get_stored_types_flag(Scene *scene, SeqCacheKey *key) { + int flag; + if (key->seq->cache_flag & SEQ_CACHE_OVERRIDE) { + flag = key->seq->cache_flag; + } + else { + flag = scene->ed->cache_flag; + } + + /* SEQ_CACHE_STORE_FINAL_OUT can not be overridden by strip cache */ + flag |= (scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT); + + return flag; +} + +static void seq_cache_put_ex(Scene *scene, SeqCacheKey *key, ImBuf *ibuf) +{ + SeqCache *cache = seq_cache_get_from_scene(scene); SeqCacheItem *item; item = BLI_mempool_alloc(cache->items_pool); item->cache_owner = cache; item->ibuf = ibuf; + const int stored_types_flag = get_stored_types_flag(scene, key); + + /* Item stored for later use. */ + if (stored_types_flag & key->type) { + key->is_temp_cache = false; + key->link_prev = cache->last_key; + } + + /* Store pointer to last cached key. */ + SeqCacheKey *temp_last_key = cache->last_key; + if (BLI_ghash_reinsert(cache->hash, key, item, seq_cache_keyfree, seq_cache_valfree)) { IMB_refImBuf(ibuf); - cache->last_key = key; + + if (!key->is_temp_cache) { + cache->last_key = key; + } + } + + /* Set last_key's reference to this key so we can look up chain backwards. + * Item is already put in cache, so cache->last_key points to current key. + */ + if (!key->is_temp_cache && temp_last_key) { + temp_last_key->link_next = cache->last_key; + } + + /* Reset linking. */ + if (key->type == SEQ_CACHE_STORE_FINAL_OUT) { + cache->last_key = NULL; } } @@ -1095,6 +1138,35 @@ static void seq_cache_create(Main *bmain, Scene *scene) BLI_mutex_unlock(&cache_create_lock); } +static void seq_cache_populate_key(SeqCacheKey *key, + const SeqRenderData *context, + Sequence *seq, + const float timeline_frame, + const int type) +{ + key->cache_owner = seq_cache_get_from_scene(context->scene); + key->seq = seq; + key->context = *context; + key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); + key->timeline_frame = timeline_frame; + key->type = type; + key->link_prev = NULL; + key->link_next = NULL; + key->is_temp_cache = true; + key->task_id = context->task_id; +} + +static SeqCacheKey *seq_cache_allocate_key(SeqCache *cache, + const SeqRenderData *context, + Sequence *seq, + const float timeline_frame, + const int type) +{ + SeqCacheKey *key = BLI_mempool_alloc(cache->keys_pool); + seq_cache_populate_key(key, context, seq, timeline_frame, type); + return key; +} + /* ***************************** API ****************************** */ void seq_cache_free_temp_cache(Scene *scene, short id, int timeline_frame) @@ -1243,8 +1315,7 @@ void seq_cache_cleanup_sequence(Scene *scene, struct ImBuf *seq_cache_get(const SeqRenderData *context, Sequence *seq, float timeline_frame, - int type, - bool skip_disk_cache) + int type) { if (context->skip_cache || context->is_proxy_render || !seq) { @@ -1274,11 +1345,7 @@ struct ImBuf *seq_cache_get(const SeqRenderData *context, /* Try RAM cache: */ if (cache && seq) { - key.seq = seq; - key.context = *context; - key.frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); - key.type = type; - + seq_cache_populate_key(&key, context, seq, timeline_frame, type); ibuf = seq_cache_get_ex(cache, &key); } seq_cache_unlock(scene); @@ -1288,7 +1355,7 @@ struct ImBuf *seq_cache_get(const SeqRenderData *context, } /* Try disk cache: */ - if (!skip_disk_cache && seq_disk_cache_is_enabled(context->bmain)) { + if (seq_disk_cache_is_enabled(context->bmain)) { if (cache->disk_cache == NULL) { seq_disk_cache_create(context->bmain, context->scene); } @@ -1296,25 +1363,23 @@ struct ImBuf *seq_cache_get(const SeqRenderData *context, BLI_mutex_lock(&cache->disk_cache->read_write_mutex); ibuf = seq_disk_cache_read_file(cache->disk_cache, &key); BLI_mutex_unlock(&cache->disk_cache->read_write_mutex); - if (ibuf) { - if (key.type == SEQ_CACHE_STORE_FINAL_OUT) { - seq_cache_put_if_possible(context, seq, timeline_frame, type, ibuf, true); - } - else { - seq_cache_put(context, seq, timeline_frame, type, ibuf, true); - } + + if (ibuf == NULL) { + return NULL; + } + + /* Store read image in RAM. Only recycle item for final type. */ + if (key.type != SEQ_CACHE_STORE_FINAL_OUT || seq_cache_recycle_item(scene)) { + SeqCacheKey *new_key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type); + seq_cache_put_ex(scene, new_key, ibuf); } } return ibuf; } -bool seq_cache_put_if_possible(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int type, - ImBuf *ibuf, - bool skip_disk_cache) +bool seq_cache_put_if_possible( + const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *ibuf) { Scene *scene = context->scene; @@ -1329,7 +1394,7 @@ bool seq_cache_put_if_possible(const SeqRenderData *context, } if (seq_cache_recycle_item(scene)) { - seq_cache_put(context, seq, timeline_frame, type, ibuf, skip_disk_cache); + seq_cache_put(context, seq, timeline_frame, type, ibuf); return true; } @@ -1338,12 +1403,8 @@ bool seq_cache_put_if_possible(const SeqRenderData *context, return false; } -void seq_cache_put(const SeqRenderData *context, - Sequence *seq, - float timeline_frame, - int type, - ImBuf *i, - bool skip_disk_cache) +void seq_cache_put( + const SeqRenderData *context, Sequence *seq, float timeline_frame, int type, ImBuf *i) { if (i == NULL || context->skip_cache || context->is_proxy_render || !seq) { return; @@ -1359,7 +1420,7 @@ void seq_cache_put(const SeqRenderData *context, } /* Prevent reinserting, it breaks cache key linking. */ - ImBuf *test = seq_cache_get(context, seq, timeline_frame, type, true); + ImBuf *test = seq_cache_get(context, seq, timeline_frame, type); if (test) { IMB_freeImBuf(test); return; @@ -1370,63 +1431,12 @@ void seq_cache_put(const SeqRenderData *context, } seq_cache_lock(scene); - SeqCache *cache = seq_cache_get_from_scene(scene); - int flag; - - if (seq->cache_flag & SEQ_CACHE_OVERRIDE) { - flag = seq->cache_flag; - /* Final_out is invalid in context of sequence override. */ - flag -= seq->cache_flag & SEQ_CACHE_STORE_FINAL_OUT; - /* If global setting is enabled however, use it. */ - flag |= scene->ed->cache_flag & SEQ_CACHE_STORE_FINAL_OUT; - } - else { - flag = scene->ed->cache_flag; - } - - SeqCacheKey *key; - key = BLI_mempool_alloc(cache->keys_pool); - key->cache_owner = cache; - key->seq = seq; - key->context = *context; - key->frame_index = seq_cache_timeline_frame_to_frame_index(seq, timeline_frame, type); - key->timeline_frame = timeline_frame; - key->type = type; - key->link_prev = NULL; - key->link_next = NULL; - key->is_temp_cache = true; - key->task_id = context->task_id; - - /* Item stored for later use */ - if (flag & type) { - key->is_temp_cache = false; - key->link_prev = cache->last_key; - } - - SeqCacheKey *temp_last_key = cache->last_key; - seq_cache_put_ex(cache, key, i); - - /* Restore pointer to previous item as this one will be freed when stack is rendered. */ - if (key->is_temp_cache) { - cache->last_key = temp_last_key; - } - - /* Set last_key's reference to this key so we can look up chain backwards. - * Item is already put in cache, so cache->last_key points to current key. - */ - if (flag & type && temp_last_key) { - temp_last_key->link_next = cache->last_key; - } - - /* Reset linking. */ - if (key->type == SEQ_CACHE_STORE_FINAL_OUT) { - cache->last_key = NULL; - } - + SeqCacheKey *key = seq_cache_allocate_key(cache, context, seq, timeline_frame, type); + seq_cache_put_ex(scene, key, i); seq_cache_unlock(scene); - if (!key->is_temp_cache && !skip_disk_cache) { + if (!key->is_temp_cache) { if (seq_disk_cache_is_enabled(context->bmain)) { if (cache->disk_cache == NULL) { seq_disk_cache_create(context->bmain, context->scene); diff --git a/source/blender/sequencer/intern/image_cache.h b/source/blender/sequencer/intern/image_cache.h index 41e8c4d1d48..63c559caee9 100644 --- a/source/blender/sequencer/intern/image_cache.h +++ b/source/blender/sequencer/intern/image_cache.h @@ -40,20 +40,17 @@ struct Sequence; struct ImBuf *seq_cache_get(const struct SeqRenderData *context, struct Sequence *seq, float timeline_frame, - int type, - bool skip_disk_cache); + int type); void seq_cache_put(const struct SeqRenderData *context, struct Sequence *seq, float timeline_frame, int type, - struct ImBuf *i, - bool skip_disk_cache); + struct ImBuf *i); bool seq_cache_put_if_possible(const struct SeqRenderData *context, struct Sequence *seq, float timeline_frame, int type, - struct ImBuf *nval, - bool skip_disk_cache); + struct ImBuf *nval); bool seq_cache_recycle_item(struct Scene *scene); void seq_cache_free_temp_cache(struct Scene *scene, short id, int timeline_frame); void seq_cache_destruct(struct Scene *scene); diff --git a/source/blender/sequencer/intern/iterator.c b/source/blender/sequencer/intern/iterator.c index bb4982d1468..f99667dea04 100644 --- a/source/blender/sequencer/intern/iterator.c +++ b/source/blender/sequencer/intern/iterator.c @@ -75,31 +75,31 @@ static void seq_build_array(ListBase *seqbase, Sequence ***array, int depth) } static void seq_array(Editing *ed, - Sequence ***seqarray, - int *tot, - const bool use_current_sequences) + const bool use_current_sequences, + Sequence ***r_seqarray, + int *r_seqarray_len) { Sequence **array; - *seqarray = NULL; - *tot = 0; + *r_seqarray = NULL; + *r_seqarray_len = 0; if (ed == NULL) { return; } if (use_current_sequences) { - seq_count(ed->seqbasep, tot); + seq_count(ed->seqbasep, r_seqarray_len); } else { - seq_count(&ed->seqbase, tot); + seq_count(&ed->seqbase, r_seqarray_len); } - if (*tot == 0) { + if (*r_seqarray_len == 0) { return; } - *seqarray = array = MEM_mallocN(sizeof(Sequence *) * (*tot), "SeqArray"); + *r_seqarray = array = MEM_mallocN(sizeof(Sequence *) * (*r_seqarray_len), "SeqArray"); if (use_current_sequences) { seq_build_array(ed->seqbasep, &array, 0); } @@ -111,7 +111,7 @@ static void seq_array(Editing *ed, void SEQ_iterator_begin(Editing *ed, SeqIterator *iter, const bool use_current_sequences) { memset(iter, 0, sizeof(*iter)); - seq_array(ed, &iter->array, &iter->tot, use_current_sequences); + seq_array(ed, use_current_sequences, &iter->array, &iter->tot); if (iter->tot) { iter->cur = 0; diff --git a/source/blender/sequencer/intern/prefetch.c b/source/blender/sequencer/intern/prefetch.c index b0e9e3c5003..4317fa3a850 100644 --- a/source/blender/sequencer/intern/prefetch.c +++ b/source/blender/sequencer/intern/prefetch.c @@ -379,28 +379,28 @@ static bool seq_prefetch_do_skip_frame(PrefetchJob *pfjob, ListBase *seqbase) if (seq_arr[i]->type == SEQ_TYPE_SCENE && (seq_arr[i]->flag & SEQ_SCENE_STRIPS) == 0) { int cached_types = 0; - ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_FINAL_OUT); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_FINAL_OUT; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_COMPOSITE, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_COMPOSITE); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_COMPOSITE; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_PREPROCESSED); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_PREPROCESSED; IMB_freeImBuf(ibuf); ibuf = NULL; } - ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW, false); + ibuf = seq_cache_get(ctx, seq_arr[i], cfra, SEQ_CACHE_STORE_RAW); if (ibuf != NULL) { cached_types |= SEQ_CACHE_STORE_RAW; IMB_freeImBuf(ibuf); diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c index 0ab2a67e560..e9de73bc093 100644 --- a/source/blender/sequencer/intern/render.c +++ b/source/blender/sequencer/intern/render.c @@ -599,10 +599,12 @@ static void multibuf(ImBuf *ibuf, const float fmul) } } -/* Effect, mask and scene in strip input strips are rendered in preview resolution. They are - * already downscaled. input_preprocess() does not expect this to happen. Other strip types are - * rendered with original media resolution, unless proxies are enabled for them. With proxies - * is_proxy_image will be set correctly to true.*/ +/** + * Effect, mask and scene in strip input strips are rendered in preview resolution. + * They are already down-scaled. #input_preprocess() does not expect this to happen. + * Other strip types are rendered with original media resolution, unless proxies are + * enabled for them. With proxies `is_proxy_image` will be set correctly to true. + */ static bool seq_need_scale_to_render_size(const Sequence *seq, bool is_proxy_image) { if (is_proxy_image) { @@ -762,14 +764,14 @@ static ImBuf *seq_render_preprocess_ibuf(const SeqRenderData *context, /* Proxies and effect strips are not stored in cache. */ if (!is_proxy_image && (seq->type & SEQ_TYPE_EFFECT) == 0) { - seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibuf); } if (use_preprocess) { ibuf = input_preprocess(context, seq, timeline_frame, ibuf, is_proxy_image); } - seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf, false); + seq_cache_put(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, ibuf); return ibuf; } @@ -1637,8 +1639,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, } if (view_id != context->view_id) { - seq_cache_put( - &localcontext, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibufs_arr[view_id], false); + seq_cache_put(&localcontext, seq, timeline_frame, SEQ_CACHE_STORE_RAW, ibufs_arr[view_id]); } RE_ReleaseResultImage(re); @@ -1813,14 +1814,14 @@ ImBuf *seq_render_strip(const SeqRenderData *context, bool use_preprocess = false; bool is_proxy_image = false; - ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED, false); + ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_PREPROCESSED); if (ibuf != NULL) { return ibuf; } /* Proxies are not stored in cache. */ if (!SEQ_can_use_proxy(seq, SEQ_rendersize_to_proxysize(context->preview_render_size))) { - ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW, false); + ibuf = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_RAW); } if (ibuf == NULL) { @@ -1927,7 +1928,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, int early_out; Sequence *seq = seq_arr[i]; - out = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_COMPOSITE, false); + out = seq_cache_get(context, seq, timeline_frame, SEQ_CACHE_STORE_COMPOSITE); if (out) { break; @@ -1956,8 +1957,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, out = seq_render_strip_stack_apply_effect(context, seq, timeline_frame, ibuf1, ibuf2); - seq_cache_put( - context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, false); + seq_cache_put(context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out); IMB_freeImBuf(ibuf1); IMB_freeImBuf(ibuf2); @@ -1983,7 +1983,7 @@ static ImBuf *seq_render_strip_stack(const SeqRenderData *context, IMB_freeImBuf(ibuf2); } - seq_cache_put(context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out, false); + seq_cache_put(context, seq_arr[i], timeline_frame, SEQ_CACHE_STORE_COMPOSITE, out); } return out; @@ -2022,8 +2022,7 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, count = seq_get_shown_sequences(seqbasep, timeline_frame, chanshown, seq_arr); if (count) { - out = seq_cache_get( - context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, false); + out = seq_cache_get(context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT); } seq_cache_free_temp_cache(context->scene, context->task_id, timeline_frame); @@ -2033,12 +2032,11 @@ ImBuf *SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, out = seq_render_strip_stack(context, &state, seqbasep, timeline_frame, chanshown); if (context->is_prefetch_render) { - seq_cache_put( - context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out, false); + seq_cache_put(context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out); } else { seq_cache_put_if_possible( - context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out, false); + context, seq_arr[count - 1], timeline_frame, SEQ_CACHE_STORE_FINAL_OUT, out); } BLI_mutex_unlock(&seq_render_mutex); } diff --git a/source/blender/sequencer/intern/strip_select.c b/source/blender/sequencer/intern/strip_select.c index 58ae281ead1..7cdd756e2d9 100644 --- a/source/blender/sequencer/intern/strip_select.c +++ b/source/blender/sequencer/intern/strip_select.c @@ -54,29 +54,29 @@ void SEQ_select_active_set(Scene *scene, Sequence *seq) ed->act_seq = seq; } -int SEQ_select_active_get_pair(Scene *scene, Sequence **seq_act, Sequence **seq_other) +int SEQ_select_active_get_pair(Scene *scene, Sequence **r_seq_act, Sequence **r_seq_other) { Editing *ed = SEQ_editing_get(scene, false); - *seq_act = SEQ_select_active_get(scene); + *r_seq_act = SEQ_select_active_get(scene); - if (*seq_act == NULL) { + if (*r_seq_act == NULL) { return 0; } Sequence *seq; - *seq_other = NULL; + *r_seq_other = NULL; for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if (seq->flag & SELECT && (seq != (*seq_act))) { - if (*seq_other) { + if (seq->flag & SELECT && (seq != (*r_seq_act))) { + if (*r_seq_other) { return 0; } - *seq_other = seq; + *r_seq_other = seq; } } - return (*seq_other != NULL); + return (*r_seq_other != NULL); } diff --git a/source/blender/simulation/intern/implicit_blender.c b/source/blender/simulation/intern/implicit_blender.c index 4c4d3e8a821..cf092d7716a 100644 --- a/source/blender/simulation/intern/implicit_blender.c +++ b/source/blender/simulation/intern/implicit_blender.c @@ -1693,7 +1693,7 @@ BLI_INLINE void dfdx_damp(float to[3][3], BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping) { - /* derivative of force wrt velocity */ + /* Derivative of force with regards to velocity. */ outerproduct(to, dir, dir); mul_m3_fl(to, -damping); } @@ -1727,7 +1727,7 @@ BLI_INLINE float fbstar(float length, float L, float kb, float cb) return tempfb_fl; } -/* function to calculae bending spring force (taken from Choi & Co) */ +/* Function to calculate bending spring force (taken from Choi & Co). */ BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) { float tempfb_fl = kb * fb(length, L); diff --git a/source/blender/simulation/intern/implicit_eigen.cpp b/source/blender/simulation/intern/implicit_eigen.cpp index ea1729589d6..8eb227d38ab 100644 --- a/source/blender/simulation/intern/implicit_eigen.cpp +++ b/source/blender/simulation/intern/implicit_eigen.cpp @@ -904,7 +904,7 @@ BLI_INLINE void dfdx_damp(float to[3][3], BLI_INLINE void dfdv_damp(float to[3][3], const float dir[3], float damping) { - /* derivative of force wrt velocity */ + /* Derivative of force with regards to velocity. */ outerproduct(to, dir, dir); mul_m3_fl(to, -damping); } @@ -936,7 +936,7 @@ BLI_INLINE float fbstar(float length, float L, float kb, float cb) } } -/* function to calculae bending spring force (taken from Choi & Co) */ +/* Function to calculate bending spring force (taken from Choi & Co). */ BLI_INLINE float fbstar_jacobi(float length, float L, float kb, float cb) { float tempfb_fl = kb * fb(length, L); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 540896664da..69177f39c04 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -685,6 +685,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid); void WM_drag_add_local_ID(struct wmDrag *drag, struct ID *id, struct ID *from_parent); struct ID *WM_drag_get_local_ID(const struct wmDrag *drag, short idcode); struct ID *WM_drag_get_local_ID_from_event(const struct wmEvent *event, short idcode); +bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode); struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode); struct ID *WM_drag_get_local_ID_or_import_from_asset(const struct wmDrag *drag, int idcode); diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h index 15be21bdbc4..564afe084b9 100644 --- a/source/blender/windowmanager/WM_keymap.h +++ b/source/blender/windowmanager/WM_keymap.h @@ -59,7 +59,7 @@ wmKeyMapItem *WM_keymap_add_item( wmKeyMapItem *WM_keymap_add_item_copy(struct wmKeyMap *keymap, wmKeyMapItem *kmi_src); bool WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); -int WM_keymap_item_to_string(wmKeyMapItem *kmi, +int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len); @@ -86,7 +86,7 @@ bool WM_keymap_remove(struct wmKeyConfig *keyconfig, struct wmKeyMap *keymap); bool WM_keymap_poll(struct bContext *C, struct wmKeyMap *keymap); wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id); -bool WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2); +bool WM_keymap_item_compare(const struct wmKeyMapItem *k1, const struct wmKeyMapItem *k2); /* keymap_utils.c */ @@ -111,13 +111,13 @@ void WM_keymap_add_context_enum_set_items(wmKeyMap *keymap, wmKeyMap *WM_keymap_guess_from_context(const struct bContext *C); wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); -bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier); +bool WM_keymap_uses_event_modifier(const wmKeyMap *keymap, const int event_modifier); void WM_keymap_fix_linking(void); /* Modal Keymap */ -int WM_modalkeymap_items_to_string(struct wmKeyMap *km, +int WM_modalkeymap_items_to_string(const struct wmKeyMap *km, const int propvalue, const bool compact, char *result, @@ -142,7 +142,7 @@ wmKeyMapItem *WM_modalkeymap_add_item( struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); wmKeyMapItem *WM_modalkeymap_add_item_str( struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value); -wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue); +const wmKeyMapItem *WM_modalkeymap_find_propvalue(const wmKeyMap *km, const int propvalue); void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname); /* Keymap Editor */ diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_api.h b/source/blender/windowmanager/gizmo/WM_gizmo_api.h index 70ddae4d724..cf1a7628267 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_api.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_api.h @@ -301,7 +301,7 @@ void WM_gizmomap_draw(struct wmGizmoMap *gzmap, void WM_gizmomap_add_handlers(struct ARegion *region, struct wmGizmoMap *gzmap); bool WM_gizmomap_select_all(struct bContext *C, struct wmGizmoMap *gzmap, const int action); bool WM_gizmomap_cursor_set(const struct wmGizmoMap *gzmap, struct wmWindow *win); -void WM_gizmomap_message_subscribe(struct bContext *C, +void WM_gizmomap_message_subscribe(const struct bContext *C, struct wmGizmoMap *gzmap, struct ARegion *region, struct wmMsgBus *mbus); diff --git a/source/blender/windowmanager/gizmo/WM_gizmo_types.h b/source/blender/windowmanager/gizmo/WM_gizmo_types.h index 8f84c02be12..fd7f9c2de7c 100644 --- a/source/blender/windowmanager/gizmo/WM_gizmo_types.h +++ b/source/blender/windowmanager/gizmo/WM_gizmo_types.h @@ -371,6 +371,14 @@ typedef struct wmGizmoType { */ wmGizmoFnMatrixBasisGet matrix_basis_get; + /** + * Returns screen-space bounding box in the window space + * (compatible with #wmEvent.x #wmEvent.y). + * + * Used for tool-tip placement (otherwise the cursor location is used). + */ + wmGizmoFnScreenBoundsGet screen_bounds_get; + /** Activate a gizmo state when the user clicks on it. */ wmGizmoFnInvoke invoke; diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c index 479768c3536..12c6eb46c12 100644 --- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c +++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_map.c @@ -1156,7 +1156,7 @@ ListBase *wm_gizmomap_groups_get(wmGizmoMap *gzmap) return &gzmap->groups; } -void WM_gizmomap_message_subscribe(bContext *C, +void WM_gizmomap_message_subscribe(const bContext *C, wmGizmoMap *gzmap, ARegion *region, struct wmMsgBus *mbus) diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h index 418e848e35b..84e6308223f 100644 --- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h +++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h @@ -62,6 +62,9 @@ typedef void (*wmGizmoFnMatrixBasisGet)(const struct wmGizmo *, float[4][4]); typedef int (*wmGizmoFnInvoke)(struct bContext *, struct wmGizmo *, const struct wmEvent *); typedef void (*wmGizmoFnExit)(struct bContext *, struct wmGizmo *, const bool); typedef int (*wmGizmoFnCursorGet)(struct wmGizmo *); +typedef void (*wmGizmoFnScreenBoundsGet)(struct bContext *, + struct wmGizmo *, + rcti *r_bounding_box); typedef void (*wmGizmoFnSelectRefresh)(struct wmGizmo *); typedef void (*wmGizmoFnFree)(struct wmGizmo *); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a10284e9740..549b59e9e1d 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -279,6 +279,8 @@ IDTypeInfo IDType_ID_WM = { .blend_read_expand = NULL, .blend_read_undo_preserve = NULL, + + .lib_override_apply_post = NULL, }; #define MAX_OP_REGISTERED 32 diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index d50516dfab2..e32552063af 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -246,8 +246,7 @@ void WM_cursor_wait(bool val) void WM_cursor_grab_enable(wmWindow *win, int wrap, bool hide, int bounds[4]) { /* Only grab cursor when not running debug. - * It helps not to get a stuck WM when hitting a breakpoint - * */ + * It helps not to get a stuck WM when hitting a break-point. */ GHOST_TGrabCursorMode mode = GHOST_kGrabNormal; GHOST_TAxisFlag mode_axis = GHOST_kAxisX | GHOST_kGrabAxisY; diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 08f60fef0d2..6fdcbab889c 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -225,7 +225,8 @@ static const char *dropbox_active(bContext *C, if (handler->dropboxes) { LISTBASE_FOREACH (wmDropBox *, drop, handler->dropboxes) { const char *tooltip = NULL; - if (drop->poll(C, drag, event, &tooltip)) { + if (drop->poll(C, drag, event, &tooltip) && + WM_operator_poll_context(C, drop->ot, drop->opcontext)) { /* XXX Doing translation here might not be ideal, but later we have no more * access to ot (and hence op context)... */ return (tooltip) ? tooltip : WM_operatortype_name(drop->ot, drop->ptr); @@ -353,6 +354,14 @@ ID *WM_drag_get_local_ID_from_event(const wmEvent *event, short idcode) return WM_drag_get_local_ID(lb->first, idcode); } +/** + * Check if the drag data is either a local ID or an external ID asset of type \a idcode. + */ +bool WM_drag_is_ID_type(const wmDrag *drag, int idcode) +{ + return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode); +} + wmDragAsset *WM_drag_get_asset_data(const wmDrag *drag, int idcode) { if (drag->type != WM_DRAG_ASSET) { diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index b11dae27d19..85611a0be93 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -346,7 +346,7 @@ static const char *wm_area_name(ScrArea *area) SPACE_NAME(SPACE_TOPBAR); SPACE_NAME(SPACE_STATUSBAR); default: - return "Unkown Space"; + return "Unknown Space"; } } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 859336d0338..e132caede0d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -543,13 +543,33 @@ void wm_event_do_notifiers(bContext *C) ED_screen_do_listen(C, note); LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) { - ED_region_do_listen(win, NULL, region, note, scene); + wmRegionListenerParams region_params = { + .window = win, + .area = NULL, + .region = region, + .scene = scene, + .notifier = note, + }; + ED_region_do_listen(®ion_params); } ED_screen_areas_iter (win, screen, area) { - ED_area_do_listen(win, area, note, scene); + wmSpaceTypeListenerParams area_params = { + .window = win, + .area = area, + .notifier = note, + .scene = scene, + }; + ED_area_do_listen(&area_params); LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - ED_region_do_listen(win, area, region, note, scene); + wmRegionListenerParams region_params = { + .window = win, + .area = area, + .region = region, + .scene = scene, + .notifier = note, + }; + ED_region_do_listen(®ion_params); } } } @@ -2079,7 +2099,7 @@ static int wm_handler_operator_call(bContext *C, handler->op = NULL; } - /* Putting back screen context, reval can pass trough after modal failures! */ + /* Putting back screen context, reval can pass through after modal failures! */ if ((retval & OPERATOR_PASS_THROUGH) || wm_event_always_pass(event)) { CTX_wm_area_set(C, area); CTX_wm_region_set(C, region); @@ -2788,8 +2808,10 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers LISTBASE_FOREACH (wmDrag *, drag, lb) { const char *tooltip = NULL; if (drop->poll(C, drag, event, &tooltip)) { - /* Optionally copy drag information to operator properties. */ - if (drop->copy) { + /* Optionally copy drag information to operator properties. Don't call it if the + * operator fails anyway, it might do more than just set properties (e.g. + * typically import an asset). */ + if (drop->copy && WM_operator_poll_context(C, drop->ot, drop->opcontext)) { drop->copy(drag, drop); } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 8bfec0dc5c9..fcb13fff0a5 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -949,9 +949,9 @@ wmKeyMapItem *WM_modalkeymap_add_item_str( return kmi; } -static wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(wmKeyMap *km, - wmKeyMapItem *kmi, - const int propvalue) +static const wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(const wmKeyMap *km, + const wmKeyMapItem *kmi, + const int propvalue) { if (km->flag & KEYMAP_MODAL) { kmi = kmi ? kmi->next : km->items.first; @@ -968,7 +968,7 @@ static wmKeyMapItem *wm_modalkeymap_find_propvalue_iter(wmKeyMap *km, return NULL; } -wmKeyMapItem *WM_modalkeymap_find_propvalue(wmKeyMap *km, const int propvalue) +const wmKeyMapItem *WM_modalkeymap_find_propvalue(const wmKeyMap *km, const int propvalue) { return wm_modalkeymap_find_propvalue_iter(km, NULL, propvalue); } @@ -1201,7 +1201,7 @@ int WM_keymap_item_raw_to_string(const short shift, #undef ADD_SEP } -int WM_keymap_item_to_string(wmKeyMapItem *kmi, +int WM_keymap_item_to_string(const wmKeyMapItem *kmi, const bool compact, char *result, const int result_len) @@ -1218,14 +1218,17 @@ int WM_keymap_item_to_string(wmKeyMapItem *kmi, result_len); } -int WM_modalkeymap_items_to_string( - wmKeyMap *km, const int propvalue, const bool compact, char *result, const int result_len) +int WM_modalkeymap_items_to_string(const wmKeyMap *km, + const int propvalue, + const bool compact, + char *result, + const int result_len) { int totlen = 0; bool add_sep = false; if (km) { - wmKeyMapItem *kmi; + const wmKeyMapItem *kmi; /* Find all shortcuts related to that propvalue! */ for (kmi = WM_modalkeymap_find_propvalue(km, propvalue); kmi && totlen < (result_len - 2); @@ -1654,7 +1657,7 @@ wmKeyMapItem *WM_key_event_operator_from_keymap(wmKeyMap *keymap, }); } -bool WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) +bool WM_keymap_item_compare(const wmKeyMapItem *k1, const wmKeyMapItem *k2) { if (k1->flag & KMI_INACTIVE || k2->flag & KMI_INACTIVE) { return 0; diff --git a/source/blender/windowmanager/intern/wm_keymap_utils.c b/source/blender/windowmanager/intern/wm_keymap_utils.c index 953fb9fed79..865889e7e64 100644 --- a/source/blender/windowmanager/intern/wm_keymap_utils.c +++ b/source/blender/windowmanager/intern/wm_keymap_utils.c @@ -477,7 +477,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) return km; } -static bool wm_keymap_item_uses_modifier(wmKeyMapItem *kmi, const int event_modifier) +static bool wm_keymap_item_uses_modifier(const wmKeyMapItem *kmi, const int event_modifier) { if (kmi->ctrl != KM_ANY) { if ((kmi->ctrl == KM_NOTHING) != ((event_modifier & KM_CTRL) == 0)) { @@ -505,9 +505,9 @@ static bool wm_keymap_item_uses_modifier(wmKeyMapItem *kmi, const int event_modi return true; } -bool WM_keymap_uses_event_modifier(wmKeyMap *keymap, const int event_modifier) +bool WM_keymap_uses_event_modifier(const wmKeyMap *keymap, const int event_modifier) { - LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { + LISTBASE_FOREACH (const wmKeyMapItem *, kmi, &keymap->items) { if ((kmi->flag & KMI_INACTIVE) == 0) { if (wm_keymap_item_uses_modifier(kmi, event_modifier)) { return true; diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c index 8dfe26fbf79..aeab1ee6fca 100644 --- a/source/blender/windowmanager/intern/wm_operator_props.c +++ b/source/blender/windowmanager/intern/wm_operator_props.c @@ -284,15 +284,15 @@ void WM_operator_properties_select_action_simple(wmOperatorType *ot, */ void WM_operator_properties_select_random(wmOperatorType *ot) { - RNA_def_float_percentage(ot->srna, - "percent", - 50.0f, - 0.0f, - 100.0f, - "Percent", - "Percentage of objects to select randomly", - 0.0f, - 100.0f); + RNA_def_float_factor(ot->srna, + "ratio", + 0.5f, + 0.0f, + 1.0f, + "Ratio", + "Portion of items to select randomly", + 0.f, + 1.0f); RNA_def_int(ot->srna, "seed", 0, diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c index 4c4fd2b1a8e..0e57a92b685 100644 --- a/source/blender/windowmanager/intern/wm_operator_type.c +++ b/source/blender/windowmanager/intern/wm_operator_type.c @@ -424,9 +424,8 @@ static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) wm_event_free_handler(&handler->head); } - /* if operator is blocking, grab cursor - * This may end up grabbing twice, but we don't care. - * */ + /* If operator is blocking, grab cursor. + * This may end up grabbing twice, but we don't care. */ if (op->opm->type->flag & OPTYPE_BLOCKING) { int bounds[4] = {-1, -1, -1, -1}; int wrap = WM_CURSOR_WRAP_NONE; diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 60bcb687dbf..1b1ebc70fd9 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -1097,6 +1097,7 @@ static void playanim_window_open(const char *title, int posx, int posy, int size posy = (scr_h - posy - sizey); g_WS.ghost_window = GHOST_CreateWindow(g_WS.ghost_system, + NULL, title, posx, posy, @@ -1104,6 +1105,7 @@ static void playanim_window_open(const char *title, int posx, int posy, int size sizey, /* could optionally start fullscreen */ GHOST_kWindowStateNormal, + false, GHOST_kDrawingContextTypeOpenGL, glsettings); } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 42fd214543f..6433cd7d12d 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -560,7 +560,6 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, wmWindow *win, bool is_dialog) { - /* a new window is created when pageflip mode is required for a window */ GHOST_GLSettings glSettings = {0}; if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) { @@ -579,30 +578,17 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, wmWindow *prev_windrawable = wm->windrawable; wm_window_clear_drawable(wm); - GHOST_WindowHandle ghostwin; - if (is_dialog && win->parent) { - ghostwin = GHOST_CreateDialogWindow(g_system, - win->parent->ghostwin, - title, - win->posx, - posy, - win->sizex, - win->sizey, - (GHOST_TWindowState)win->windowstate, - GHOST_kDrawingContextTypeOpenGL, - glSettings); - } - else { - ghostwin = GHOST_CreateWindow(g_system, - title, - win->posx, - posy, - win->sizex, - win->sizey, - (GHOST_TWindowState)win->windowstate, - GHOST_kDrawingContextTypeOpenGL, - glSettings); - } + GHOST_WindowHandle ghostwin = GHOST_CreateWindow(g_system, + (win->parent) ? win->parent->ghostwin : NULL, + title, + win->posx, + posy, + win->sizex, + win->sizey, + (GHOST_TWindowState)win->windowstate, + is_dialog, + GHOST_kDrawingContextTypeOpenGL, + glSettings); if (ghostwin) { win->gpuctx = GPU_context_create(ghostwin); @@ -858,13 +844,15 @@ wmWindow *WM_window_open_temp(bContext *C, /* changes rect to fit within desktop */ wm_window_check_position(&rect); - /* Reuse temporary or dialog window if one is open (but don't use a dialog for a regular - * temporary window, or vice versa). */ + /* Reuse temporary windows when they share the same title. */ wmWindow *win = NULL; LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) { - if (WM_window_is_temp_screen(win_iter) && - (dialog == GHOST_IsDialogWindow(win_iter->ghostwin))) { - win = win_iter; + if (WM_window_is_temp_screen(win_iter)) { + char *wintitle = GHOST_GetTitle(win_iter->ghostwin); + if (strcmp(title, wintitle) == 0) { + win = win_iter; + } + free(wintitle); } } diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c index 499ec136e03..cc4a7e41e82 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c @@ -129,7 +129,7 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata) /* Some systems have drawing glitches without this. */ GPU_clear_depth(1.0f); - /* Draws the view into the surface_data->viewport's framebuffers */ + /* Draws the view into the surface_data->viewport's frame-buffers. */ ED_view3d_draw_offscreen_simple(draw_data->depsgraph, draw_data->scene, &settings->shading, diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 7db936b3e51..fd1d721d869 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -74,7 +74,7 @@ endif() if(WITH_TBB) blender_include_dirs(${TBB_INCLUDE_DIRS}) if(NOT APPLE) - # APPLE plaform uses full paths for linking libraries. + # APPLE platform uses full paths for linking libraries. link_directories(${LIBDIR}/tbb/lib) endif() endif() @@ -764,7 +764,7 @@ elseif(WIN32) PATTERN "*.pyo" EXCLUDE # * any cache * ) - install( + install( DIRECTORY ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/lib DESTINATION ${BLENDER_VERSION}/python/ CONFIGURATIONS Debug @@ -772,7 +772,6 @@ elseif(WIN32) PATTERN "__pycache__" EXCLUDE # * any cache * PATTERN "*.pyc" EXCLUDE # * any cache * PATTERN "*.pyo" EXCLUDE # * any cache *) - ) install( diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index 6836cbec18c..e31be24ec7b 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -590,8 +590,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo BLI_args_print_arg_doc(ba, "--debug-ghost"); BLI_args_print_arg_doc(ba, "--debug-gpu"); BLI_args_print_arg_doc(ba, "--debug-gpu-force-workarounds"); - BLI_args_print_arg_doc(ba, "--debug-gpu-shaders"); - BLI_args_print_arg_doc(ba, "--debug-gpumem"); BLI_args_print_arg_doc(ba, "--debug-wm"); # ifdef WITH_XR_OPENXR BLI_args_print_arg_doc(ba, "--debug-xr"); @@ -988,9 +986,9 @@ static const char arg_handle_debug_mode_generic_set_doc_depsgraph_no_threads[] = static const char arg_handle_debug_mode_generic_set_doc_depsgraph_pretty[] = "\n\t" "Enable colors for dependency graph debug messages."; -static const char arg_handle_debug_mode_generic_set_doc_gpumem[] = +static const char arg_handle_debug_mode_generic_set_doc_gpu_force_workarounds[] = "\n\t" - "Enable GPU memory stats in status bar."; + "Enable workarounds for typical GPU issues and disable all GPU extensions."; static int arg_handle_debug_mode_generic_set(int UNUSED(argc), const char **UNUSED(argv), @@ -1160,7 +1158,7 @@ static int arg_handle_env_system_set(int argc, const char **argv, void *UNUSED(d } for (; *ch_src; ch_src++, ch_dst++) { - *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* toupper() */ + *ch_dst = (*ch_src == '-') ? '_' : (*ch_src) - 32; /* Inline #toupper() */ } *ch_dst = '\0'; @@ -1958,7 +1956,7 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data) if (success) { if (G.background) { - /* ensuer we use 'C->data.scene' for background render */ + /* Ensure we use 'C->data.scene' for background render. */ CTX_wm_window_set(C, NULL); } } @@ -2170,18 +2168,8 @@ void main_args_setup(bContext *C, bArgs *ba) (void *)G_DEBUG_DEPSGRAPH_UUID); BLI_args_add(ba, NULL, - "--debug-gpumem", - CB_EX(arg_handle_debug_mode_generic_set, gpumem), - (void *)G_DEBUG_GPU_MEM); - BLI_args_add(ba, - NULL, - "--debug-gpu-shaders", - CB_EX(arg_handle_debug_mode_generic_set, gpumem), - (void *)G_DEBUG_GPU_SHADERS); - BLI_args_add(ba, - NULL, "--debug-gpu-force-workarounds", - CB_EX(arg_handle_debug_mode_generic_set, gpumem), + CB_EX(arg_handle_debug_mode_generic_set, gpu_force_workarounds), (void *)G_DEBUG_GPU_FORCE_WORKAROUNDS); BLI_args_add(ba, NULL, "--debug-exit-on-error", CB(arg_handle_debug_exit_on_error), NULL); diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt index 85b80979074..1fe8cf21810 100644 --- a/tests/gtests/runner/CMakeLists.txt +++ b/tests/gtests/runner/CMakeLists.txt @@ -62,12 +62,31 @@ if(WIN32) target_link_options(blender_test PRIVATE /wholearchive:$<TARGET_FILE:${_lib}>) endforeach() elseif(APPLE) + # force_load for `_test_libs` ensures that all symbols definitely make it into the test binary. + # But linking against them again using `target_link_libraries` creates duplicate symbol + # errors when linker cannot deduplicate a force loaded and linked library. + # So force load test libraries separately, and link against their non-"test libraries" + # dependencies separately. + + # Gather dependencies of all test libraries. + set(_test_libs_dependencies) foreach(_lib ${_test_libs}) - # We need -force_load for every test library and target_link_libraries will - # deduplicate it. So explicitly set as linker option for every test lib. - target_link_libraries(blender_test ${_lib}) + get_target_property(_interface_libs ${_lib} INTERFACE_LINK_LIBRARIES) + if(_interface_libs) + list(APPEND _test_libs_dependencies ${_interface_libs}) + endif() + unset(_interface_libs) + endforeach() + + # Force load test libraries. Ensure that they are not linked twice in case they + # are used as dependencies of other test libraries. + foreach(_lib ${_test_libs}) + list(REMOVE_ITEM _test_libs_dependencies ${_lib}) target_link_options(blender_test PRIVATE "LINKER:-force_load,$<TARGET_FILE:${_lib}>") endforeach() + + target_link_libraries(blender_test "${_test_libs_dependencies}") + unset(_test_libs_dependencies) endif() unset(_test_libs) |