Overlay-Next: Initial implementation #107045
|
@ -176,3 +176,4 @@ if(UNIX AND NOT APPLE)
|
|||
endif()
|
||||
|
||||
include(cmake/harvest.cmake)
|
||||
include(cmake/cve_check.cmake)
|
||||
|
|
|
@ -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
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
vendor,product,version
|
||||
@SBOMCONTENTS@
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -43,6 +43,10 @@ Session::Session(const SessionParams ¶ms_, 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. */
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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, ®istry_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 */
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ®ion);
|
||||
/**
|
||||
* 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
|
|
@ -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. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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. */
|
||||
}
|
||||
|
|
|
@ -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 = <->def[i1];
|
||||
const BPoint *bp_mirr = <->def[i2];
|
||||
|
||||
bp = <->def[i1];
|
||||
bp_mirr = <->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 = <->dvert[i1];
|
||||
dvert_mirr = <->dvert[i2];
|
||||
|
||||
VGROUP_MIRR_OP;
|
||||
dvert_mirror_op(<->dvert[i1],
|
||||
<->dvert[i2],
|
||||
sel,
|
||||
sel_mirr,
|
||||
flip_map,
|
||||
flip_map_len,
|
||||
mirror_weights,
|
||||
flip_vgroups,
|
||||
all_vgroups,
|
||||
def_nr);
|
||||
totmirr++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 ®ion)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue