Overlay-Next: Initial implementation #107045

Closed
Clément Foucault wants to merge 28 commits from fclem/blender:overlay-next into main

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

View File

@ -176,3 +176,4 @@ if(UNIX AND NOT APPLE)
endif()
include(cmake/harvest.cmake)
include(cmake/cve_check.cmake)

View File

@ -0,0 +1,73 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# CVE Check requirements
#
# - A working installation of intels cve-bin-tool [1] has to be available in
# your path
#
# - Not strictly required, but highly recommended is obtaining a NVD key from
# nist since it significantly speeds up downloading/updating the required
# databases one can request a key on the following website:
# https://nvd.nist.gov/developers/request-an-api-key
# Bill of Materials construction
#
# This constructs a CSV cve-bin-tool [1] can read and process. Sadly
# cve-bin-tool at this point does not take a list of CPE's and output a check
# based on that list. so we need to pick apart the CPE retrieve the vendor,
# product and version tokens and generate a CSV.
#
# [1] https://github.com/intel/cve-bin-tool
# Because not all deps are downloaded (ie python packages) but can still have a
# xxx_CPE declared loop over all variables and look for variables ending in CPE.
set(SBOMCONTENTS)
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
if(_variableName MATCHES "CPE$")
string(REPLACE ":" ";" CPE_LIST ${${_variableName}})
list(GET CPE_LIST 3 CPE_VENDOR)
list(GET CPE_LIST 4 CPE_NAME)
list(GET CPE_LIST 5 CPE_VERSION)
set(SBOMCONTENTS "${SBOMCONTENTS}${CPE_VENDOR},${CPE_NAME},${CPE_VERSION}\n")
endif()
endforeach()
configure_file(${CMAKE_SOURCE_DIR}/cmake/cve_check.csv.in ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv @ONLY)
# Custom Targets
#
# This defines two new custom targets one could run in the build folder
# `cve_check` which will output the report to the console, and `cve_check_html`
# which will write out blender_dependencies.html in the build folder that one
# could share with other people or be used to get more information on the
# reported CVE's.
#
# cve-bin-tool takes data from the nist nvd database which rate limits
# unauthenticated requests to 1 requests per 6 seconds making the database
# download take "quite a bit" of time.
#
# When adding -DCVE_CHECK_NVD_KEY=your_api_key_here to your cmake invocation
# this key will be passed on to cve-bin-tool speeding up the process.
#
if(DEFINED CVE_CHECK_NVD_KEY)
set(NVD_ARGS --nvd-api-key ${CVE_CHECK_NVD_KEY})
endif()
# This will just report to the console
add_custom_target(cve_check
COMMAND cve-bin-tool
${NVD_ARGS}
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
--affected-versions
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
)
# This will write out blender_dependencies.html
add_custom_target(cve_check_html
COMMAND cve-bin-tool
${NVD_ARGS}
-i ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
-f html
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/cve_check.csv
)

View File

@ -0,0 +1,2 @@
vendor,product,version
@SBOMCONTENTS@

View File

@ -43,6 +43,7 @@ if(WIN32)
else()
ExternalProject_Add_Step(external_openpgl after_install
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openpgl/lib/openpgl_d.lib ${HARVEST_TARGET}/openpgl/lib/openpgl_d.lib
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION}/openpgl_Exports-debug.cmake ${HARVEST_TARGET}/openpgl/lib/cmake/openpgl-${OPENPGL_SHORT_VERSION}/openpgl_Exports-debug.cmake
DEPENDEES install
)
endif()

View File

@ -1,10 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# CPE's are used to identify dependencies, for more information on what they
# are please see https://nvd.nist.gov/products/cpe
#
# We use them in combination with cve-bin-tool to scan for known security issues.
#
# Not all of our dependencies are currently in the nvd database so not all
# dependencies have one assigned.
set(ZLIB_VERSION 1.2.12)
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
set(ZLIB_HASH_TYPE MD5)
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
set(ZLIB_CPE "cpe:2.3:a:zlib:zlib:${ZLIB_VERSION}:*:*:*:*:*:*:*")
set(OPENAL_VERSION 1.21.1)
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
@ -17,12 +26,14 @@ set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.
set(PNG_HASH 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca)
set(PNG_HASH_TYPE SHA256)
set(PNG_FILE libpng-${PNG_VERSION}.tar.xz)
set(PNG_CPE "cpe:2.3:a:libpng:libpng:${PNG_VERSION}:*:*:*:*:*:*:*")
set(JPEG_VERSION 2.1.3)
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
set(JPEG_HASH 627b980fad0573e08e4c3b80b290fc91)
set(JPEG_HASH_TYPE MD5)
set(JPEG_FILE libjpeg-turbo-${JPEG_VERSION}.tar.gz)
set(JPEG_CPE "cpe:2.3:a:d.r.commander:libjpeg-turbo:${JPEG_VERSION}:*:*:*:*:*:*:*")
set(BOOST_VERSION 1.78.0)
set(BOOST_VERSION_SHORT 1.78)
@ -32,12 +43,14 @@ set(BOOST_URI https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION
set(BOOST_HASH c2f6428ac52b0e5a3c9b2e1d8cc832b5)
set(BOOST_HASH_TYPE MD5)
set(BOOST_FILE boost_${BOOST_VERSION_NODOTS}.tar.gz)
set(BOOST_CPE "cpe:2.3:a:boost:boost:${BOOST_VERSION}:*:*:*:*:*:*:*")
set(BLOSC_VERSION 1.21.1)
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
set(BLOSC_HASH_TYPE MD5)
set(BLOSC_FILE blosc-${BLOSC_VERSION}.tar.gz)
set(BLOSC_CPE "cpe:2.3:a:c-blosc2_project:c-blosc2:${BLOSC_VERSION}:*:*:*:*:*:*:*")
set(PTHREADS_VERSION 3.0.0)
set(PTHREADS_URI http://prdownloads.sourceforge.net/pthreads4w/pthreads4w-code-v${PTHREADS_VERSION}.zip)
@ -50,6 +63,7 @@ set(OPENEXR_URI https://github.com/AcademySoftwareFoundation/openexr/archive/v${
set(OPENEXR_HASH a92f38eedd43e56c0af56d4852506886)
set(OPENEXR_HASH_TYPE MD5)
set(OPENEXR_FILE openexr-${OPENEXR_VERSION}.tar.gz)
set(OPENEXR_CPE "cpe:2.3:a:openexr:openexr:${OPENEXR_VERSION}:*:*:*:*:*:*:*")
set(IMATH_VERSION 3.1.5)
set(IMATH_URI https://github.com/AcademySoftwareFoundation/Imath/archive/v${OPENEXR_VERSION}.tar.gz)
@ -79,6 +93,7 @@ set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
set(FREETYPE_HASH_TYPE MD5)
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
set(EPOXY_VERSION 1.5.10)
set(EPOXY_URI https://github.com/anholt/libepoxy/archive/refs/tags/${EPOXY_VERSION}.tar.gz)
@ -97,6 +112,7 @@ set(ALEMBIC_URI https://github.com/alembic/alembic/archive/${ALEMBIC_VERSION}.ta
set(ALEMBIC_HASH 2cd8d6e5a3ac4a014e24a4b04f4fadf9)
set(ALEMBIC_HASH_TYPE MD5)
set(ALEMBIC_FILE alembic-${ALEMBIC_VERSION}.tar.gz)
SET(FREETYPE_CPE "cpe:2.3:a:freetype:freetype:${FREETYPE_VERSION}:*:*:*:*:*:*:*")
set(OPENSUBDIV_VERSION v3_4_4)
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
@ -109,6 +125,7 @@ set(SDL_URI https://www.libsdl.org/release/SDL2-${SDL_VERSION}.tar.gz)
set(SDL_HASH a53acc02e1cca98c4123229069b67c9e)
set(SDL_HASH_TYPE MD5)
set(SDL_FILE SDL2-${SDL_VERSION}.tar.gz)
set(SDL_CPE "cpe:2.3:a:libsdl:sdl:${SDL_VERSION}:*:*:*:*:*:*:*")
set(OPENCOLLADA_VERSION v1.6.68)
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
@ -127,6 +144,7 @@ set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LL
set(LLVM_HASH 5a4fab4d7fc84aefffb118ac2c8a4fc0)
set(LLVM_HASH_TYPE MD5)
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
set(LLVM_CPE "cpe:2.3:a:llvm:compiler:${LLVM_VERSION}:*:*:*:*:*:*:*")
if(APPLE)
# Cloth physics test is crashing due to this bug:
@ -154,6 +172,7 @@ set(FMT_URI https://github.com/fmtlib/fmt/archive/refs/tags/${FMT_VERSION}.tar.g
set(FMT_HASH 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
set(FMT_HASH_TYPE SHA256)
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
set(FMT_CPE "cpe:2.3:a:fmt:fmt:${FMT_VERSION}:*:*:*:*:*:*:*")
# 0.6.2 is currently oiio's preferred version although never versions may be available.
# the preferred version can be found in oiio's externalpackages.cmake
@ -168,6 +187,7 @@ set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_HASH 376f17f189e9d02280dfe709b2b2bbea)
set(TIFF_HASH_TYPE MD5)
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
set(TIFF_CPE "cpe:2.3:a:libtiff:libtiff:${TIFF_VERSION}:*:*:*:*:*:*:*")
set(OSL_VERSION 1.11.17.0)
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
@ -182,12 +202,15 @@ set(PYTHON_URI https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTH
set(PYTHON_HASH 14e8c22458ed7779a1957b26cde01db9)
set(PYTHON_HASH_TYPE MD5)
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
set(PYTHON_CPE "cpe:2.3:a:python:python:${PYTHON_VERSION}:-:*:*:*:*:*:*")
set(TBB_VERSION 2020_U3)
set(TBB_YEAR 2020)
set(TBB_VERSION ${TBB_YEAR}_U3)
set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
set(TBB_HASH 55ec8df6eae5ed6364a47f0e671e460c)
set(TBB_HASH_TYPE MD5)
set(TBB_FILE oneTBB-${TBB_VERSION}.tar.gz)
set(TBB_CPE "cpe:2.3:a:intel:threading_building_blocks:${TBB_YEAR}:*:*:*:*:*:*:*")
set(OPENVDB_VERSION 9.0.0)
set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
@ -198,6 +221,7 @@ set(OPENVDB_FILE openvdb-${OPENVDB_VERSION}.tar.gz)
set(IDNA_VERSION 3.3)
set(CHARSET_NORMALIZER_VERSION 2.0.10)
set(URLLIB3_VERSION 1.26.8)
set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*")
set(CERTIFI_VERSION 2021.10.8)
set(REQUESTS_VERSION 2.27.1)
set(CYTHON_VERSION 0.29.26)
@ -214,12 +238,14 @@ set(NUMPY_URI https://github.com/numpy/numpy/releases/download/v${NUMPY_VERSION}
set(NUMPY_HASH 252de134862a27bd66705d29622edbfe)
set(NUMPY_HASH_TYPE MD5)
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
set(NUMPY_CPE "cpe:2.3:a:numpy:numpy:${NUMPY_VERSION}:*:*:*:*:*:*:*")
set(LAME_VERSION 3.100)
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
set(LAME_HASH_TYPE MD5)
set(LAME_FILE lame-${LAME_VERSION}.tar.gz)
set(LAME_CPE "cpe:2.3:a:lame_project:lame:${LAME_VERSION}:*:*:*:*:*:*:*")
set(OGG_VERSION 1.3.5)
set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
@ -232,6 +258,7 @@ set(VORBIS_URI http://downloads.xiph.org/releases/vorbis/libvorbis-${VORBIS_VERS
set(VORBIS_HASH 0e982409a9c3fc82ee06e08205b1355e5c6aa4c36bca58146ef399621b0ce5ab)
set(VORBIS_HASH_TYPE SHA256)
set(VORBIS_FILE libvorbis-${VORBIS_VERSION}.tar.gz)
set(VORBIS_CPE "cpe:2.3:a:xiph.org:libvorbis:${VORBIS_VERSION}:*:*:*:*:*:*:*")
set(THEORA_VERSION 1.1.1)
set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
@ -244,12 +271,14 @@ set(FLAC_URI http://downloads.xiph.org/releases/flac/flac-${FLAC_VERSION}.tar.xz
set(FLAC_HASH 8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737 )
set(FLAC_HASH_TYPE SHA256)
set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
set(FLAC_CPE "cpe:2.3:a:flac_project:flac:${FLAC_VERSION}:*:*:*:*:*:*:*")
set(VPX_VERSION 1.11.0)
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_HASH 965e51c91ad9851e2337aebcc0f517440c637c506f3a03948062e3d5ea129a83)
set(VPX_HASH_TYPE SHA256)
set(VPX_FILE libvpx-v${VPX_VERSION}.tar.gz)
set(VPX_CPE "cpe:2.3:a:webmproject:libvpx:${VPX_VERSION}:*:*:*:*:*:*:*")
set(OPUS_VERSION 1.3.1)
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
@ -275,12 +304,14 @@ set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSI
set(OPENJPEG_HASH 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
set(OPENJPEG_HASH_TYPE SHA256)
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
set(OPENJPEG_CPE "cpe:2.3:a:uclouvain:openjpeg:${OPENJPEG_VERSION}:*:*:*:*:*:*:*")
set(FFMPEG_VERSION 5.0)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
set(FFMPEG_HASH_TYPE SHA256)
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
set(FFMPEG_CPE "cpe:2.3:a:ffmpeg:ffmpeg:${FFMPEG_VERSION}:*:*:*:*:*:*:*")
set(FFTW_VERSION 3.3.10)
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
@ -299,12 +330,14 @@ set(SNDFILE_URI http://www.mega-nerd.com/libsndfile/files/libsndfile-${SNDFILE_V
set(SNDFILE_HASH 646b5f98ce89ac60cdb060fcd398247c)
set(SNDFILE_HASH_TYPE MD5)
set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz)
set(SNDFILE_CPE "cpe:2.3:a:libsndfile_project:libsndfile:${SNDFILE_VERSION}:*:*:*:*:*:*:*")
set(WEBP_VERSION 1.2.2)
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
set(WEBP_HASH b5e2e414a8adee4c25fe56b18dd9c549)
set(WEBP_HASH_TYPE MD5)
set(WEBP_FILE libwebp-${WEBP_VERSION}.tar.gz)
set(WEBP_CPE "cpe:2.3:a:webmproject:libwebp:${WEBP_VERSION}:*:*:*:*:*:*:*")
set(SPNAV_VERSION 0.2.3)
set(SPNAV_URI http://downloads.sourceforge.net/project/spacenav/spacenav%20library%20%28SDK%29/libspnav%20${SPNAV_VERSION}/libspnav-${SPNAV_VERSION}.tar.gz)
@ -323,6 +356,7 @@ set(XML2_URI http://xmlsoft.org/sources/libxml2-${XML2_VERSION}.tar.gz)
set(XML2_HASH 10942a1dc23137a8aa07f0639cbfece5)
set(XML2_HASH_TYPE MD5)
set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
set(XML2_CPE "cpe:2.3:a:xmlsoft:libxml2:${XML2_VERSION}:*:*:*:*:*:*:*")
set(TINYXML_VERSION 2_6_2)
set(TINYXML_VERSION_DOTS 2.6.2)
@ -330,12 +364,14 @@ set(TINYXML_URI https://nchc.dl.sourceforge.net/project/tinyxml/tinyxml/${TINYXM
set(TINYXML_HASH c1b864c96804a10526540c664ade67f0)
set(TINYXML_HASH_TYPE MD5)
set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz)
set(TINYXML_CPE "cpe:2.3:a:tinyxml_project:tinyxml:${TINYXML_VERSION_DOTS}:*:*:*:*:*:*:*")
set(YAMLCPP_VERSION 0.6.3)
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
set(YAMLCPP_HASH_TYPE MD5)
set(YAMLCPP_FILE yaml-cpp-${YAMLCPP_VERSION}.tar.gz)
set(YAMLCPP "cpe:2.3:a:yaml-cpp_project:yaml-cpp:${YAMLCPP_VERSION}:*:*:*:*:*:*:*")
set(PYSTRING_VERSION v1.1.3)
set(PYSTRING_URI https://codeload.github.com/imageworks/pystring/tar.gz/refs/tags/${PYSTRING_VERSION})
@ -344,16 +380,19 @@ set(PYSTRING_HASH_TYPE MD5)
set(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz)
set(EXPAT_VERSION 2_4_4)
set(EXPAT_VERSION_DOTS 2.4.4)
set(EXPAT_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
set(EXPAT_HASH_TYPE MD5)
set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz)
set(EXPAT_CPE "cpe:2.3:a:libexpat_project:libexpat:${EXPAT_VERSION_DOTS}:*:*:*:*:*:*:*")
set(PUGIXML_VERSION 1.10)
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
set(PUGIXML_HASH_TYPE MD5)
set(PUGIXML_FILE pugixml-${PUGIXML_VERSION}.tar.gz)
set(PUGIXML_CPE "cpe:2.3:a:pugixml_project:pugixml:${PUGIXML_VERSION}:*:*:*:*:*:*:*")
set(FLEXBISON_VERSION 2.5.24)
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison/win_flex_bison-${FLEXBISON_VERSION}.zip)
@ -376,12 +415,14 @@ set(BZIP2_URI http://http.debian.net/debian/pool/main/b/bzip2/bzip2_${BZIP2_VERS
set(BZIP2_HASH ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
set(BZIP2_HASH_TYPE SHA256)
set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz)
set(BZIP2_CPE "cpe:2.3:a:bzip:bzip2:${BZIP2_VERSION}:*:*:*:*:*:*:*")
set(FFI_VERSION 3.3)
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
set(FFI_HASH_TYPE SHA256)
set(FFI_FILE libffi-${FFI_VERSION}.tar.gz)
set(FFI_CPE "cpe:2.3:a:libffi_project:libffi:${FFI_VERSION}:*:*:*:*:*:*:*")
set(LZMA_VERSION 5.2.5)
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
@ -403,12 +444,14 @@ else()
set(SSL_HASH_TYPE SHA256)
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
endif()
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
set(SQLITE_VERSION 3.31.1)
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
set(SQLITE_HASH_TYPE SHA1)
set(SQLITE_FILE sqlite-src-3240000.zip)
set(SQLITE_CPE "cpe:2.3:a:sqlite:sqlite:${SQLITE_VERSION}:*:*:*:*:*:*:*")
set(EMBREE_VERSION 3.13.4)
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
@ -439,12 +482,14 @@ set(MESA_URI ftp://ftp.freedesktop.org/pub/mesa/mesa-${MESA_VERSION}.tar.xz)
set(MESA_HASH 022c7293074aeeced2278c872db4fa693147c70f8595b076cf3f1ef81520766d)
set(MESA_HASH_TYPE SHA256)
set(MESA_FILE mesa-${MESA_VERSION}.tar.xz)
set(MESA_CPE "cpe:2.3:a:mesa3d:mesa:${MESA_VERSION}:*:*:*:*:*:*:*")
set(NASM_VERSION 2.15.02)
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
set(NASM_HASH_TYPE SHA256)
set(NASM_FILE nasm-${NASM_VERSION}.tar.gz)
set(NASM_PCE "cpe:2.3:a:nasm:nasm:${NASM_VERSION}:*:*:*:*:*:*:*")
set(XR_OPENXR_SDK_VERSION 1.0.22)
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
@ -481,12 +526,14 @@ set(GMP_URI https://gmplib.org/download/gmp/gmp-${GMP_VERSION}.tar.xz)
set(GMP_HASH 0b82665c4a92fd2ade7440c13fcaa42b)
set(GMP_HASH_TYPE MD5)
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
set(GMP_CPE "cpe:2.3:a:gmplib:gmp:${GMP_VERSION}:*:*:*:*:*:*:*")
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(POTRACE_HASH_TYPE MD5)
set(POTRACE_FILE potrace-${POTRACE_VERSION}.tar.gz)
set(POTRACE_CPE "cpe:2.3:a:icoasoft:potrace:${POTRACE_VERSION}:*:*:*:*:*:*:*")
set(HARU_VERSION 2_3_0)
set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz)
@ -499,6 +546,7 @@ set(ZSTD_URI https://github.com/facebook/zstd/releases/download/v${ZSTD_VERSION}
set(ZSTD_HASH 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94)
set(ZSTD_HASH_TYPE SHA256)
set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
set(ZSTD_CPE "cpe:2.3:a:facebook:zstandard:${ZSTD_VERSION}:*:*:*:*:*:*:*")
set(SSE2NEON_VERSION fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
set(SSE2NEON_URI https://github.com/DLTcollab/sse2neon/archive/${SSE2NEON_VERSION}.tar.gz)
@ -506,11 +554,12 @@ set(SSE2NEON_HASH 0780253525d299c31775ef95853698d03db9c7739942af8570000f4a25a5d6
set(SSE2NEON_HASH_TYPE SHA256)
set(SSE2NEON_FILE sse2neon-${SSE2NEON_VERSION}.tar.gz)
set(BROTLI_VERSION v1.0.9)
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/${BROTLI_VERSION}.tar.gz)
set(BROTLI_VERSION 1.0.9)
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz)
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
set(BROTLI_HASH_TYPE SHA256)
set(BROTLI_FILE brotli-${BROTLI_VERSION}.tar.gz)
set(BROTLI_FILE brotli-v${BROTLI_VERSION}.tar.gz)
set(BROTLI_CPE "cpe:2.3:a:google:brotli:${BROTLI_VERSION}:*:*:*:*:*:*:*")
set(OPENPGL_VERSION v0.3.1-beta)
set(OPENPGL_SHORT_VERSION 0.3.1)

View File

@ -778,31 +778,11 @@ if(WITH_GHOST_WAYLAND)
endif()
endif()
list(APPEND PLATFORM_LINKLIBS
${xkbcommon_LINK_LIBRARIES}
)
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND PLATFORM_LINKLIBS
${wayland-client_LINK_LIBRARIES}
${wayland-egl_LINK_LIBRARIES}
${wayland-cursor_LINK_LIBRARIES}
)
endif()
if(WITH_GHOST_WAYLAND_DBUS)
list(APPEND PLATFORM_LINKLIBS
${dbus_LINK_LIBRARIES}
)
add_definitions(-DWITH_GHOST_WAYLAND_DBUS)
endif()
if(WITH_GHOST_WAYLAND_LIBDECOR)
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND PLATFORM_LINKLIBS
${libdecor_LIBRARIES}
)
endif()
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
endif()
@ -855,12 +835,8 @@ if(WITH_GHOST_X11)
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
if(WITH_X11_XINPUT)
if(X11_Xinput_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
else()
if(NOT X11_Xinput_LIB)
message(FATAL_ERROR "LibXi not found. Disable WITH_X11_XINPUT if you
want to build without tablet support")
endif()
@ -870,18 +846,14 @@ if(WITH_GHOST_X11)
# XXX, why doesn't cmake make this available?
find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
mark_as_advanced(X11_Xxf86vmode_LIB)
if(X11_Xxf86vmode_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xxf86vmode_LIB})
else()
if(NOT X11_Xxf86vmode_LIB)
message(FATAL_ERROR "libXxf86vm not found. Disable WITH_X11_XF86VMODE if you
want to build without")
endif()
endif()
if(WITH_X11_XFIXES)
if(X11_Xfixes_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xfixes_LIB})
else()
if(NOT X11_Xfixes_LIB)
message(FATAL_ERROR "libXfixes not found. Disable WITH_X11_XFIXES if you
want to build without")
endif()
@ -890,9 +862,7 @@ if(WITH_GHOST_X11)
if(WITH_X11_ALPHA)
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
mark_as_advanced(X11_Xrender_LIB)
if(X11_Xrender_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xrender_LIB})
else()
if(NOT X11_Xrender_LIB)
message(FATAL_ERROR "libXrender not found. Disable WITH_X11_ALPHA if you
want to build without")
endif()

View File

@ -1,4 +1,4 @@
sphinx==5.1.1
sphinx==5.2.3
# Sphinx dependencies that are important
Jinja2==3.1.2
@ -6,7 +6,7 @@ Pygments==2.13.0
docutils==0.17.1
snowballstemmer==2.2.0
babel==2.10.3
requests==2.27.1
requests==2.28.1
# Only needed to match the theme used for the official documentation.
# Without this theme, the default theme will be used.

View File

@ -88,18 +88,26 @@ BVHLayoutMask OneapiDevice::get_bvh_layout_mask() const
bool OneapiDevice::load_kernels(const uint requested_features)
{
assert(device_queue_);
/* NOTE(@nsirgien): oneAPI can support compilation of kernel code with certain feature set
* with specialization constants, but it hasn't been implemented yet. */
(void)requested_features;
bool is_finished_ok = oneapi_run_test_kernel(device_queue_);
if (is_finished_ok == false) {
set_error("oneAPI kernel load: got runtime exception \"" + oneapi_error_string_ + "\"");
set_error("oneAPI test kernel execution: got a runtime exception \"" + oneapi_error_string_ +
"\"");
return false;
}
else {
VLOG_INFO << "Runtime compilation done for \"" << info.description << "\"";
VLOG_INFO << "Test kernel has been executed successfully for \"" << info.description << "\"";
assert(device_queue_);
}
is_finished_ok = oneapi_load_kernels(device_queue_, (const unsigned int)requested_features);
if (is_finished_ok == false) {
set_error("oneAPI kernels loading: got a runtime exception \"" + oneapi_error_string_ + "\"");
}
else {
VLOG_INFO << "Kernels loading (compilation) has been done for \"" << info.description << "\"";
}
return is_finished_ok;
}

View File

@ -43,8 +43,11 @@ PathTrace::PathTrace(Device *device,
/* Create path tracing work in advance, so that it can be reused by incremental sampling as much
* as possible. */
device_->foreach_device([&](Device *path_trace_device) {
path_trace_works_.emplace_back(PathTraceWork::create(
path_trace_device, film, device_scene, &render_cancel_.is_requested));
unique_ptr<PathTraceWork> work = PathTraceWork::create(
path_trace_device, film, device_scene, &render_cancel_.is_requested);
if (work) {
path_trace_works_.emplace_back(std::move(work));
}
});
work_balance_infos_.resize(path_trace_works_.size());

View File

@ -23,6 +23,10 @@ unique_ptr<PathTraceWork> PathTraceWork::create(Device *device,
if (device->info.type == DEVICE_CPU) {
return make_unique<PathTraceWorkCPU>(device, film, device_scene, cancel_requested_flag);
}
if (device->info.type == DEVICE_DUMMY) {
/* Dummy devices can't perform any work. */
return nullptr;
}
return make_unique<PathTraceWorkGPU>(device, film, device_scene, cancel_requested_flag);
}

View File

@ -17,6 +17,9 @@ void work_balance_do_initial(vector<WorkBalanceInfo> &work_balance_infos)
work_balance_infos[0].weight = 1.0;
return;
}
else if (num_infos == 0) {
return;
}
/* There is no statistics available, so start with an equal distribution. */
const double weight = 1.0 / num_infos;

View File

@ -123,6 +123,52 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
return std::min(limit_work_group_size, preferred_work_group_size);
}
bool oneapi_load_kernels(SyclQueue *queue_, const uint requested_features)
{
assert(queue_);
sycl::queue *queue = reinterpret_cast<sycl::queue *>(queue_);
try {
sycl::kernel_bundle<sycl::bundle_state::input> all_kernels_bundle =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(),
{queue->get_device()});
for (const sycl::kernel_id &kernel_id : all_kernels_bundle.get_kernel_ids()) {
const std::string &kernel_name = kernel_id.get_name();
/* NOTE(@nsirgien): Names in this conditions below should match names from
* oneapi_call macro in oneapi_enqueue_kernel below */
if (((requested_features & KERNEL_FEATURE_VOLUME) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_volume") != std::string::npos) {
continue;
}
if (((requested_features & KERNEL_FEATURE_MNEE) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_surface_mnee") != std::string::npos) {
continue;
}
if (((requested_features & KERNEL_FEATURE_NODE_RAYTRACE) == 0) &&
kernel_name.find("oneapi_kernel_integrator_shade_surface_raytrace") !=
std::string::npos) {
continue;
}
sycl::kernel_bundle<sycl::bundle_state::input> one_kernel_bundle =
sycl::get_kernel_bundle<sycl::bundle_state::input>(queue->get_context(), {kernel_id});
sycl::build(one_kernel_bundle, {queue->get_device()}, sycl::property::queue::in_order());
}
}
catch (sycl::exception const &e) {
if (s_error_cb) {
s_error_cb(e.what(), s_error_user_ptr);
}
return false;
}
return true;
}
bool oneapi_enqueue_kernel(KernelContext *kernel_context,
int kernel,
size_t global_size,

View File

@ -48,6 +48,8 @@ CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_enqueue_kernel(KernelContext *context,
int kernel,
size_t global_size,
void **args);
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_load_kernels(SyclQueue *queue,
const unsigned int requested_features);
# ifdef __cplusplus
}
# endif

View File

@ -43,6 +43,10 @@ Session::Session(const SessionParams &params_, const SceneParams &scene_params)
device = Device::create(params.device, stats, profiler);
if (device->have_error()) {
progress.set_error(device->error_message());
}
scene = new Scene(scene_params, device);
/* Configure path tracer. */

View File

@ -262,6 +262,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
${xkbcommon_INCLUDE_DIRS}
${wayland-cursor_INCLUDE_DIRS}
)
list(APPEND LIB
${xkbcommon_LINK_LIBRARIES}
)
if(WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND INC_SYS
@ -271,18 +274,32 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
bf_intern_wayland_dynload
)
add_definitions(-DWITH_GHOST_WAYLAND_DYNLOAD)
else()
list(APPEND LIB
${wayland-client_LINK_LIBRARIES}
${wayland-egl_LINK_LIBRARIES}
${wayland-cursor_LINK_LIBRARIES}
)
endif()
if(WITH_GHOST_WAYLAND_DBUS)
list(APPEND INC_SYS
${dbus_INCLUDE_DIRS}
)
list(APPEND LIB
${dbus_LINK_LIBRARIES}
)
endif()
if(WITH_GHOST_WAYLAND_LIBDECOR)
list(APPEND INC_SYS
${libdecor_INCLUDE_DIRS}
)
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
list(APPEND LIB
${libdecor_LIBRARIES}
)
endif()
endif()
include(CheckSymbolExists)
@ -332,16 +349,16 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
${INC_DST}
)
if(NOT WITH_GHOST_WAYLAND_LIBDECOR)
# `xdg-shell`.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
)
# `xdg-decoration`.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
)
endif()
# Used when: LIBDECOR is not needed.
# `xdg-shell`.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
)
# `xdg-decoration`.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
)
# End LIBDECOR alternative.
# `xdg-output`.
generate_protocol_bindings(

View File

@ -48,7 +48,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
/* Pass. */
#elif defined(WITH_GHOST_WAYLAND)
# if defined(WITH_GHOST_WAYLAND_DYNLOAD)
const bool has_wayland_libraries = ghost_wl_dynload_libraries();
const bool has_wayland_libraries = ghost_wl_dynload_libraries_init();
# else
const bool has_wayland_libraries = true;
# endif
@ -66,6 +66,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
ghost_wl_dynload_libraries_exit();
# endif
}
}
else {
@ -101,6 +104,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
catch (const std::runtime_error &) {
delete m_system;
m_system = nullptr;
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
ghost_wl_dynload_libraries_exit();
# endif
}
}
else {

View File

@ -54,6 +54,11 @@
#include <tablet-unstable-v2-client-protocol.h>
#include <xdg-output-unstable-v1-client-protocol.h>
/* Decorations `xdg_decor`. */
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h>
/* End `xdg_decor`. */
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
@ -64,6 +69,15 @@
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
static bool use_libdecor = true;
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
static bool has_libdecor = false;
# else
static bool has_libdecor = true;
# endif
#endif
static void keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
static void output_handle_done(void *data, struct wl_output *wl_output);
@ -106,6 +120,15 @@ static bool use_gnome_confine_hack = false;
*/
#define USE_GNOME_KEYBOARD_SUPPRESS_WARNING
/**
* When GNOME is found, require `libdecor`.
* This is a hack because it seems there is no way to check if the compositor supports
* server side decorations when initializing WAYLAND.
*/
#if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_GHOST_X11)
# define USE_GNOME_NEEDS_LIBDECOR_HACK
#endif
/** \} */
/* -------------------------------------------------------------------- */
@ -357,6 +380,36 @@ struct WGL_KeyboardDepressedState {
int16_t mods[GHOST_KEY_MODIFIER_NUM] = {0};
};
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
struct WGL_LibDecor_System {
struct libdecor *context = nullptr;
};
static void wgl_libdecor_system_destroy(WGL_LibDecor_System *decor)
{
if (decor->context) {
libdecor_unref(decor->context);
}
delete decor;
}
#endif
struct WGL_XDG_Decor_System {
struct xdg_wm_base *shell = nullptr;
struct zxdg_decoration_manager_v1 *manager = nullptr;
};
static void wgl_xdg_decor_system_destroy(WGL_XDG_Decor_System *decor)
{
if (decor->manager) {
zxdg_decoration_manager_v1_destroy(decor->manager);
}
if (decor->shell) {
xdg_wm_base_destroy(decor->shell);
}
delete decor;
}
struct GWL_Seat {
GHOST_SystemWayland *system = nullptr;
@ -455,11 +508,10 @@ struct GWL_Display {
struct wl_compositor *compositor = nullptr;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
struct libdecor *decor_context = nullptr;
#else
struct xdg_wm_base *xdg_shell = nullptr;
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
WGL_LibDecor_System *libdecor = nullptr;
bool libdecor_required = false;
#endif
WGL_XDG_Decor_System *xdg_decor = nullptr;
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
struct wl_shm *shm = nullptr;
@ -626,19 +678,19 @@ static void display_destroy(GWL_Display *d)
}
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (d->decor_context) {
libdecor_unref(d->decor_context);
if (use_libdecor) {
if (d->libdecor) {
wgl_libdecor_system_destroy(d->libdecor);
}
}
#else
if (d->xdg_decoration_manager) {
zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
else
#endif
{
if (d->xdg_decor) {
wgl_xdg_decor_system_destroy(d->xdg_decor);
}
}
if (d->xdg_shell) {
xdg_wm_base_destroy(d->xdg_shell);
}
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
if (eglGetDisplay) {
::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
}
@ -2903,10 +2955,8 @@ static const struct wl_output_listener output_listener = {
/** \name Listener (XDG WM Base), #xdg_wm_base_listener
* \{ */
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
static CLG_LogRef LOG_WL_XDG_WM_BASE = {"ghost.wl.handle.xdg_wm_base"};
# define LOG (&LOG_WL_XDG_WM_BASE)
#define LOG (&LOG_WL_XDG_WM_BASE)
static void shell_handle_ping(void * /*data*/,
struct xdg_wm_base *xdg_wm_base,
@ -2920,9 +2970,7 @@ static const struct xdg_wm_base_listener shell_listener = {
shell_handle_ping,
};
# undef LOG
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
#undef LOG
/** \} */
@ -2978,19 +3026,17 @@ static void global_handle_add(void *data,
display->compositor = static_cast<wl_compositor *>(
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
}
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* Pass. */
#else
else if (STREQ(interface, xdg_wm_base_interface.name)) {
display->xdg_shell = static_cast<xdg_wm_base *>(
WGL_XDG_Decor_System &decor = *display->xdg_decor;
decor.shell = static_cast<xdg_wm_base *>(
wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, 1));
xdg_wm_base_add_listener(display->xdg_shell, &shell_listener, nullptr);
xdg_wm_base_add_listener(decor.shell, &shell_listener, nullptr);
}
else if (STREQ(interface, zxdg_decoration_manager_v1_interface.name)) {
display->xdg_decoration_manager = static_cast<zxdg_decoration_manager_v1 *>(
WGL_XDG_Decor_System &decor = *display->xdg_decor;
decor.manager = static_cast<zxdg_decoration_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, 1));
}
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
@ -3048,6 +3094,14 @@ static void global_handle_add(void *data,
}
else {
found = false;
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
if (STRPREFIX(interface, "gtk_shell")) { /* `gtk_shell1` at time of writing. */
/* Only require `libdecor` when built with X11 support,
* otherwise there is nothing to fall back on. */
display->libdecor_required = true;
}
#endif
}
CLOG_INFO(LOG,
@ -3102,6 +3156,9 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
throw std::runtime_error("Wayland: unable to connect to display!");
}
/* This may be removed later if decorations are required, needed as part of registration. */
d->xdg_decor = new WGL_XDG_Decor_System;
/* Register interfaces. */
struct wl_registry *registry = wl_display_get_registry(d->display);
wl_registry_add_listener(registry, &registry_listener, d);
@ -3112,17 +3169,45 @@ GHOST_SystemWayland::GHOST_SystemWayland() : GHOST_System(), d(new GWL_Display)
wl_registry_destroy(registry);
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
d->decor_context = libdecor_new(d->display, &libdecor_interface);
if (!d->decor_context) {
display_destroy(d);
throw std::runtime_error("Wayland: unable to create window decorations!");
if (d->libdecor_required) {
wgl_xdg_decor_system_destroy(d->xdg_decor);
d->xdg_decor = nullptr;
if (!has_libdecor) {
# ifdef WITH_GHOST_X11
/* LIBDECOR was the only reason X11 was used, let the user know they need it installed. */
fprintf(stderr,
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
"falling back to X11\n");
# endif
display_destroy(d);
throw std::runtime_error("Wayland: unable to find libdecor!");
}
}
#else
if (!d->xdg_shell) {
display_destroy(d);
throw std::runtime_error("Wayland: unable to access xdg_shell!");
else {
use_libdecor = false;
}
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
d->libdecor = new WGL_LibDecor_System;
WGL_LibDecor_System &decor = *d->libdecor;
decor.context = libdecor_new(d->display, &libdecor_interface);
if (!decor.context) {
display_destroy(d);
throw std::runtime_error("Wayland: unable to create window decorations!");
}
}
else
#endif
{
WGL_XDG_Decor_System &decor = *d->xdg_decor;
if (!decor.shell) {
display_destroy(d);
throw std::runtime_error("Wayland: unable to access xdg_shell!");
}
}
/* Register data device per seat for IPC between Wayland clients. */
if (d->data_device_manager) {
@ -4052,25 +4137,25 @@ wl_compositor *GHOST_SystemWayland::compositor()
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *GHOST_SystemWayland::decor_context()
libdecor *GHOST_SystemWayland::libdecor_context()
{
return d->decor_context;
}
#else /* WITH_GHOST_WAYLAND_LIBDECOR */
xdg_wm_base *GHOST_SystemWayland::xdg_shell()
{
return d->xdg_shell;
}
zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decoration_manager()
{
return d->xdg_decoration_manager;
return d->libdecor->context;
}
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
xdg_wm_base *GHOST_SystemWayland::xdg_decor_shell()
{
return d->xdg_decor->shell;
}
zxdg_decoration_manager_v1 *GHOST_SystemWayland::xdg_decor_manager()
{
return d->xdg_decor->manager;
}
/* End `xdg_decor`. */
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs() const
{
return d->outputs;
@ -4317,57 +4402,52 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
return GHOST_kSuccess;
}
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
bool ghost_wl_dynload_libraries()
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
bool GHOST_SystemWayland::use_libdecor_runtime()
{
return use_libdecor;
}
#endif
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
bool ghost_wl_dynload_libraries_init()
{
/* Only report when `libwayland-client` is not found when building without X11,
* which will be used as a fallback. */
# ifdef WITH_GHOST_X11
bool verbose = false;
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* When running in Wayland, let the user know if libdecor is the only reason WAYLAND
* could not be used. Otherwise it's not obvious why X11 is used as a fallback. */
bool verbose_libdecor = getenv("WAYLAND_DISPLAY") != nullptr;
# endif
/* When running in WAYLAND, let the user know when a missing library is the only reason
* WAYLAND could not be used. Otherwise it's not obvious why X11 is used as a fallback.
* Otherwise when X11 is used, reporting WAYLAND library warnings is unwelcome noise. */
bool verbose = getenv("WAYLAND_DISPLAY") != nullptr;
# else
bool verbose = true;
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
bool verbose_libdecor = true;
# endif
# endif /* !WITH_GHOST_X11 */
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
int8_t libdecor_init = -1;
# endif
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
wayland_dynload_egl_init(verbose) && /* `libwayland-egl`. */
wayland_dynload_egl_init(verbose) /* `libwayland-egl`. */
) {
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
(libdecor_init = wayland_dynload_libdecor_init(verbose_libdecor)) && /* `libdecor-0`. */
has_libdecor = wayland_dynload_libdecor_init(verbose); /* `libdecor-0`. */
# endif
true) {
return true;
}
# if defined(WITH_GHOST_WAYLAND_LIBDECOR) && defined(WITH_GHOST_X11)
if (libdecor_init == 0) {
/* LIBDECOR was the only reason X11 was used, let the user know they need it installed. */
fprintf(stderr,
"WAYLAND found but libdecor was not, install libdecor for Wayland support, "
"falling back to X11\n");
}
# endif
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
wayland_dynload_libdecor_exit();
# endif
wayland_dynload_client_exit();
wayland_dynload_cursor_exit();
wayland_dynload_egl_exit();
return false;
}
void ghost_wl_dynload_libraries_exit()
{
wayland_dynload_client_exit();
wayland_dynload_cursor_exit();
wayland_dynload_egl_exit();
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
wayland_dynload_libdecor_exit();
# endif
}
#endif /* WITH_GHOST_WAYLAND_DYNLOAD */
/** \} */

View File

@ -21,18 +21,12 @@
# include <wayland_dynload_libdecor.h>
# endif
# include <libdecor.h>
#else
/* Generated by `wayland-scanner`. */
# include <xdg-decoration-unstable-v1-client-protocol.h>
# include <xdg-shell-client-protocol.h>
#endif
#include <string>
class GHOST_WindowWayland;
struct GWL_Display;
bool ghost_wl_output_own(const struct wl_output *wl_output);
void ghost_wl_output_tag(struct wl_output *wl_output);
struct GWL_Output *ghost_wl_output_user_data(struct wl_output *wl_output);
@ -52,7 +46,8 @@ void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
* Return true when all required WAYLAND libraries are present,
* Performs dynamic loading when `WITH_GHOST_WAYLAND_DYNLOAD` is in use.
*/
bool ghost_wl_dynload_libraries();
bool ghost_wl_dynload_libraries_init();
void ghost_wl_dynload_libraries_exit();
#endif
struct GWL_Output {
@ -167,11 +162,11 @@ class GHOST_SystemWayland : public GHOST_System {
wl_compositor *compositor();
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *decor_context();
#else
xdg_wm_base *xdg_shell();
zxdg_decoration_manager_v1 *xdg_decoration_manager();
libdecor *libdecor_context();
#endif
struct xdg_wm_base *xdg_decor_shell();
struct zxdg_decoration_manager_v1 *xdg_decor_manager();
/* End `xdg_decor`. */
const std::vector<GWL_Output *> &outputs() const;
@ -192,6 +187,10 @@ class GHOST_SystemWayland : public GHOST_System {
wl_surface *wl_surface,
int scale);
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
static bool use_libdecor_runtime();
#endif
private:
struct GWL_Display *d;
std::string selection;

View File

@ -2435,11 +2435,11 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
utf8Str,
8,
PropModeReplace,
(const unsigned char *)title,
(const uchar *)title,
int(strlen(title)));
XChangeProperty(
m_display, window, winType, XA_ATOM, 32, PropModeReplace, (unsigned char *)&typeDialog, 1);
m_display, window, winType, XA_ATOM, 32, PropModeReplace, (uchar *)&typeDialog, 1);
}
/* Create buttons GC */

View File

@ -31,13 +31,52 @@
# include <libdecor.h>
#endif
/* Generated by `wayland-scanner`. */
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h>
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
static constexpr size_t base_dpi = 96;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* Access `use_libdecor` in #GHOST_SystemWayland. */
# define use_libdecor GHOST_SystemWayland::use_libdecor_runtime()
#endif
static GHOST_WindowManager *window_manager = nullptr;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
struct WGL_LibDecor_Window {
struct libdecor_frame *frame = nullptr;
bool configured = false;
};
static void wgl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
{
libdecor_frame_unref(decor->frame);
delete decor;
}
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
struct WGL_XDG_Decor_Window {
struct xdg_surface *surface = nullptr;
struct zxdg_toplevel_decoration_v1 *toplevel_decor = nullptr;
struct xdg_toplevel *toplevel = nullptr;
enum zxdg_toplevel_decoration_v1_mode mode = (enum zxdg_toplevel_decoration_v1_mode)0;
};
static void wgl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
{
if (decor->toplevel_decor) {
zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor);
}
xdg_toplevel_destroy(decor->toplevel);
xdg_surface_destroy(decor->surface);
delete decor;
}
struct GWL_Window {
GHOST_WindowWayland *w = nullptr;
struct wl_surface *wl_surface = nullptr;
@ -60,15 +99,9 @@ struct GWL_Window {
uint32_t dpi = 0;
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
struct libdecor_frame *decor_frame = nullptr;
bool decor_configured = false;
#else
struct xdg_surface *xdg_surface = nullptr;
struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration = nullptr;
struct xdg_toplevel *xdg_toplevel = nullptr;
enum zxdg_toplevel_decoration_v1_mode decoration_mode = (enum zxdg_toplevel_decoration_v1_mode)0;
WGL_LibDecor_Window *libdecor = nullptr;
#endif
WGL_XDG_Decor_Window *xdg_decor = nullptr;
wl_egl_window *egl_window = nullptr;
bool is_maximised = false;
@ -146,10 +179,8 @@ static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs
/** \name Listener (XDG Top Level), #xdg_toplevel_listener
* \{ */
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
static CLG_LogRef LOG_WL_XDG_TOPLEVEL = {"ghost.wl.handle.xdg_toplevel"};
# define LOG (&LOG_WL_XDG_TOPLEVEL)
#define LOG (&LOG_WL_XDG_TOPLEVEL)
static void xdg_toplevel_handle_configure(void *data,
xdg_toplevel * /*xdg_toplevel*/,
@ -197,9 +228,7 @@ static const xdg_toplevel_listener toplevel_listener = {
xdg_toplevel_handle_close,
};
# undef LOG
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
#undef LOG
/** \} */
@ -250,7 +279,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
win->decor_configured = true;
win->libdecor->configured = true;
}
static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
@ -285,10 +314,8 @@ static struct libdecor_frame_interface libdecor_frame_iface = {
/** \name Listener (XDG Decoration Listener), #zxdg_toplevel_decoration_v1_listener
* \{ */
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
static CLG_LogRef LOG_WL_XDG_TOPLEVEL_DECORATION = {"ghost.wl.handle.xdg_toplevel_decoration"};
# define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
#define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
static void xdg_toplevel_decoration_handle_configure(
void *data,
@ -296,16 +323,14 @@ static void xdg_toplevel_decoration_handle_configure(
const uint32_t mode)
{
CLOG_INFO(LOG, 2, "configure (mode=%u)", mode);
static_cast<GWL_Window *>(data)->decoration_mode = (zxdg_toplevel_decoration_v1_mode)mode;
static_cast<GWL_Window *>(data)->xdg_decor->mode = (zxdg_toplevel_decoration_v1_mode)mode;
}
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
xdg_toplevel_decoration_handle_configure,
};
# undef LOG
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
#undef LOG
/** \} */
@ -313,10 +338,8 @@ static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listene
/** \name Listener (XDG Surface Handle Configure), #xdg_surface_listener
* \{ */
#ifndef WITH_GHOST_WAYLAND_LIBDECOR
static CLG_LogRef LOG_WL_XDG_SURFACE = {"ghost.wl.handle.xdg_surface"};
# define LOG (&LOG_WL_XDG_SURFACE)
#define LOG (&LOG_WL_XDG_SURFACE)
static void xdg_surface_handle_configure(void *data,
xdg_surface *xdg_surface,
@ -324,7 +347,7 @@ static void xdg_surface_handle_configure(void *data,
{
GWL_Window *win = static_cast<GWL_Window *>(data);
if (win->xdg_surface != xdg_surface) {
if (win->xdg_decor->surface != xdg_surface) {
CLOG_INFO(LOG, 2, "configure (skipped)");
return;
}
@ -354,9 +377,7 @@ static const xdg_surface_listener xdg_surface_listener = {
xdg_surface_handle_configure,
};
# undef LOG
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
#undef LOG
/** \} */
@ -477,42 +498,52 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
const int32_t size_min[2] = {320, 240};
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* create window decorations */
w->decor_frame = libdecor_decorate(
m_system->decor_context(), w->wl_surface, &libdecor_frame_iface, w);
libdecor_frame_map(w->decor_frame);
if (use_libdecor) {
w->libdecor = new WGL_LibDecor_Window;
WGL_LibDecor_Window &decor = *w->libdecor;
libdecor_frame_set_min_content_size(w->decor_frame, UNPACK2(size_min));
/* create window decorations */
decor.frame = libdecor_decorate(
m_system->libdecor_context(), w->wl_surface, &libdecor_frame_iface, w);
libdecor_frame_map(w->libdecor->frame);
if (parentWindow) {
libdecor_frame_set_parent(
w->decor_frame, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->decor_frame);
libdecor_frame_set_min_content_size(decor.frame, UNPACK2(size_min));
if (parentWindow) {
WGL_LibDecor_Window &decor_parent =
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->libdecor;
libdecor_frame_set_parent(decor.frame, decor_parent.frame);
}
}
#else
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->xdg_shell(), w->wl_surface);
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
else
#endif
{
w->xdg_decor = new WGL_XDG_Decor_Window;
WGL_XDG_Decor_Window &decor = *w->xdg_decor;
decor.surface = xdg_wm_base_get_xdg_surface(m_system->xdg_decor_shell(), w->wl_surface);
decor.toplevel = xdg_surface_get_toplevel(decor.surface);
xdg_toplevel_set_min_size(w->xdg_toplevel, UNPACK2(size_min));
xdg_toplevel_set_min_size(decor.toplevel, UNPACK2(size_min));
if (m_system->xdg_decoration_manager()) {
w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
m_system->xdg_decoration_manager(), w->xdg_toplevel);
zxdg_toplevel_decoration_v1_add_listener(
w->xdg_toplevel_decoration, &toplevel_decoration_v1_listener, w);
zxdg_toplevel_decoration_v1_set_mode(w->xdg_toplevel_decoration,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
if (m_system->xdg_decor_manager()) {
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
m_system->xdg_decor_manager(), decor.toplevel);
zxdg_toplevel_decoration_v1_add_listener(
decor.toplevel_decor, &toplevel_decoration_v1_listener, w);
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
xdg_surface_add_listener(decor.surface, &xdg_surface_listener, w);
xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, w);
if (parentWindow && is_dialog) {
WGL_XDG_Decor_Window &decor_parent =
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_decor;
xdg_toplevel_set_parent(decor.toplevel, decor_parent.toplevel);
}
}
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
xdg_toplevel_add_listener(w->xdg_toplevel, &toplevel_listener, w);
if (parentWindow && is_dialog) {
xdg_toplevel_set_parent(
w->xdg_toplevel, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->xdg_toplevel);
}
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
setTitle(title);
wl_surface_set_user_data(w->wl_surface, this);
@ -522,11 +553,14 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
wl_display_roundtrip(m_system->display());
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
/* It's important not to return until the window is configured or
* calls to `setState` from Blender will crash `libdecor`. */
while (!w->decor_configured) {
if (libdecor_dispatch(m_system->decor_context(), 0) < 0) {
break;
if (use_libdecor) {
WGL_LibDecor_Window &decor = *w->libdecor;
/* It's important not to return until the window is configured or
* calls to `setState` from Blender will crash `libdecor`. */
while (!decor.configured) {
if (libdecor_dispatch(m_system->libdecor_context(), 0) < 0) {
break;
}
}
}
#endif
@ -535,9 +569,13 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
setOpaque();
#endif
#ifndef WITH_GHOST_WAYLAND_LIBDECOR /* Causes a glitch with `libdecor` for some reason. */
setState(state);
/* Causes a glitch with `libdecor` for some reason. */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor == false)
#endif
{
setState(state);
}
/* EGL context. */
if (setDrawingContextType(type) == GHOST_kFailure) {
@ -596,12 +634,18 @@ GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
void GHOST_WindowWayland::setTitle(const char *title)
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_set_app_id(w->decor_frame, title);
libdecor_frame_set_title(w->decor_frame, title);
#else
xdg_toplevel_set_title(w->xdg_toplevel, title);
xdg_toplevel_set_app_id(w->xdg_toplevel, title);
if (use_libdecor) {
WGL_LibDecor_Window &decor = *w->libdecor;
libdecor_frame_set_app_id(decor.frame, title);
libdecor_frame_set_title(decor.frame, title);
}
else
#endif
{
WGL_XDG_Decor_Window &decor = *w->xdg_decor;
xdg_toplevel_set_title(decor.toplevel, title);
xdg_toplevel_set_app_id(decor.toplevel, title);
}
this->title = title;
}
@ -672,14 +716,14 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
wl_egl_window_destroy(w->egl_window);
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_unref(w->decor_frame);
#else
if (w->xdg_toplevel_decoration) {
zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
if (use_libdecor) {
wgl_libdecor_window_destroy(w->libdecor);
}
xdg_toplevel_destroy(w->xdg_toplevel);
xdg_surface_destroy(w->xdg_surface);
else
#endif
{
wgl_xdg_decor_window_destroy(w->xdg_decor);
}
/* Clear any pointers to this window. This is needed because there are no guarantees
* that flushing the display will the "leave" handlers before handling events. */
@ -711,47 +755,74 @@ GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
case GHOST_kWindowStateNormal:
/* Unset states. */
switch (getState()) {
case GHOST_kWindowStateMaximized:
case GHOST_kWindowStateMaximized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_unset_maximized(w->decor_frame);
#else
xdg_toplevel_unset_maximized(w->xdg_toplevel);
if (use_libdecor) {
libdecor_frame_unset_maximized(w->libdecor->frame);
}
else
#endif
{
xdg_toplevel_unset_maximized(w->xdg_decor->toplevel);
}
break;
case GHOST_kWindowStateFullScreen:
}
case GHOST_kWindowStateFullScreen: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_unset_fullscreen(w->decor_frame);
#else
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
if (use_libdecor) {
libdecor_frame_unset_fullscreen(w->libdecor->frame);
}
else
#endif
{
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
}
break;
default:
}
default: {
break;
}
}
break;
case GHOST_kWindowStateMaximized:
case GHOST_kWindowStateMaximized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_set_maximized(w->decor_frame);
#else
xdg_toplevel_set_maximized(w->xdg_toplevel);
if (use_libdecor) {
libdecor_frame_set_maximized(w->libdecor->frame);
}
else
#endif
{
xdg_toplevel_set_maximized(w->xdg_decor->toplevel);
}
break;
case GHOST_kWindowStateMinimized:
}
case GHOST_kWindowStateMinimized: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_set_minimized(w->decor_frame);
#else
xdg_toplevel_set_minimized(w->xdg_toplevel);
if (use_libdecor) {
libdecor_frame_set_minimized(w->libdecor->frame);
}
else
#endif
{
xdg_toplevel_set_minimized(w->xdg_decor->toplevel);
}
break;
case GHOST_kWindowStateFullScreen:
}
case GHOST_kWindowStateFullScreen: {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
#else
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
if (use_libdecor) {
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
}
else
#endif
{
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
}
break;
case GHOST_kWindowStateEmbedded:
}
case GHOST_kWindowStateEmbedded: {
return GHOST_kFailure;
}
}
return GHOST_kSuccess;
}
@ -780,20 +851,29 @@ GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
#else
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
if (use_libdecor) {
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
}
else
#endif
{
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
}
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
{
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor_frame_unset_fullscreen(w->decor_frame);
#else
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
if (use_libdecor) {
libdecor_frame_unset_fullscreen(w->libdecor->frame);
}
else
#endif
{
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
}
return GHOST_kSuccess;
}

View File

@ -43,7 +43,7 @@ void (*MEM_set_error_callback)(void (*func)(const char *)) = MEM_lockfree_set_er
bool (*MEM_consistency_check)(void) = MEM_lockfree_consistency_check;
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
size_t (*MEM_get_memory_in_use)(void) = MEM_lockfree_get_memory_in_use;
unsigned int (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
uint (*MEM_get_memory_blocks_in_use)(void) = MEM_lockfree_get_memory_blocks_in_use;
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;

View File

@ -233,7 +233,7 @@ void *MEM_lockfree_callocN(size_t len, const char *str)
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
SIZET_ARG(len),
str,
(unsigned int)mem_in_use);
(uint)mem_in_use);
return NULL;
}
@ -278,7 +278,7 @@ void *MEM_lockfree_mallocN(size_t len, const char *str)
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
SIZET_ARG(len),
str,
(unsigned int)mem_in_use);
(uint)mem_in_use);
return NULL;
}
@ -292,7 +292,7 @@ void *MEM_lockfree_malloc_arrayN(size_t len, size_t size, const char *str)
SIZET_ARG(len),
SIZET_ARG(size),
str,
(unsigned int)mem_in_use);
(uint)mem_in_use);
abort();
return NULL;
}
@ -349,7 +349,7 @@ void *MEM_lockfree_mallocN_aligned(size_t len, size_t alignment, const char *str
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
SIZET_ARG(len),
str,
(unsigned int)mem_in_use);
(uint)mem_in_use);
return NULL;
}
@ -401,7 +401,7 @@ size_t MEM_lockfree_get_memory_in_use(void)
return mem_in_use;
}
unsigned int MEM_lockfree_get_memory_blocks_in_use(void)
uint MEM_lockfree_get_memory_blocks_in_use(void)
{
return totblock;
}

View File

@ -22,7 +22,7 @@ bool wayland_dynload_egl_init(const bool verbose)
{
/* Library paths. */
const char *paths[] = {
"libwayland-egl.so.0",
"libwayland-egl.so.1",
"libwayland-egl.so",
};
const int paths_num = sizeof(paths) / sizeof(*paths);

View File

@ -239,6 +239,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
bl_translation_context = i18n_contexts.id_particlesettings
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
@classmethod

View File

@ -2,7 +2,10 @@
import bpy
from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
from bpy.app.translations import (
pgettext_iface as iface_,
contexts as i18n_contexts,
)
from bl_ui.utils import PresetPanel
from bl_ui.properties_grease_pencil_common import (
AnnotationDrawingToolsPanel,
@ -1751,6 +1754,7 @@ class CLIP_MT_marker_pie(Menu):
class CLIP_MT_tracking_pie(Menu):
# Tracking Operators
bl_label = "Tracking"
bl_translation_context = i18n_contexts.id_movieclip
@classmethod
def poll(cls, context):

View File

@ -1528,36 +1528,23 @@ class IMAGE_PT_overlay_guides(Panel):
layout.active = overlay.show_overlays
row = layout.row()
row_el = row.column()
row_el.prop(overlay, "show_grid_background", text="Grid")
row.prop(overlay, "show_grid_background", text="Grid")
if overlay.show_grid_background:
layout.use_property_split = True
col = layout.column(align=False, heading="Grid Over Image")
col.use_property_decorate = False
row = col.row(align=True)
sub = row.row(align=True)
sub.prop(uvedit, "show_grid_over_image", text="")
sub = row.row()
sub.prop(uvedit, "show_grid_over_image", text="Over Image")
sub.active = sima.image is not None
col = layout.column(align=False, heading="Fixed Subdivisions")
col.use_property_decorate = False
layout.row().prop(uvedit, "grid_shape_source", expand=True)
row = col.row(align=True)
sub = row.row(align=True)
sub.prop(uvedit, "use_custom_grid", text="")
if uvedit.use_custom_grid:
row = layout.row()
row.use_property_split = True
row.use_property_decorate = False
sub = sub.row(align=True)
sub.prop(uvedit, "custom_grid_subdivisions", text="")
layout.use_property_split = True
layout.use_property_decorate = False
row = layout.row()
row.use_property_split = True
row.use_property_decorate = False
row.prop(uvedit, "tile_grid_shape", text="Tiles")
row.prop(uvedit, "custom_grid_subdivisions", text="Fixed Subdivisions")
row.active = uvedit.grid_shape_source == 'FIXED'
layout.prop(uvedit, "tile_grid_shape", text="Tiles")
class IMAGE_PT_overlay_uv_edit(Panel):

View File

@ -683,7 +683,7 @@ class SEQUENCER_MT_add(Menu):
elif bpy_data_movieclips_len > 0:
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip", icon='TRACKER')
else:
layout.menu("SEQUENCER_MT_add_empty", text="Clip", icon='TRACKER')
layout.menu("SEQUENCER_MT_add_empty", text="Clip", text_ctxt=i18n_contexts.id_movieclip, icon='TRACKER')
del bpy_data_movieclips_len
bpy_data_masks_len = len(bpy.data.masks)

View File

@ -3356,8 +3356,7 @@ class VIEW3D_MT_face_sets(Menu):
op = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
op.mode = 'INVERT'
op = layout.operator("sculpt.face_set_change_visibility", text='Show All Face Sets')
op.mode = 'SHOW_ALL'
op = layout.operator("sculpt.reveal_all", text='Show All Face Sets')
layout.separator()
@ -5518,8 +5517,7 @@ class VIEW3D_MT_sculpt_face_sets_edit_pie(Menu):
op = pie.operator("sculpt.face_set_change_visibility", text='Invert Visible')
op.mode = 'INVERT'
op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
op.mode = 'SHOW_ALL'
op = pie.operator("sculpt.reveal_all", text='Show All')
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):

View File

@ -490,7 +490,7 @@ void BKE_mesh_calc_normals(struct Mesh *me);
* Called after calculating all modifiers.
*/
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
void BKE_mesh_calc_normals_looptri(struct MVert *mverts,
void BKE_mesh_calc_normals_looptri(const struct MVert *mverts,
int numVerts,
const struct MLoop *mloop,
const struct MLoopTri *looptri,

View File

@ -246,6 +246,24 @@ float BKE_nlastrip_compute_frame_from_previous_strip(struct NlaStrip *strip);
*/
float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip);
/**
* Returns the next strip in this strip's NLA track, or a null pointer.
*
* \param strip The strip to find the next trip from.
* \param check_transitions Whether or not to skip transitions.
* \return The next strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions);
/**
* Returns the previous strip in this strip's NLA track, or a null pointer.
*
* \param strip The strip to find the previous trip from.
* \param check_transitions Whether or not to skip transitions.
* \return The previous strip in the track, or NULL if none are present.
*/
struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions);
/* ............ */
/**

View File

@ -125,6 +125,7 @@ typedef enum {
PBVH_UpdateTopology = 1 << 13,
PBVH_UpdateColor = 1 << 14,
PBVH_RebuildPixels = 1 << 15,
PBVH_TopologyUpdated = 1 << 16, /* Used internally by pbvh_bmesh.c */
} PBVHNodeFlags;
@ -485,7 +486,10 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
*
* Skips triangles that are hidden.
*/
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm,
struct BMLog *log,
PBVHNode *node,
bool use_original);
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
/* Update Bounding Box/Redraw and clear flags. */
@ -664,7 +668,8 @@ void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot);
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
float (**r_orco_coords)[3]);
float (**r_orco_coords)[3],
struct BMVert ***r_orco_verts);
/**
* \note doing a full search on all vertices here seems expensive,

View File

@ -1899,7 +1899,7 @@ struct MappedUserData {
static void make_vertexcos__mapFunc(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
MappedUserData *mappedData = (MappedUserData *)userData;

View File

@ -1167,7 +1167,7 @@ static Mesh *cloth_make_rest_mesh(ClothModifierData *clmd, Mesh *mesh)
MVert *mvert = BKE_mesh_verts_for_write(mesh);
/* vertex count is already ensured to match */
for (unsigned i = 0; i < mesh->totvert; i++, verts++) {
for (uint i = 0; i < mesh->totvert; i++, verts++) {
copy_v3_v3(mvert[i].co, verts->xrest);
}
BKE_mesh_tag_coords_changed(new_mesh);

View File

@ -189,7 +189,7 @@ struct CageUserData {
static void cage_mapped_verts_callback(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
CageUserData *data = static_cast<CageUserData *>(userData);

View File

@ -1856,6 +1856,10 @@ bool BKE_gpencil_stroke_close(bGPDstroke *gps)
pt->strength = interpf(pt2->strength, pt1->strength, step);
pt->flag = 0;
interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
/* Set point as selected. */
if (gps->flag & GP_STROKE_SELECT) {
pt->flag |= GP_SPOINT_SELECT;
}
/* Set weights. */
if (gps->dvert != nullptr) {

View File

@ -364,7 +364,7 @@ struct MappedVCosData {
static void get_vertexcos__mapFunc(void *user_data,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;

View File

@ -470,7 +470,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#endif
}
void BKE_mesh_calc_normals_looptri(MVert *mverts,
void BKE_mesh_calc_normals_looptri(const MVert *mverts,
int numVerts,
const MLoop *mloop,
const MLoopTri *looptri,
@ -508,7 +508,7 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
for (int i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
const MVert *mv = &mverts[i];
float *no = tnorms[i];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {

View File

@ -1272,6 +1272,34 @@ float BKE_nlastrip_compute_frame_to_next_strip(NlaStrip *strip)
return limit_next;
}
NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions)
{
NlaStrip *next = strip->next;
while (next != NULL) {
if (skip_transitions && (next->type & NLASTRIP_TYPE_TRANSITION)) {
next = next->next;
}
else {
return next;
}
}
return NULL;
}
NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions)
{
NlaStrip *prev = strip->prev;
while (prev != NULL) {
if (skip_transitions && (prev->type & NLASTRIP_TYPE_TRANSITION)) {
prev = prev->prev;
}
else {
return prev;
}
}
return NULL;
}
NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
{
if (nlt == NULL) {

View File

@ -2287,9 +2287,9 @@ PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
}
BKE_pbvh_pmap_set(pbvh, ob->sculpt->pmap);
sculpt_attribute_update_refs(ob);
ob->sculpt->pbvh = pbvh;
sculpt_attribute_update_refs(ob);
return pbvh;
}

View File

@ -2044,11 +2044,16 @@ void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *pro
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
float (**r_orco_coords)[3])
float (**r_orco_coords)[3],
BMVert ***r_orco_verts)
{
*r_orco_tris = node->bm_ortri;
*r_orco_tris_num = node->bm_tot_ortri;
*r_orco_coords = node->bm_orco;
if (r_orco_verts) {
*r_orco_verts = node->bm_orvert;
}
}
bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node)

View File

@ -493,7 +493,7 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
BLI_gset_insert(node->bm_unique_verts, v);
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
/* Log the new vertex */
BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
@ -519,7 +519,7 @@ static BMFace *pbvh_bmesh_face_create(
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
/* mark node for update */
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_TopologyUpdated;
node->flag &= ~PBVH_FullyHidden;
/* Log the new face */
@ -594,7 +594,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner,
{
PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
BLI_assert(current_owner != new_owner);
@ -608,7 +608,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner,
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
/* mark node for update */
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
}
static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
@ -631,7 +631,7 @@ static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
f_node_index_prev = f_node_index;
PBVHNode *f_node = &pbvh->nodes[f_node_index];
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB | PBVH_TopologyUpdated;
/* Remove current ownership */
BLI_gset_remove(f_node->bm_other_verts, v, NULL);
@ -680,7 +680,7 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
BM_log_face_removed(pbvh->bm_log, f);
/* mark node for update */
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_TopologyUpdated;
}
static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
@ -701,14 +701,9 @@ static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
{
if (node->bm_orco) {
MEM_freeN(node->bm_orco);
}
if (node->bm_ortri) {
MEM_freeN(node->bm_ortri);
}
node->bm_orco = NULL;
node->bm_ortri = NULL;
MEM_SAFE_FREE(node->bm_orco);
MEM_SAFE_FREE(node->bm_ortri);
MEM_SAFE_FREE(node->bm_orvert);
node->bm_tot_ortri = 0;
}
@ -1507,29 +1502,51 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
bool hit = false;
float nearest_vertex_co[3] = {0.0f};
BLI_assert(!use_original || (BLI_gset_len(node->bm_faces) > 0 && node->bm_tot_ortri));
use_original = use_original && node->bm_tot_ortri;
GSetIterator gs_iter;
if (use_original && node->bm_tot_ortri) {
for (int i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
hit |= ray_face_intersection_tri(ray_start,
isect_precalc,
node->bm_orco[t[0]],
node->bm_orco[t[1]],
node->bm_orco[t[2]],
depth);
float *cos[3];
cos[0] = node->bm_orco[node->bm_ortri[i][0]];
cos[1] = node->bm_orco[node->bm_ortri[i][1]];
cos[2] = node->bm_orco[node->bm_ortri[i][2]];
if (ray_face_intersection_tri(ray_start, isect_precalc, cos[0], cos[1], cos[2], depth)) {
hit = true;
if (r_face_normal) {
normal_tri_v3(r_face_normal, cos[0], cos[1], cos[2]);
}
if (r_active_vertex) {
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
if (len_squared_v3v3(location, cos[j]) <
len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, cos[j]);
r_active_vertex->i = (intptr_t)node->bm_orvert[node->bm_ortri[i][j]];
}
}
}
}
}
}
else {
GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
BLI_assert(f->len == 3);
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
BMVert *v_tri[3];
BM_face_as_array_vert_tri(f, v_tri);
if (ray_face_intersection_tri(
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
hit = true;
@ -2016,6 +2033,21 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
BLI_buffer_free(&edge_loops);
BLI_buffer_free(&deleted_faces);
/* Go over all changed nodes and check if anything needs to be updated. */
for (int n = 0; n < pbvh->totnode; n++) {
PBVHNode *node = &pbvh->nodes[n];
if (node->flag & PBVH_Leaf && node->flag & PBVH_TopologyUpdated) {
node->flag &= ~PBVH_TopologyUpdated;
if (node->bm_ortri) {
/* Reallocate original triangle data. */
pbvh_bmesh_node_drop_orig(node);
BKE_pbvh_bmesh_node_save_orig(pbvh->header.bm, pbvh->bm_log, node, true);
}
}
}
#ifdef USE_VERIFY
pbvh_bmesh_verify(pbvh);
#endif
@ -2023,7 +2055,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
return modified;
}
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, BMLog *log, PBVHNode *node, bool use_original)
{
/* Skip if original coords/triangles are already saved */
if (node->bm_orco) {
@ -2036,19 +2068,38 @@ void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
node->bm_orvert = MEM_mallocN(sizeof(*node->bm_orvert) * totvert, __func__);
/* Copy out the vertices and assign a temporary index */
int i = 0;
GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_unique_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
copy_v3_v3(node->bm_orco[i], v->co);
const float *origco = BM_log_original_vert_co(log, v);
if (use_original && origco) {
copy_v3_v3(node->bm_orco[i], origco);
}
else {
copy_v3_v3(node->bm_orco[i], v->co);
}
node->bm_orvert[i] = v;
BM_elem_index_set(v, i); /* set_dirty! */
i++;
}
GSET_ITER (gs_iter, node->bm_other_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
copy_v3_v3(node->bm_orco[i], v->co);
const float *origco = BM_log_original_vert_co(log, v);
if (use_original && origco) {
copy_v3_v3(node->bm_orco[i], BM_log_original_vert_co(log, v));
}
else {
copy_v3_v3(node->bm_orco[i], v->co);
}
node->bm_orvert[i] = v;
BM_elem_index_set(v, i); /* set_dirty! */
i++;
}

View File

@ -96,7 +96,7 @@ struct PBVHNode {
/* Indicates whether this node is a leaf or not; also used for
* marking various updates that need to be applied. */
PBVHNodeFlags flag : 16;
PBVHNodeFlags flag : 32;
/* Used for raycasting: how close bb is to the ray point. */
float tmin;
@ -116,8 +116,11 @@ struct PBVHNode {
GSet *bm_faces;
GSet *bm_unique_verts;
GSet *bm_other_verts;
/* Deprecated. Stores original coordinates of triangles. */
float (*bm_orco)[3];
int (*bm_ortri)[3];
BMVert **bm_orvert;
int bm_tot_ortri;
/* Used to store the brush color during a stroke and composite it over the original color */

View File

@ -244,7 +244,7 @@ static void scene_init_data(ID *id)
/* Master Collection */
scene->master_collection = BKE_collection_master_add(scene);
BKE_view_layer_add(scene, "ViewLayer", nullptr, VIEWLAYER_ADD_NEW);
BKE_view_layer_add(scene, DATA_("ViewLayer"), nullptr, VIEWLAYER_ADD_NEW);
}
static void scene_copy_markers(Scene *scene_dst, const Scene *scene_src, const int flag)

View File

@ -128,7 +128,7 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv)
subdiv_ccg->num_grids = num_grids;
subdiv_ccg->grids = static_cast<CCGElem **>(
MEM_calloc_arrayN(num_grids, sizeof(CCGElem *), "subdiv ccg grids"));
subdiv_ccg->grids_storage = static_cast<unsigned char *>(
subdiv_ccg->grids_storage = static_cast<uchar *>(
MEM_calloc_arrayN(num_grids, size_t(grid_area) * element_size, "subdiv ccg grids storage"));
const size_t grid_size_in_bytes = size_t(grid_area) * element_size;
for (int grid_index = 0; grid_index < num_grids; grid_index++) {
@ -286,7 +286,7 @@ static void subdiv_ccg_eval_special_grid(CCGEvalGridsData *data, const int face_
static void subdiv_ccg_eval_grids_task(void *__restrict userdata_v,
const int face_index,
const TaskParallelTLS *__restrict UNUSED(tls))
const TaskParallelTLS *__restrict /*tls*/)
{
CCGEvalGridsData *data = static_cast<CCGEvalGridsData *>(userdata_v);
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
@ -779,7 +779,7 @@ static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v,
subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index);
}
static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict UNUSED(userdata),
static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict /*userdata*/,
void *__restrict tls_v)
{
RecalcInnerNormalsTLSData *tls = static_cast<RecalcInnerNormalsTLSData *>(tls_v);
@ -842,7 +842,7 @@ static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userda
subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
}
static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict UNUSED(userdata),
static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict /*userdata*/,
void *__restrict tls_v)
{
RecalcInnerNormalsTLSData *tls = static_cast<RecalcInnerNormalsTLSData *>(tls_v);
@ -1016,7 +1016,7 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg,
static void subdiv_ccg_average_inner_grids_task(void *__restrict userdata_v,
const int face_index,
const TaskParallelTLS *__restrict UNUSED(tls_v))
const TaskParallelTLS *__restrict /*tls_v*/)
{
AverageInnerGridsData *data = static_cast<AverageInnerGridsData *>(userdata_v);
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
@ -1095,7 +1095,7 @@ static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v
subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, tls);
}
static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict UNUSED(userdata),
static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict /*userdata*/,
void *__restrict tls_v)
{
AverageGridsBoundariesTLSData *tls = static_cast<AverageGridsBoundariesTLSData *>(tls_v);
@ -1137,7 +1137,7 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg,
static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v,
const int n,
const TaskParallelTLS *__restrict UNUSED(tls_v))
const TaskParallelTLS *__restrict /*tls_v*/)
{
AverageGridsCornerData *data = static_cast<AverageGridsCornerData *>(userdata_v);
const int adjacent_vertex_index = data->adjacent_vert_index_map ?
@ -1323,10 +1323,9 @@ struct StitchFacesInnerGridsData {
CCGFace **effected_ccg_faces;
};
static void subdiv_ccg_stitch_face_inner_grids_task(
void *__restrict userdata_v,
const int face_index,
const TaskParallelTLS *__restrict UNUSED(tls_v))
static void subdiv_ccg_stitch_face_inner_grids_task(void *__restrict userdata_v,
const int face_index,
const TaskParallelTLS *__restrict /*tls_v*/)
{
StitchFacesInnerGridsData *data = static_cast<StitchFacesInnerGridsData *>(userdata_v);
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
@ -1447,7 +1446,7 @@ BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG *subdiv_ccg,
return false;
}
BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG *UNUSED(subdiv_ccg),
BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG * /*subdiv_ccg*/,
const SubdivCCGCoord *coord)
{
BLI_assert(coord->y > 0);
@ -1465,7 +1464,7 @@ BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG *subdiv_ccg,
return result;
}
BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG *UNUSED(subdiv_ccg),
BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG * /*subdiv_ccg*/,
const SubdivCCGCoord *coord)
{
BLI_assert(coord->x > 0);

View File

@ -3379,7 +3379,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
SpaceImage *sima = (SpaceImage *)sl;
sima->flag &= ~(SI_FLAG_UNUSED_0 | SI_FLAG_UNUSED_1 | SI_FLAG_UNUSED_3 |
SI_FLAG_UNUSED_6 | SI_FLAG_UNUSED_7 | SI_FLAG_UNUSED_8 |
SI_FLAG_UNUSED_17 | SI_CUSTOM_GRID | SI_FLAG_UNUSED_23 |
SI_FLAG_UNUSED_17 | SI_FLAG_UNUSED_18 | SI_FLAG_UNUSED_23 |
SI_FLAG_UNUSED_24);
break;
}

View File

@ -3604,6 +3604,13 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain)
v3d->overlay.flag |= V3D_OVERLAY_VIEWER_ATTRIBUTE;
v3d->overlay.viewer_attribute_opacity = 1.0f;
}
if (sl->spacetype == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)sl;
if (sima->flag & SI_FLAG_UNUSED_18) { /* Was #SI_CUSTOM_GRID. */
sima->grid_shape_source = SI_GRID_SHAPE_FIXED;
sima->flag &= ~SI_FLAG_UNUSED_18;
}
}
}
}
}

View File

@ -3,7 +3,7 @@
/** \file
* \ingroup bmesh
*
* normal recalculation.
* Functionality for flipping faces to make normals consistent.
*/
#include "MEM_guardedalloc.h"
@ -47,7 +47,7 @@ static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_
* +------------+
* </pre>
*
* In the example above, the a\ face can point towards the \a center
* In the example above, the \a face can point towards the \a center
* which would end up flipping the normals inwards.
*
* To take these spikes into account, find the furthest face-loop-vertex.

View File

@ -10,6 +10,7 @@
#include "COM_MultilayerImageOperation.h"
#include "COM_RenderLayersProg.h"
#include "COM_SetAlphaMultiplyOperation.h"
#include "COM_SetAlphaReplaceOperation.h"
#include "COM_SetColorOperation.h"
namespace blender::compositor {
@ -48,7 +49,7 @@ void CryptomatteBaseNode::convert_to_operations(NodeConverter &converter,
converter.map_output_socket(output_image_socket, apply_mask_operation->get_output_socket(0));
NodeOutput *output_pick_socket = this->get_output_socket(2);
SetAlphaMultiplyOperation *extract_pick_operation = new SetAlphaMultiplyOperation();
SetAlphaReplaceOperation *extract_pick_operation = new SetAlphaReplaceOperation();
converter.add_operation(extract_pick_operation);
converter.add_input_value(extract_pick_operation->get_input_socket(1), 1.0f);
converter.add_link(cryptomatte_operation->get_output_socket(0),

View File

@ -2,6 +2,7 @@
set(INC
.
./algorithms
../../blenkernel
../../blenlib
../../gpu
@ -53,6 +54,10 @@ set(SRC
COM_static_shader_manager.hh
COM_texture_pool.hh
COM_utilities.hh
algorithms/intern/algorithm_parallel_reduction.cc
algorithms/COM_algorithm_parallel_reduction.hh
)
set(LIB

View File

@ -0,0 +1,58 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_math_vec_types.hh"
#include "GPU_texture.h"
#include "COM_context.hh"
namespace blender::realtime_compositor {
/* --------------------------------------------------------------------
* Sum Reductions.
*/
/* Computes the sum of the red channel of all pixels in the given texture. */
float sum_red(Context &context, GPUTexture *texture);
/* Computes the sum of the green channel of all pixels in the given texture. */
float sum_green(Context &context, GPUTexture *texture);
/* Computes the sum of the blue channel of all pixels in the given texture. */
float sum_blue(Context &context, GPUTexture *texture);
/* Computes the sum of the luminance of all pixels in the given texture, using the given luminance
* coefficients to compute the luminance. */
float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients);
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
/* Computes the sum of the squared difference between the red channel of all pixels in the given
* texture and the given subtrahend. This can be used to compute the standard deviation if the
* given subtrahend is the mean. */
float sum_red_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
/* Computes the sum of the squared difference between the green channel of all pixels in the given
* texture and the given subtrahend. This can be used to compute the standard deviation if the
* given subtrahend is the mean. */
float sum_green_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
/* Computes the sum of the squared difference between the blue channel of all pixels in the given
* texture and the given subtrahend. This can be used to compute the standard deviation if the
* given subtrahend is the mean. */
float sum_blue_squared_difference(Context &context, GPUTexture *texture, float subtrahend);
/* Computes the sum of the squared difference between the luminance of all pixels in the given
* texture and the given subtrahend, using the given luminance coefficients to compute the
* luminance. This can be used to compute the standard deviation if the given subtrahend is the
* mean. */
float sum_luminance_squared_difference(Context &context,
GPUTexture *texture,
float3 luminance_coefficients,
float subtrahend);
} // namespace blender::realtime_compositor

View File

@ -0,0 +1,205 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_math_vec_types.hh"
#include "BLI_math_vector.hh"
#include "MEM_guardedalloc.h"
#include "GPU_compute.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "COM_context.hh"
#include "COM_utilities.hh"
#include "COM_algorithm_parallel_reduction.hh"
namespace blender::realtime_compositor {
/* Reduces the given texture into a single value and returns it. The return value should be freed
* by a call to MEM_freeN. The return value is either a pointer to a float, or a pointer to an
* array of floats that represents a vector. This depends on the given format, which should be
* compatible with the reduction shader.
*
* The given reduction shader should be bound when calling the function and the shader is expected
* to be derived from the compositor_parallel_reduction.glsl shader, see that file for more
* information. Also see the compositor_parallel_reduction_info.hh file for example shader
* definitions. */
static float *parallel_reduction_dispatch(Context &context,
GPUTexture *texture,
GPUShader *shader,
eGPUTextureFormat format)
{
GPU_shader_uniform_1b(shader, "is_initial_reduction", true);
GPUTexture *texture_to_reduce = texture;
int2 size_to_reduce = int2(GPU_texture_width(texture), GPU_texture_height(texture));
/* Dispatch the reduction shader until the texture reduces to a single pixel. */
while (size_to_reduce != int2(1)) {
const int2 reduced_size = math::divide_ceil(size_to_reduce, int2(16));
GPUTexture *reduced_texture = context.texture_pool().acquire(reduced_size, format);
GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH);
const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx");
GPU_texture_bind(texture_to_reduce, texture_image_unit);
const int image_unit = GPU_shader_get_texture_binding(shader, "output_img");
GPU_texture_image_bind(reduced_texture, image_unit);
GPU_compute_dispatch(shader, reduced_size.x, reduced_size.y, 1);
GPU_texture_image_unbind(reduced_texture);
GPU_texture_unbind(texture_to_reduce);
/* Release the input texture only if it is not the source texture, since the source texture is
* not acquired or owned by the function. */
if (texture_to_reduce != texture) {
context.texture_pool().release(texture_to_reduce);
}
texture_to_reduce = reduced_texture;
size_to_reduce = reduced_size;
GPU_shader_uniform_1b(shader, "is_initial_reduction", false);
}
GPU_memory_barrier(GPU_BARRIER_TEXTURE_UPDATE);
float *pixel = static_cast<float *>(GPU_texture_read(texture_to_reduce, GPU_DATA_FLOAT, 0));
/* Release the final texture only if it is not the source texture, since the source texture is
* not acquired or owned by the function. */
if (texture_to_reduce != texture) {
context.texture_pool().release(texture_to_reduce);
}
return pixel;
}
/* --------------------------------------------------------------------
* Sum Reductions.
*/
float sum_red(Context &context, GPUTexture *texture)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_red");
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_green(Context &context, GPUTexture *texture)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_green");
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_blue(Context &context, GPUTexture *texture)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_blue");
GPU_shader_bind(shader);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_luminance(Context &context, GPUTexture *texture, float3 luminance_coefficients)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_luminance");
GPU_shader_bind(shader);
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
/* --------------------------------------------------------------------
* Sum Of Squared Difference Reductions.
*/
float sum_red_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_red_squared_difference");
GPU_shader_bind(shader);
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_green_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_green_squared_difference");
GPU_shader_bind(shader);
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_blue_squared_difference(Context &context, GPUTexture *texture, float subtrahend)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_blue_squared_difference");
GPU_shader_bind(shader);
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
float sum_luminance_squared_difference(Context &context,
GPUTexture *texture,
float3 luminance_coefficients,
float subtrahend)
{
GPUShader *shader = context.shader_manager().get("compositor_sum_luminance_squared_difference");
GPU_shader_bind(shader);
GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
float *reduced_value = parallel_reduction_dispatch(context, texture, shader, GPU_R32F);
const float sum = *reduced_value;
MEM_freeN(reduced_value);
GPU_shader_unbind();
return sum;
}
} // namespace blender::realtime_compositor

View File

@ -77,7 +77,7 @@ set(SRC
intern/draw_cache_impl_particles.c
intern/draw_cache_impl_pointcloud.cc
intern/draw_cache_impl_subdivision.cc
intern/draw_cache_impl_volume.c
intern/draw_cache_impl_volume.cc
intern/draw_color_management.cc
intern/draw_command.cc
intern/draw_common.c

View File

@ -812,6 +812,10 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
if (ob->sculpt && ob->sculpt->pbvh) {
BKE_pbvh_is_drawing_set(ob->sculpt->pbvh, use_sculpt_pbvh);
}
/* First get materials for this mesh. */
if (ELEM(ob->type, OB_MESH, OB_SURF)) {
const int materials_len = DRW_cache_object_material_count_get(ob);

View File

@ -332,6 +332,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
offset++;
}
}
IMB_gpu_clamp_half_float(&extracted_buffer);
GPU_texture_update_sub(texture,
GPU_DATA_FLOAT,
@ -388,6 +389,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
}
BKE_image_release_ibuf(image, tile_buffer, lock);
}
IMB_gpu_clamp_half_float(&texture_buffer);
GPU_texture_update(info.texture, GPU_DATA_FLOAT, texture_buffer.rect_float);
imb_freerectImbuf_all(&texture_buffer);
}

View File

@ -60,8 +60,10 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
const bool draw_grid = is_uv_edit || !ED_space_image_has_buffer(sima);
if (background_enabled && draw_grid) {
grid_flag |= SHOW_GRID;
if (is_uv_edit && (sima->flag & SI_CUSTOM_GRID) != 0) {
grid_flag |= CUSTOM_GRID;
if (is_uv_edit) {
if (sima->grid_shape_source != SI_GRID_SHAPE_DYNAMIC) {
grid_flag |= CUSTOM_GRID;
}
}
}

View File

@ -7,7 +7,7 @@
* \brief Volume API for render engines
*/
#include <string.h>
#include <cstring>
#include "MEM_guardedalloc.h"
@ -39,7 +39,7 @@ static void volume_batch_cache_clear(Volume *volume);
/* ---------------------------------------------------------------------- */
/* Volume GPUBatch Cache */
typedef struct VolumeBatchCache {
struct VolumeBatchCache {
/* 3D textures */
ListBase grids;
@ -54,22 +54,22 @@ typedef struct VolumeBatchCache {
/* settings to determine if cache is invalid */
bool is_dirty;
} VolumeBatchCache;
};
/* GPUBatch cache management. */
static bool volume_batch_cache_valid(Volume *volume)
{
VolumeBatchCache *cache = volume->batch_cache;
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
return (cache && cache->is_dirty == false);
}
static void volume_batch_cache_init(Volume *volume)
{
VolumeBatchCache *cache = volume->batch_cache;
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
if (!cache) {
cache = volume->batch_cache = MEM_callocN(sizeof(*cache), __func__);
volume->batch_cache = cache = MEM_cnew<VolumeBatchCache>(__func__);
}
else {
memset(cache, 0, sizeof(*cache));
@ -89,13 +89,13 @@ void DRW_volume_batch_cache_validate(Volume *volume)
static VolumeBatchCache *volume_batch_cache_get(Volume *volume)
{
DRW_volume_batch_cache_validate(volume);
return volume->batch_cache;
return static_cast<VolumeBatchCache *>(volume->batch_cache);
}
void DRW_volume_batch_cache_dirty_tag(Volume *volume, int mode)
{
VolumeBatchCache *cache = volume->batch_cache;
if (cache == NULL) {
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
if (cache == nullptr) {
return;
}
switch (mode) {
@ -109,7 +109,7 @@ void DRW_volume_batch_cache_dirty_tag(Volume *volume, int mode)
static void volume_batch_cache_clear(Volume *volume)
{
VolumeBatchCache *cache = volume->batch_cache;
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
if (!cache) {
return;
}
@ -130,18 +130,18 @@ void DRW_volume_batch_cache_free(Volume *volume)
volume_batch_cache_clear(volume);
MEM_SAFE_FREE(volume->batch_cache);
}
typedef struct VolumeWireframeUserData {
struct VolumeWireframeUserData {
Volume *volume;
Scene *scene;
} VolumeWireframeUserData;
};
static void drw_volume_wireframe_cb(
void *userdata, const float (*verts)[3], const int (*edges)[2], int totvert, int totedge)
{
VolumeWireframeUserData *data = userdata;
VolumeWireframeUserData *data = static_cast<VolumeWireframeUserData *>(userdata);
Scene *scene = data->scene;
Volume *volume = data->volume;
VolumeBatchCache *cache = volume->batch_cache;
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
GPU_use_hq_normals_workaround();
@ -181,7 +181,7 @@ static void drw_volume_wireframe_cb(
if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) {
/* Create batch. */
cache->face_wire.batch = GPU_batch_create(
GPU_PRIM_POINTS, cache->face_wire.pos_nor_in_order, NULL);
GPU_PRIM_POINTS, cache->face_wire.pos_nor_in_order, nullptr);
}
else {
/* Create edge index buffer. */
@ -203,15 +203,15 @@ static void drw_volume_wireframe_cb(
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
{
if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) {
return NULL;
return nullptr;
}
VolumeBatchCache *cache = volume_batch_cache_get(volume);
if (cache->face_wire.batch == NULL) {
if (cache->face_wire.batch == nullptr) {
const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
if (volume_grid == NULL) {
return NULL;
if (volume_grid == nullptr) {
return nullptr;
}
/* Create wireframe from OpenVDB tree. */
@ -228,8 +228,8 @@ GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
static void drw_volume_selection_surface_cb(
void *userdata, float (*verts)[3], int (*tris)[3], int totvert, int tottris)
{
Volume *volume = userdata;
VolumeBatchCache *cache = volume->batch_cache;
Volume *volume = static_cast<Volume *>(userdata);
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
static GPUVertFormat format = {0};
static uint pos_id;
@ -257,10 +257,10 @@ static void drw_volume_selection_surface_cb(
GPUBatch *DRW_volume_batch_cache_get_selection_surface(Volume *volume)
{
VolumeBatchCache *cache = volume_batch_cache_get(volume);
if (cache->selection_surface == NULL) {
if (cache->selection_surface == nullptr) {
const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
if (volume_grid == NULL) {
return NULL;
if (volume_grid == nullptr) {
return nullptr;
}
BKE_volume_grid_selection_surface(
volume, volume_grid, drw_volume_selection_surface_cb, volume);
@ -275,15 +275,14 @@ static DRWVolumeGrid *volume_grid_cache_get(const Volume *volume,
const char *name = BKE_volume_grid_name(grid);
/* Return cached grid. */
DRWVolumeGrid *cache_grid;
for (cache_grid = cache->grids.first; cache_grid; cache_grid = cache_grid->next) {
LISTBASE_FOREACH (DRWVolumeGrid *, cache_grid, &cache->grids) {
if (STREQ(cache_grid->name, name)) {
return cache_grid;
}
}
/* Allocate new grid. */
cache_grid = MEM_callocN(sizeof(DRWVolumeGrid), __func__);
DRWVolumeGrid *cache_grid = MEM_cnew<DRWVolumeGrid>(__func__);
cache_grid->name = BLI_strdup(name);
BLI_addtail(&cache->grids, cache_grid);
@ -316,7 +315,7 @@ static DRWVolumeGrid *volume_grid_cache_get(const Volume *volume,
dense_grid.voxels);
/* The texture can be null if the resolution along one axis is larger than
* GL_MAX_3D_TEXTURE_SIZE. */
if (cache_grid->texture != NULL) {
if (cache_grid->texture != nullptr) {
GPU_texture_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
GPU_texture_wrap_mode(cache_grid->texture, false, false);
BKE_volume_dense_float_grid_clear(&dense_grid);
@ -339,7 +338,7 @@ DRWVolumeGrid *DRW_volume_batch_cache_get_grid(Volume *volume, const VolumeGrid
{
VolumeBatchCache *cache = volume_batch_cache_get(volume);
DRWVolumeGrid *grid = volume_grid_cache_get(volume, volume_grid, cache);
return (grid->texture != NULL) ? grid : NULL;
return (grid->texture != nullptr) ? grid : nullptr;
}
int DRW_volume_material_count_get(Volume *volume)

View File

@ -1158,8 +1158,17 @@ struct PBVHBatches {
}
for (PBVHBatch &batch : batches.values()) {
GPU_batch_elembuf_set(batch.tris, tri_index, false);
GPU_batch_elembuf_set(batch.lines, lines_index, false);
if (tri_index) {
GPU_batch_elembuf_set(batch.tris, tri_index, false);
}
else {
/* Still flag the batch as dirty even if we're using the default index layout. */
batch.tris->flag |= GPU_BATCH_DIRTY;
}
if (lines_index) {
GPU_batch_elembuf_set(batch.lines, lines_index, false);
}
}
}

View File

@ -623,6 +623,7 @@ void GPENCIL_OT_layer_duplicate_object(wmOperatorType *ot)
true,
"Only Active",
"Copy only active Layer, uncheck to append all layers");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_GPENCIL);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@ -3686,6 +3687,7 @@ void GPENCIL_OT_materials_copy_to_object(wmOperatorType *ot)
true,
"Only Active",
"Append only active material, uncheck to append all materials");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_GPENCIL);
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}

View File

@ -87,17 +87,6 @@ void ED_node_tag_update_id(struct ID *id);
float ED_node_grid_size(void);
/* node_relationships.cc */
/**
* Test == 0, clear all intersect flags.
*/
void ED_node_link_intersect_test(struct ScrArea *area, int test);
/**
* Assumes link with #NODE_LINKFLAG_HILITE set.
*/
void ED_node_link_insert(struct Main *bmain, struct ScrArea *area);
/* node_edit.cc */
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
@ -186,3 +175,20 @@ bool ED_space_node_color_sample(struct Main *bmain,
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
/* node_relationships.cc */
namespace blender::ed::space_node {
void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion &region);
/**
* Assumes link with #NODE_LINKFLAG_HILITE set.
*/
void node_insert_on_link_flags(Main &bmain, SpaceNode &snode);
void node_insert_on_link_flags_clear(bNodeTree &node_tree);
} // namespace blender::ed::space_node
#endif

View File

@ -339,12 +339,20 @@ bool ED_uvedit_udim_params_from_image_space(const struct SpaceImage *sima,
bool use_active,
struct UVMapUDIM_Params *udim_params);
typedef enum {
ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */
ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */
ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */
} eUVPackIsland_MarginMethod;
struct UVPackIsland_Params {
uint rotate : 1;
uint only_selected_uvs : 1;
uint only_selected_faces : 1;
uint use_seams : 1;
uint correct_aspect : 1;
eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */
float margin; /* Additional space to add around each island. */
};
/**

View File

@ -89,7 +89,7 @@ static void ui_drop_material_copy(bContext * /*C*/, wmDrag *drag, wmDropBox *dro
static char *ui_drop_material_tooltip(bContext *C,
wmDrag *drag,
const int UNUSED(xy[2]),
const int /*xy*/[2],
struct wmDropBox * /*drop*/)
{
PointerRNA rna_ptr = CTX_data_pointer_get_type(C, "object", &RNA_Object);

View File

@ -222,7 +222,7 @@ int UI_pie_menu_invoke(struct bContext *C, const char *idname, const wmEvent *ev
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
pie = UI_pie_menu_begin(C, IFACE_(mt->label), ICON_NONE, event);
pie = UI_pie_menu_begin(C, CTX_IFACE_(mt->translation_context, mt->label), ICON_NONE, event);
layout = UI_pie_menu_layout(pie);
UI_menutype_draw(C, mt, layout);

View File

@ -559,7 +559,7 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
pup = UI_popup_menu_begin(C, IFACE_(mt->label), ICON_NONE);
pup = UI_popup_menu_begin(C, CTX_IFACE_(mt->translation_context, mt->label), ICON_NONE);
layout = UI_popup_menu_layout(pup);
UI_menutype_draw(C, mt, layout);

View File

@ -3269,7 +3269,7 @@ void uiTemplatePreview(uiLayout *layout,
uiDefButS(block,
UI_BTYPE_ROW,
B_MATPRV,
IFACE_("World"),
CTX_IFACE_(BLT_I18NCONTEXT_ID_WORLD, "World"),
0,
0,
UI_UNIT_X * 10,

View File

@ -658,7 +658,7 @@ void WM_OT_alembic_import(wmOperatorType *ot)
ot->name = "Import Alembic";
ot->description = "Load an Alembic archive";
ot->idname = "WM_OT_alembic_import";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
ot->invoke = wm_alembic_import_invoke;
ot->exec = wm_alembic_import_exec;

View File

@ -770,14 +770,12 @@ void WM_OT_collada_import(wmOperatorType *ot)
ot->name = "Import COLLADA";
ot->description = "Load a Collada file";
ot->idname = "WM_OT_collada_import";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
ot->invoke = WM_operator_filesel;
ot->exec = wm_collada_import_exec;
ot->poll = WM_operator_winactive;
// ot->flag = OPTYPE_PRESET;
ot->ui = wm_collada_import_draw;
WM_operator_properties_filesel(ot,

View File

@ -492,7 +492,7 @@ void WM_OT_obj_import(struct wmOperatorType *ot)
ot->name = "Import Wavefront OBJ";
ot->description = "Load a Wavefront OBJ scene";
ot->idname = "WM_OT_obj_import";
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
ot->invoke = wm_obj_import_invoke;
ot->exec = wm_obj_import_exec;

View File

@ -95,7 +95,7 @@ void WM_OT_stl_import(struct wmOperatorType *ot)
ot->exec = wm_stl_import_execute;
ot->poll = WM_operator_winactive;
ot->check = wm_stl_import_check;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER,

View File

@ -500,7 +500,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
ot->poll = WM_operator_winactive;
ot->ui = wm_usd_import_draw;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_PRESET;
WM_operator_properties_filesel(ot,
FILE_TYPE_FOLDER | FILE_TYPE_USD,

View File

@ -100,7 +100,7 @@ typedef struct KnifeColors {
/* Knife-tool Operator. */
typedef struct KnifeVert {
Object *ob;
uint base_index;
uint ob_index;
BMVert *v; /* Non-NULL if this is an original vert. */
ListBase edges;
ListBase faces;
@ -142,7 +142,7 @@ typedef struct KnifeLineHit {
KnifeVert *v;
BMFace *f;
Object *ob;
uint base_index;
uint ob_index;
} KnifeLineHit;
typedef struct KnifePosData {
@ -156,7 +156,7 @@ typedef struct KnifePosData {
KnifeEdge *edge;
BMFace *bmface;
Object *ob; /* Object of the vert, edge or bmface. */
uint base_index;
uint ob_index;
/* When true, the cursor isn't over a face. */
bool is_space;
@ -182,7 +182,7 @@ typedef struct KnifeBVH {
BVHTree *tree; /* Knife Custom BVH Tree. */
BMLoop *(*looptris)[3]; /* Used by #knife_bvh_raycast_cb to store the intersecting looptri. */
float uv[2]; /* Used by #knife_bvh_raycast_cb to store the intersecting uv. */
uint base_index;
uint ob_index;
/* Use #bm_ray_cast_cb_elem_not_in_face_check. */
bool (*filter_cb)(BMFace *f, void *userdata);
@ -218,6 +218,7 @@ typedef struct KnifeTool_OpData {
/* Used for swapping current object when in multi-object edit mode. */
Object **objects;
uint objects_len;
bool objects_free;
/** Array `objects_len` length of additional per-object data. */
KnifeObjectInfo *objects_info;
@ -1158,11 +1159,11 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
* \{ */
static const int *knife_bm_tri_index_get(const KnifeTool_OpData *kcd,
int base_index,
int ob_index,
int tri_index,
int tri_index_buf[3])
{
const KnifeObjectInfo *obinfo = &kcd->objects_info[base_index];
const KnifeObjectInfo *obinfo = &kcd->objects_info[ob_index];
if (obinfo->tri_indices) {
return obinfo->tri_indices[tri_index];
}
@ -1173,25 +1174,25 @@ static const int *knife_bm_tri_index_get(const KnifeTool_OpData *kcd,
}
static void knife_bm_tri_cagecos_get(const KnifeTool_OpData *kcd,
int base_index,
int ob_index,
int tri_index,
float cos[3][3])
{
const KnifeObjectInfo *obinfo = &kcd->objects_info[base_index];
const KnifeObjectInfo *obinfo = &kcd->objects_info[ob_index];
int tri_ind_buf[3];
const int *tri_ind = knife_bm_tri_index_get(kcd, base_index, tri_index, tri_ind_buf);
const int *tri_ind = knife_bm_tri_index_get(kcd, ob_index, tri_index, tri_ind_buf);
for (int i = 0; i < 3; i++) {
copy_v3_v3(cos[i], obinfo->cagecos[tri_ind[i]]);
}
}
static void knife_bm_tri_cagecos_get_worldspace(const KnifeTool_OpData *kcd,
int base_index,
int ob_index,
int tri_index,
float cos[3][3])
{
knife_bm_tri_cagecos_get(kcd, base_index, tri_index, cos);
const Object *ob = kcd->objects[base_index];
knife_bm_tri_cagecos_get(kcd, ob_index, tri_index, cos);
const Object *ob = kcd->objects[ob_index];
for (int i = 0; i < 3; i++) {
mul_m4_v3(ob->obmat, cos[i]);
}
@ -1236,9 +1237,9 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
bool test_fn_ret = false;
/* Calculate tottri. */
for (uint b = 0; b < kcd->objects_len; b++) {
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
ob_tottri = 0;
ob = kcd->objects[b];
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
for (int i = 0; i < em->tottri; i++) {
@ -1268,8 +1269,8 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
* Don't forget to update #knife_bvh_intersect_plane!
*/
tottri = 0;
for (uint b = 0; b < kcd->objects_len; b++) {
ob = kcd->objects[b];
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
looptris = em->looptris;
@ -1286,7 +1287,7 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
}
float tri_cos[3][3];
knife_bm_tri_cagecos_get_worldspace(kcd, b, i, tri_cos);
knife_bm_tri_cagecos_get_worldspace(kcd, ob_index, i, tri_cos);
BLI_bvhtree_insert(kcd->bvh.tree, i + tottri, &tri_cos[0][0], 3);
}
@ -1324,10 +1325,10 @@ static void knife_bvh_raycast_cb(void *userdata,
int tottri;
tottri = 0;
uint b = 0;
for (; b < kcd->objects_len; b++) {
uint ob_index = 0;
for (; ob_index < kcd->objects_len; ob_index++) {
index -= tottri;
ob = kcd->objects[b];
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
tottri = em->tottri;
if (index < tottri) {
@ -1343,7 +1344,7 @@ static void knife_bvh_raycast_cb(void *userdata,
}
float tri_cos[3][3];
knife_bm_tri_cagecos_get_worldspace(kcd, b, index, tri_cos);
knife_bm_tri_cagecos_get_worldspace(kcd, ob_index, index, tri_cos);
isect = (ray->radius > 0.0f ?
isect_ray_tri_epsilon_v3(
ray->origin, ray->direction, UNPACK3(tri_cos), &dist, uv, ray->radius) :
@ -1370,7 +1371,7 @@ static void knife_bvh_raycast_cb(void *userdata,
kcd->bvh.looptris = em->looptris;
copy_v2_v2(kcd->bvh.uv, uv);
kcd->bvh.base_index = b;
kcd->bvh.ob_index = ob_index;
}
}
@ -1382,7 +1383,7 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
float *r_dist,
float r_hitout[3],
float r_cagehit[3],
uint *r_base_index)
uint *r_ob_index)
{
BMFace *face;
BVHTreeRayHit hit;
@ -1399,7 +1400,7 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
/* Hits returned in world space. */
if (r_hitout) {
float tri_cos[3][3];
knife_bm_tri_cagecos_get_worldspace(kcd, kcd->bvh.base_index, hit.index, tri_cos);
knife_bm_tri_cagecos_get_worldspace(kcd, kcd->bvh.ob_index, hit.index, tri_cos);
interp_v3_v3v3v3_uv(r_hitout, UNPACK3(tri_cos), kcd->bvh.uv);
if (r_cagehit) {
@ -1411,8 +1412,8 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
*r_dist = hit.dist;
}
if (r_base_index) {
*r_base_index = kcd->bvh.base_index;
if (r_ob_index) {
*r_ob_index = kcd->bvh.ob_index;
}
return face;
@ -1428,7 +1429,7 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
float *r_dist,
float r_hitout[3],
float r_cagehit[3],
uint *r_base_index,
uint *r_ob_index,
bool (*filter_cb)(BMFace *f, void *userdata),
void *filter_userdata)
{
@ -1453,7 +1454,7 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
/* Hits returned in world space. */
if (r_hitout) {
float tri_cos[3][3];
knife_bm_tri_cagecos_get_worldspace(kcd, kcd->bvh.base_index, hit.index, tri_cos);
knife_bm_tri_cagecos_get_worldspace(kcd, kcd->bvh.ob_index, hit.index, tri_cos);
interp_v3_v3v3v3_uv(r_hitout, UNPACK3(tri_cos), kcd->bvh.uv);
if (r_cagehit) {
@ -1465,8 +1466,8 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
*r_dist = hit.dist;
}
if (r_base_index) {
*r_base_index = kcd->bvh.base_index;
if (r_ob_index) {
*r_ob_index = kcd->bvh.ob_index;
}
return face;
@ -1726,7 +1727,7 @@ static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd)
}
/* Get a KnifeVert wrapper for an existing BMVert. */
static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob, uint base_index)
static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob, uint ob_index)
{
KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
const float *cageco;
@ -1736,7 +1737,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob
BMFace *f;
if (BM_elem_index_get(v) >= 0) {
cageco = kcd->objects_info[base_index].cagecos[BM_elem_index_get(v)];
cageco = kcd->objects_info[ob_index].cagecos[BM_elem_index_get(v)];
}
else {
cageco = v->co;
@ -1748,7 +1749,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob
kfv = new_knife_vert(kcd, v->co, cageco_ws);
kfv->v = v;
kfv->ob = ob;
kfv->base_index = base_index;
kfv->ob_index = ob_index;
BLI_ghash_insert(kcd->origvertmap, v, kfv);
BM_ITER_ELEM (f, &bmiter, v, BM_FACES_OF_VERT) {
@ -1760,7 +1761,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob
}
/* Get a KnifeEdge wrapper for an existing BMEdge. */
static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e, Object *ob, uint base_index)
static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e, Object *ob, uint ob_index)
{
KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
if (!kfe) {
@ -1769,8 +1770,8 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e, Object *ob
kfe = new_knife_edge(kcd);
kfe->e = e;
kfe->v1 = get_bm_knife_vert(kcd, e->v1, ob, base_index);
kfe->v2 = get_bm_knife_vert(kcd, e->v2, ob, base_index);
kfe->v1 = get_bm_knife_vert(kcd, e->v1, ob, ob_index);
kfe->v2 = get_bm_knife_vert(kcd, e->v2, ob, ob_index);
knife_add_to_vert_edges(kcd, kfe);
@ -1784,10 +1785,7 @@ static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e, Object *ob
return kfe;
}
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd,
Object *ob,
uint base_index,
BMFace *f)
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, Object *ob, uint ob_index, BMFace *f)
{
ListBase *list = BLI_ghash_lookup(kcd->kedgefacemap, f);
@ -1798,7 +1796,7 @@ static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd,
list = knife_empty_list(kcd);
BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
knife_append_list(kcd, list, get_bm_knife_edge(kcd, e, ob, base_index));
knife_append_list(kcd, list, get_bm_knife_edge(kcd, e, ob, ob_index));
}
BLI_ghash_insert(kcd->kedgefacemap, f, list);
@ -1809,7 +1807,7 @@ static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd,
static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f)
{
knife_append_list(kcd, knife_get_face_kedges(kcd, kfe->v1->ob, kfe->v1->base_index, f), kfe);
knife_append_list(kcd, knife_get_face_kedges(kcd, kfe->v1->ob, kfe->v1->ob_index, f), kfe);
knife_append_list(kcd, &kfe->faces, f);
}
@ -1826,7 +1824,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd,
newkfe->v1 = kfe->v1;
newkfe->v2 = new_knife_vert(kcd, co, cageco);
newkfe->v2->ob = kfe->v1->ob;
newkfe->v2->base_index = kfe->v1->base_index;
newkfe->v2->ob_index = kfe->v1->ob_index;
newkfe->v2->is_cut = true;
if (kfe->e) {
knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
@ -2123,7 +2121,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd,
BLI_assert(lh1->f);
kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
kfe->v1->ob = lh1->ob;
kfe->v1->base_index = lh1->base_index;
kfe->v1->ob_index = lh1->ob_index;
kfe->v1->is_cut = true;
kfe->v1->is_face = true;
knife_append_list(kcd, &kfe->v1->faces, lh1->f);
@ -2141,7 +2139,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd,
BLI_assert(lh2->f);
kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
kfe->v2->ob = lh2->ob;
kfe->v2->base_index = lh2->base_index;
kfe->v2->ob_index = lh2->ob_index;
kfe->v2->is_cut = true;
kfe->v2->is_face = true;
knife_append_list(kcd, &kfe->v2->faces, lh2->f);
@ -2567,7 +2565,7 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
const float v1[3],
const float v2[3],
Object *ob,
uint base_index,
uint ob_index,
BMFace *f,
const float face_tol_sq,
float hit_co[3],
@ -2600,7 +2598,7 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
break;
}
knife_bm_tri_cagecos_get_worldspace(kcd, base_index, tri_i, tri_cos);
knife_bm_tri_cagecos_get_worldspace(kcd, ob_index, tri_i, tri_cos);
/* Using epsilon test in case ray is directly through an internal
* tessellation edge and might not hit either tessellation tri with
@ -2617,7 +2615,7 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
}
interp_v3_v3v3v3_uv(hit_cageco, UNPACK3(tri_cos), ray_tri_uv);
/* Now check that far enough away from verts and edges. */
list = knife_get_face_kedges(kcd, ob, base_index, f);
list = knife_get_face_kedges(kcd, ob, ob_index, f);
for (ref = list->first; ref; ref = ref->next) {
kfe = ref->ref;
if (kfe->is_invalid) {
@ -2651,11 +2649,11 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
float ws[3];
INIT_MINMAX(min, max);
for (uint b = 0; b < kcd->objects_len; b++) {
ob = kcd->objects[b];
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
const float(*cagecos)[3] = kcd->objects_info[b].cagecos;
const float(*cagecos)[3] = kcd->objects_info[ob_index].cagecos;
if (cagecos) {
for (int i = 0; i < em->bm->totvert; i++) {
copy_v3_v3(ws, cagecos[i]);
@ -2930,11 +2928,11 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
Object *ob;
BMEditMesh *em;
uint b = 0;
for (i = 0, result = results; i < tot; i++, result++) {
for (b = 0; b < kcd->objects_len; b++) {
ob = kcd->objects[b];
uint ob_index = 0;
for (ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
if (*result >= 0 && *result < em->tottri) {
ls = (BMLoop **)em->looptris[*result];
@ -2956,9 +2954,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
/* Don't care what the value is except that it is non-NULL, for iterator. */
BLI_smallhash_insert(&faces, (uintptr_t)f, f);
BLI_smallhash_insert(&fobs, (uintptr_t)f, (void *)(uintptr_t)b);
BLI_smallhash_insert(&fobs, (uintptr_t)f, (void *)(uintptr_t)ob_index);
list = knife_get_face_kedges(kcd, ob, b, f);
list = knife_get_face_kedges(kcd, ob, ob_index, f);
for (ref = list->first; ref; ref = ref->next) {
kfe = ref->ref;
if (kfe->is_invalid) {
@ -3033,7 +3031,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
hit.ob = v->ob;
hit.base_index = v->base_index;
hit.ob_index = v->ob_index;
copy_v3_v3(hit.hit, v->co);
copy_v3_v3(hit.cagehit, v->cageco);
copy_v2_v2(hit.schit, s);
@ -3109,7 +3107,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
transform_point_by_seg_v3(
hit.hit, p_cage, kfe->v1->co, kfe->v2->co, kfe->v1->cageco, kfe->v2->cageco);
hit.ob = kfe->v1->ob;
hit.base_index = kfe->v1->base_index;
hit.ob_index = kfe->v1->ob_index;
copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, sint);
hit.perc = lambda;
@ -3129,16 +3127,16 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
float p[3], p_cage[3];
uint base_index = (uint)(uintptr_t)BLI_smallhash_lookup(&fobs, (uintptr_t)f);
ob = kcd->objects[base_index];
uint ob_index = (uint)(uintptr_t)BLI_smallhash_lookup(&fobs, (uintptr_t)f);
ob = kcd->objects[ob_index];
if (use_hit_prev &&
knife_ray_intersect_face(kcd, s1, v1, v3, ob, base_index, f, face_tol_sq, p, p_cage)) {
knife_ray_intersect_face(kcd, s1, v1, v3, ob, ob_index, f, face_tol_sq, p, p_cage)) {
if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
hit.ob = ob;
hit.base_index = base_index;
hit.ob_index = ob_index;
copy_v3_v3(hit.hit, p);
copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, s1);
@ -3148,12 +3146,12 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
if (use_hit_curr &&
knife_ray_intersect_face(kcd, s2, v2, v4, ob, base_index, f, face_tol_sq, p, p_cage)) {
knife_ray_intersect_face(kcd, s2, v2, v4, ob, ob_index, f, face_tol_sq, p, p_cage)) {
if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
hit.ob = ob;
hit.base_index = base_index;
hit.ob_index = ob_index;
copy_v3_v3(hit.hit, p);
copy_v3_v3(hit.cagehit, p_cage);
copy_v2_v2(hit.schit, s2);
@ -3205,7 +3203,7 @@ static void knife_pos_data_clear(KnifePosData *kpd)
static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
Object **r_ob,
uint *r_base_index,
uint *r_ob_index,
bool *is_space,
float r_co[3],
float r_cageco[3])
@ -3221,7 +3219,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
sub_v3_v3v3(ray, origin_ofs, origin);
normalize_v3_v3(ray_normal, ray);
f = knife_bvh_raycast(kcd, origin, ray_normal, 0.0f, NULL, r_co, r_cageco, r_base_index);
f = knife_bvh_raycast(kcd, origin, ray_normal, 0.0f, NULL, r_co, r_cageco, r_ob_index);
if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
f = NULL;
@ -3232,7 +3230,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
}
if (f) {
*r_ob = kcd->objects[*r_base_index];
*r_ob = kcd->objects[*r_ob_index];
}
else {
if (kcd->is_interactive) {
@ -3267,7 +3265,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
static int knife_sample_screen_density_from_closest_face(KnifeTool_OpData *kcd,
const float radius,
Object *ob,
uint base_index,
uint ob_index,
BMFace *f,
const float cageco[3])
{
@ -3280,7 +3278,7 @@ static int knife_sample_screen_density_from_closest_face(KnifeTool_OpData *kcd,
knife_project_v2(kcd, cageco, sco);
list = knife_get_face_kedges(kcd, ob, base_index, f);
list = knife_get_face_kedges(kcd, ob, ob_index, f);
for (ref = list->first; ref; ref = ref->next) {
KnifeEdge *kfe = ref->ref;
int i;
@ -3329,7 +3327,7 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
if (!kcd->curr.is_space) {
density = (float)knife_sample_screen_density_from_closest_face(
kcd, maxsize * 2.0f, kcd->curr.ob, kcd->curr.base_index, kcd->curr.bmface, kcd->curr.cage);
kcd, maxsize * 2.0f, kcd->curr.ob, kcd->curr.ob_index, kcd->curr.bmface, kcd->curr.cage);
}
return density ? min_ff(maxsize / ((float)density * 0.5f), maxsize) : maxsize;
@ -3388,7 +3386,7 @@ static void knife_interp_v3_v3v3(const KnifeTool_OpData *kcd,
/* p is closest point on edge to the mouse cursor. */
static KnifeEdge *knife_find_closest_edge_of_face(
KnifeTool_OpData *kcd, Object *ob, uint base_index, BMFace *f, float p[3], float cagep[3])
KnifeTool_OpData *kcd, Object *ob, uint ob_index, BMFace *f, float p[3], float cagep[3])
{
float sco[2];
float maxdist;
@ -3414,7 +3412,7 @@ static KnifeEdge *knife_find_closest_edge_of_face(
knife_project_v2(kcd, cagep, sco);
/* Look through all edges associated with this face. */
list = knife_get_face_kedges(kcd, ob, base_index, f);
list = knife_get_face_kedges(kcd, ob, ob_index, f);
for (ref = list->first; ref; ref = ref->next) {
KnifeEdge *kfe = ref->ref;
float kfv1_sco[2], kfv2_sco[2], test_cagep[3];
@ -3479,7 +3477,7 @@ static KnifeEdge *knife_find_closest_edge_of_face(
* this is important for angle snap, which uses the previous mouse position. */
edgesnap = new_knife_vert(kcd, p, cagep);
edgesnap->ob = ob;
edgesnap->base_index = base_index;
edgesnap->ob_index = ob_index;
knife_project_v2(kcd, edgesnap->cageco, kcd->curr.mval);
}
@ -3906,14 +3904,14 @@ static bool knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[
kcd->curr.ob = kcd->vc.obedit;
kcd->curr.bmface = knife_find_closest_face(kcd,
&kcd->curr.ob,
&kcd->curr.base_index,
&kcd->curr.ob_index,
&kcd->curr.is_space,
kcd->curr.co,
kcd->curr.cage);
if (kcd->curr.bmface) {
kcd->curr.edge = knife_find_closest_edge_of_face(
kcd, kcd->curr.ob, kcd->curr.base_index, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage);
kcd, kcd->curr.ob, kcd->curr.ob_index, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage);
}
if (kcd->curr.edge) {
@ -4017,7 +4015,7 @@ static void knifetool_undo(KnifeTool_OpData *kcd)
static void knifetool_init_obinfo(KnifeTool_OpData *kcd,
Object *ob,
uint base_index,
uint ob_index,
bool use_tri_indices)
{
@ -4027,7 +4025,7 @@ static void knifetool_init_obinfo(KnifeTool_OpData *kcd,
BM_mesh_elem_index_ensure(em_eval->bm, BM_VERT);
KnifeObjectInfo *obinfo = &kcd->objects_info[base_index];
KnifeObjectInfo *obinfo = &kcd->objects_info[ob_index];
obinfo->em = em_eval;
obinfo->cagecos = (const float(*)[3])BKE_editmesh_vert_coords_alloc(
kcd->vc.depsgraph, em_eval, scene_eval, obedit_eval, NULL);
@ -4045,10 +4043,10 @@ static void knifetool_init_obinfo(KnifeTool_OpData *kcd,
}
}
static void knifetool_free_obinfo(KnifeTool_OpData *kcd, uint base_index)
static void knifetool_free_obinfo(KnifeTool_OpData *kcd, uint ob_index)
{
MEM_SAFE_FREE(kcd->objects_info[base_index].cagecos);
MEM_SAFE_FREE(kcd->objects_info[base_index].tri_indices);
MEM_SAFE_FREE(kcd->objects_info[ob_index].cagecos);
MEM_SAFE_FREE(kcd->objects_info[ob_index].tri_indices);
}
/** \} */
@ -4081,6 +4079,8 @@ static void knife_init_colors(KnifeColors *colors)
/* called when modal loop selection gets set up... */
static void knifetool_init(ViewContext *vc,
KnifeTool_OpData *kcd,
Object **objects,
const int objects_len,
const bool only_select,
const bool cut_through,
const bool xray,
@ -4101,16 +4101,24 @@ static void knifetool_init(ViewContext *vc,
kcd->scene = scene;
kcd->region = vc->region;
kcd->objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
vc->scene, vc->view_layer, vc->v3d, &kcd->objects_len);
if (objects) {
kcd->objects = objects;
kcd->objects_len = objects_len;
kcd->objects_free = false;
}
else {
kcd->objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
vc->scene, vc->view_layer, vc->v3d, &kcd->objects_len);
kcd->objects_free = true;
}
Object *ob;
BMEditMesh *em;
kcd->objects_info = MEM_callocN(sizeof(*kcd->objects_info) * kcd->objects_len, "knife cagecos");
for (uint b = 0; b < kcd->objects_len; b++) {
ob = kcd->objects[b];
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
ob = kcd->objects[ob_index];
em = BKE_editmesh_from_object(ob);
knifetool_init_obinfo(kcd, ob, b, use_tri_indices);
knifetool_init_obinfo(kcd, ob, ob_index, use_tri_indices);
/* Can't usefully select resulting edges in face mode. */
kcd->select_result = (em->selectmode != SCE_SELECT_FACE);
@ -4225,7 +4233,9 @@ static void knifetool_exit_ex(KnifeTool_OpData *kcd)
}
/* Free object bases. */
MEM_freeN(kcd->objects);
if (kcd->objects_free) {
MEM_freeN(kcd->objects);
}
/* Destroy kcd itself. */
MEM_freeN(kcd);
@ -4318,9 +4328,15 @@ static void knifetool_finish_single_post(KnifeTool_OpData *UNUSED(kcd), Object *
/* Called on tool confirmation. */
static void knifetool_finish_ex(KnifeTool_OpData *kcd)
{
for (uint b = 0; b < kcd->objects_len; b++) {
Object *ob = kcd->objects[b];
/* Separate pre/post passes are needed because `em->looptris` recalculation from the 'post' pass
* causes causes triangle indices in #KnifeTool_OpData.bvh to get out of sync.
* So perform all the cuts before doing any mesh recalculation, see: T101721. */
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
Object *ob = kcd->objects[ob_index];
knifetool_finish_single_pre(kcd, ob);
}
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
Object *ob = kcd->objects[ob_index];
knifetool_finish_single_post(kcd, ob);
}
}
@ -4789,6 +4805,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
knifetool_init(&vc,
kcd,
NULL,
0,
only_select,
cut_through,
xray,
@ -4802,8 +4820,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
BMEditMesh *em;
bool faces_selected = false;
for (uint b = 0; b < kcd->objects_len; b++) {
obedit = kcd->objects[b];
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
obedit = kcd->objects[ob_index];
em = BKE_editmesh_from_object(obedit);
if (em->bm->totfacesel != 0) {
faces_selected = true;
@ -4942,7 +4960,12 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
return false;
}
void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_through)
void EDBM_mesh_knife(ViewContext *vc,
Object **objects,
const int objects_len,
LinkNode *polys,
bool use_tag,
bool cut_through)
{
KnifeTool_OpData *kcd;
@ -4959,6 +4982,8 @@ void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_th
knifetool_init(vc,
kcd,
objects,
objects_len,
only_select,
cut_through,
xray,
@ -5000,18 +5025,21 @@ void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_th
/* Finish. */
{
Object *ob;
BMEditMesh *em;
for (uint b = 0; b < kcd->objects_len; b++) {
ob = kcd->objects[b];
em = BKE_editmesh_from_object(ob);
/* See #knifetool_finish_ex for why multiple passes are needed. */
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
Object *ob = kcd->objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(ob);
if (use_tag) {
BM_mesh_elem_hflag_enable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
}
knifetool_finish_single_pre(kcd, ob);
}
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
Object *ob = kcd->objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(ob);
/* Tag faces inside! */
if (use_tag) {
@ -5104,9 +5132,12 @@ void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_th
#undef F_ISECT_SET_UNKNOWN
#undef F_ISECT_SET_OUTSIDE
}
}
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
/* Defer freeing data until the BVH tree is finished with, see: #point_is_visible and
* the doc-string for #knifetool_finish_single_post. */
Object *ob = kcd->objects[ob_index];
knifetool_finish_single_post(kcd, ob);
}

View File

@ -132,22 +132,21 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
ViewContext vc;
em_setup_viewcontext(C, &vc);
/* TODO: Ideally meshes would occlude each other, currently they don't
* since each knife-project runs as a separate operation. */
uint objects_len;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
vc.scene, vc.view_layer, vc.v3d, &objects_len);
EDBM_mesh_knife(&vc, objects, objects_len, polys, true, cut_through);
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
ED_view3d_viewcontext_init_object(&vc, obedit);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
EDBM_mesh_knife(&vc, polys, true, cut_through);
/* select only tagged faces */
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
EDBM_selectmode_disable_multi(C, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
EDBM_selectmode_disable(scene, em, SCE_SELECT_VERTEX, SCE_SELECT_EDGE);
BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG);

View File

@ -231,7 +231,7 @@ static void um_arraystore_cd_compact(CustomData *cdata,
}
bcd->states[i] = BLI_array_store_state_add(
bs, layer->data, (size_t)data_len * stride, state_reference);
bs, layer->data, size_t(data_len) * stride, state_reference);
}
else {
bcd->states[i] = nullptr;
@ -334,7 +334,7 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool
um_ref->store.keyblocks[i] :
nullptr;
um->store.keyblocks[i] = BLI_array_store_state_add(
bs, keyblock->data, (size_t)keyblock->totelem * stride, state_reference);
bs, keyblock->data, size_t(keyblock->totelem) * stride, state_reference);
}
if (keyblock->data) {
@ -352,7 +352,7 @@ static void um_arraystore_compact_ex(UndoMesh *um, const UndoMesh *um_ref, bool
BArrayStore *bs = BLI_array_store_at_size_ensure(
&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
um->store.mselect = BLI_array_store_state_add(
bs, me->mselect, (size_t)me->totselect * stride, state_reference);
bs, me->mselect, size_t(me->totselect) * stride, state_reference);
}
/* keep me->totselect for validation */

View File

@ -18,6 +18,7 @@ struct BMElem;
struct BMOperator;
struct EnumPropertyItem;
struct LinkNode;
struct Object;
struct bContext;
struct wmKeyConfig;
struct wmKeyMap;
@ -177,6 +178,8 @@ void MESH_OT_knife_project(struct wmOperatorType *ot);
* \param use_tag: When set, tag all faces inside the polylines.
*/
void EDBM_mesh_knife(struct ViewContext *vc,
struct Object **objects,
int objects_len,
struct LinkNode *polys,
bool use_tag,
bool cut_through);

View File

@ -1335,7 +1335,7 @@ struct VertPickData {
static void ed_mesh_pick_vert__mapFunc(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
VertPickData *data = static_cast<VertPickData *>(userData);
if (data->hide_vert && data->hide_vert[index]) {

View File

@ -2318,12 +2318,33 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
id_root = &collection->id;
user_overrides_from_selected_objects = true;
}
/* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
/* Else, poll func ensures us that ID_IS_LINKED(obact) is true, or that it is already an existing
* liboverride. */
else {
BLI_assert(ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY_REAL(obact));
id_root = &obact->id;
user_overrides_from_selected_objects = true;
}
/* Make already existing selected liboverrides editable. */
bool is_active_override = false;
FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
ob_iter->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
is_active_override = is_active_override || (&ob_iter->id == id_root);
DEG_id_tag_update(&ob_iter->id, ID_RECALC_COPY_ON_WRITE);
}
}
FOREACH_SELECTED_OBJECT_END;
/* If the active object is a liboverride, there is no point going further, since in the weird
* case where some other selected objects would be linked ones, there is no way to properly
* create overrides for them currently.
*
* Could be added later if really needed, but would rather avoid that extra complexity here. */
if (is_active_override) {
return OPERATOR_FINISHED;
}
const bool do_fully_editable = !user_overrides_from_selected_objects;
GSet *user_overrides_objects_uids = do_fully_editable ? NULL :
@ -2331,14 +2352,6 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
BLI_ghashutil_intcmp,
__func__);
/* Make already existing selected liboverrides editable. */
FOREACH_SELECTED_OBJECT_BEGIN (view_layer, CTX_wm_view3d(C), ob_iter) {
if (ID_IS_OVERRIDE_LIBRARY_REAL(ob_iter) && !ID_IS_LINKED(ob_iter)) {
ob_iter->id.override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
}
}
FOREACH_SELECTED_OBJECT_END;
if (do_fully_editable) {
/* Pass. */
}

View File

@ -2376,22 +2376,6 @@ void ED_vgroup_mirror(Object *ob,
/* TODO: vgroup locking.
* TODO: face masking. */
#define VGROUP_MIRR_OP \
dvert_mirror_op(dvert, \
dvert_mirr, \
sel, \
sel_mirr, \
flip_map, \
flip_map_len, \
mirror_weights, \
flip_vgroups, \
all_vgroups, \
def_nr)
BMVert *eve, *eve_mirr;
MDeformVert *dvert_mirr;
char sel, sel_mirr;
int *flip_map = nullptr, flip_map_len;
const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
int totmirr = 0, totfail = 0;
@ -2404,6 +2388,8 @@ void ED_vgroup_mirror(Object *ob,
return;
}
int *flip_map = nullptr;
int flip_map_len;
if (flip_vgroups) {
flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, false, &flip_map_len) :
BKE_object_defgroup_flip_map_single(ob, false, def_nr, &flip_map_len);
@ -2438,21 +2424,27 @@ void ED_vgroup_mirror(Object *ob,
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
/* Go through the list of edit-vertices and assign them. */
BMVert *eve, *eve_mirr;
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
if (eve_mirr != eve) {
if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
const bool sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
const bool sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
if ((sel || sel_mirr) && (eve != eve_mirr)) {
MDeformVert *dvert = static_cast<MDeformVert *>(
BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
dvert_mirr = static_cast<MDeformVert *>(
BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset));
VGROUP_MIRR_OP;
dvert_mirror_op(
static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)),
static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset)),
sel,
sel_mirr,
flip_map,
flip_map_len,
mirror_weights,
flip_vgroups,
all_vgroups,
def_nr);
totmirr++;
}
@ -2471,39 +2463,38 @@ void ED_vgroup_mirror(Object *ob,
}
else {
/* object mode / weight paint */
int vidx, vidx_mirr;
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
if (me->deform_verts().is_empty()) {
goto cleanup;
}
if (!use_vert_sel) {
sel = sel_mirr = true;
}
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
const bke::AttributeAccessor attributes = me->attributes();
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
".select_vert", ATTR_DOMAIN_POINT, false);
for (vidx = 0; vidx < me->totvert; vidx++) {
for (int vidx = 0; vidx < me->totvert; vidx++) {
if (!BLI_BITMAP_TEST(vert_tag, vidx)) {
int vidx_mirr;
if ((vidx_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology)) != -1) {
if (vidx != vidx_mirr) {
if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) {
if (use_vert_sel) {
sel = select_vert[vidx];
sel_mirr = select_vert[vidx_mirr];
}
const bool sel = use_vert_sel ? select_vert[vidx] : true;
const bool sel_mirr = use_vert_sel ? select_vert[vidx_mirr] : true;
if (sel || sel_mirr) {
MDeformVert *dvert = &dverts[vidx];
dvert_mirr = &dvert[vidx_mirr];
VGROUP_MIRR_OP;
dvert_mirror_op(&dverts[vidx],
&dverts[vidx_mirr],
sel,
sel_mirr,
flip_map,
flip_map_len,
mirror_weights,
flip_vgroups,
all_vgroups,
def_nr);
totmirr++;
}
@ -2523,9 +2514,6 @@ void ED_vgroup_mirror(Object *ob,
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = vgroup_edit_lattice(ob);
int i1, i2;
int u, v, w;
int pntsu_half;
/* half but found up odd value */
if (lt->pntsu == 1 || lt->dvert == nullptr) {
@ -2535,29 +2523,33 @@ void ED_vgroup_mirror(Object *ob,
/* unlike editmesh we know that by only looping over the first half of
* the 'u' indices it will cover all points except the middle which is
* ok in this case */
pntsu_half = lt->pntsu / 2;
int pntsu_half = lt->pntsu / 2;
for (w = 0; w < lt->pntsw; w++) {
for (v = 0; v < lt->pntsv; v++) {
for (u = 0; u < pntsu_half; u++) {
for (int w = 0; w < lt->pntsw; w++) {
for (int v = 0; v < lt->pntsv; v++) {
for (int u = 0; u < pntsu_half; u++) {
int u_inv = (lt->pntsu - 1) - u;
if (u != u_inv) {
BPoint *bp, *bp_mirr;
const int i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
const int i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
i1 = BKE_lattice_index_from_uvw(lt, u, v, w);
i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
const BPoint *bp = &lt->def[i1];
const BPoint *bp_mirr = &lt->def[i2];
bp = &lt->def[i1];
bp_mirr = &lt->def[i2];
sel = bp->f1 & SELECT;
sel_mirr = bp_mirr->f1 & SELECT;
const bool sel = bp->f1 & SELECT;
const bool sel_mirr = bp_mirr->f1 & SELECT;
if (sel || sel_mirr) {
MDeformVert *dvert = &lt->dvert[i1];
dvert_mirr = &lt->dvert[i2];
VGROUP_MIRR_OP;
dvert_mirror_op(&lt->dvert[i1],
&lt->dvert[i2],
sel,
sel_mirr,
flip_map,
flip_map_len,
mirror_weights,
flip_vgroups,
all_vgroups,
def_nr);
totmirr++;
}
}

View File

@ -879,7 +879,7 @@ static int new_world_exec(bContext *C, wmOperator * /*op*/)
wo = new_wo;
}
else {
wo = BKE_world_add(bmain, DATA_("World"));
wo = BKE_world_add(bmain, CTX_DATA_(BLT_I18NCONTEXT_ID_WORLD, "World"));
ED_node_shader_default(C, &wo->id);
wo->use_nodes = true;
}

View File

@ -286,6 +286,7 @@ static void SCENE_OT_new(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(ot->srna, "type", scene_new_items, SCE_COPY_NEW, "Type", "");
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_SCENE);
}
/** \} */

View File

@ -74,11 +74,8 @@ class AbstractPaintMode {
class ImagePaintMode : public AbstractPaintMode {
public:
void *paint_new_stroke(bContext *C,
wmOperator *op,
Object * /*ob*/,
const float UNUSED(mouse[2]),
int mode) override
void *paint_new_stroke(
bContext *C, wmOperator *op, Object * /*ob*/, const float /*mouse*/[2], int mode) override
{
return paint_2d_new_stroke(C, op, mode);
}

View File

@ -1981,7 +1981,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
int(*orco_tris)[3];
int orco_tris_num;
BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords);
BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords, NULL);
for (int i = 0; i < orco_tris_num; i++) {
const float *co_tri[3] = {
@ -3265,7 +3265,7 @@ static void sculpt_topology_update(Sculpt *sd,
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]);
BKE_pbvh_bmesh_node_save_orig(ss->bm, ss->bm_log, nodes[n], false);
}
}
@ -4272,7 +4272,8 @@ static void sculpt_update_cache_invariants(
bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mval[2])
{
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
ToolSettings *tool_settings = CTX_data_tool_settings(C);
UnifiedPaintSettings *ups = &tool_settings->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
ViewContext *vc = paint_stroke_view_context(op->customdata);
Object *ob = CTX_data_active_object(C);
@ -4407,6 +4408,13 @@ static void sculpt_update_cache_invariants(
}
}
/* Original coordinates require the sculpt undo system, which isn't used
* for image brushes. It's also not necessary, just disable it. */
if (brush && brush->sculpt_tool == SCULPT_TOOL_PAINT &&
SCULPT_use_image_paint_brush(&tool_settings->paint_mode, ob)) {
cache->original = false;
}
cache->first_time = true;
#define PIXEL_INPUT_THRESHHOLD 5

View File

@ -503,7 +503,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
PBVHVertRef vert,
AutomaskingNodeData *automask_data)
{
if (!automasking) {
if (!automasking || vert.i == PBVH_REF_NONE) {
return 1.0f;
}

View File

@ -2149,6 +2149,8 @@ static void do_elastic_deform_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);
SCULPT_automasking_node_update(ss, &automask_data, &vd);
float final_disp[3];
switch (brush->elastic_deform_type) {
case BRUSH_ELASTIC_DEFORM_GRAB:

View File

@ -827,9 +827,6 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
const int tot_vert = SCULPT_vertex_count_get(ss);
const int active_face_set = SCULPT_active_face_set_get(ss);
SCULPT_undo_push_begin(ob, op);
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode **nodes;
@ -842,62 +839,86 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
SCULPT_undo_push_node(ob, nodes[0], SCULPT_UNDO_FACE_SETS);
const int active_face_set = SCULPT_active_face_set_get(ss);
if (mode == SCULPT_FACE_SET_VISIBILITY_TOGGLE) {
bool hidden_vertex = false;
SCULPT_undo_push_begin(ob, op);
for (int i = 0; i < totnode; i++) {
SCULPT_undo_push_node(ob, nodes[i], SCULPT_UNDO_HIDDEN);
}
/* This can fail with regular meshes with non-manifold geometry as the visibility state can't
* be synced from face sets to non-manifold vertices. */
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
for (int i = 0; i < tot_vert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
switch (mode) {
case SCULPT_FACE_SET_VISIBILITY_TOGGLE: {
bool hidden_vertex = false;
if (!SCULPT_vertex_visible_get(ss, vertex)) {
hidden_vertex = true;
break;
/* This can fail with regular meshes with non-manifold geometry as the visibility state can't
* be synced from face sets to non-manifold vertices. */
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
for (int i = 0; i < tot_vert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ss->pbvh, i);
if (!SCULPT_vertex_visible_get(ss, vertex)) {
hidden_vertex = true;
break;
}
}
}
}
if (ss->hide_poly) {
for (int i = 0; i < ss->totfaces; i++) {
if (ss->hide_poly[i]) {
hidden_vertex = true;
break;
if (ss->hide_poly) {
for (int i = 0; i < ss->totfaces; i++) {
if (ss->hide_poly[i]) {
hidden_vertex = true;
break;
}
}
}
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
if (hidden_vertex) {
SCULPT_face_visibility_all_set(ss, true);
}
else {
if (ss->face_sets) {
SCULPT_face_visibility_all_set(ss, false);
SCULPT_face_set_visibility_set(ss, active_face_set, true);
}
else {
SCULPT_face_visibility_all_set(ss, true);
}
}
break;
}
case SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE:
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
if (ss->face_sets) {
SCULPT_face_visibility_all_set(ss, false);
SCULPT_face_set_visibility_set(ss, active_face_set, true);
}
else {
SCULPT_face_set_visibility_set(ss, active_face_set, true);
}
break;
case SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE:
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
if (hidden_vertex) {
SCULPT_face_visibility_all_set(ss, true);
}
else {
SCULPT_face_visibility_all_set(ss, false);
SCULPT_face_set_visibility_set(ss, active_face_set, true);
}
}
if (ss->face_sets) {
SCULPT_face_set_visibility_set(ss, active_face_set, false);
}
else {
SCULPT_face_visibility_all_set(ss, false);
}
if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) {
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
SCULPT_face_visibility_all_set(ss, false);
SCULPT_face_set_visibility_set(ss, active_face_set, true);
}
if (mode == SCULPT_FACE_SET_VISIBILITY_HIDE_ACTIVE) {
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
SCULPT_face_set_visibility_set(ss, active_face_set, false);
}
if (mode == SCULPT_FACE_SET_VISIBILITY_INVERT) {
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
SCULPT_face_visibility_all_invert(ss);
break;
case SCULPT_FACE_SET_VISIBILITY_INVERT:
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
SCULPT_face_visibility_all_invert(ss);
break;
}
/* For modes that use the cursor active vertex, update the rotation origin for viewport
* navigation. */
* navigation.
*/
if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
float location[3];
@ -912,7 +933,6 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
SCULPT_visibility_sync_all_from_faces(ob);
SCULPT_undo_push_end(ob);
for (int i = 0; i < totnode; i++) {
BKE_pbvh_node_mark_update_visibility(nodes[i]);
}

View File

@ -1116,10 +1116,7 @@ static int sculpt_bake_cavity_exec(bContext *C, wmOperator *op)
SCULPT_undo_push_end(ob);
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
/* Unlike other operators we do not tag the ID for update here;
* it triggers a PBVH rebuild which is too slow and ruins
* the interactivity of the tool. */
SCULPT_tag_update_overlays(C);
return OPERATOR_FINISHED;
}

View File

@ -1611,7 +1611,9 @@ void CLIP_OT_mode_set(wmOperatorType *ot)
ot->poll = ED_space_clip_poll;
/* properties */
RNA_def_enum(ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", "");
ot->prop = RNA_def_enum(
ot->srna, "mode", rna_enum_clip_editor_mode_items, SC_MODE_TRACKING, "Mode", "");
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
}
/** \} */

View File

@ -589,15 +589,27 @@ void ED_space_image_grid_steps(SpaceImage *sima,
float grid_steps_y[SI_GRID_STEPS_LEN],
const int grid_dimension)
{
const int flag = sima->flag;
const eSpaceImage_GridShapeSource grid_shape_source = sima->grid_shape_source;
for (int step = 0; step < SI_GRID_STEPS_LEN; step++) {
if (flag & SI_CUSTOM_GRID) {
grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0];
grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1];
}
else {
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
switch (grid_shape_source) {
case SI_GRID_SHAPE_DYNAMIC:
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
break;
case SI_GRID_SHAPE_FIXED:
grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0];
grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1];
break;
case SI_GRID_SHAPE_PIXEL: {
int pixel_width = IMG_SIZE_FALLBACK;
int pixel_height = IMG_SIZE_FALLBACK;
ED_space_image_get_size(sima, &pixel_width, &pixel_height);
BLI_assert(pixel_width > 0 && pixel_height > 0);
grid_steps_x[step] = 1.0f / pixel_width;
grid_steps_y[step] = 1.0f / pixel_height;
} break;
default:
BLI_assert_unreachable();
}
}
}

View File

@ -2641,6 +2641,8 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op)
void NLA_OT_fmodifier_add(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name = "Add F-Modifier";
ot->idname = "NLA_OT_fmodifier_add";
@ -2659,11 +2661,12 @@ void NLA_OT_fmodifier_add(wmOperatorType *ot)
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
RNA_def_boolean(ot->srna,
"only_active",
true,
"Only Active",
"Only add a F-Modifier of the specified type to the active strip");
prop = RNA_def_boolean(ot->srna,
"only_active",
true,
"Only Active",
"Only add a F-Modifier of the specified type to the active strip");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ACTION);
}
/** \} */
@ -2832,8 +2835,10 @@ void NLA_OT_fmodifier_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
RNA_def_boolean(
ot->prop = RNA_def_boolean(
ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
RNA_def_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
RNA_def_boolean(
ot->srna,
"replace",

View File

@ -64,6 +64,10 @@ struct NodeInsertOfsData {
float offset_x; /* offset to apply to node chain */
};
namespace blender::ed::space_node {
bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out);
static void clear_picking_highlight(ListBase *links)
{
LISTBASE_FOREACH (bNodeLink *, link, links) {
@ -71,8 +75,6 @@ static void clear_picking_highlight(ListBase *links)
}
}
namespace blender::ed::space_node {
void update_multi_input_indices_for_removed_links(bNode &node);
/* -------------------------------------------------------------------- */
@ -1750,29 +1752,31 @@ static int node_attach_invoke(bContext *C, wmOperator * /*op*/, const wmEvent *e
}
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) {
if (node->flag & NODE_SELECT) {
if (node->parent == nullptr) {
/* disallow moving a parent into its child */
if (nodeAttachNodeCheck(frame, node) == false) {
/* attach all unparented nodes */
nodeAttachNode(node, frame);
if (!(node->flag & NODE_SELECT)) {
continue;
}
if (node->parent == nullptr) {
/* disallow moving a parent into its child */
if (nodeAttachNodeCheck(frame, node) == false) {
/* attach all unparented nodes */
nodeAttachNode(node, frame);
}
}
else {
/* attach nodes which share parent with the frame */
bNode *parent;
for (parent = frame->parent; parent; parent = parent->parent) {
if (parent == node->parent) {
break;
}
}
else {
/* attach nodes which share parent with the frame */
bNode *parent;
for (parent = frame->parent; parent; parent = parent->parent) {
if (parent == node->parent) {
break;
}
}
if (parent) {
/* disallow moving a parent into its child */
if (nodeAttachNodeCheck(frame, node) == false) {
nodeDetachNode(node);
nodeAttachNode(node, frame);
}
if (parent) {
/* disallow moving a parent into its child */
if (nodeAttachNodeCheck(frame, node) == false) {
nodeDetachNode(node);
nodeAttachNode(node, frame);
}
}
}
@ -1881,100 +1885,55 @@ void NODE_OT_detach(wmOperatorType *ot)
/** \name Automatic Node Insert on Dragging
* \{ */
/* prevent duplicate testing code below */
static bool ed_node_link_conditions(ScrArea *area,
bool test,
SpaceNode **r_snode,
bNode **r_select)
static bNode *get_selected_node_for_insertion(bNodeTree &node_tree)
{
SpaceNode *snode = area ? (SpaceNode *)area->spacedata.first : nullptr;
*r_snode = snode;
*r_select = nullptr;
/* no unlucky accidents */
if (area == nullptr || area->spacetype != SPACE_NODE) {
return false;
}
if (!test) {
/* no need to look for a node */
return true;
}
bNode *node;
bNode *select = nullptr;
for (node = (bNode *)snode->edittree->nodes.first; node; node = node->next) {
bNode *selected_node = nullptr;
int selected_node_count = 0;
for (bNode *node : node_tree.all_nodes()) {
if (node->flag & SELECT) {
if (select) {
break;
}
select = node;
selected_node = node;
selected_node_count++;
}
if (selected_node_count > 1) {
return nullptr;
}
}
/* only one selected */
if (node || select == nullptr) {
return false;
if (!selected_node) {
return nullptr;
}
/* correct node */
if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) {
return false;
if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) {
return nullptr;
}
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
/* test node for links */
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
if (node_link_is_hidden_or_dimmed(region->v2d, *link)) {
continue;
}
if (link->tonode == select || link->fromnode == select) {
return false;
}
if (std::any_of(selected_node->input_sockets().begin(),
selected_node->input_sockets().end(),
[&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) {
return nullptr;
}
*r_select = select;
return true;
if (std::any_of(selected_node->output_sockets().begin(),
selected_node->output_sockets().end(),
[&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) {
return nullptr;
};
return selected_node;
}
/** \} */
} // namespace blender::ed::space_node
/* -------------------------------------------------------------------- */
/** \name Node Line Intersection Test
* \{ */
void ED_node_link_intersect_test(ScrArea *area, int test)
void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion &region)
{
using namespace blender;
using namespace blender::ed::space_node;
bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache();
bNode *select;
SpaceNode *snode;
if (!ed_node_link_conditions(area, test, &snode, &select)) {
node_insert_on_link_flags_clear(node_tree);
bNode *node_to_insert = get_selected_node_for_insertion(node_tree);
if (!node_to_insert) {
return;
}
/* clear flags */
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
link->flag &= ~NODE_LINKFLAG_HILITE;
}
if (test == 0) {
return;
}
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
/* find link to select/highlight */
bNodeLink *selink = nullptr;
float dist_best = FLT_MAX;
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
if (node_link_is_hidden_or_dimmed(region->v2d, *link)) {
LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
continue;
}
@ -1986,10 +1945,10 @@ void ED_node_link_intersect_test(ScrArea *area, int test)
* upper left node edge of a intersected line segment */
for (int i = 0; i < NODE_LINK_RESOL; i++) {
/* Check if the node rectangle intersects the line from this point to next one. */
if (BLI_rctf_isect_segment(&select->totr, coords[i], coords[i + 1])) {
if (BLI_rctf_isect_segment(&node_to_insert->totr, coords[i], coords[i + 1])) {
/* store the shortest distance to the upper left edge
* of all intersections found so far */
const float node_xy[] = {select->totr.xmin, select->totr.ymax};
const float node_xy[] = {node_to_insert->totr.xmin, node_to_insert->totr.ymax};
/* to be precise coords should be clipped by select->totr,
* but not done since there's no real noticeable difference */
@ -2009,9 +1968,89 @@ void ED_node_link_intersect_test(ScrArea *area, int test)
}
}
/** \} */
void node_insert_on_link_flags_clear(bNodeTree &node_tree)
{
LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
link->flag &= ~NODE_LINKFLAG_HILITE;
}
}
namespace blender::ed::space_node {
void node_insert_on_link_flags(Main &bmain, SpaceNode &snode)
{
bNodeTree &node_tree = *snode.edittree;
node_tree.ensure_topology_cache();
bNode *node_to_insert = get_selected_node_for_insertion(node_tree);
if (!node_to_insert) {
return;
}
/* Find link to insert on. */
bNodeTree &ntree = *snode.edittree;
bNodeLink *old_link = nullptr;
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
if (link->flag & NODE_LINKFLAG_HILITE) {
old_link = link;
break;
}
}
if (old_link == nullptr) {
return;
}
old_link->flag &= ~NODE_LINKFLAG_HILITE;
bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN);
bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT);
if (node_to_insert->type != NODE_REROUTE) {
/* Ignore main sockets when the types don't match. */
if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr &&
!ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type),
static_cast<eNodeSocketDatatype>(best_input->type))) {
best_input = nullptr;
}
if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr &&
!ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type),
static_cast<eNodeSocketDatatype>(old_link->tosock->type))) {
best_output = nullptr;
}
}
bNode *from_node = old_link->fromnode;
bNodeSocket *from_socket = old_link->fromsock;
bNode *to_node = old_link->tonode;
if (best_output != nullptr) {
/* Relink the "start" of the existing link to the newly inserted node. */
old_link->fromnode = node_to_insert;
old_link->fromsock = best_output;
BKE_ntree_update_tag_link_changed(&ntree);
}
else {
nodeRemLink(&ntree, old_link);
}
if (best_input != nullptr) {
/* Add a new link that connects the node on the left to the newly inserted node. */
nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input);
}
/* Set up insert offset data, it needs stuff from here. */
if ((snode.flag & SNODE_SKIP_INSOFFSET) == 0) {
BLI_assert(snode.runtime->iofsd == nullptr);
NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__);
iofsd->insert = node_to_insert;
iofsd->prev = from_node;
iofsd->next = to_node;
snode.runtime->iofsd = iofsd;
}
ED_node_tree_propagate_change(nullptr, &bmain, &ntree);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Node Insert Offset Operator
@ -2048,7 +2087,7 @@ static int get_main_socket_priority(const bNodeSocket *socket)
}
/** Get the "main" socket based on the node declaration or an heuristic. */
static bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out)
bNodeSocket *get_main_socket(bNodeTree &ntree, bNode &node, eNodeSocketInOut in_out)
{
ListBase *sockets = (in_out == SOCK_IN) ? &node.inputs : &node.outputs;
@ -2426,85 +2465,3 @@ void NODE_OT_insert_offset(wmOperatorType *ot)
/** \} */
} // namespace blender::ed::space_node
/* -------------------------------------------------------------------- */
/** \name Note Link Insert
* \{ */
void ED_node_link_insert(Main *bmain, ScrArea *area)
{
using namespace blender::ed::space_node;
bNode *node_to_insert;
SpaceNode *snode;
if (!ed_node_link_conditions(area, true, &snode, &node_to_insert)) {
return;
}
/* Find link to insert on. */
bNodeTree &ntree = *snode->edittree;
bNodeLink *old_link = nullptr;
LISTBASE_FOREACH (bNodeLink *, link, &ntree.links) {
if (link->flag & NODE_LINKFLAG_HILITE) {
old_link = link;
break;
}
}
if (old_link == nullptr) {
return;
}
old_link->flag &= ~NODE_LINKFLAG_HILITE;
bNodeSocket *best_input = get_main_socket(ntree, *node_to_insert, SOCK_IN);
bNodeSocket *best_output = get_main_socket(ntree, *node_to_insert, SOCK_OUT);
if (node_to_insert->type != NODE_REROUTE) {
/* Ignore main sockets when the types don't match. */
if (best_input != nullptr && ntree.typeinfo->validate_link != nullptr &&
!ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(old_link->fromsock->type),
static_cast<eNodeSocketDatatype>(best_input->type))) {
best_input = nullptr;
}
if (best_output != nullptr && ntree.typeinfo->validate_link != nullptr &&
!ntree.typeinfo->validate_link(static_cast<eNodeSocketDatatype>(best_output->type),
static_cast<eNodeSocketDatatype>(old_link->tosock->type))) {
best_output = nullptr;
}
}
bNode *from_node = old_link->fromnode;
bNodeSocket *from_socket = old_link->fromsock;
bNode *to_node = old_link->tonode;
if (best_output != nullptr) {
/* Relink the "start" of the existing link to the newly inserted node. */
old_link->fromnode = node_to_insert;
old_link->fromsock = best_output;
BKE_ntree_update_tag_link_changed(&ntree);
}
else {
nodeRemLink(&ntree, old_link);
}
if (best_input != nullptr) {
/* Add a new link that connects the node on the left to the newly inserted node. */
nodeAddLink(&ntree, from_node, from_socket, node_to_insert, best_input);
}
/* Set up insert offset data, it needs stuff from here. */
if ((snode->flag & SNODE_SKIP_INSOFFSET) == 0) {
BLI_assert(snode->runtime->iofsd == nullptr);
NodeInsertOfsData *iofsd = MEM_cnew<NodeInsertOfsData>(__func__);
iofsd->insert = node_to_insert;
iofsd->prev = from_node;
iofsd->next = to_node;
snode->runtime->iofsd = iofsd;
}
ED_node_tree_propagate_change(nullptr, bmain, snode->edittree);
}
/** \} */

View File

@ -888,7 +888,7 @@ static bool datastack_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
static char *datastack_drop_tooltip(bContext * /*C*/,
wmDrag *drag,
const int UNUSED(xy[2]),
const int /*xy*/[2],
struct wmDropBox * /*drop*/)
{
StackDropData *drop_data = static_cast<StackDropData *>(drag->poin);

View File

@ -487,37 +487,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
return geometry_set;
}
class GeometryComponentCacheKey : public SpreadsheetCache::Key {
public:
/* Use the pointer to the geometry component as a key to detect when the geometry changed. */
const GeometryComponent *component;
GeometryComponentCacheKey(const GeometryComponent &component) : component(&component)
{
}
uint64_t hash() const override
{
return get_default_hash(this->component);
}
bool is_equal_to(const Key &other) const override
{
if (const GeometryComponentCacheKey *other_geo =
dynamic_cast<const GeometryComponentCacheKey *>(&other)) {
return this->component == other_geo->component;
}
return false;
}
};
class GeometryComponentCacheValue : public SpreadsheetCache::Value {
public:
/* Stores the result of fields evaluated on a geometry component. Without this, fields would have
* to be reevaluated on every redraw. */
Map<std::pair<eAttrDomain, GField>, GArray<>> arrays;
};
std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval)
{
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);

View File

@ -631,7 +631,7 @@ static bool view3d_object_data_drop_poll(bContext *C, wmDrag *drag, const wmEven
static char *view3d_object_data_drop_tooltip(bContext * /*C*/,
wmDrag * /*drag*/,
const int UNUSED(xy[2]),
const int /*xy*/[2],
wmDropBox * /*drop*/)
{
return BLI_strdup(TIP_("Create object instance from object-data"));

View File

@ -262,7 +262,7 @@ struct foreachScreenFace_userData {
static void meshobject_foreachScreenVert__mapFunc(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
foreachScreenObjectVert_userData *data = static_cast<foreachScreenObjectVert_userData *>(
userData);
@ -316,7 +316,7 @@ void meshobject_foreachScreenVert(
static void mesh_foreachScreenVert__mapFunc(void *userData,
int index,
const float co[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
foreachScreenVert_userData *data = static_cast<foreachScreenVert_userData *>(userData);
BMVert *eve = BM_vert_at_index(data->vc.em->bm, index);
@ -538,7 +538,7 @@ void mesh_foreachScreenEdge_clip_bb_segment(ViewContext *vc,
static void mesh_foreachScreenFace__mapFunc(void *userData,
int index,
const float cent[3],
const float UNUSED(no[3]))
const float /*no*/[3])
{
foreachScreenFace_userData *data = static_cast<foreachScreenFace_userData *>(userData);
BMFace *efa = BM_face_at_index(data->vc.em->bm, index);

View File

@ -40,7 +40,7 @@ set(SRC
transform_convert_mesh_uv.c
transform_convert_mesh_vert_cdata.c
transform_convert_nla.c
transform_convert_node.c
transform_convert_node.cc
transform_convert_object.c
transform_convert_object_texspace.c
transform_convert_paintcurve.c

View File

@ -1518,26 +1518,26 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
bool use_prop_edit = false;
int prop_edit_flag = 0;
if (t->flag & T_PROP_EDIT_ALL) {
if (t->flag & T_PROP_EDIT) {
use_prop_edit = true;
/* Save proportional edit settings.
* Skip saving proportional edit if it was not actually used. */
if (!(t->options & CTX_NO_PET)) {
bool use_prop_edit = false;
int prop_edit_flag = 0;
if (t->flag & T_PROP_EDIT_ALL) {
if (t->flag & T_PROP_EDIT) {
use_prop_edit = true;
}
if (t->flag & T_PROP_CONNECTED) {
prop_edit_flag |= PROP_EDIT_CONNECTED;
}
if (t->flag & T_PROP_PROJECTED) {
prop_edit_flag |= PROP_EDIT_PROJECTED;
}
}
if (t->flag & T_PROP_CONNECTED) {
prop_edit_flag |= PROP_EDIT_CONNECTED;
}
if (t->flag & T_PROP_PROJECTED) {
prop_edit_flag |= PROP_EDIT_PROJECTED;
}
}
/* If modal, save settings back in scene if not set as operator argument */
if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
/* save settings if not set in operator */
/* skip saving proportional edit if it was not actually used */
if (!(t->options & CTX_NO_PET)) {
/* If modal, save settings back in scene if not set as operator argument */
if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
/* save settings if not set in operator */
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) &&
!RNA_property_is_set(op->ptr, prop)) {
BKE_view_layer_synced_ensure(t->scene, t->view_layer);
@ -1576,6 +1576,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
ts->prop_mode = t->prop_mode;
}
}
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
RNA_property_boolean_set(op->ptr, prop, use_prop_edit);
RNA_boolean_set(op->ptr, "use_proportional_connected", prop_edit_flag & PROP_EDIT_CONNECTED);
RNA_boolean_set(op->ptr, "use_proportional_projected", prop_edit_flag & PROP_EDIT_PROJECTED);
RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
RNA_float_set(op->ptr, "proportional_size", t->prop_size);
}
}
/* Save snapping settings. */
@ -1635,14 +1643,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
}
}
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit"))) {
RNA_property_boolean_set(op->ptr, prop, use_prop_edit);
RNA_boolean_set(op->ptr, "use_proportional_connected", prop_edit_flag & PROP_EDIT_CONNECTED);
RNA_boolean_set(op->ptr, "use_proportional_projected", prop_edit_flag & PROP_EDIT_PROJECTED);
RNA_enum_set(op->ptr, "proportional_edit_falloff", t->prop_mode);
RNA_float_set(op->ptr, "proportional_size", t->prop_size);
}
if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
}

View File

@ -19,6 +19,10 @@
#include "transform_data.h"
#ifdef __cplusplus
extern "C" {
#endif
/* use node center for transform instead of upper-left corner.
* disabled since it makes absolute snapping not work so nicely
*/
@ -141,6 +145,7 @@ typedef enum {
/** No cursor wrapping on region bounds */
T_NO_CURSOR_WRAP = 1 << 23,
} eTFlag;
ENUM_OPERATORS(eTFlag, T_NO_CURSOR_WRAP);
#define T_ALL_RESTRICTIONS (T_NO_CONSTRAINT | T_NULL_ONE)
#define T_PROP_EDIT_ALL (T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED)
@ -864,3 +869,7 @@ bool checkUseAxisMatrix(TransInfo *t);
th++, i++)
/** \} */
#ifdef __cplusplus
}
#endif

View File

@ -10,6 +10,10 @@
#include "RE_engine.h"
#ifdef __cplusplus
extern "C" {
#endif
struct BMEditMesh;
struct BMesh;
struct BezTriple;
@ -244,7 +248,7 @@ extern TransConvertTypeInfo TransConvertType_MeshVertCData;
extern TransConvertTypeInfo TransConvertType_NLA;
/* transform_convert_node.c */
/* transform_convert_node.cc */
extern TransConvertTypeInfo TransConvertType_Node;
@ -279,3 +283,7 @@ extern TransConvertTypeInfo TransConvertType_SequencerImage;
/* transform_convert_tracking.c */
extern TransConvertTypeInfo TransConvertType_Tracking;
#ifdef __cplusplus
}
#endif

View File

@ -55,6 +55,29 @@ typedef struct TransDataNla {
int handle;
} TransDataNla;
/* -------------------------------------------------------------------- */
/** \name Transform application to NLA strips
* \{ */
/**
* \brief Applies a translation to the given NlaStrip.
* \param strip_rna_ptr The RNA pointer of the NLA strip to modify.
* \param transdata The transformation info structure.
*/
static void applyTransformNLA_translation(PointerRNA *strip_rna_ptr, const TransDataNla *transdata)
{
/* NOTE: we write these twice to avoid truncation errors which can arise when
* moving the strips a large distance using numeric input T33852.
*/
RNA_float_set(strip_rna_ptr, "frame_start", transdata->h1[0]);
RNA_float_set(strip_rna_ptr, "frame_end", transdata->h2[0]);
RNA_float_set(strip_rna_ptr, "frame_start", transdata->h1[0]);
RNA_float_set(strip_rna_ptr, "frame_end", transdata->h2[0]);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name NLA Transform Creation
* \{ */
@ -329,15 +352,8 @@ static 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;
}
NlaStrip *prev = BKE_nlastrip_prev_in_track(strip, true);
NlaStrip *next = BKE_nlastrip_next_in_track(strip, true);
for (short iter = 0; iter < 5; iter++) {
const bool pExceeded = (prev != NULL) && (tdn->h1[0] < prev->end);
@ -380,17 +396,10 @@ static void recalcData_nla(TransInfo *t)
/* Use RNA to write the values to ensure that constraints on these are obeyed
* (e.g. for transition strips, the values are taken from the neighbors)
*
* NOTE: we write these twice to avoid truncation errors which can arise when
* moving the strips a large distance using numeric input T33852.
*/
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
RNA_float_set(&strip_ptr, "frame_end", tdn->h2[0]);
applyTransformNLA_translation(&strip_ptr, tdn);
/* flush transforms to child strips (since this should be a meta) */
BKE_nlameta_flush_transforms(strip);

View File

@ -96,13 +96,13 @@ static bool is_node_parent_select(bNode *node)
return false;
}
static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
static void createTransNodeData(bContext * /*C*/, TransInfo *t)
{
const float dpi_fac = UI_DPI_FAC;
SpaceNode *snode = t->area->spacedata.first;
SpaceNode *snode = static_cast<SpaceNode *>(t->area->spacedata.first);
/* Custom data to enable edge panning during the node transform */
struct TransCustomDataNode *customdata = MEM_callocN(sizeof(*customdata), __func__);
TransCustomDataNode *customdata = MEM_cnew<TransCustomDataNode>(__func__);
UI_view2d_edge_pan_init(t->context,
&customdata->edgepan_data,
NODE_EDGE_PAN_INSIDE_PAD,
@ -125,7 +125,7 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
}
/* Nodes don't support PET and probably never will. */
t->flag &= ~T_PROP_EDIT_ALL;
t->flag = t->flag & ~T_PROP_EDIT_ALL;
/* set transform flags on nodes */
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
@ -142,9 +142,8 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
return;
}
TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
"TransNode TransData2D");
TransData *td = tc->data = MEM_cnew_array<TransData>(tc->data_len, __func__);
TransData2D *td2d = tc->data_2d = MEM_cnew_array<TransData2D>(tc->data_len, __func__);
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
if (node->flag & NODE_TRANSFORM) {
@ -161,9 +160,11 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
static void flushTransNodes(TransInfo *t)
{
using namespace blender::ed;
const float dpi_fac = UI_DPI_FAC;
SpaceNode *snode = static_cast<SpaceNode *>(t->area->spacedata.first);
struct TransCustomDataNode *customdata = (struct TransCustomDataNode *)t->custom.type.data;
TransCustomDataNode *customdata = (TransCustomDataNode *)t->custom.type.data;
if (t->options & CTX_VIEW2D_EDGE_PAN) {
if (t->state == TRANS_CANCEL) {
@ -196,7 +197,7 @@ static void flushTransNodes(TransInfo *t)
for (int i = 0; i < tc->data_len; i++) {
TransData *td = &tc->data[i];
TransData2D *td2d = &tc->data_2d[i];
bNode *node = td->extra;
bNode *node = static_cast<bNode *>(td->extra);
float loc[2];
add_v2_v2v2(loc, td2d->loc, offset);
@ -221,7 +222,7 @@ static void flushTransNodes(TransInfo *t)
/* handle intersection with noodles */
if (tc->data_len == 1) {
ED_node_link_intersect_test(t->area, 1);
space_node::node_insert_on_link_flags_set(*snode, *t->region);
}
}
}
@ -234,13 +235,15 @@ static void flushTransNodes(TransInfo *t)
static void special_aftertrans_update__node(bContext *C, TransInfo *t)
{
struct Main *bmain = CTX_data_main(C);
using namespace blender::ed;
Main *bmain = CTX_data_main(C);
SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
bNodeTree *ntree = snode->edittree;
const bool canceled = (t->state == TRANS_CANCEL);
SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
if (canceled && t->remove_on_cancel) {
/* remove selected nodes on cancel */
bNodeTree *ntree = snode->edittree;
if (ntree) {
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
if (node->flag & NODE_SELECT) {
@ -253,11 +256,10 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
if (!canceled) {
ED_node_post_apply_transform(C, snode->edittree);
ED_node_link_insert(bmain, t->area);
space_node::node_insert_on_link_flags(*bmain, *snode);
}
/* clear link line */
ED_node_link_intersect_test(t->area, 0);
space_node::node_insert_on_link_flags_clear(*ntree);
}
/** \} */

View File

@ -523,9 +523,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
static bool transform_poll_property(const bContext *UNUSED(C),
wmOperator *op,
const PropertyRNA *prop)
static bool transform_poll_property(const bContext *C, wmOperator *op, const PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
@ -559,12 +557,21 @@ static bool transform_poll_property(const bContext *UNUSED(C),
}
/* Proportional Editing. */
{
if (STRPREFIX(prop_id, "proportional") || STRPREFIX(prop_id, "use_proportional")) {
ScrArea *area = CTX_wm_area(C);
if (area->spacetype == SPACE_NLA) {
/* Hide properties that are not supported in some spaces. */
return false;
}
PropertyRNA *prop_pet = RNA_struct_find_property(op->ptr, "use_proportional_edit");
if (prop_pet && (prop_pet != prop) && (RNA_property_boolean_get(op->ptr, prop_pet) == false)) {
if (STRPREFIX(prop_id, "proportional") || STRPREFIX(prop_id, "use_proportional")) {
return false;
}
if ((prop_pet != prop) && (RNA_property_boolean_get(op->ptr, prop_pet) == false)) {
/* If "use_proportional_edit" is false, hide:
* - "proportional_edit_falloff",
* - "proportional_size",
* - "use_proportional_connected",
* - "use_proportional_projected". */
return false;
}
}

View File

@ -11,6 +11,10 @@
/* For enum. */
#include "DNA_space_types.h"
#ifdef __cplusplus
extern "C" {
#endif
bool peelObjectsTransform(struct TransInfo *t,
const float mval[2],
bool use_peel_object,
@ -92,3 +96,7 @@ void transform_snap_anim_flush_data(TransInfo *t,
TransData *td,
eAnimEdit_AutoSnap autosnap,
float *r_val_final);
#ifdef __cplusplus
}
#endif

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