Overlay-Next: Initial implementation #107045
|
@ -176,3 +176,4 @@ if(UNIX AND NOT APPLE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(cmake/harvest.cmake)
|
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()
|
else()
|
||||||
ExternalProject_Add_Step(external_openpgl after_install
|
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/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
|
DEPENDEES install
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# 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_VERSION 1.2.12)
|
||||||
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
|
set(ZLIB_URI https://zlib.net/zlib-${ZLIB_VERSION}.tar.gz)
|
||||||
set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
|
set(ZLIB_HASH 5fc414a9726be31427b440b434d05f78)
|
||||||
set(ZLIB_HASH_TYPE MD5)
|
set(ZLIB_HASH_TYPE MD5)
|
||||||
set(ZLIB_FILE zlib-${ZLIB_VERSION}.tar.gz)
|
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_VERSION 1.21.1)
|
||||||
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
|
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 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca)
|
||||||
set(PNG_HASH_TYPE SHA256)
|
set(PNG_HASH_TYPE SHA256)
|
||||||
set(PNG_FILE libpng-${PNG_VERSION}.tar.xz)
|
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_VERSION 2.1.3)
|
||||||
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
|
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
|
||||||
set(JPEG_HASH 627b980fad0573e08e4c3b80b290fc91)
|
set(JPEG_HASH 627b980fad0573e08e4c3b80b290fc91)
|
||||||
set(JPEG_HASH_TYPE MD5)
|
set(JPEG_HASH_TYPE MD5)
|
||||||
set(JPEG_FILE libjpeg-turbo-${JPEG_VERSION}.tar.gz)
|
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 1.78.0)
|
||||||
set(BOOST_VERSION_SHORT 1.78)
|
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 c2f6428ac52b0e5a3c9b2e1d8cc832b5)
|
||||||
set(BOOST_HASH_TYPE MD5)
|
set(BOOST_HASH_TYPE MD5)
|
||||||
set(BOOST_FILE boost_${BOOST_VERSION_NODOTS}.tar.gz)
|
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_VERSION 1.21.1)
|
||||||
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
|
set(BLOSC_URI https://github.com/Blosc/c-blosc/archive/v${BLOSC_VERSION}.tar.gz)
|
||||||
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
|
set(BLOSC_HASH 134b55813b1dca57019d2a2dc1f7a923)
|
||||||
set(BLOSC_HASH_TYPE MD5)
|
set(BLOSC_HASH_TYPE MD5)
|
||||||
set(BLOSC_FILE blosc-${BLOSC_VERSION}.tar.gz)
|
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_VERSION 3.0.0)
|
||||||
set(PTHREADS_URI http://prdownloads.sourceforge.net/pthreads4w/pthreads4w-code-v${PTHREADS_VERSION}.zip)
|
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 a92f38eedd43e56c0af56d4852506886)
|
||||||
set(OPENEXR_HASH_TYPE MD5)
|
set(OPENEXR_HASH_TYPE MD5)
|
||||||
set(OPENEXR_FILE openexr-${OPENEXR_VERSION}.tar.gz)
|
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_VERSION 3.1.5)
|
||||||
set(IMATH_URI https://github.com/AcademySoftwareFoundation/Imath/archive/v${OPENEXR_VERSION}.tar.gz)
|
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 bd4e3b007474319909a6b79d50908e85)
|
||||||
set(FREETYPE_HASH_TYPE MD5)
|
set(FREETYPE_HASH_TYPE MD5)
|
||||||
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
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_VERSION 1.5.10)
|
||||||
set(EPOXY_URI https://github.com/anholt/libepoxy/archive/refs/tags/${EPOXY_VERSION}.tar.gz)
|
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 2cd8d6e5a3ac4a014e24a4b04f4fadf9)
|
||||||
set(ALEMBIC_HASH_TYPE MD5)
|
set(ALEMBIC_HASH_TYPE MD5)
|
||||||
set(ALEMBIC_FILE alembic-${ALEMBIC_VERSION}.tar.gz)
|
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_VERSION v3_4_4)
|
||||||
set(OPENSUBDIV_URI https://github.com/PixarAnimationStudios/OpenSubdiv/archive/${OPENSUBDIV_VERSION}.tar.gz)
|
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 a53acc02e1cca98c4123229069b67c9e)
|
||||||
set(SDL_HASH_TYPE MD5)
|
set(SDL_HASH_TYPE MD5)
|
||||||
set(SDL_FILE SDL2-${SDL_VERSION}.tar.gz)
|
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_VERSION v1.6.68)
|
||||||
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
|
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 5a4fab4d7fc84aefffb118ac2c8a4fc0)
|
||||||
set(LLVM_HASH_TYPE MD5)
|
set(LLVM_HASH_TYPE MD5)
|
||||||
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
|
set(LLVM_FILE llvm-project-${LLVM_VERSION}.src.tar.xz)
|
||||||
|
set(LLVM_CPE "cpe:2.3:a:llvm:compiler:${LLVM_VERSION}:*:*:*:*:*:*:*")
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
# Cloth physics test is crashing due to this bug:
|
# 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 7bce0e9e022e586b178b150002e7c2339994e3c2bbe44027e9abb0d60f9cce83)
|
||||||
set(FMT_HASH_TYPE SHA256)
|
set(FMT_HASH_TYPE SHA256)
|
||||||
set(FMT_FILE fmt-${FMT_VERSION}.tar.gz)
|
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.
|
# 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
|
# 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 376f17f189e9d02280dfe709b2b2bbea)
|
||||||
set(TIFF_HASH_TYPE MD5)
|
set(TIFF_HASH_TYPE MD5)
|
||||||
set(TIFF_FILE tiff-${TIFF_VERSION}.tar.gz)
|
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_VERSION 1.11.17.0)
|
||||||
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
|
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 14e8c22458ed7779a1957b26cde01db9)
|
||||||
set(PYTHON_HASH_TYPE MD5)
|
set(PYTHON_HASH_TYPE MD5)
|
||||||
set(PYTHON_FILE Python-${PYTHON_VERSION}.tar.xz)
|
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_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
|
||||||
set(TBB_HASH 55ec8df6eae5ed6364a47f0e671e460c)
|
set(TBB_HASH 55ec8df6eae5ed6364a47f0e671e460c)
|
||||||
set(TBB_HASH_TYPE MD5)
|
set(TBB_HASH_TYPE MD5)
|
||||||
set(TBB_FILE oneTBB-${TBB_VERSION}.tar.gz)
|
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_VERSION 9.0.0)
|
||||||
set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
|
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(IDNA_VERSION 3.3)
|
||||||
set(CHARSET_NORMALIZER_VERSION 2.0.10)
|
set(CHARSET_NORMALIZER_VERSION 2.0.10)
|
||||||
set(URLLIB3_VERSION 1.26.8)
|
set(URLLIB3_VERSION 1.26.8)
|
||||||
|
set(URLLIB3_CPE "cpe:2.3:a:urllib3:urllib3:${URLLIB3_VERSION}:*:*:*:*:*:*:*")
|
||||||
set(CERTIFI_VERSION 2021.10.8)
|
set(CERTIFI_VERSION 2021.10.8)
|
||||||
set(REQUESTS_VERSION 2.27.1)
|
set(REQUESTS_VERSION 2.27.1)
|
||||||
set(CYTHON_VERSION 0.29.26)
|
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 252de134862a27bd66705d29622edbfe)
|
||||||
set(NUMPY_HASH_TYPE MD5)
|
set(NUMPY_HASH_TYPE MD5)
|
||||||
set(NUMPY_FILE numpy-${NUMPY_VERSION}.zip)
|
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_VERSION 3.100)
|
||||||
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
|
set(LAME_URI http://downloads.sourceforge.net/project/lame/lame/3.100/lame-${LAME_VERSION}.tar.gz)
|
||||||
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
|
set(LAME_HASH 83e260acbe4389b54fe08e0bdbf7cddb)
|
||||||
set(LAME_HASH_TYPE MD5)
|
set(LAME_HASH_TYPE MD5)
|
||||||
set(LAME_FILE lame-${LAME_VERSION}.tar.gz)
|
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_VERSION 1.3.5)
|
||||||
set(OGG_URI http://downloads.xiph.org/releases/ogg/libogg-${OGG_VERSION}.tar.gz)
|
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 0e982409a9c3fc82ee06e08205b1355e5c6aa4c36bca58146ef399621b0ce5ab)
|
||||||
set(VORBIS_HASH_TYPE SHA256)
|
set(VORBIS_HASH_TYPE SHA256)
|
||||||
set(VORBIS_FILE libvorbis-${VORBIS_VERSION}.tar.gz)
|
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_VERSION 1.1.1)
|
||||||
set(THEORA_URI http://downloads.xiph.org/releases/theora/libtheora-${THEORA_VERSION}.tar.bz2)
|
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 8ff0607e75a322dd7cd6ec48f4f225471404ae2730d0ea945127b1355155e737 )
|
||||||
set(FLAC_HASH_TYPE SHA256)
|
set(FLAC_HASH_TYPE SHA256)
|
||||||
set(FLAC_FILE flac-${FLAC_VERSION}.tar.xz)
|
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_VERSION 1.11.0)
|
||||||
set(VPX_URI https://github.com/webmproject/libvpx/archive/v${VPX_VERSION}/libvpx-v${VPX_VERSION}.tar.gz)
|
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 965e51c91ad9851e2337aebcc0f517440c637c506f3a03948062e3d5ea129a83)
|
||||||
set(VPX_HASH_TYPE SHA256)
|
set(VPX_HASH_TYPE SHA256)
|
||||||
set(VPX_FILE libvpx-v${VPX_VERSION}.tar.gz)
|
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_VERSION 1.3.1)
|
||||||
set(OPUS_URI https://archive.mozilla.org/pub/opus/opus-${OPUS_VERSION}.tar.gz)
|
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 8702ba68b442657f11aaeb2b338443ca8d5fb95b0d845757968a7be31ef7f16d)
|
||||||
set(OPENJPEG_HASH_TYPE SHA256)
|
set(OPENJPEG_HASH_TYPE SHA256)
|
||||||
set(OPENJPEG_FILE openjpeg-v${OPENJPEG_VERSION}.tar.gz)
|
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_VERSION 5.0)
|
||||||
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
||||||
set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
|
set(FFMPEG_HASH c0130b8db2c763430fd1c6905288d61bc44ee0548ad5fcd2dfd650b88432bed9)
|
||||||
set(FFMPEG_HASH_TYPE SHA256)
|
set(FFMPEG_HASH_TYPE SHA256)
|
||||||
set(FFMPEG_FILE ffmpeg-${FFMPEG_VERSION}.tar.bz2)
|
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_VERSION 3.3.10)
|
||||||
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
|
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 646b5f98ce89ac60cdb060fcd398247c)
|
||||||
set(SNDFILE_HASH_TYPE MD5)
|
set(SNDFILE_HASH_TYPE MD5)
|
||||||
set(SNDFILE_FILE libsndfile-${SNDFILE_VERSION}.tar.gz)
|
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_VERSION 1.2.2)
|
||||||
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
|
set(WEBP_URI https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-${WEBP_VERSION}.tar.gz)
|
||||||
set(WEBP_HASH b5e2e414a8adee4c25fe56b18dd9c549)
|
set(WEBP_HASH b5e2e414a8adee4c25fe56b18dd9c549)
|
||||||
set(WEBP_HASH_TYPE MD5)
|
set(WEBP_HASH_TYPE MD5)
|
||||||
set(WEBP_FILE libwebp-${WEBP_VERSION}.tar.gz)
|
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_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)
|
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 10942a1dc23137a8aa07f0639cbfece5)
|
||||||
set(XML2_HASH_TYPE MD5)
|
set(XML2_HASH_TYPE MD5)
|
||||||
set(XML2_FILE libxml2-${XML2_VERSION}.tar.gz)
|
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 2_6_2)
|
||||||
set(TINYXML_VERSION_DOTS 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 c1b864c96804a10526540c664ade67f0)
|
||||||
set(TINYXML_HASH_TYPE MD5)
|
set(TINYXML_HASH_TYPE MD5)
|
||||||
set(TINYXML_FILE tinyxml_${TINYXML_VERSION}.tar.gz)
|
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_VERSION 0.6.3)
|
||||||
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
|
set(YAMLCPP_URI https://codeload.github.com/jbeder/yaml-cpp/tar.gz/yaml-cpp-${YAMLCPP_VERSION})
|
||||||
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
|
set(YAMLCPP_HASH b45bf1089a382e81f6b661062c10d0c2)
|
||||||
set(YAMLCPP_HASH_TYPE MD5)
|
set(YAMLCPP_HASH_TYPE MD5)
|
||||||
set(YAMLCPP_FILE yaml-cpp-${YAMLCPP_VERSION}.tar.gz)
|
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_VERSION v1.1.3)
|
||||||
set(PYSTRING_URI https://codeload.github.com/imageworks/pystring/tar.gz/refs/tags/${PYSTRING_VERSION})
|
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(PYSTRING_FILE pystring-${PYSTRING_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(EXPAT_VERSION 2_4_4)
|
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_URI https://github.com/libexpat/libexpat/archive/R_${EXPAT_VERSION}.tar.gz)
|
||||||
set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
|
set(EXPAT_HASH 2d3e81dee94b452369dc6394ff0f8f98)
|
||||||
set(EXPAT_HASH_TYPE MD5)
|
set(EXPAT_HASH_TYPE MD5)
|
||||||
set(EXPAT_FILE libexpat-${EXPAT_VERSION}.tar.gz)
|
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_VERSION 1.10)
|
||||||
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
|
set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
|
||||||
set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
|
set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
|
||||||
set(PUGIXML_HASH_TYPE MD5)
|
set(PUGIXML_HASH_TYPE MD5)
|
||||||
set(PUGIXML_FILE pugixml-${PUGIXML_VERSION}.tar.gz)
|
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_VERSION 2.5.24)
|
||||||
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison/win_flex_bison-${FLEXBISON_VERSION}.zip)
|
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 ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269)
|
||||||
set(BZIP2_HASH_TYPE SHA256)
|
set(BZIP2_HASH_TYPE SHA256)
|
||||||
set(BZIP2_FILE bzip2_${BZIP2_VERSION}.orig.tar.gz)
|
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_VERSION 3.3)
|
||||||
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
|
set(FFI_URI https://sourceware.org/pub/libffi/libffi-${FFI_VERSION}.tar.gz)
|
||||||
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
|
set(FFI_HASH 72fba7922703ddfa7a028d513ac15a85c8d54c8d67f55fa5a4802885dc652056)
|
||||||
set(FFI_HASH_TYPE SHA256)
|
set(FFI_HASH_TYPE SHA256)
|
||||||
set(FFI_FILE libffi-${FFI_VERSION}.tar.gz)
|
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_VERSION 5.2.5)
|
||||||
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
|
set(LZMA_URI https://tukaani.org/xz/xz-${LZMA_VERSION}.tar.bz2)
|
||||||
|
@ -403,12 +444,14 @@ else()
|
||||||
set(SSL_HASH_TYPE SHA256)
|
set(SSL_HASH_TYPE SHA256)
|
||||||
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
|
set(SSL_FILE openssl-${SSL_VERSION}.tar.gz)
|
||||||
endif()
|
endif()
|
||||||
|
set(SSL_CPE "cpe:2.3:a:openssl:openssl:${SSL_VERSION}:*:*:*:*:*:*:*")
|
||||||
|
|
||||||
set(SQLITE_VERSION 3.31.1)
|
set(SQLITE_VERSION 3.31.1)
|
||||||
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
|
set(SQLITE_URI https://www.sqlite.org/2018/sqlite-src-3240000.zip)
|
||||||
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
|
set(SQLITE_HASH fb558c49ee21a837713c4f1e7e413309aabdd9c7)
|
||||||
set(SQLITE_HASH_TYPE SHA1)
|
set(SQLITE_HASH_TYPE SHA1)
|
||||||
set(SQLITE_FILE sqlite-src-3240000.zip)
|
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_VERSION 3.13.4)
|
||||||
set(EMBREE_URI https://github.com/embree/embree/archive/v${EMBREE_VERSION}.zip)
|
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 022c7293074aeeced2278c872db4fa693147c70f8595b076cf3f1ef81520766d)
|
||||||
set(MESA_HASH_TYPE SHA256)
|
set(MESA_HASH_TYPE SHA256)
|
||||||
set(MESA_FILE mesa-${MESA_VERSION}.tar.xz)
|
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_VERSION 2.15.02)
|
||||||
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
|
set(NASM_URI https://github.com/netwide-assembler/nasm/archive/nasm-${NASM_VERSION}.tar.gz)
|
||||||
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
|
set(NASM_HASH aded8b796c996a486a56e0515c83e414116decc3b184d88043480b32eb0a8589)
|
||||||
set(NASM_HASH_TYPE SHA256)
|
set(NASM_HASH_TYPE SHA256)
|
||||||
set(NASM_FILE nasm-${NASM_VERSION}.tar.gz)
|
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_VERSION 1.0.22)
|
||||||
set(XR_OPENXR_SDK_URI https://github.com/KhronosGroup/OpenXR-SDK/archive/release-${XR_OPENXR_SDK_VERSION}.tar.gz)
|
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 0b82665c4a92fd2ade7440c13fcaa42b)
|
||||||
set(GMP_HASH_TYPE MD5)
|
set(GMP_HASH_TYPE MD5)
|
||||||
set(GMP_FILE gmp-${GMP_VERSION}.tar.xz)
|
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_VERSION 1.16)
|
||||||
set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz)
|
set(POTRACE_URI http://potrace.sourceforge.net/download/${POTRACE_VERSION}/potrace-${POTRACE_VERSION}.tar.gz)
|
||||||
set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69)
|
set(POTRACE_HASH 5f0bd87ddd9a620b0c4e65652ef93d69)
|
||||||
set(POTRACE_HASH_TYPE MD5)
|
set(POTRACE_HASH_TYPE MD5)
|
||||||
set(POTRACE_FILE potrace-${POTRACE_VERSION}.tar.gz)
|
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_VERSION 2_3_0)
|
||||||
set(HARU_URI https://github.com/libharu/libharu/archive/RELEASE_${HARU_VERSION}.tar.gz)
|
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 5194fbfa781fcf45b98c5e849651aa7b3b0a008c6b72d4a0db760f3002291e94)
|
||||||
set(ZSTD_HASH_TYPE SHA256)
|
set(ZSTD_HASH_TYPE SHA256)
|
||||||
set(ZSTD_FILE zstd-${ZSTD_VERSION}.tar.gz)
|
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_VERSION fe5ff00bb8d19b327714a3c290f3e2ce81ba3525)
|
||||||
set(SSE2NEON_URI https://github.com/DLTcollab/sse2neon/archive/${SSE2NEON_VERSION}.tar.gz)
|
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_HASH_TYPE SHA256)
|
||||||
set(SSE2NEON_FILE sse2neon-${SSE2NEON_VERSION}.tar.gz)
|
set(SSE2NEON_FILE sse2neon-${SSE2NEON_VERSION}.tar.gz)
|
||||||
|
|
||||||
set(BROTLI_VERSION v1.0.9)
|
set(BROTLI_VERSION 1.0.9)
|
||||||
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/${BROTLI_VERSION}.tar.gz)
|
set(BROTLI_URI https://github.com/google/brotli/archive/refs/tags/v${BROTLI_VERSION}.tar.gz)
|
||||||
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
|
set(BROTLI_HASH f9e8d81d0405ba66d181529af42a3354f838c939095ff99930da6aa9cdf6fe46)
|
||||||
set(BROTLI_HASH_TYPE SHA256)
|
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_VERSION v0.3.1-beta)
|
||||||
set(OPENPGL_SHORT_VERSION 0.3.1)
|
set(OPENPGL_SHORT_VERSION 0.3.1)
|
||||||
|
|
|
@ -778,31 +778,11 @@ if(WITH_GHOST_WAYLAND)
|
||||||
endif()
|
endif()
|
||||||
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)
|
if(WITH_GHOST_WAYLAND_DBUS)
|
||||||
list(APPEND PLATFORM_LINKLIBS
|
|
||||||
${dbus_LINK_LIBRARIES}
|
|
||||||
)
|
|
||||||
add_definitions(-DWITH_GHOST_WAYLAND_DBUS)
|
add_definitions(-DWITH_GHOST_WAYLAND_DBUS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||||
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
|
|
||||||
list(APPEND PLATFORM_LINKLIBS
|
|
||||||
${libdecor_LIBRARIES}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
add_definitions(-DWITH_GHOST_WAYLAND_LIBDECOR)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -855,12 +835,8 @@ if(WITH_GHOST_X11)
|
||||||
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
|
find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH})
|
||||||
mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
|
mark_as_advanced(X11_XF86keysym_INCLUDE_PATH)
|
||||||
|
|
||||||
list(APPEND PLATFORM_LINKLIBS ${X11_X11_LIB})
|
|
||||||
|
|
||||||
if(WITH_X11_XINPUT)
|
if(WITH_X11_XINPUT)
|
||||||
if(X11_Xinput_LIB)
|
if(NOT X11_Xinput_LIB)
|
||||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xinput_LIB})
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "LibXi not found. Disable WITH_X11_XINPUT if you
|
message(FATAL_ERROR "LibXi not found. Disable WITH_X11_XINPUT if you
|
||||||
want to build without tablet support")
|
want to build without tablet support")
|
||||||
endif()
|
endif()
|
||||||
|
@ -870,18 +846,14 @@ if(WITH_GHOST_X11)
|
||||||
# XXX, why doesn't cmake make this available?
|
# XXX, why doesn't cmake make this available?
|
||||||
find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
|
find_library(X11_Xxf86vmode_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
|
||||||
mark_as_advanced(X11_Xxf86vmode_LIB)
|
mark_as_advanced(X11_Xxf86vmode_LIB)
|
||||||
if(X11_Xxf86vmode_LIB)
|
if(NOT X11_Xxf86vmode_LIB)
|
||||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xxf86vmode_LIB})
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "libXxf86vm not found. Disable WITH_X11_XF86VMODE if you
|
message(FATAL_ERROR "libXxf86vm not found. Disable WITH_X11_XF86VMODE if you
|
||||||
want to build without")
|
want to build without")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_X11_XFIXES)
|
if(WITH_X11_XFIXES)
|
||||||
if(X11_Xfixes_LIB)
|
if(NOT X11_Xfixes_LIB)
|
||||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xfixes_LIB})
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "libXfixes not found. Disable WITH_X11_XFIXES if you
|
message(FATAL_ERROR "libXfixes not found. Disable WITH_X11_XFIXES if you
|
||||||
want to build without")
|
want to build without")
|
||||||
endif()
|
endif()
|
||||||
|
@ -890,9 +862,7 @@ if(WITH_GHOST_X11)
|
||||||
if(WITH_X11_ALPHA)
|
if(WITH_X11_ALPHA)
|
||||||
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
|
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
|
||||||
mark_as_advanced(X11_Xrender_LIB)
|
mark_as_advanced(X11_Xrender_LIB)
|
||||||
if(X11_Xrender_LIB)
|
if(NOT X11_Xrender_LIB)
|
||||||
list(APPEND PLATFORM_LINKLIBS ${X11_Xrender_LIB})
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "libXrender not found. Disable WITH_X11_ALPHA if you
|
message(FATAL_ERROR "libXrender not found. Disable WITH_X11_ALPHA if you
|
||||||
want to build without")
|
want to build without")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
sphinx==5.1.1
|
sphinx==5.2.3
|
||||||
|
|
||||||
# Sphinx dependencies that are important
|
# Sphinx dependencies that are important
|
||||||
Jinja2==3.1.2
|
Jinja2==3.1.2
|
||||||
|
@ -6,7 +6,7 @@ Pygments==2.13.0
|
||||||
docutils==0.17.1
|
docutils==0.17.1
|
||||||
snowballstemmer==2.2.0
|
snowballstemmer==2.2.0
|
||||||
babel==2.10.3
|
babel==2.10.3
|
||||||
requests==2.27.1
|
requests==2.28.1
|
||||||
|
|
||||||
# Only needed to match the theme used for the official documentation.
|
# Only needed to match the theme used for the official documentation.
|
||||||
# Without this theme, the default theme will be used.
|
# 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)
|
bool OneapiDevice::load_kernels(const uint requested_features)
|
||||||
{
|
{
|
||||||
assert(device_queue_);
|
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_);
|
bool is_finished_ok = oneapi_run_test_kernel(device_queue_);
|
||||||
if (is_finished_ok == false) {
|
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 {
|
else {
|
||||||
VLOG_INFO << "Runtime compilation done for \"" << info.description << "\"";
|
VLOG_INFO << "Test kernel has been executed successfully for \"" << info.description << "\"";
|
||||||
assert(device_queue_);
|
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;
|
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
|
/* Create path tracing work in advance, so that it can be reused by incremental sampling as much
|
||||||
* as possible. */
|
* as possible. */
|
||||||
device_->foreach_device([&](Device *path_trace_device) {
|
device_->foreach_device([&](Device *path_trace_device) {
|
||||||
path_trace_works_.emplace_back(PathTraceWork::create(
|
unique_ptr<PathTraceWork> work = PathTraceWork::create(
|
||||||
path_trace_device, film, device_scene, &render_cancel_.is_requested));
|
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());
|
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) {
|
if (device->info.type == DEVICE_CPU) {
|
||||||
return make_unique<PathTraceWorkCPU>(device, film, device_scene, cancel_requested_flag);
|
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);
|
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;
|
work_balance_infos[0].weight = 1.0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (num_infos == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* There is no statistics available, so start with an equal distribution. */
|
/* There is no statistics available, so start with an equal distribution. */
|
||||||
const double weight = 1.0 / num_infos;
|
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);
|
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,
|
bool oneapi_enqueue_kernel(KernelContext *kernel_context,
|
||||||
int kernel,
|
int kernel,
|
||||||
size_t global_size,
|
size_t global_size,
|
||||||
|
|
|
@ -48,6 +48,8 @@ CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_enqueue_kernel(KernelContext *context,
|
||||||
int kernel,
|
int kernel,
|
||||||
size_t global_size,
|
size_t global_size,
|
||||||
void **args);
|
void **args);
|
||||||
|
CYCLES_KERNEL_ONEAPI_EXPORT bool oneapi_load_kernels(SyclQueue *queue,
|
||||||
|
const unsigned int requested_features);
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
|
@ -43,6 +43,10 @@ Session::Session(const SessionParams ¶ms_, const SceneParams &scene_params)
|
||||||
|
|
||||||
device = Device::create(params.device, stats, profiler);
|
device = Device::create(params.device, stats, profiler);
|
||||||
|
|
||||||
|
if (device->have_error()) {
|
||||||
|
progress.set_error(device->error_message());
|
||||||
|
}
|
||||||
|
|
||||||
scene = new Scene(scene_params, device);
|
scene = new Scene(scene_params, device);
|
||||||
|
|
||||||
/* Configure path tracer. */
|
/* Configure path tracer. */
|
||||||
|
|
|
@ -262,6 +262,9 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
||||||
${xkbcommon_INCLUDE_DIRS}
|
${xkbcommon_INCLUDE_DIRS}
|
||||||
${wayland-cursor_INCLUDE_DIRS}
|
${wayland-cursor_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
list(APPEND LIB
|
||||||
|
${xkbcommon_LINK_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND_DYNLOAD)
|
if(WITH_GHOST_WAYLAND_DYNLOAD)
|
||||||
list(APPEND INC_SYS
|
list(APPEND INC_SYS
|
||||||
|
@ -271,18 +274,32 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
||||||
bf_intern_wayland_dynload
|
bf_intern_wayland_dynload
|
||||||
)
|
)
|
||||||
add_definitions(-DWITH_GHOST_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()
|
endif()
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND_DBUS)
|
if(WITH_GHOST_WAYLAND_DBUS)
|
||||||
list(APPEND INC_SYS
|
list(APPEND INC_SYS
|
||||||
${dbus_INCLUDE_DIRS}
|
${dbus_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
list(APPEND LIB
|
||||||
|
${dbus_LINK_LIBRARIES}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
if(WITH_GHOST_WAYLAND_LIBDECOR)
|
||||||
list(APPEND INC_SYS
|
list(APPEND INC_SYS
|
||||||
${libdecor_INCLUDE_DIRS}
|
${libdecor_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
if(NOT WITH_GHOST_WAYLAND_DYNLOAD)
|
||||||
|
list(APPEND LIB
|
||||||
|
${libdecor_LIBRARIES}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
|
@ -332,16 +349,16 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
|
||||||
${INC_DST}
|
${INC_DST}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT WITH_GHOST_WAYLAND_LIBDECOR)
|
# Used when: LIBDECOR is not needed.
|
||||||
# `xdg-shell`.
|
# `xdg-shell`.
|
||||||
generate_protocol_bindings(
|
generate_protocol_bindings(
|
||||||
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||||
)
|
)
|
||||||
# `xdg-decoration`.
|
# `xdg-decoration`.
|
||||||
generate_protocol_bindings(
|
generate_protocol_bindings(
|
||||||
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||||
)
|
)
|
||||||
endif()
|
# End LIBDECOR alternative.
|
||||||
|
|
||||||
# `xdg-output`.
|
# `xdg-output`.
|
||||||
generate_protocol_bindings(
|
generate_protocol_bindings(
|
||||||
|
|
|
@ -48,7 +48,7 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
||||||
/* Pass. */
|
/* Pass. */
|
||||||
#elif defined(WITH_GHOST_WAYLAND)
|
#elif defined(WITH_GHOST_WAYLAND)
|
||||||
# if defined(WITH_GHOST_WAYLAND_DYNLOAD)
|
# 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
|
# else
|
||||||
const bool has_wayland_libraries = true;
|
const bool has_wayland_libraries = true;
|
||||||
# endif
|
# endif
|
||||||
|
@ -66,6 +66,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
||||||
catch (const std::runtime_error &) {
|
catch (const std::runtime_error &) {
|
||||||
delete m_system;
|
delete m_system;
|
||||||
m_system = nullptr;
|
m_system = nullptr;
|
||||||
|
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||||
|
ghost_wl_dynload_libraries_exit();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -101,6 +104,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem(bool verbose)
|
||||||
catch (const std::runtime_error &) {
|
catch (const std::runtime_error &) {
|
||||||
delete m_system;
|
delete m_system;
|
||||||
m_system = nullptr;
|
m_system = nullptr;
|
||||||
|
# ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
||||||
|
ghost_wl_dynload_libraries_exit();
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -54,6 +54,11 @@
|
||||||
#include <tablet-unstable-v2-client-protocol.h>
|
#include <tablet-unstable-v2-client-protocol.h>
|
||||||
#include <xdg-output-unstable-v1-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 <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -64,6 +69,15 @@
|
||||||
/* Logging, use `ghost.wl.*` prefix. */
|
/* Logging, use `ghost.wl.*` prefix. */
|
||||||
#include "CLG_log.h"
|
#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 keyboard_handle_key_repeat_cancel(struct GWL_Seat *seat);
|
||||||
|
|
||||||
static void output_handle_done(void *data, struct wl_output *wl_output);
|
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
|
#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};
|
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 {
|
struct GWL_Seat {
|
||||||
GHOST_SystemWayland *system = nullptr;
|
GHOST_SystemWayland *system = nullptr;
|
||||||
|
|
||||||
|
@ -455,11 +508,10 @@ struct GWL_Display {
|
||||||
struct wl_compositor *compositor = nullptr;
|
struct wl_compositor *compositor = nullptr;
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
struct libdecor *decor_context = nullptr;
|
WGL_LibDecor_System *libdecor = nullptr;
|
||||||
#else
|
bool libdecor_required = false;
|
||||||
struct xdg_wm_base *xdg_shell = nullptr;
|
|
||||||
struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
|
WGL_XDG_Decor_System *xdg_decor = nullptr;
|
||||||
|
|
||||||
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
|
struct zxdg_output_manager_v1 *xdg_output_manager = nullptr;
|
||||||
struct wl_shm *shm = nullptr;
|
struct wl_shm *shm = nullptr;
|
||||||
|
@ -626,19 +678,19 @@ static void display_destroy(GWL_Display *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
if (d->decor_context) {
|
if (use_libdecor) {
|
||||||
libdecor_unref(d->decor_context);
|
if (d->libdecor) {
|
||||||
|
wgl_libdecor_system_destroy(d->libdecor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
else
|
||||||
if (d->xdg_decoration_manager) {
|
#endif
|
||||||
zxdg_decoration_manager_v1_destroy(d->xdg_decoration_manager);
|
{
|
||||||
|
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) {
|
if (eglGetDisplay) {
|
||||||
::eglTerminate(eglGetDisplay(EGLNativeDisplayType(d->display)));
|
::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
|
/** \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"};
|
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*/,
|
static void shell_handle_ping(void * /*data*/,
|
||||||
struct xdg_wm_base *xdg_wm_base,
|
struct xdg_wm_base *xdg_wm_base,
|
||||||
|
@ -2920,9 +2970,7 @@ static const struct xdg_wm_base_listener shell_listener = {
|
||||||
shell_handle_ping,
|
shell_handle_ping,
|
||||||
};
|
};
|
||||||
|
|
||||||
# undef LOG
|
#undef LOG
|
||||||
|
|
||||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
@ -2978,19 +3026,17 @@ static void global_handle_add(void *data,
|
||||||
display->compositor = static_cast<wl_compositor *>(
|
display->compositor = static_cast<wl_compositor *>(
|
||||||
wl_registry_bind(wl_registry, name, &wl_compositor_interface, 3));
|
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)) {
|
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));
|
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)) {
|
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));
|
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)) {
|
else if (STREQ(interface, zxdg_output_manager_v1_interface.name)) {
|
||||||
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
|
display->xdg_output_manager = static_cast<zxdg_output_manager_v1 *>(
|
||||||
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
|
wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2));
|
||||||
|
@ -3048,6 +3094,14 @@ static void global_handle_add(void *data,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
found = false;
|
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,
|
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!");
|
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. */
|
/* Register interfaces. */
|
||||||
struct wl_registry *registry = wl_display_get_registry(d->display);
|
struct wl_registry *registry = wl_display_get_registry(d->display);
|
||||||
wl_registry_add_listener(registry, ®istry_listener, d);
|
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);
|
wl_registry_destroy(registry);
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
d->decor_context = libdecor_new(d->display, &libdecor_interface);
|
if (d->libdecor_required) {
|
||||||
if (!d->decor_context) {
|
wgl_xdg_decor_system_destroy(d->xdg_decor);
|
||||||
display_destroy(d);
|
d->xdg_decor = nullptr;
|
||||||
throw std::runtime_error("Wayland: unable to create window decorations!");
|
|
||||||
|
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
|
else {
|
||||||
if (!d->xdg_shell) {
|
use_libdecor = false;
|
||||||
display_destroy(d);
|
|
||||||
throw std::runtime_error("Wayland: unable to access xdg_shell!");
|
|
||||||
}
|
}
|
||||||
|
#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
|
#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. */
|
/* Register data device per seat for IPC between Wayland clients. */
|
||||||
if (d->data_device_manager) {
|
if (d->data_device_manager) {
|
||||||
|
@ -4052,25 +4137,25 @@ wl_compositor *GHOST_SystemWayland::compositor()
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
|
|
||||||
libdecor *GHOST_SystemWayland::decor_context()
|
libdecor *GHOST_SystemWayland::libdecor_context()
|
||||||
{
|
{
|
||||||
return d->decor_context;
|
return d->libdecor->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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR */
|
#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
|
const std::vector<GWL_Output *> &GHOST_SystemWayland::outputs() const
|
||||||
{
|
{
|
||||||
return d->outputs;
|
return d->outputs;
|
||||||
|
@ -4317,57 +4402,52 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
bool ghost_wl_dynload_libraries()
|
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
|
# ifdef WITH_GHOST_X11
|
||||||
bool verbose = false;
|
/* When running in WAYLAND, let the user know when a missing library is the only reason
|
||||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
* WAYLAND could not be used. Otherwise it's not obvious why X11 is used as a fallback.
|
||||||
/* When running in Wayland, let the user know if libdecor is the only reason WAYLAND
|
* Otherwise when X11 is used, reporting WAYLAND library warnings is unwelcome noise. */
|
||||||
* could not be used. Otherwise it's not obvious why X11 is used as a fallback. */
|
bool verbose = getenv("WAYLAND_DISPLAY") != nullptr;
|
||||||
bool verbose_libdecor = getenv("WAYLAND_DISPLAY") != nullptr;
|
|
||||||
# endif
|
|
||||||
# else
|
# else
|
||||||
bool verbose = true;
|
bool verbose = true;
|
||||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
|
||||||
bool verbose_libdecor = true;
|
|
||||||
# endif
|
|
||||||
# endif /* !WITH_GHOST_X11 */
|
# endif /* !WITH_GHOST_X11 */
|
||||||
|
|
||||||
# ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
|
||||||
int8_t libdecor_init = -1;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
|
if (wayland_dynload_client_init(verbose) && /* `libwayland-client`. */
|
||||||
wayland_dynload_cursor_init(verbose) && /* `libwayland-cursor`. */
|
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
|
# 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
|
# endif
|
||||||
true) {
|
|
||||||
return 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_client_exit();
|
||||||
wayland_dynload_cursor_exit();
|
wayland_dynload_cursor_exit();
|
||||||
wayland_dynload_egl_exit();
|
wayland_dynload_egl_exit();
|
||||||
|
|
||||||
return false;
|
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 */
|
#endif /* WITH_GHOST_WAYLAND_DYNLOAD */
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
|
@ -21,18 +21,12 @@
|
||||||
# include <wayland_dynload_libdecor.h>
|
# include <wayland_dynload_libdecor.h>
|
||||||
# endif
|
# endif
|
||||||
# include <libdecor.h>
|
# include <libdecor.h>
|
||||||
#else
|
|
||||||
/* Generated by `wayland-scanner`. */
|
|
||||||
# include <xdg-decoration-unstable-v1-client-protocol.h>
|
|
||||||
# include <xdg-shell-client-protocol.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class GHOST_WindowWayland;
|
class GHOST_WindowWayland;
|
||||||
|
|
||||||
struct GWL_Display;
|
|
||||||
|
|
||||||
bool ghost_wl_output_own(const struct wl_output *wl_output);
|
bool ghost_wl_output_own(const struct wl_output *wl_output);
|
||||||
void ghost_wl_output_tag(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);
|
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,
|
* Return true when all required WAYLAND libraries are present,
|
||||||
* Performs dynamic loading when `WITH_GHOST_WAYLAND_DYNLOAD` is in use.
|
* 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
|
#endif
|
||||||
|
|
||||||
struct GWL_Output {
|
struct GWL_Output {
|
||||||
|
@ -167,11 +162,11 @@ class GHOST_SystemWayland : public GHOST_System {
|
||||||
wl_compositor *compositor();
|
wl_compositor *compositor();
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor *decor_context();
|
libdecor *libdecor_context();
|
||||||
#else
|
|
||||||
xdg_wm_base *xdg_shell();
|
|
||||||
zxdg_decoration_manager_v1 *xdg_decoration_manager();
|
|
||||||
#endif
|
#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;
|
const std::vector<GWL_Output *> &outputs() const;
|
||||||
|
|
||||||
|
@ -192,6 +187,10 @@ class GHOST_SystemWayland : public GHOST_System {
|
||||||
wl_surface *wl_surface,
|
wl_surface *wl_surface,
|
||||||
int scale);
|
int scale);
|
||||||
|
|
||||||
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
|
static bool use_libdecor_runtime();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct GWL_Display *d;
|
struct GWL_Display *d;
|
||||||
std::string selection;
|
std::string selection;
|
||||||
|
|
|
@ -2435,11 +2435,11 @@ GHOST_TSuccess GHOST_SystemX11::showMessageBox(const char *title,
|
||||||
utf8Str,
|
utf8Str,
|
||||||
8,
|
8,
|
||||||
PropModeReplace,
|
PropModeReplace,
|
||||||
(const unsigned char *)title,
|
(const uchar *)title,
|
||||||
int(strlen(title)));
|
int(strlen(title)));
|
||||||
|
|
||||||
XChangeProperty(
|
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 */
|
/* Create buttons GC */
|
||||||
|
|
|
@ -31,13 +31,52 @@
|
||||||
# include <libdecor.h>
|
# include <libdecor.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Generated by `wayland-scanner`. */
|
||||||
|
#include <xdg-decoration-unstable-v1-client-protocol.h>
|
||||||
|
#include <xdg-shell-client-protocol.h>
|
||||||
|
|
||||||
/* Logging, use `ghost.wl.*` prefix. */
|
/* Logging, use `ghost.wl.*` prefix. */
|
||||||
#include "CLG_log.h"
|
#include "CLG_log.h"
|
||||||
|
|
||||||
static constexpr size_t base_dpi = 96;
|
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;
|
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 {
|
struct GWL_Window {
|
||||||
GHOST_WindowWayland *w = nullptr;
|
GHOST_WindowWayland *w = nullptr;
|
||||||
struct wl_surface *wl_surface = nullptr;
|
struct wl_surface *wl_surface = nullptr;
|
||||||
|
@ -60,15 +99,9 @@ struct GWL_Window {
|
||||||
uint32_t dpi = 0;
|
uint32_t dpi = 0;
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
struct libdecor_frame *decor_frame = nullptr;
|
WGL_LibDecor_Window *libdecor = 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;
|
|
||||||
#endif
|
#endif
|
||||||
|
WGL_XDG_Decor_Window *xdg_decor = nullptr;
|
||||||
|
|
||||||
wl_egl_window *egl_window = nullptr;
|
wl_egl_window *egl_window = nullptr;
|
||||||
bool is_maximised = false;
|
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
|
/** \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"};
|
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,
|
static void xdg_toplevel_handle_configure(void *data,
|
||||||
xdg_toplevel * /*xdg_toplevel*/,
|
xdg_toplevel * /*xdg_toplevel*/,
|
||||||
|
@ -197,9 +228,7 @@ static const xdg_toplevel_listener toplevel_listener = {
|
||||||
xdg_toplevel_handle_close,
|
xdg_toplevel_handle_close,
|
||||||
};
|
};
|
||||||
|
|
||||||
# undef LOG
|
#undef LOG
|
||||||
|
|
||||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
@ -250,7 +279,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
|
||||||
libdecor_frame_commit(frame, state, configuration);
|
libdecor_frame_commit(frame, state, configuration);
|
||||||
libdecor_state_free(state);
|
libdecor_state_free(state);
|
||||||
|
|
||||||
win->decor_configured = true;
|
win->libdecor->configured = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frame_handle_close(struct libdecor_frame * /*frame*/, void *data)
|
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
|
/** \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"};
|
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(
|
static void xdg_toplevel_decoration_handle_configure(
|
||||||
void *data,
|
void *data,
|
||||||
|
@ -296,16 +323,14 @@ static void xdg_toplevel_decoration_handle_configure(
|
||||||
const uint32_t mode)
|
const uint32_t mode)
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG, 2, "configure (mode=%u)", 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 = {
|
static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
|
||||||
xdg_toplevel_decoration_handle_configure,
|
xdg_toplevel_decoration_handle_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
# undef LOG
|
#undef LOG
|
||||||
|
|
||||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
@ -313,10 +338,8 @@ static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listene
|
||||||
/** \name Listener (XDG Surface Handle Configure), #xdg_surface_listener
|
/** \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"};
|
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,
|
static void xdg_surface_handle_configure(void *data,
|
||||||
xdg_surface *xdg_surface,
|
xdg_surface *xdg_surface,
|
||||||
|
@ -324,7 +347,7 @@ static void xdg_surface_handle_configure(void *data,
|
||||||
{
|
{
|
||||||
GWL_Window *win = static_cast<GWL_Window *>(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)");
|
CLOG_INFO(LOG, 2, "configure (skipped)");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -354,9 +377,7 @@ static const xdg_surface_listener xdg_surface_listener = {
|
||||||
xdg_surface_handle_configure,
|
xdg_surface_handle_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
# undef LOG
|
#undef LOG
|
||||||
|
|
||||||
#endif /* !WITH_GHOST_WAYLAND_LIBDECOR. */
|
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
@ -477,42 +498,52 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
||||||
const int32_t size_min[2] = {320, 240};
|
const int32_t size_min[2] = {320, 240};
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
/* create window decorations */
|
if (use_libdecor) {
|
||||||
w->decor_frame = libdecor_decorate(
|
w->libdecor = new WGL_LibDecor_Window;
|
||||||
m_system->decor_context(), w->wl_surface, &libdecor_frame_iface, w);
|
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||||
libdecor_frame_map(w->decor_frame);
|
|
||||||
|
|
||||||
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_min_content_size(decor.frame, UNPACK2(size_min));
|
||||||
libdecor_frame_set_parent(
|
|
||||||
w->decor_frame, dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->w->decor_frame);
|
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
|
else
|
||||||
w->xdg_surface = xdg_wm_base_get_xdg_surface(m_system->xdg_shell(), w->wl_surface);
|
#endif
|
||||||
w->xdg_toplevel = xdg_surface_get_toplevel(w->xdg_surface);
|
{
|
||||||
|
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()) {
|
if (m_system->xdg_decor_manager()) {
|
||||||
w->xdg_toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||||
m_system->xdg_decoration_manager(), w->xdg_toplevel);
|
m_system->xdg_decor_manager(), decor.toplevel);
|
||||||
zxdg_toplevel_decoration_v1_add_listener(
|
zxdg_toplevel_decoration_v1_add_listener(
|
||||||
w->xdg_toplevel_decoration, &toplevel_decoration_v1_listener, w);
|
decor.toplevel_decor, &toplevel_decoration_v1_listener, w);
|
||||||
zxdg_toplevel_decoration_v1_set_mode(w->xdg_toplevel_decoration,
|
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
|
||||||
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
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);
|
setTitle(title);
|
||||||
|
|
||||||
wl_surface_set_user_data(w->wl_surface, this);
|
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());
|
wl_display_roundtrip(m_system->display());
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
/* It's important not to return until the window is configured or
|
if (use_libdecor) {
|
||||||
* calls to `setState` from Blender will crash `libdecor`. */
|
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||||
while (!w->decor_configured) {
|
/* It's important not to return until the window is configured or
|
||||||
if (libdecor_dispatch(m_system->decor_context(), 0) < 0) {
|
* calls to `setState` from Blender will crash `libdecor`. */
|
||||||
break;
|
while (!decor.configured) {
|
||||||
|
if (libdecor_dispatch(m_system->libdecor_context(), 0) < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -535,9 +569,13 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
||||||
setOpaque();
|
setOpaque();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WITH_GHOST_WAYLAND_LIBDECOR /* Causes a glitch with `libdecor` for some reason. */
|
/* Causes a glitch with `libdecor` for some reason. */
|
||||||
setState(state);
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
|
if (use_libdecor == false)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
setState(state);
|
||||||
|
}
|
||||||
|
|
||||||
/* EGL context. */
|
/* EGL context. */
|
||||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||||
|
@ -596,12 +634,18 @@ GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
|
||||||
void GHOST_WindowWayland::setTitle(const char *title)
|
void GHOST_WindowWayland::setTitle(const char *title)
|
||||||
{
|
{
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_set_app_id(w->decor_frame, title);
|
if (use_libdecor) {
|
||||||
libdecor_frame_set_title(w->decor_frame, title);
|
WGL_LibDecor_Window &decor = *w->libdecor;
|
||||||
#else
|
libdecor_frame_set_app_id(decor.frame, title);
|
||||||
xdg_toplevel_set_title(w->xdg_toplevel, title);
|
libdecor_frame_set_title(decor.frame, title);
|
||||||
xdg_toplevel_set_app_id(w->xdg_toplevel, title);
|
}
|
||||||
|
else
|
||||||
#endif
|
#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;
|
this->title = title;
|
||||||
}
|
}
|
||||||
|
@ -672,14 +716,14 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
|
||||||
wl_egl_window_destroy(w->egl_window);
|
wl_egl_window_destroy(w->egl_window);
|
||||||
|
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_unref(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
wgl_libdecor_window_destroy(w->libdecor);
|
||||||
if (w->xdg_toplevel_decoration) {
|
|
||||||
zxdg_toplevel_decoration_v1_destroy(w->xdg_toplevel_decoration);
|
|
||||||
}
|
}
|
||||||
xdg_toplevel_destroy(w->xdg_toplevel);
|
else
|
||||||
xdg_surface_destroy(w->xdg_surface);
|
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
wgl_xdg_decor_window_destroy(w->xdg_decor);
|
||||||
|
}
|
||||||
|
|
||||||
/* Clear any pointers to this window. This is needed because there are no guarantees
|
/* 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. */
|
* 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:
|
case GHOST_kWindowStateNormal:
|
||||||
/* Unset states. */
|
/* Unset states. */
|
||||||
switch (getState()) {
|
switch (getState()) {
|
||||||
case GHOST_kWindowStateMaximized:
|
case GHOST_kWindowStateMaximized: {
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_unset_maximized(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_unset_maximized(w->libdecor->frame);
|
||||||
xdg_toplevel_unset_maximized(w->xdg_toplevel);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_unset_maximized(w->xdg_decor->toplevel);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GHOST_kWindowStateFullScreen:
|
}
|
||||||
|
case GHOST_kWindowStateFullScreen: {
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_unset_fullscreen(w->libdecor->frame);
|
||||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
|
default: {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GHOST_kWindowStateMaximized:
|
case GHOST_kWindowStateMaximized: {
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_set_maximized(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_set_maximized(w->libdecor->frame);
|
||||||
xdg_toplevel_set_maximized(w->xdg_toplevel);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_maximized(w->xdg_decor->toplevel);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GHOST_kWindowStateMinimized:
|
}
|
||||||
|
case GHOST_kWindowStateMinimized: {
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_set_minimized(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_set_minimized(w->libdecor->frame);
|
||||||
xdg_toplevel_set_minimized(w->xdg_toplevel);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_minimized(w->xdg_decor->toplevel);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GHOST_kWindowStateFullScreen:
|
}
|
||||||
|
case GHOST_kWindowStateFullScreen: {
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
|
||||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GHOST_kWindowStateEmbedded:
|
}
|
||||||
|
case GHOST_kWindowStateEmbedded: {
|
||||||
return GHOST_kFailure;
|
return GHOST_kFailure;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
@ -780,20 +851,29 @@ GHOST_TSuccess GHOST_WindowWayland::setOrder(GHOST_TWindowOrder /*order*/)
|
||||||
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
|
GHOST_TSuccess GHOST_WindowWayland::beginFullScreen() const
|
||||||
{
|
{
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_set_fullscreen(w->decor_frame, nullptr);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_set_fullscreen(w->libdecor->frame, nullptr);
|
||||||
xdg_toplevel_set_fullscreen(w->xdg_toplevel, nullptr);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_set_fullscreen(w->xdg_decor->toplevel, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return GHOST_kSuccess;
|
return GHOST_kSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
|
GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
|
||||||
{
|
{
|
||||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||||
libdecor_frame_unset_fullscreen(w->decor_frame);
|
if (use_libdecor) {
|
||||||
#else
|
libdecor_frame_unset_fullscreen(w->libdecor->frame);
|
||||||
xdg_toplevel_unset_fullscreen(w->xdg_toplevel);
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
xdg_toplevel_unset_fullscreen(w->xdg_decor->toplevel);
|
||||||
|
}
|
||||||
return GHOST_kSuccess;
|
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;
|
bool (*MEM_consistency_check)(void) = MEM_lockfree_consistency_check;
|
||||||
void (*MEM_set_memory_debug)(void) = MEM_lockfree_set_memory_debug;
|
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;
|
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;
|
void (*MEM_reset_peak_memory)(void) = MEM_lockfree_reset_peak_memory;
|
||||||
size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_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",
|
print_error("Calloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||||
SIZET_ARG(len),
|
SIZET_ARG(len),
|
||||||
str,
|
str,
|
||||||
(unsigned int)mem_in_use);
|
(uint)mem_in_use);
|
||||||
return NULL;
|
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",
|
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||||
SIZET_ARG(len),
|
SIZET_ARG(len),
|
||||||
str,
|
str,
|
||||||
(unsigned int)mem_in_use);
|
(uint)mem_in_use);
|
||||||
return NULL;
|
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(len),
|
||||||
SIZET_ARG(size),
|
SIZET_ARG(size),
|
||||||
str,
|
str,
|
||||||
(unsigned int)mem_in_use);
|
(uint)mem_in_use);
|
||||||
abort();
|
abort();
|
||||||
return NULL;
|
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",
|
print_error("Malloc returns null: len=" SIZET_FORMAT " in %s, total %u\n",
|
||||||
SIZET_ARG(len),
|
SIZET_ARG(len),
|
||||||
str,
|
str,
|
||||||
(unsigned int)mem_in_use);
|
(uint)mem_in_use);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ size_t MEM_lockfree_get_memory_in_use(void)
|
||||||
return mem_in_use;
|
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;
|
return totblock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ bool wayland_dynload_egl_init(const bool verbose)
|
||||||
{
|
{
|
||||||
/* Library paths. */
|
/* Library paths. */
|
||||||
const char *paths[] = {
|
const char *paths[] = {
|
||||||
"libwayland-egl.so.0",
|
"libwayland-egl.so.1",
|
||||||
"libwayland-egl.so",
|
"libwayland-egl.so",
|
||||||
};
|
};
|
||||||
const int paths_num = sizeof(paths) / sizeof(*paths);
|
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):
|
class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
|
||||||
bl_label = "Emission"
|
bl_label = "Emission"
|
||||||
|
bl_translation_context = i18n_contexts.id_particlesettings
|
||||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
|
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_EEVEE_NEXT', 'BLENDER_WORKBENCH'}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.types import Panel, Header, Menu, UIList
|
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.utils import PresetPanel
|
||||||
from bl_ui.properties_grease_pencil_common import (
|
from bl_ui.properties_grease_pencil_common import (
|
||||||
AnnotationDrawingToolsPanel,
|
AnnotationDrawingToolsPanel,
|
||||||
|
@ -1751,6 +1754,7 @@ class CLIP_MT_marker_pie(Menu):
|
||||||
class CLIP_MT_tracking_pie(Menu):
|
class CLIP_MT_tracking_pie(Menu):
|
||||||
# Tracking Operators
|
# Tracking Operators
|
||||||
bl_label = "Tracking"
|
bl_label = "Tracking"
|
||||||
|
bl_translation_context = i18n_contexts.id_movieclip
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def poll(cls, context):
|
def poll(cls, context):
|
||||||
|
|
|
@ -1528,36 +1528,23 @@ class IMAGE_PT_overlay_guides(Panel):
|
||||||
layout.active = overlay.show_overlays
|
layout.active = overlay.show_overlays
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row_el = row.column()
|
row.prop(overlay, "show_grid_background", text="Grid")
|
||||||
row_el.prop(overlay, "show_grid_background", text="Grid")
|
|
||||||
|
|
||||||
if overlay.show_grid_background:
|
if overlay.show_grid_background:
|
||||||
layout.use_property_split = True
|
sub = row.row()
|
||||||
|
sub.prop(uvedit, "show_grid_over_image", text="Over Image")
|
||||||
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.active = sima.image is not None
|
sub.active = sima.image is not None
|
||||||
|
|
||||||
col = layout.column(align=False, heading="Fixed Subdivisions")
|
layout.row().prop(uvedit, "grid_shape_source", expand=True)
|
||||||
col.use_property_decorate = False
|
|
||||||
|
|
||||||
row = col.row(align=True)
|
layout.use_property_split = True
|
||||||
sub = row.row(align=True)
|
layout.use_property_decorate = False
|
||||||
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="")
|
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.use_property_split = True
|
row.prop(uvedit, "custom_grid_subdivisions", text="Fixed Subdivisions")
|
||||||
row.use_property_decorate = False
|
row.active = uvedit.grid_shape_source == 'FIXED'
|
||||||
row.prop(uvedit, "tile_grid_shape", text="Tiles")
|
|
||||||
|
layout.prop(uvedit, "tile_grid_shape", text="Tiles")
|
||||||
|
|
||||||
|
|
||||||
class IMAGE_PT_overlay_uv_edit(Panel):
|
class IMAGE_PT_overlay_uv_edit(Panel):
|
||||||
|
|
|
@ -683,7 +683,7 @@ class SEQUENCER_MT_add(Menu):
|
||||||
elif bpy_data_movieclips_len > 0:
|
elif bpy_data_movieclips_len > 0:
|
||||||
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip", icon='TRACKER')
|
layout.operator_menu_enum("sequencer.movieclip_strip_add", "clip", text="Clip", icon='TRACKER')
|
||||||
else:
|
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
|
del bpy_data_movieclips_len
|
||||||
|
|
||||||
bpy_data_masks_len = len(bpy.data.masks)
|
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 = layout.operator("sculpt.face_set_change_visibility", text='Invert Visible Face Sets')
|
||||||
op.mode = 'INVERT'
|
op.mode = 'INVERT'
|
||||||
|
|
||||||
op = layout.operator("sculpt.face_set_change_visibility", text='Show All Face Sets')
|
op = layout.operator("sculpt.reveal_all", text='Show All Face Sets')
|
||||||
op.mode = 'SHOW_ALL'
|
|
||||||
|
|
||||||
layout.separator()
|
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 = pie.operator("sculpt.face_set_change_visibility", text='Invert Visible')
|
||||||
op.mode = 'INVERT'
|
op.mode = 'INVERT'
|
||||||
|
|
||||||
op = pie.operator("sculpt.face_set_change_visibility", text='Show All')
|
op = pie.operator("sculpt.reveal_all", text='Show All')
|
||||||
op.mode = 'SHOW_ALL'
|
|
||||||
|
|
||||||
|
|
||||||
class VIEW3D_MT_wpaint_vgroup_lock_pie(Menu):
|
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.
|
* Called after calculating all modifiers.
|
||||||
*/
|
*/
|
||||||
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
|
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,
|
int numVerts,
|
||||||
const struct MLoop *mloop,
|
const struct MLoop *mloop,
|
||||||
const struct MLoopTri *looptri,
|
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);
|
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_UpdateTopology = 1 << 13,
|
||||||
PBVH_UpdateColor = 1 << 14,
|
PBVH_UpdateColor = 1 << 14,
|
||||||
PBVH_RebuildPixels = 1 << 15,
|
PBVH_RebuildPixels = 1 << 15,
|
||||||
|
PBVH_TopologyUpdated = 1 << 16, /* Used internally by pbvh_bmesh.c */
|
||||||
|
|
||||||
} PBVHNodeFlags;
|
} PBVHNodeFlags;
|
||||||
|
|
||||||
|
@ -485,7 +486,10 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
|
||||||
*
|
*
|
||||||
* Skips triangles that are hidden.
|
* 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);
|
void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
|
||||||
|
|
||||||
/* Update Bounding Box/Redraw and clear flags. */
|
/* 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,
|
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||||
int (**r_orco_tris)[3],
|
int (**r_orco_tris)[3],
|
||||||
int *r_orco_tris_num,
|
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,
|
* \note doing a full search on all vertices here seems expensive,
|
||||||
|
|
|
@ -1899,7 +1899,7 @@ struct MappedUserData {
|
||||||
static void make_vertexcos__mapFunc(void *userData,
|
static void make_vertexcos__mapFunc(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
MappedUserData *mappedData = (MappedUserData *)userData;
|
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);
|
MVert *mvert = BKE_mesh_verts_for_write(mesh);
|
||||||
|
|
||||||
/* vertex count is already ensured to match */
|
/* 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);
|
copy_v3_v3(mvert[i].co, verts->xrest);
|
||||||
}
|
}
|
||||||
BKE_mesh_tag_coords_changed(new_mesh);
|
BKE_mesh_tag_coords_changed(new_mesh);
|
||||||
|
|
|
@ -189,7 +189,7 @@ struct CageUserData {
|
||||||
static void cage_mapped_verts_callback(void *userData,
|
static void cage_mapped_verts_callback(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
CageUserData *data = static_cast<CageUserData *>(userData);
|
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->strength = interpf(pt2->strength, pt1->strength, step);
|
||||||
pt->flag = 0;
|
pt->flag = 0;
|
||||||
interp_v4_v4v4(pt->vert_color, pt1->vert_color, pt2->vert_color, step);
|
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. */
|
/* Set weights. */
|
||||||
if (gps->dvert != nullptr) {
|
if (gps->dvert != nullptr) {
|
||||||
|
|
|
@ -364,7 +364,7 @@ struct MappedVCosData {
|
||||||
static void get_vertexcos__mapFunc(void *user_data,
|
static void get_vertexcos__mapFunc(void *user_data,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
|
MappedVCosData *mapped_vcos_data = (MappedVCosData *)user_data;
|
||||||
|
|
||||||
|
|
|
@ -470,7 +470,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void BKE_mesh_calc_normals_looptri(MVert *mverts,
|
void BKE_mesh_calc_normals_looptri(const MVert *mverts,
|
||||||
int numVerts,
|
int numVerts,
|
||||||
const MLoop *mloop,
|
const MLoop *mloop,
|
||||||
const MLoopTri *looptri,
|
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. */
|
/* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
|
||||||
for (int i = 0; i < numVerts; i++) {
|
for (int i = 0; i < numVerts; i++) {
|
||||||
MVert *mv = &mverts[i];
|
const MVert *mv = &mverts[i];
|
||||||
float *no = tnorms[i];
|
float *no = tnorms[i];
|
||||||
|
|
||||||
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
|
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
|
||||||
|
|
|
@ -1272,6 +1272,34 @@ float BKE_nlastrip_compute_frame_to_next_strip(NlaStrip *strip)
|
||||||
return limit_next;
|
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)
|
NlaStrip *BKE_nlastrip_find_active(NlaTrack *nlt)
|
||||||
{
|
{
|
||||||
if (nlt == NULL) {
|
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);
|
BKE_pbvh_pmap_set(pbvh, ob->sculpt->pmap);
|
||||||
sculpt_attribute_update_refs(ob);
|
|
||||||
|
|
||||||
ob->sculpt->pbvh = pbvh;
|
ob->sculpt->pbvh = pbvh;
|
||||||
|
|
||||||
|
sculpt_attribute_update_refs(ob);
|
||||||
return pbvh;
|
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,
|
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
|
||||||
int (**r_orco_tris)[3],
|
int (**r_orco_tris)[3],
|
||||||
int *r_orco_tris_num,
|
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 = node->bm_ortri;
|
||||||
*r_orco_tris_num = node->bm_tot_ortri;
|
*r_orco_tris_num = node->bm_tot_ortri;
|
||||||
*r_orco_coords = node->bm_orco;
|
*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)
|
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);
|
BLI_gset_insert(node->bm_unique_verts, v);
|
||||||
BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
|
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 */
|
/* Log the new vertex */
|
||||||
BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
|
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);
|
BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
|
||||||
|
|
||||||
/* mark node for update */
|
/* mark node for update */
|
||||||
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
|
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_TopologyUpdated;
|
||||||
node->flag &= ~PBVH_FullyHidden;
|
node->flag &= ~PBVH_FullyHidden;
|
||||||
|
|
||||||
/* Log the new face */
|
/* 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);
|
PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v);
|
||||||
/* mark node for update */
|
/* 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);
|
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));
|
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
|
||||||
|
|
||||||
/* mark node for update */
|
/* 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)
|
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;
|
f_node_index_prev = f_node_index;
|
||||||
|
|
||||||
PBVHNode *f_node = &pbvh->nodes[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 */
|
/* Remove current ownership */
|
||||||
BLI_gset_remove(f_node->bm_other_verts, v, NULL);
|
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);
|
BM_log_face_removed(pbvh->bm_log, f);
|
||||||
|
|
||||||
/* mark node for update */
|
/* 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)
|
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)
|
static void pbvh_bmesh_node_drop_orig(PBVHNode *node)
|
||||||
{
|
{
|
||||||
if (node->bm_orco) {
|
MEM_SAFE_FREE(node->bm_orco);
|
||||||
MEM_freeN(node->bm_orco);
|
MEM_SAFE_FREE(node->bm_ortri);
|
||||||
}
|
MEM_SAFE_FREE(node->bm_orvert);
|
||||||
if (node->bm_ortri) {
|
|
||||||
MEM_freeN(node->bm_ortri);
|
|
||||||
}
|
|
||||||
node->bm_orco = NULL;
|
|
||||||
node->bm_ortri = NULL;
|
|
||||||
node->bm_tot_ortri = 0;
|
node->bm_tot_ortri = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,29 +1502,51 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
|
||||||
bool hit = false;
|
bool hit = false;
|
||||||
float nearest_vertex_co[3] = {0.0f};
|
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) {
|
if (use_original && node->bm_tot_ortri) {
|
||||||
for (int i = 0; i < node->bm_tot_ortri; i++) {
|
for (int i = 0; i < node->bm_tot_ortri; i++) {
|
||||||
const int *t = node->bm_ortri[i];
|
float *cos[3];
|
||||||
hit |= ray_face_intersection_tri(ray_start,
|
|
||||||
isect_precalc,
|
cos[0] = node->bm_orco[node->bm_ortri[i][0]];
|
||||||
node->bm_orco[t[0]],
|
cos[1] = node->bm_orco[node->bm_ortri[i][1]];
|
||||||
node->bm_orco[t[1]],
|
cos[2] = node->bm_orco[node->bm_ortri[i][2]];
|
||||||
node->bm_orco[t[2]],
|
|
||||||
depth);
|
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 {
|
else {
|
||||||
GSetIterator gs_iter;
|
|
||||||
|
|
||||||
GSET_ITER (gs_iter, node->bm_faces) {
|
GSET_ITER (gs_iter, node->bm_faces) {
|
||||||
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
|
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
|
||||||
|
|
||||||
BLI_assert(f->len == 3);
|
BLI_assert(f->len == 3);
|
||||||
|
|
||||||
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
|
||||||
BMVert *v_tri[3];
|
BMVert *v_tri[3];
|
||||||
|
|
||||||
BM_face_as_array_vert_tri(f, v_tri);
|
BM_face_as_array_vert_tri(f, v_tri);
|
||||||
|
|
||||||
if (ray_face_intersection_tri(
|
if (ray_face_intersection_tri(
|
||||||
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
|
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth)) {
|
||||||
hit = true;
|
hit = true;
|
||||||
|
@ -2016,6 +2033,21 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
||||||
BLI_buffer_free(&edge_loops);
|
BLI_buffer_free(&edge_loops);
|
||||||
BLI_buffer_free(&deleted_faces);
|
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
|
#ifdef USE_VERIFY
|
||||||
pbvh_bmesh_verify(pbvh);
|
pbvh_bmesh_verify(pbvh);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2023,7 +2055,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
|
||||||
return modified;
|
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 */
|
/* Skip if original coords/triangles are already saved */
|
||||||
if (node->bm_orco) {
|
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_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
|
||||||
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __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 */
|
/* Copy out the vertices and assign a temporary index */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
GSetIterator gs_iter;
|
GSetIterator gs_iter;
|
||||||
GSET_ITER (gs_iter, node->bm_unique_verts) {
|
GSET_ITER (gs_iter, node->bm_unique_verts) {
|
||||||
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
|
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! */
|
BM_elem_index_set(v, i); /* set_dirty! */
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
GSET_ITER (gs_iter, node->bm_other_verts) {
|
GSET_ITER (gs_iter, node->bm_other_verts) {
|
||||||
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
|
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! */
|
BM_elem_index_set(v, i); /* set_dirty! */
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ struct PBVHNode {
|
||||||
|
|
||||||
/* Indicates whether this node is a leaf or not; also used for
|
/* Indicates whether this node is a leaf or not; also used for
|
||||||
* marking various updates that need to be applied. */
|
* 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. */
|
/* Used for raycasting: how close bb is to the ray point. */
|
||||||
float tmin;
|
float tmin;
|
||||||
|
@ -116,8 +116,11 @@ struct PBVHNode {
|
||||||
GSet *bm_faces;
|
GSet *bm_faces;
|
||||||
GSet *bm_unique_verts;
|
GSet *bm_unique_verts;
|
||||||
GSet *bm_other_verts;
|
GSet *bm_other_verts;
|
||||||
|
|
||||||
|
/* Deprecated. Stores original coordinates of triangles. */
|
||||||
float (*bm_orco)[3];
|
float (*bm_orco)[3];
|
||||||
int (*bm_ortri)[3];
|
int (*bm_ortri)[3];
|
||||||
|
BMVert **bm_orvert;
|
||||||
int bm_tot_ortri;
|
int bm_tot_ortri;
|
||||||
|
|
||||||
/* Used to store the brush color during a stroke and composite it over the original color */
|
/* 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 */
|
/* Master Collection */
|
||||||
scene->master_collection = BKE_collection_master_add(scene);
|
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)
|
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->num_grids = num_grids;
|
||||||
subdiv_ccg->grids = static_cast<CCGElem **>(
|
subdiv_ccg->grids = static_cast<CCGElem **>(
|
||||||
MEM_calloc_arrayN(num_grids, sizeof(CCGElem *), "subdiv ccg grids"));
|
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"));
|
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;
|
const size_t grid_size_in_bytes = size_t(grid_area) * element_size;
|
||||||
for (int grid_index = 0; grid_index < num_grids; grid_index++) {
|
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,
|
static void subdiv_ccg_eval_grids_task(void *__restrict userdata_v,
|
||||||
const int face_index,
|
const int face_index,
|
||||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
const TaskParallelTLS *__restrict /*tls*/)
|
||||||
{
|
{
|
||||||
CCGEvalGridsData *data = static_cast<CCGEvalGridsData *>(userdata_v);
|
CCGEvalGridsData *data = static_cast<CCGEvalGridsData *>(userdata_v);
|
||||||
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
|
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);
|
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)
|
void *__restrict tls_v)
|
||||||
{
|
{
|
||||||
RecalcInnerNormalsTLSData *tls = static_cast<RecalcInnerNormalsTLSData *>(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);
|
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)
|
void *__restrict tls_v)
|
||||||
{
|
{
|
||||||
RecalcInnerNormalsTLSData *tls = static_cast<RecalcInnerNormalsTLSData *>(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,
|
static void subdiv_ccg_average_inner_grids_task(void *__restrict userdata_v,
|
||||||
const int face_index,
|
const int face_index,
|
||||||
const TaskParallelTLS *__restrict UNUSED(tls_v))
|
const TaskParallelTLS *__restrict /*tls_v*/)
|
||||||
{
|
{
|
||||||
AverageInnerGridsData *data = static_cast<AverageInnerGridsData *>(userdata_v);
|
AverageInnerGridsData *data = static_cast<AverageInnerGridsData *>(userdata_v);
|
||||||
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
|
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);
|
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)
|
void *__restrict tls_v)
|
||||||
{
|
{
|
||||||
AverageGridsBoundariesTLSData *tls = static_cast<AverageGridsBoundariesTLSData *>(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,
|
static void subdiv_ccg_average_grids_corners_task(void *__restrict userdata_v,
|
||||||
const int n,
|
const int n,
|
||||||
const TaskParallelTLS *__restrict UNUSED(tls_v))
|
const TaskParallelTLS *__restrict /*tls_v*/)
|
||||||
{
|
{
|
||||||
AverageGridsCornerData *data = static_cast<AverageGridsCornerData *>(userdata_v);
|
AverageGridsCornerData *data = static_cast<AverageGridsCornerData *>(userdata_v);
|
||||||
const int adjacent_vertex_index = data->adjacent_vert_index_map ?
|
const int adjacent_vertex_index = data->adjacent_vert_index_map ?
|
||||||
|
@ -1323,10 +1323,9 @@ struct StitchFacesInnerGridsData {
|
||||||
CCGFace **effected_ccg_faces;
|
CCGFace **effected_ccg_faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void subdiv_ccg_stitch_face_inner_grids_task(
|
static void subdiv_ccg_stitch_face_inner_grids_task(void *__restrict userdata_v,
|
||||||
void *__restrict userdata_v,
|
const int face_index,
|
||||||
const int face_index,
|
const TaskParallelTLS *__restrict /*tls_v*/)
|
||||||
const TaskParallelTLS *__restrict UNUSED(tls_v))
|
|
||||||
{
|
{
|
||||||
StitchFacesInnerGridsData *data = static_cast<StitchFacesInnerGridsData *>(userdata_v);
|
StitchFacesInnerGridsData *data = static_cast<StitchFacesInnerGridsData *>(userdata_v);
|
||||||
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
|
SubdivCCG *subdiv_ccg = data->subdiv_ccg;
|
||||||
|
@ -1447,7 +1446,7 @@ BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG *subdiv_ccg,
|
||||||
return false;
|
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)
|
const SubdivCCGCoord *coord)
|
||||||
{
|
{
|
||||||
BLI_assert(coord->y > 0);
|
BLI_assert(coord->y > 0);
|
||||||
|
@ -1465,7 +1464,7 @@ BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG *subdiv_ccg,
|
||||||
return result;
|
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)
|
const SubdivCCGCoord *coord)
|
||||||
{
|
{
|
||||||
BLI_assert(coord->x > 0);
|
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;
|
SpaceImage *sima = (SpaceImage *)sl;
|
||||||
sima->flag &= ~(SI_FLAG_UNUSED_0 | SI_FLAG_UNUSED_1 | SI_FLAG_UNUSED_3 |
|
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_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);
|
SI_FLAG_UNUSED_24);
|
||||||
break;
|
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.flag |= V3D_OVERLAY_VIEWER_ATTRIBUTE;
|
||||||
v3d->overlay.viewer_attribute_opacity = 1.0f;
|
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
|
/** \file
|
||||||
* \ingroup bmesh
|
* \ingroup bmesh
|
||||||
*
|
*
|
||||||
* normal recalculation.
|
* Functionality for flipping faces to make normals consistent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
@ -47,7 +47,7 @@ static bool bmo_recalc_normal_loop_filter_cb(const BMLoop *l, void *UNUSED(user_
|
||||||
* +------------+
|
* +------------+
|
||||||
* </pre>
|
* </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.
|
* which would end up flipping the normals inwards.
|
||||||
*
|
*
|
||||||
* To take these spikes into account, find the furthest face-loop-vertex.
|
* To take these spikes into account, find the furthest face-loop-vertex.
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "COM_MultilayerImageOperation.h"
|
#include "COM_MultilayerImageOperation.h"
|
||||||
#include "COM_RenderLayersProg.h"
|
#include "COM_RenderLayersProg.h"
|
||||||
#include "COM_SetAlphaMultiplyOperation.h"
|
#include "COM_SetAlphaMultiplyOperation.h"
|
||||||
|
#include "COM_SetAlphaReplaceOperation.h"
|
||||||
#include "COM_SetColorOperation.h"
|
#include "COM_SetColorOperation.h"
|
||||||
|
|
||||||
namespace blender::compositor {
|
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));
|
converter.map_output_socket(output_image_socket, apply_mask_operation->get_output_socket(0));
|
||||||
|
|
||||||
NodeOutput *output_pick_socket = this->get_output_socket(2);
|
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_operation(extract_pick_operation);
|
||||||
converter.add_input_value(extract_pick_operation->get_input_socket(1), 1.0f);
|
converter.add_input_value(extract_pick_operation->get_input_socket(1), 1.0f);
|
||||||
converter.add_link(cryptomatte_operation->get_output_socket(0),
|
converter.add_link(cryptomatte_operation->get_output_socket(0),
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
set(INC
|
set(INC
|
||||||
.
|
.
|
||||||
|
./algorithms
|
||||||
../../blenkernel
|
../../blenkernel
|
||||||
../../blenlib
|
../../blenlib
|
||||||
../../gpu
|
../../gpu
|
||||||
|
@ -53,6 +54,10 @@ set(SRC
|
||||||
COM_static_shader_manager.hh
|
COM_static_shader_manager.hh
|
||||||
COM_texture_pool.hh
|
COM_texture_pool.hh
|
||||||
COM_utilities.hh
|
COM_utilities.hh
|
||||||
|
|
||||||
|
algorithms/intern/algorithm_parallel_reduction.cc
|
||||||
|
|
||||||
|
algorithms/COM_algorithm_parallel_reduction.hh
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB
|
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_particles.c
|
||||||
intern/draw_cache_impl_pointcloud.cc
|
intern/draw_cache_impl_pointcloud.cc
|
||||||
intern/draw_cache_impl_subdivision.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_color_management.cc
|
||||||
intern/draw_command.cc
|
intern/draw_command.cc
|
||||||
intern/draw_common.c
|
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) &&
|
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
|
||||||
!DRW_state_is_image_render();
|
!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. */
|
/* First get materials for this mesh. */
|
||||||
if (ELEM(ob->type, OB_MESH, OB_SURF)) {
|
if (ELEM(ob->type, OB_MESH, OB_SURF)) {
|
||||||
const int materials_len = DRW_cache_object_material_count_get(ob);
|
const int materials_len = DRW_cache_object_material_count_get(ob);
|
||||||
|
|
|
@ -332,6 +332,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
|
||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
IMB_gpu_clamp_half_float(&extracted_buffer);
|
||||||
|
|
||||||
GPU_texture_update_sub(texture,
|
GPU_texture_update_sub(texture,
|
||||||
GPU_DATA_FLOAT,
|
GPU_DATA_FLOAT,
|
||||||
|
@ -388,6 +389,7 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
|
||||||
}
|
}
|
||||||
BKE_image_release_ibuf(image, tile_buffer, lock);
|
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);
|
GPU_texture_update(info.texture, GPU_DATA_FLOAT, texture_buffer.rect_float);
|
||||||
imb_freerectImbuf_all(&texture_buffer);
|
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);
|
const bool draw_grid = is_uv_edit || !ED_space_image_has_buffer(sima);
|
||||||
if (background_enabled && draw_grid) {
|
if (background_enabled && draw_grid) {
|
||||||
grid_flag |= SHOW_GRID;
|
grid_flag |= SHOW_GRID;
|
||||||
if (is_uv_edit && (sima->flag & SI_CUSTOM_GRID) != 0) {
|
if (is_uv_edit) {
|
||||||
grid_flag |= CUSTOM_GRID;
|
if (sima->grid_shape_source != SI_GRID_SHAPE_DYNAMIC) {
|
||||||
|
grid_flag |= CUSTOM_GRID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* \brief Volume API for render engines
|
* \brief Volume API for render engines
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <cstring>
|
||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ static void volume_batch_cache_clear(Volume *volume);
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* Volume GPUBatch Cache */
|
/* Volume GPUBatch Cache */
|
||||||
|
|
||||||
typedef struct VolumeBatchCache {
|
struct VolumeBatchCache {
|
||||||
/* 3D textures */
|
/* 3D textures */
|
||||||
ListBase grids;
|
ListBase grids;
|
||||||
|
|
||||||
|
@ -54,22 +54,22 @@ typedef struct VolumeBatchCache {
|
||||||
|
|
||||||
/* settings to determine if cache is invalid */
|
/* settings to determine if cache is invalid */
|
||||||
bool is_dirty;
|
bool is_dirty;
|
||||||
} VolumeBatchCache;
|
};
|
||||||
|
|
||||||
/* GPUBatch cache management. */
|
/* GPUBatch cache management. */
|
||||||
|
|
||||||
static bool volume_batch_cache_valid(Volume *volume)
|
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);
|
return (cache && cache->is_dirty == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void volume_batch_cache_init(Volume *volume)
|
static void volume_batch_cache_init(Volume *volume)
|
||||||
{
|
{
|
||||||
VolumeBatchCache *cache = volume->batch_cache;
|
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
|
||||||
|
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
cache = volume->batch_cache = MEM_callocN(sizeof(*cache), __func__);
|
volume->batch_cache = cache = MEM_cnew<VolumeBatchCache>(__func__);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memset(cache, 0, sizeof(*cache));
|
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)
|
static VolumeBatchCache *volume_batch_cache_get(Volume *volume)
|
||||||
{
|
{
|
||||||
DRW_volume_batch_cache_validate(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)
|
void DRW_volume_batch_cache_dirty_tag(Volume *volume, int mode)
|
||||||
{
|
{
|
||||||
VolumeBatchCache *cache = volume->batch_cache;
|
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
|
||||||
if (cache == NULL) {
|
if (cache == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (mode) {
|
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)
|
static void volume_batch_cache_clear(Volume *volume)
|
||||||
{
|
{
|
||||||
VolumeBatchCache *cache = volume->batch_cache;
|
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
|
||||||
if (!cache) {
|
if (!cache) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -130,18 +130,18 @@ void DRW_volume_batch_cache_free(Volume *volume)
|
||||||
volume_batch_cache_clear(volume);
|
volume_batch_cache_clear(volume);
|
||||||
MEM_SAFE_FREE(volume->batch_cache);
|
MEM_SAFE_FREE(volume->batch_cache);
|
||||||
}
|
}
|
||||||
typedef struct VolumeWireframeUserData {
|
struct VolumeWireframeUserData {
|
||||||
Volume *volume;
|
Volume *volume;
|
||||||
Scene *scene;
|
Scene *scene;
|
||||||
} VolumeWireframeUserData;
|
};
|
||||||
|
|
||||||
static void drw_volume_wireframe_cb(
|
static void drw_volume_wireframe_cb(
|
||||||
void *userdata, const float (*verts)[3], const int (*edges)[2], int totvert, int totedge)
|
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;
|
Scene *scene = data->scene;
|
||||||
Volume *volume = data->volume;
|
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 ||
|
const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 ||
|
||||||
GPU_use_hq_normals_workaround();
|
GPU_use_hq_normals_workaround();
|
||||||
|
|
||||||
|
@ -181,7 +181,7 @@ static void drw_volume_wireframe_cb(
|
||||||
if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) {
|
if (volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS) {
|
||||||
/* Create batch. */
|
/* Create batch. */
|
||||||
cache->face_wire.batch = GPU_batch_create(
|
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 {
|
else {
|
||||||
/* Create edge index buffer. */
|
/* Create edge index buffer. */
|
||||||
|
@ -203,15 +203,15 @@ static void drw_volume_wireframe_cb(
|
||||||
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
|
GPUBatch *DRW_volume_batch_cache_get_wireframes_face(Volume *volume)
|
||||||
{
|
{
|
||||||
if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) {
|
if (volume->display.wireframe_type == VOLUME_WIREFRAME_NONE) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeBatchCache *cache = volume_batch_cache_get(volume);
|
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);
|
const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
|
||||||
if (volume_grid == NULL) {
|
if (volume_grid == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create wireframe from OpenVDB tree. */
|
/* 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(
|
static void drw_volume_selection_surface_cb(
|
||||||
void *userdata, float (*verts)[3], int (*tris)[3], int totvert, int tottris)
|
void *userdata, float (*verts)[3], int (*tris)[3], int totvert, int tottris)
|
||||||
{
|
{
|
||||||
Volume *volume = userdata;
|
Volume *volume = static_cast<Volume *>(userdata);
|
||||||
VolumeBatchCache *cache = volume->batch_cache;
|
VolumeBatchCache *cache = static_cast<VolumeBatchCache *>(volume->batch_cache);
|
||||||
|
|
||||||
static GPUVertFormat format = {0};
|
static GPUVertFormat format = {0};
|
||||||
static uint pos_id;
|
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)
|
GPUBatch *DRW_volume_batch_cache_get_selection_surface(Volume *volume)
|
||||||
{
|
{
|
||||||
VolumeBatchCache *cache = volume_batch_cache_get(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);
|
const VolumeGrid *volume_grid = BKE_volume_grid_active_get_for_read(volume);
|
||||||
if (volume_grid == NULL) {
|
if (volume_grid == nullptr) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
BKE_volume_grid_selection_surface(
|
BKE_volume_grid_selection_surface(
|
||||||
volume, volume_grid, drw_volume_selection_surface_cb, volume);
|
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);
|
const char *name = BKE_volume_grid_name(grid);
|
||||||
|
|
||||||
/* Return cached grid. */
|
/* Return cached grid. */
|
||||||
DRWVolumeGrid *cache_grid;
|
LISTBASE_FOREACH (DRWVolumeGrid *, cache_grid, &cache->grids) {
|
||||||
for (cache_grid = cache->grids.first; cache_grid; cache_grid = cache_grid->next) {
|
|
||||||
if (STREQ(cache_grid->name, name)) {
|
if (STREQ(cache_grid->name, name)) {
|
||||||
return cache_grid;
|
return cache_grid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate new grid. */
|
/* Allocate new grid. */
|
||||||
cache_grid = MEM_callocN(sizeof(DRWVolumeGrid), __func__);
|
DRWVolumeGrid *cache_grid = MEM_cnew<DRWVolumeGrid>(__func__);
|
||||||
cache_grid->name = BLI_strdup(name);
|
cache_grid->name = BLI_strdup(name);
|
||||||
BLI_addtail(&cache->grids, cache_grid);
|
BLI_addtail(&cache->grids, cache_grid);
|
||||||
|
|
||||||
|
@ -316,7 +315,7 @@ static DRWVolumeGrid *volume_grid_cache_get(const Volume *volume,
|
||||||
dense_grid.voxels);
|
dense_grid.voxels);
|
||||||
/* The texture can be null if the resolution along one axis is larger than
|
/* The texture can be null if the resolution along one axis is larger than
|
||||||
* GL_MAX_3D_TEXTURE_SIZE. */
|
* 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_swizzle_set(cache_grid->texture, (channels == 3) ? "rgb1" : "rrr1");
|
||||||
GPU_texture_wrap_mode(cache_grid->texture, false, false);
|
GPU_texture_wrap_mode(cache_grid->texture, false, false);
|
||||||
BKE_volume_dense_float_grid_clear(&dense_grid);
|
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);
|
VolumeBatchCache *cache = volume_batch_cache_get(volume);
|
||||||
DRWVolumeGrid *grid = volume_grid_cache_get(volume, volume_grid, cache);
|
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)
|
int DRW_volume_material_count_get(Volume *volume)
|
|
@ -1158,8 +1158,17 @@ struct PBVHBatches {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PBVHBatch &batch : batches.values()) {
|
for (PBVHBatch &batch : batches.values()) {
|
||||||
GPU_batch_elembuf_set(batch.tris, tri_index, false);
|
if (tri_index) {
|
||||||
GPU_batch_elembuf_set(batch.lines, lines_index, false);
|
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,
|
true,
|
||||||
"Only Active",
|
"Only Active",
|
||||||
"Copy only active Layer, uncheck to append all layers");
|
"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);
|
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3686,6 +3687,7 @@ void GPENCIL_OT_materials_copy_to_object(wmOperatorType *ot)
|
||||||
true,
|
true,
|
||||||
"Only Active",
|
"Only Active",
|
||||||
"Append only active material, uncheck to append all materials");
|
"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);
|
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);
|
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 */
|
/* node_edit.cc */
|
||||||
|
|
||||||
void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typeinfo);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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,
|
bool use_active,
|
||||||
struct UVMapUDIM_Params *udim_params);
|
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 {
|
struct UVPackIsland_Params {
|
||||||
uint rotate : 1;
|
uint rotate : 1;
|
||||||
uint only_selected_uvs : 1;
|
uint only_selected_uvs : 1;
|
||||||
uint only_selected_faces : 1;
|
uint only_selected_faces : 1;
|
||||||
uint use_seams : 1;
|
uint use_seams : 1;
|
||||||
uint correct_aspect : 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,
|
static char *ui_drop_material_tooltip(bContext *C,
|
||||||
wmDrag *drag,
|
wmDrag *drag,
|
||||||
const int UNUSED(xy[2]),
|
const int /*xy*/[2],
|
||||||
struct wmDropBox * /*drop*/)
|
struct wmDropBox * /*drop*/)
|
||||||
{
|
{
|
||||||
PointerRNA rna_ptr = CTX_data_pointer_get_type(C, "object", &RNA_Object);
|
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);
|
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);
|
layout = UI_pie_menu_layout(pie);
|
||||||
|
|
||||||
UI_menutype_draw(C, mt, layout);
|
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);
|
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);
|
layout = UI_popup_menu_layout(pup);
|
||||||
|
|
||||||
UI_menutype_draw(C, mt, layout);
|
UI_menutype_draw(C, mt, layout);
|
||||||
|
|
|
@ -3269,7 +3269,7 @@ void uiTemplatePreview(uiLayout *layout,
|
||||||
uiDefButS(block,
|
uiDefButS(block,
|
||||||
UI_BTYPE_ROW,
|
UI_BTYPE_ROW,
|
||||||
B_MATPRV,
|
B_MATPRV,
|
||||||
IFACE_("World"),
|
CTX_IFACE_(BLT_I18NCONTEXT_ID_WORLD, "World"),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
UI_UNIT_X * 10,
|
UI_UNIT_X * 10,
|
||||||
|
|
|
@ -658,7 +658,7 @@ void WM_OT_alembic_import(wmOperatorType *ot)
|
||||||
ot->name = "Import Alembic";
|
ot->name = "Import Alembic";
|
||||||
ot->description = "Load an Alembic archive";
|
ot->description = "Load an Alembic archive";
|
||||||
ot->idname = "WM_OT_alembic_import";
|
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->invoke = wm_alembic_import_invoke;
|
||||||
ot->exec = wm_alembic_import_exec;
|
ot->exec = wm_alembic_import_exec;
|
||||||
|
|
|
@ -770,14 +770,12 @@ void WM_OT_collada_import(wmOperatorType *ot)
|
||||||
ot->name = "Import COLLADA";
|
ot->name = "Import COLLADA";
|
||||||
ot->description = "Load a Collada file";
|
ot->description = "Load a Collada file";
|
||||||
ot->idname = "WM_OT_collada_import";
|
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->invoke = WM_operator_filesel;
|
||||||
ot->exec = wm_collada_import_exec;
|
ot->exec = wm_collada_import_exec;
|
||||||
ot->poll = WM_operator_winactive;
|
ot->poll = WM_operator_winactive;
|
||||||
|
|
||||||
// ot->flag = OPTYPE_PRESET;
|
|
||||||
|
|
||||||
ot->ui = wm_collada_import_draw;
|
ot->ui = wm_collada_import_draw;
|
||||||
|
|
||||||
WM_operator_properties_filesel(ot,
|
WM_operator_properties_filesel(ot,
|
||||||
|
|
|
@ -492,7 +492,7 @@ void WM_OT_obj_import(struct wmOperatorType *ot)
|
||||||
ot->name = "Import Wavefront OBJ";
|
ot->name = "Import Wavefront OBJ";
|
||||||
ot->description = "Load a Wavefront OBJ scene";
|
ot->description = "Load a Wavefront OBJ scene";
|
||||||
ot->idname = "WM_OT_obj_import";
|
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->invoke = wm_obj_import_invoke;
|
||||||
ot->exec = wm_obj_import_exec;
|
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->exec = wm_stl_import_execute;
|
||||||
ot->poll = WM_operator_winactive;
|
ot->poll = WM_operator_winactive;
|
||||||
ot->check = wm_stl_import_check;
|
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,
|
WM_operator_properties_filesel(ot,
|
||||||
FILE_TYPE_FOLDER,
|
FILE_TYPE_FOLDER,
|
||||||
|
|
|
@ -500,7 +500,7 @@ void WM_OT_usd_import(struct wmOperatorType *ot)
|
||||||
ot->poll = WM_operator_winactive;
|
ot->poll = WM_operator_winactive;
|
||||||
ot->ui = wm_usd_import_draw;
|
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,
|
WM_operator_properties_filesel(ot,
|
||||||
FILE_TYPE_FOLDER | FILE_TYPE_USD,
|
FILE_TYPE_FOLDER | FILE_TYPE_USD,
|
||||||
|
|
|
@ -100,7 +100,7 @@ typedef struct KnifeColors {
|
||||||
/* Knife-tool Operator. */
|
/* Knife-tool Operator. */
|
||||||
typedef struct KnifeVert {
|
typedef struct KnifeVert {
|
||||||
Object *ob;
|
Object *ob;
|
||||||
uint base_index;
|
uint ob_index;
|
||||||
BMVert *v; /* Non-NULL if this is an original vert. */
|
BMVert *v; /* Non-NULL if this is an original vert. */
|
||||||
ListBase edges;
|
ListBase edges;
|
||||||
ListBase faces;
|
ListBase faces;
|
||||||
|
@ -142,7 +142,7 @@ typedef struct KnifeLineHit {
|
||||||
KnifeVert *v;
|
KnifeVert *v;
|
||||||
BMFace *f;
|
BMFace *f;
|
||||||
Object *ob;
|
Object *ob;
|
||||||
uint base_index;
|
uint ob_index;
|
||||||
} KnifeLineHit;
|
} KnifeLineHit;
|
||||||
|
|
||||||
typedef struct KnifePosData {
|
typedef struct KnifePosData {
|
||||||
|
@ -156,7 +156,7 @@ typedef struct KnifePosData {
|
||||||
KnifeEdge *edge;
|
KnifeEdge *edge;
|
||||||
BMFace *bmface;
|
BMFace *bmface;
|
||||||
Object *ob; /* Object of the vert, edge or 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. */
|
/* When true, the cursor isn't over a face. */
|
||||||
bool is_space;
|
bool is_space;
|
||||||
|
@ -182,7 +182,7 @@ typedef struct KnifeBVH {
|
||||||
BVHTree *tree; /* Knife Custom BVH Tree. */
|
BVHTree *tree; /* Knife Custom BVH Tree. */
|
||||||
BMLoop *(*looptris)[3]; /* Used by #knife_bvh_raycast_cb to store the intersecting looptri. */
|
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. */
|
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. */
|
/* Use #bm_ray_cast_cb_elem_not_in_face_check. */
|
||||||
bool (*filter_cb)(BMFace *f, void *userdata);
|
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. */
|
/* Used for swapping current object when in multi-object edit mode. */
|
||||||
Object **objects;
|
Object **objects;
|
||||||
uint objects_len;
|
uint objects_len;
|
||||||
|
bool objects_free;
|
||||||
|
|
||||||
/** Array `objects_len` length of additional per-object data. */
|
/** Array `objects_len` length of additional per-object data. */
|
||||||
KnifeObjectInfo *objects_info;
|
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,
|
static const int *knife_bm_tri_index_get(const KnifeTool_OpData *kcd,
|
||||||
int base_index,
|
int ob_index,
|
||||||
int tri_index,
|
int tri_index,
|
||||||
int tri_index_buf[3])
|
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) {
|
if (obinfo->tri_indices) {
|
||||||
return obinfo->tri_indices[tri_index];
|
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,
|
static void knife_bm_tri_cagecos_get(const KnifeTool_OpData *kcd,
|
||||||
int base_index,
|
int ob_index,
|
||||||
int tri_index,
|
int tri_index,
|
||||||
float cos[3][3])
|
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];
|
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++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
copy_v3_v3(cos[i], obinfo->cagecos[tri_ind[i]]);
|
copy_v3_v3(cos[i], obinfo->cagecos[tri_ind[i]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void knife_bm_tri_cagecos_get_worldspace(const KnifeTool_OpData *kcd,
|
static void knife_bm_tri_cagecos_get_worldspace(const KnifeTool_OpData *kcd,
|
||||||
int base_index,
|
int ob_index,
|
||||||
int tri_index,
|
int tri_index,
|
||||||
float cos[3][3])
|
float cos[3][3])
|
||||||
{
|
{
|
||||||
knife_bm_tri_cagecos_get(kcd, base_index, tri_index, cos);
|
knife_bm_tri_cagecos_get(kcd, ob_index, tri_index, cos);
|
||||||
const Object *ob = kcd->objects[base_index];
|
const Object *ob = kcd->objects[ob_index];
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
mul_m4_v3(ob->obmat, cos[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;
|
bool test_fn_ret = false;
|
||||||
|
|
||||||
/* Calculate tottri. */
|
/* 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_tottri = 0;
|
||||||
ob = kcd->objects[b];
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
em = BKE_editmesh_from_object(ob);
|
||||||
|
|
||||||
for (int i = 0; i < em->tottri; i++) {
|
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!
|
* Don't forget to update #knife_bvh_intersect_plane!
|
||||||
*/
|
*/
|
||||||
tottri = 0;
|
tottri = 0;
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
ob = kcd->objects[b];
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
em = BKE_editmesh_from_object(ob);
|
||||||
looptris = em->looptris;
|
looptris = em->looptris;
|
||||||
|
|
||||||
|
@ -1286,7 +1287,7 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
|
||||||
}
|
}
|
||||||
|
|
||||||
float tri_cos[3][3];
|
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);
|
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;
|
int tottri;
|
||||||
|
|
||||||
tottri = 0;
|
tottri = 0;
|
||||||
uint b = 0;
|
uint ob_index = 0;
|
||||||
for (; b < kcd->objects_len; b++) {
|
for (; ob_index < kcd->objects_len; ob_index++) {
|
||||||
index -= tottri;
|
index -= tottri;
|
||||||
ob = kcd->objects[b];
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
em = BKE_editmesh_from_object(ob);
|
||||||
tottri = em->tottri;
|
tottri = em->tottri;
|
||||||
if (index < tottri) {
|
if (index < tottri) {
|
||||||
|
@ -1343,7 +1344,7 @@ static void knife_bvh_raycast_cb(void *userdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
float tri_cos[3][3];
|
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->radius > 0.0f ?
|
||||||
isect_ray_tri_epsilon_v3(
|
isect_ray_tri_epsilon_v3(
|
||||||
ray->origin, ray->direction, UNPACK3(tri_cos), &dist, uv, ray->radius) :
|
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;
|
kcd->bvh.looptris = em->looptris;
|
||||||
copy_v2_v2(kcd->bvh.uv, uv);
|
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_dist,
|
||||||
float r_hitout[3],
|
float r_hitout[3],
|
||||||
float r_cagehit[3],
|
float r_cagehit[3],
|
||||||
uint *r_base_index)
|
uint *r_ob_index)
|
||||||
{
|
{
|
||||||
BMFace *face;
|
BMFace *face;
|
||||||
BVHTreeRayHit hit;
|
BVHTreeRayHit hit;
|
||||||
|
@ -1399,7 +1400,7 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
|
||||||
/* Hits returned in world space. */
|
/* Hits returned in world space. */
|
||||||
if (r_hitout) {
|
if (r_hitout) {
|
||||||
float tri_cos[3][3];
|
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);
|
interp_v3_v3v3v3_uv(r_hitout, UNPACK3(tri_cos), kcd->bvh.uv);
|
||||||
|
|
||||||
if (r_cagehit) {
|
if (r_cagehit) {
|
||||||
|
@ -1411,8 +1412,8 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
|
||||||
*r_dist = hit.dist;
|
*r_dist = hit.dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_base_index) {
|
if (r_ob_index) {
|
||||||
*r_base_index = kcd->bvh.base_index;
|
*r_ob_index = kcd->bvh.ob_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
|
@ -1428,7 +1429,7 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
|
||||||
float *r_dist,
|
float *r_dist,
|
||||||
float r_hitout[3],
|
float r_hitout[3],
|
||||||
float r_cagehit[3],
|
float r_cagehit[3],
|
||||||
uint *r_base_index,
|
uint *r_ob_index,
|
||||||
bool (*filter_cb)(BMFace *f, void *userdata),
|
bool (*filter_cb)(BMFace *f, void *userdata),
|
||||||
void *filter_userdata)
|
void *filter_userdata)
|
||||||
{
|
{
|
||||||
|
@ -1453,7 +1454,7 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
|
||||||
/* Hits returned in world space. */
|
/* Hits returned in world space. */
|
||||||
if (r_hitout) {
|
if (r_hitout) {
|
||||||
float tri_cos[3][3];
|
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);
|
interp_v3_v3v3v3_uv(r_hitout, UNPACK3(tri_cos), kcd->bvh.uv);
|
||||||
|
|
||||||
if (r_cagehit) {
|
if (r_cagehit) {
|
||||||
|
@ -1465,8 +1466,8 @@ static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
|
||||||
*r_dist = hit.dist;
|
*r_dist = hit.dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (r_base_index) {
|
if (r_ob_index) {
|
||||||
*r_base_index = kcd->bvh.base_index;
|
*r_ob_index = kcd->bvh.ob_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
|
@ -1726,7 +1727,7 @@ static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a KnifeVert wrapper for an existing BMVert. */
|
/* 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);
|
KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
|
||||||
const float *cageco;
|
const float *cageco;
|
||||||
|
@ -1736,7 +1737,7 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v, Object *ob
|
||||||
BMFace *f;
|
BMFace *f;
|
||||||
|
|
||||||
if (BM_elem_index_get(v) >= 0) {
|
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 {
|
else {
|
||||||
cageco = v->co;
|
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 = new_knife_vert(kcd, v->co, cageco_ws);
|
||||||
kfv->v = v;
|
kfv->v = v;
|
||||||
kfv->ob = ob;
|
kfv->ob = ob;
|
||||||
kfv->base_index = base_index;
|
kfv->ob_index = ob_index;
|
||||||
|
|
||||||
BLI_ghash_insert(kcd->origvertmap, v, kfv);
|
BLI_ghash_insert(kcd->origvertmap, v, kfv);
|
||||||
BM_ITER_ELEM (f, &bmiter, v, BM_FACES_OF_VERT) {
|
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. */
|
/* 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);
|
KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e);
|
||||||
if (!kfe) {
|
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 = new_knife_edge(kcd);
|
||||||
kfe->e = e;
|
kfe->e = e;
|
||||||
kfe->v1 = get_bm_knife_vert(kcd, e->v1, 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, base_index);
|
kfe->v2 = get_bm_knife_vert(kcd, e->v2, ob, ob_index);
|
||||||
|
|
||||||
knife_add_to_vert_edges(kcd, kfe);
|
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;
|
return kfe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd,
|
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, Object *ob, uint ob_index, BMFace *f)
|
||||||
Object *ob,
|
|
||||||
uint base_index,
|
|
||||||
BMFace *f)
|
|
||||||
{
|
{
|
||||||
ListBase *list = BLI_ghash_lookup(kcd->kedgefacemap, 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);
|
list = knife_empty_list(kcd);
|
||||||
|
|
||||||
BM_ITER_ELEM (e, &bmiter, f, BM_EDGES_OF_FACE) {
|
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);
|
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)
|
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);
|
knife_append_list(kcd, &kfe->faces, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1826,7 +1824,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd,
|
||||||
newkfe->v1 = kfe->v1;
|
newkfe->v1 = kfe->v1;
|
||||||
newkfe->v2 = new_knife_vert(kcd, co, cageco);
|
newkfe->v2 = new_knife_vert(kcd, co, cageco);
|
||||||
newkfe->v2->ob = kfe->v1->ob;
|
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;
|
newkfe->v2->is_cut = true;
|
||||||
if (kfe->e) {
|
if (kfe->e) {
|
||||||
knife_add_edge_faces_to_vert(kcd, newkfe->v2, 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);
|
BLI_assert(lh1->f);
|
||||||
kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
|
kfe->v1 = new_knife_vert(kcd, lh1->hit, lh1->cagehit);
|
||||||
kfe->v1->ob = lh1->ob;
|
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_cut = true;
|
||||||
kfe->v1->is_face = true;
|
kfe->v1->is_face = true;
|
||||||
knife_append_list(kcd, &kfe->v1->faces, lh1->f);
|
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);
|
BLI_assert(lh2->f);
|
||||||
kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
|
kfe->v2 = new_knife_vert(kcd, lh2->hit, lh2->cagehit);
|
||||||
kfe->v2->ob = lh2->ob;
|
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_cut = true;
|
||||||
kfe->v2->is_face = true;
|
kfe->v2->is_face = true;
|
||||||
knife_append_list(kcd, &kfe->v2->faces, lh2->f);
|
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 v1[3],
|
||||||
const float v2[3],
|
const float v2[3],
|
||||||
Object *ob,
|
Object *ob,
|
||||||
uint base_index,
|
uint ob_index,
|
||||||
BMFace *f,
|
BMFace *f,
|
||||||
const float face_tol_sq,
|
const float face_tol_sq,
|
||||||
float hit_co[3],
|
float hit_co[3],
|
||||||
|
@ -2600,7 +2598,7 @@ static bool knife_ray_intersect_face(KnifeTool_OpData *kcd,
|
||||||
break;
|
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
|
/* Using epsilon test in case ray is directly through an internal
|
||||||
* tessellation edge and might not hit either tessellation tri with
|
* 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);
|
interp_v3_v3v3v3_uv(hit_cageco, UNPACK3(tri_cos), ray_tri_uv);
|
||||||
/* Now check that far enough away from verts and edges. */
|
/* 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) {
|
for (ref = list->first; ref; ref = ref->next) {
|
||||||
kfe = ref->ref;
|
kfe = ref->ref;
|
||||||
if (kfe->is_invalid) {
|
if (kfe->is_invalid) {
|
||||||
|
@ -2651,11 +2649,11 @@ static void calc_ortho_extent(KnifeTool_OpData *kcd)
|
||||||
float ws[3];
|
float ws[3];
|
||||||
INIT_MINMAX(min, max);
|
INIT_MINMAX(min, max);
|
||||||
|
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
ob = kcd->objects[b];
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
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) {
|
if (cagecos) {
|
||||||
for (int i = 0; i < em->bm->totvert; i++) {
|
for (int i = 0; i < em->bm->totvert; i++) {
|
||||||
copy_v3_v3(ws, cagecos[i]);
|
copy_v3_v3(ws, cagecos[i]);
|
||||||
|
@ -2930,11 +2928,11 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
|
||||||
|
|
||||||
Object *ob;
|
Object *ob;
|
||||||
BMEditMesh *em;
|
BMEditMesh *em;
|
||||||
uint b = 0;
|
|
||||||
|
|
||||||
for (i = 0, result = results; i < tot; i++, result++) {
|
for (i = 0, result = results; i < tot; i++, result++) {
|
||||||
for (b = 0; b < kcd->objects_len; b++) {
|
uint ob_index = 0;
|
||||||
ob = kcd->objects[b];
|
for (ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
em = BKE_editmesh_from_object(ob);
|
||||||
if (*result >= 0 && *result < em->tottri) {
|
if (*result >= 0 && *result < em->tottri) {
|
||||||
ls = (BMLoop **)em->looptris[*result];
|
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. */
|
/* 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(&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) {
|
for (ref = list->first; ref; ref = ref->next) {
|
||||||
kfe = ref->ref;
|
kfe = ref->ref;
|
||||||
if (kfe->is_invalid) {
|
if (kfe->is_invalid) {
|
||||||
|
@ -3033,7 +3031,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
|
||||||
}
|
}
|
||||||
|
|
||||||
hit.ob = v->ob;
|
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.hit, v->co);
|
||||||
copy_v3_v3(hit.cagehit, v->cageco);
|
copy_v3_v3(hit.cagehit, v->cageco);
|
||||||
copy_v2_v2(hit.schit, s);
|
copy_v2_v2(hit.schit, s);
|
||||||
|
@ -3109,7 +3107,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
|
||||||
transform_point_by_seg_v3(
|
transform_point_by_seg_v3(
|
||||||
hit.hit, p_cage, kfe->v1->co, kfe->v2->co, kfe->v1->cageco, kfe->v2->cageco);
|
hit.hit, p_cage, kfe->v1->co, kfe->v2->co, kfe->v1->cageco, kfe->v2->cageco);
|
||||||
hit.ob = kfe->v1->ob;
|
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_v3_v3(hit.cagehit, p_cage);
|
||||||
copy_v2_v2(hit.schit, sint);
|
copy_v2_v2(hit.schit, sint);
|
||||||
hit.perc = lambda;
|
hit.perc = lambda;
|
||||||
|
@ -3129,16 +3127,16 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
|
||||||
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
|
val = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) {
|
||||||
float p[3], p_cage[3];
|
float p[3], p_cage[3];
|
||||||
|
|
||||||
uint base_index = (uint)(uintptr_t)BLI_smallhash_lookup(&fobs, (uintptr_t)f);
|
uint ob_index = (uint)(uintptr_t)BLI_smallhash_lookup(&fobs, (uintptr_t)f);
|
||||||
ob = kcd->objects[base_index];
|
ob = kcd->objects[ob_index];
|
||||||
|
|
||||||
if (use_hit_prev &&
|
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)) {
|
if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
|
||||||
memset(&hit, 0, sizeof(hit));
|
memset(&hit, 0, sizeof(hit));
|
||||||
hit.f = f;
|
hit.f = f;
|
||||||
hit.ob = ob;
|
hit.ob = ob;
|
||||||
hit.base_index = base_index;
|
hit.ob_index = ob_index;
|
||||||
copy_v3_v3(hit.hit, p);
|
copy_v3_v3(hit.hit, p);
|
||||||
copy_v3_v3(hit.cagehit, p_cage);
|
copy_v3_v3(hit.cagehit, p_cage);
|
||||||
copy_v2_v2(hit.schit, s1);
|
copy_v2_v2(hit.schit, s1);
|
||||||
|
@ -3148,12 +3146,12 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_hit_curr &&
|
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)) {
|
if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
|
||||||
memset(&hit, 0, sizeof(hit));
|
memset(&hit, 0, sizeof(hit));
|
||||||
hit.f = f;
|
hit.f = f;
|
||||||
hit.ob = ob;
|
hit.ob = ob;
|
||||||
hit.base_index = base_index;
|
hit.ob_index = ob_index;
|
||||||
copy_v3_v3(hit.hit, p);
|
copy_v3_v3(hit.hit, p);
|
||||||
copy_v3_v3(hit.cagehit, p_cage);
|
copy_v3_v3(hit.cagehit, p_cage);
|
||||||
copy_v2_v2(hit.schit, s2);
|
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,
|
static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
|
||||||
Object **r_ob,
|
Object **r_ob,
|
||||||
uint *r_base_index,
|
uint *r_ob_index,
|
||||||
bool *is_space,
|
bool *is_space,
|
||||||
float r_co[3],
|
float r_co[3],
|
||||||
float r_cageco[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);
|
sub_v3_v3v3(ray, origin_ofs, origin);
|
||||||
normalize_v3_v3(ray_normal, ray);
|
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) {
|
if (f && kcd->only_select && BM_elem_flag_test(f, BM_ELEM_SELECT) == 0) {
|
||||||
f = NULL;
|
f = NULL;
|
||||||
|
@ -3232,7 +3230,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f) {
|
if (f) {
|
||||||
*r_ob = kcd->objects[*r_base_index];
|
*r_ob = kcd->objects[*r_ob_index];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (kcd->is_interactive) {
|
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,
|
static int knife_sample_screen_density_from_closest_face(KnifeTool_OpData *kcd,
|
||||||
const float radius,
|
const float radius,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
uint base_index,
|
uint ob_index,
|
||||||
BMFace *f,
|
BMFace *f,
|
||||||
const float cageco[3])
|
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);
|
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) {
|
for (ref = list->first; ref; ref = ref->next) {
|
||||||
KnifeEdge *kfe = ref->ref;
|
KnifeEdge *kfe = ref->ref;
|
||||||
int i;
|
int i;
|
||||||
|
@ -3329,7 +3327,7 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
|
||||||
|
|
||||||
if (!kcd->curr.is_space) {
|
if (!kcd->curr.is_space) {
|
||||||
density = (float)knife_sample_screen_density_from_closest_face(
|
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;
|
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. */
|
/* p is closest point on edge to the mouse cursor. */
|
||||||
static KnifeEdge *knife_find_closest_edge_of_face(
|
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 sco[2];
|
||||||
float maxdist;
|
float maxdist;
|
||||||
|
@ -3414,7 +3412,7 @@ static KnifeEdge *knife_find_closest_edge_of_face(
|
||||||
knife_project_v2(kcd, cagep, sco);
|
knife_project_v2(kcd, cagep, sco);
|
||||||
|
|
||||||
/* Look through all edges associated with this face. */
|
/* 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) {
|
for (ref = list->first; ref; ref = ref->next) {
|
||||||
KnifeEdge *kfe = ref->ref;
|
KnifeEdge *kfe = ref->ref;
|
||||||
float kfv1_sco[2], kfv2_sco[2], test_cagep[3];
|
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. */
|
* this is important for angle snap, which uses the previous mouse position. */
|
||||||
edgesnap = new_knife_vert(kcd, p, cagep);
|
edgesnap = new_knife_vert(kcd, p, cagep);
|
||||||
edgesnap->ob = ob;
|
edgesnap->ob = ob;
|
||||||
edgesnap->base_index = base_index;
|
edgesnap->ob_index = ob_index;
|
||||||
knife_project_v2(kcd, edgesnap->cageco, kcd->curr.mval);
|
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.ob = kcd->vc.obedit;
|
||||||
kcd->curr.bmface = knife_find_closest_face(kcd,
|
kcd->curr.bmface = knife_find_closest_face(kcd,
|
||||||
&kcd->curr.ob,
|
&kcd->curr.ob,
|
||||||
&kcd->curr.base_index,
|
&kcd->curr.ob_index,
|
||||||
&kcd->curr.is_space,
|
&kcd->curr.is_space,
|
||||||
kcd->curr.co,
|
kcd->curr.co,
|
||||||
kcd->curr.cage);
|
kcd->curr.cage);
|
||||||
|
|
||||||
if (kcd->curr.bmface) {
|
if (kcd->curr.bmface) {
|
||||||
kcd->curr.edge = knife_find_closest_edge_of_face(
|
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) {
|
if (kcd->curr.edge) {
|
||||||
|
@ -4017,7 +4015,7 @@ static void knifetool_undo(KnifeTool_OpData *kcd)
|
||||||
|
|
||||||
static void knifetool_init_obinfo(KnifeTool_OpData *kcd,
|
static void knifetool_init_obinfo(KnifeTool_OpData *kcd,
|
||||||
Object *ob,
|
Object *ob,
|
||||||
uint base_index,
|
uint ob_index,
|
||||||
bool use_tri_indices)
|
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);
|
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->em = em_eval;
|
||||||
obinfo->cagecos = (const float(*)[3])BKE_editmesh_vert_coords_alloc(
|
obinfo->cagecos = (const float(*)[3])BKE_editmesh_vert_coords_alloc(
|
||||||
kcd->vc.depsgraph, em_eval, scene_eval, obedit_eval, NULL);
|
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[ob_index].cagecos);
|
||||||
MEM_SAFE_FREE(kcd->objects_info[base_index].tri_indices);
|
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... */
|
/* called when modal loop selection gets set up... */
|
||||||
static void knifetool_init(ViewContext *vc,
|
static void knifetool_init(ViewContext *vc,
|
||||||
KnifeTool_OpData *kcd,
|
KnifeTool_OpData *kcd,
|
||||||
|
Object **objects,
|
||||||
|
const int objects_len,
|
||||||
const bool only_select,
|
const bool only_select,
|
||||||
const bool cut_through,
|
const bool cut_through,
|
||||||
const bool xray,
|
const bool xray,
|
||||||
|
@ -4101,16 +4101,24 @@ static void knifetool_init(ViewContext *vc,
|
||||||
kcd->scene = scene;
|
kcd->scene = scene;
|
||||||
kcd->region = vc->region;
|
kcd->region = vc->region;
|
||||||
|
|
||||||
kcd->objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
if (objects) {
|
||||||
vc->scene, vc->view_layer, vc->v3d, &kcd->objects_len);
|
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;
|
Object *ob;
|
||||||
BMEditMesh *em;
|
BMEditMesh *em;
|
||||||
kcd->objects_info = MEM_callocN(sizeof(*kcd->objects_info) * kcd->objects_len, "knife cagecos");
|
kcd->objects_info = MEM_callocN(sizeof(*kcd->objects_info) * kcd->objects_len, "knife cagecos");
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
ob = kcd->objects[b];
|
ob = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(ob);
|
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. */
|
/* Can't usefully select resulting edges in face mode. */
|
||||||
kcd->select_result = (em->selectmode != SCE_SELECT_FACE);
|
kcd->select_result = (em->selectmode != SCE_SELECT_FACE);
|
||||||
|
@ -4225,7 +4233,9 @@ static void knifetool_exit_ex(KnifeTool_OpData *kcd)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free object bases. */
|
/* Free object bases. */
|
||||||
MEM_freeN(kcd->objects);
|
if (kcd->objects_free) {
|
||||||
|
MEM_freeN(kcd->objects);
|
||||||
|
}
|
||||||
|
|
||||||
/* Destroy kcd itself. */
|
/* Destroy kcd itself. */
|
||||||
MEM_freeN(kcd);
|
MEM_freeN(kcd);
|
||||||
|
@ -4318,9 +4328,15 @@ static void knifetool_finish_single_post(KnifeTool_OpData *UNUSED(kcd), Object *
|
||||||
/* Called on tool confirmation. */
|
/* Called on tool confirmation. */
|
||||||
static void knifetool_finish_ex(KnifeTool_OpData *kcd)
|
static void knifetool_finish_ex(KnifeTool_OpData *kcd)
|
||||||
{
|
{
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
/* Separate pre/post passes are needed because `em->looptris` recalculation from the 'post' pass
|
||||||
Object *ob = kcd->objects[b];
|
* 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);
|
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);
|
knifetool_finish_single_post(kcd, ob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4789,6 +4805,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
|
|
||||||
knifetool_init(&vc,
|
knifetool_init(&vc,
|
||||||
kcd,
|
kcd,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
only_select,
|
only_select,
|
||||||
cut_through,
|
cut_through,
|
||||||
xray,
|
xray,
|
||||||
|
@ -4802,8 +4820,8 @@ static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
BMEditMesh *em;
|
BMEditMesh *em;
|
||||||
bool faces_selected = false;
|
bool faces_selected = false;
|
||||||
|
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
obedit = kcd->objects[b];
|
obedit = kcd->objects[ob_index];
|
||||||
em = BKE_editmesh_from_object(obedit);
|
em = BKE_editmesh_from_object(obedit);
|
||||||
if (em->bm->totfacesel != 0) {
|
if (em->bm->totfacesel != 0) {
|
||||||
faces_selected = true;
|
faces_selected = true;
|
||||||
|
@ -4942,7 +4960,12 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
|
||||||
return false;
|
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;
|
KnifeTool_OpData *kcd;
|
||||||
|
|
||||||
|
@ -4959,6 +4982,8 @@ void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_th
|
||||||
|
|
||||||
knifetool_init(vc,
|
knifetool_init(vc,
|
||||||
kcd,
|
kcd,
|
||||||
|
objects,
|
||||||
|
objects_len,
|
||||||
only_select,
|
only_select,
|
||||||
cut_through,
|
cut_through,
|
||||||
xray,
|
xray,
|
||||||
|
@ -5000,18 +5025,21 @@ void EDBM_mesh_knife(ViewContext *vc, LinkNode *polys, bool use_tag, bool cut_th
|
||||||
|
|
||||||
/* Finish. */
|
/* Finish. */
|
||||||
{
|
{
|
||||||
Object *ob;
|
/* See #knifetool_finish_ex for why multiple passes are needed. */
|
||||||
BMEditMesh *em;
|
for (uint ob_index = 0; ob_index < kcd->objects_len; ob_index++) {
|
||||||
for (uint b = 0; b < kcd->objects_len; b++) {
|
Object *ob = kcd->objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
||||||
ob = kcd->objects[b];
|
|
||||||
em = BKE_editmesh_from_object(ob);
|
|
||||||
|
|
||||||
if (use_tag) {
|
if (use_tag) {
|
||||||
BM_mesh_elem_hflag_enable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
|
BM_mesh_elem_hflag_enable_all(em->bm, BM_EDGE, BM_ELEM_TAG, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
knifetool_finish_single_pre(kcd, ob);
|
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! */
|
/* Tag faces inside! */
|
||||||
if (use_tag) {
|
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_UNKNOWN
|
||||||
#undef F_ISECT_SET_OUTSIDE
|
#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
|
/* Defer freeing data until the BVH tree is finished with, see: #point_is_visible and
|
||||||
* the doc-string for #knifetool_finish_single_post. */
|
* the doc-string for #knifetool_finish_single_post. */
|
||||||
|
Object *ob = kcd->objects[ob_index];
|
||||||
knifetool_finish_single_post(kcd, ob);
|
knifetool_finish_single_post(kcd, ob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,22 +132,21 @@ static int knifeproject_exec(bContext *C, wmOperator *op)
|
||||||
ViewContext vc;
|
ViewContext vc;
|
||||||
em_setup_viewcontext(C, &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;
|
uint objects_len;
|
||||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||||
vc.scene, vc.view_layer, vc.v3d, &objects_len);
|
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++) {
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
Object *obedit = objects[ob_index];
|
Object *obedit = objects[ob_index];
|
||||||
ED_view3d_viewcontext_init_object(&vc, obedit);
|
ED_view3d_viewcontext_init_object(&vc, obedit);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
|
||||||
EDBM_mesh_knife(&vc, polys, true, cut_through);
|
|
||||||
|
|
||||||
/* select only tagged faces */
|
/* select only tagged faces */
|
||||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
|
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);
|
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(
|
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 {
|
else {
|
||||||
bcd->states[i] = nullptr;
|
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] :
|
um_ref->store.keyblocks[i] :
|
||||||
nullptr;
|
nullptr;
|
||||||
um->store.keyblocks[i] = BLI_array_store_state_add(
|
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) {
|
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(
|
BArrayStore *bs = BLI_array_store_at_size_ensure(
|
||||||
&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
|
&um_arraystore.bs_stride, stride, ARRAY_CHUNK_SIZE);
|
||||||
um->store.mselect = BLI_array_store_state_add(
|
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 */
|
/* keep me->totselect for validation */
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct BMElem;
|
||||||
struct BMOperator;
|
struct BMOperator;
|
||||||
struct EnumPropertyItem;
|
struct EnumPropertyItem;
|
||||||
struct LinkNode;
|
struct LinkNode;
|
||||||
|
struct Object;
|
||||||
struct bContext;
|
struct bContext;
|
||||||
struct wmKeyConfig;
|
struct wmKeyConfig;
|
||||||
struct wmKeyMap;
|
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.
|
* \param use_tag: When set, tag all faces inside the polylines.
|
||||||
*/
|
*/
|
||||||
void EDBM_mesh_knife(struct ViewContext *vc,
|
void EDBM_mesh_knife(struct ViewContext *vc,
|
||||||
|
struct Object **objects,
|
||||||
|
int objects_len,
|
||||||
struct LinkNode *polys,
|
struct LinkNode *polys,
|
||||||
bool use_tag,
|
bool use_tag,
|
||||||
bool cut_through);
|
bool cut_through);
|
||||||
|
|
|
@ -1335,7 +1335,7 @@ struct VertPickData {
|
||||||
static void ed_mesh_pick_vert__mapFunc(void *userData,
|
static void ed_mesh_pick_vert__mapFunc(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
VertPickData *data = static_cast<VertPickData *>(userData);
|
VertPickData *data = static_cast<VertPickData *>(userData);
|
||||||
if (data->hide_vert && data->hide_vert[index]) {
|
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;
|
id_root = &collection->id;
|
||||||
user_overrides_from_selected_objects = true;
|
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 {
|
else {
|
||||||
|
BLI_assert(ID_IS_LINKED(obact) || ID_IS_OVERRIDE_LIBRARY_REAL(obact));
|
||||||
id_root = &obact->id;
|
id_root = &obact->id;
|
||||||
user_overrides_from_selected_objects = true;
|
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;
|
const bool do_fully_editable = !user_overrides_from_selected_objects;
|
||||||
|
|
||||||
GSet *user_overrides_objects_uids = do_fully_editable ? NULL :
|
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,
|
BLI_ghashutil_intcmp,
|
||||||
__func__);
|
__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) {
|
if (do_fully_editable) {
|
||||||
/* Pass. */
|
/* Pass. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -2376,22 +2376,6 @@ void ED_vgroup_mirror(Object *ob,
|
||||||
/* TODO: vgroup locking.
|
/* TODO: vgroup locking.
|
||||||
* TODO: face masking. */
|
* 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;
|
const int def_nr = BKE_object_defgroup_active_index_get(ob) - 1;
|
||||||
int totmirr = 0, totfail = 0;
|
int totmirr = 0, totfail = 0;
|
||||||
|
|
||||||
|
@ -2404,6 +2388,8 @@ void ED_vgroup_mirror(Object *ob,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int *flip_map = nullptr;
|
||||||
|
int flip_map_len;
|
||||||
if (flip_vgroups) {
|
if (flip_vgroups) {
|
||||||
flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, false, &flip_map_len) :
|
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);
|
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);
|
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
|
||||||
|
|
||||||
/* Go through the list of edit-vertices and assign them. */
|
/* 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) {
|
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
|
||||||
if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
|
if (!BM_elem_flag_test(eve, BM_ELEM_TAG)) {
|
||||||
if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
|
if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
|
||||||
if (eve_mirr != eve) {
|
if (eve_mirr != eve) {
|
||||||
if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
|
if (!BM_elem_flag_test(eve_mirr, BM_ELEM_TAG)) {
|
||||||
sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
|
const bool sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
|
||||||
sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
|
const bool sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
|
||||||
|
|
||||||
if ((sel || sel_mirr) && (eve != eve_mirr)) {
|
if ((sel || sel_mirr) && (eve != eve_mirr)) {
|
||||||
MDeformVert *dvert = static_cast<MDeformVert *>(
|
dvert_mirror_op(
|
||||||
BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset));
|
static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset)),
|
||||||
dvert_mirr = static_cast<MDeformVert *>(
|
static_cast<MDeformVert *>(BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset)),
|
||||||
BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset));
|
sel,
|
||||||
|
sel_mirr,
|
||||||
VGROUP_MIRR_OP;
|
flip_map,
|
||||||
|
flip_map_len,
|
||||||
|
mirror_weights,
|
||||||
|
flip_vgroups,
|
||||||
|
all_vgroups,
|
||||||
|
def_nr);
|
||||||
totmirr++;
|
totmirr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2471,39 +2463,38 @@ void ED_vgroup_mirror(Object *ob,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* object mode / weight paint */
|
/* object mode / weight paint */
|
||||||
int vidx, vidx_mirr;
|
|
||||||
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
|
const bool use_vert_sel = (me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
|
||||||
|
|
||||||
if (me->deform_verts().is_empty()) {
|
if (me->deform_verts().is_empty()) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!use_vert_sel) {
|
|
||||||
sel = sel_mirr = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
|
BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
|
||||||
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
|
MutableSpan<MDeformVert> dverts = me->deform_verts_for_write();
|
||||||
const bke::AttributeAccessor attributes = me->attributes();
|
const bke::AttributeAccessor attributes = me->attributes();
|
||||||
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
|
const VArray<bool> select_vert = attributes.lookup_or_default<bool>(
|
||||||
".select_vert", ATTR_DOMAIN_POINT, false);
|
".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)) {
|
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_mirr = mesh_get_x_mirror_vert(ob, nullptr, vidx, use_topology)) != -1) {
|
||||||
if (vidx != vidx_mirr) {
|
if (vidx != vidx_mirr) {
|
||||||
if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) {
|
if (!BLI_BITMAP_TEST(vert_tag, vidx_mirr)) {
|
||||||
|
const bool sel = use_vert_sel ? select_vert[vidx] : true;
|
||||||
if (use_vert_sel) {
|
const bool sel_mirr = use_vert_sel ? select_vert[vidx_mirr] : true;
|
||||||
sel = select_vert[vidx];
|
|
||||||
sel_mirr = select_vert[vidx_mirr];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sel || sel_mirr) {
|
if (sel || sel_mirr) {
|
||||||
MDeformVert *dvert = &dverts[vidx];
|
dvert_mirror_op(&dverts[vidx],
|
||||||
dvert_mirr = &dvert[vidx_mirr];
|
&dverts[vidx_mirr],
|
||||||
|
sel,
|
||||||
VGROUP_MIRR_OP;
|
sel_mirr,
|
||||||
|
flip_map,
|
||||||
|
flip_map_len,
|
||||||
|
mirror_weights,
|
||||||
|
flip_vgroups,
|
||||||
|
all_vgroups,
|
||||||
|
def_nr);
|
||||||
totmirr++;
|
totmirr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2523,9 +2514,6 @@ void ED_vgroup_mirror(Object *ob,
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_LATTICE) {
|
else if (ob->type == OB_LATTICE) {
|
||||||
Lattice *lt = vgroup_edit_lattice(ob);
|
Lattice *lt = vgroup_edit_lattice(ob);
|
||||||
int i1, i2;
|
|
||||||
int u, v, w;
|
|
||||||
int pntsu_half;
|
|
||||||
/* half but found up odd value */
|
/* half but found up odd value */
|
||||||
|
|
||||||
if (lt->pntsu == 1 || lt->dvert == nullptr) {
|
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
|
/* 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
|
* the 'u' indices it will cover all points except the middle which is
|
||||||
* ok in this case */
|
* ok in this case */
|
||||||
pntsu_half = lt->pntsu / 2;
|
int pntsu_half = lt->pntsu / 2;
|
||||||
|
|
||||||
for (w = 0; w < lt->pntsw; w++) {
|
for (int w = 0; w < lt->pntsw; w++) {
|
||||||
for (v = 0; v < lt->pntsv; v++) {
|
for (int v = 0; v < lt->pntsv; v++) {
|
||||||
for (u = 0; u < pntsu_half; u++) {
|
for (int u = 0; u < pntsu_half; u++) {
|
||||||
int u_inv = (lt->pntsu - 1) - u;
|
int u_inv = (lt->pntsu - 1) - u;
|
||||||
if (u != u_inv) {
|
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);
|
const BPoint *bp = <->def[i1];
|
||||||
i2 = BKE_lattice_index_from_uvw(lt, u_inv, v, w);
|
const BPoint *bp_mirr = <->def[i2];
|
||||||
|
|
||||||
bp = <->def[i1];
|
const bool sel = bp->f1 & SELECT;
|
||||||
bp_mirr = <->def[i2];
|
const bool sel_mirr = bp_mirr->f1 & SELECT;
|
||||||
|
|
||||||
sel = bp->f1 & SELECT;
|
|
||||||
sel_mirr = bp_mirr->f1 & SELECT;
|
|
||||||
|
|
||||||
if (sel || sel_mirr) {
|
if (sel || sel_mirr) {
|
||||||
MDeformVert *dvert = <->dvert[i1];
|
dvert_mirror_op(<->dvert[i1],
|
||||||
dvert_mirr = <->dvert[i2];
|
<->dvert[i2],
|
||||||
|
sel,
|
||||||
VGROUP_MIRR_OP;
|
sel_mirr,
|
||||||
|
flip_map,
|
||||||
|
flip_map_len,
|
||||||
|
mirror_weights,
|
||||||
|
flip_vgroups,
|
||||||
|
all_vgroups,
|
||||||
|
def_nr);
|
||||||
totmirr++;
|
totmirr++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -879,7 +879,7 @@ static int new_world_exec(bContext *C, wmOperator * /*op*/)
|
||||||
wo = new_wo;
|
wo = new_wo;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
ED_node_shader_default(C, &wo->id);
|
||||||
wo->use_nodes = true;
|
wo->use_nodes = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,7 @@ static void SCENE_OT_new(wmOperatorType *ot)
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
ot->prop = RNA_def_enum(ot->srna, "type", scene_new_items, SCE_COPY_NEW, "Type", "");
|
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 {
|
class ImagePaintMode : public AbstractPaintMode {
|
||||||
public:
|
public:
|
||||||
void *paint_new_stroke(bContext *C,
|
void *paint_new_stroke(
|
||||||
wmOperator *op,
|
bContext *C, wmOperator *op, Object * /*ob*/, const float /*mouse*/[2], int mode) override
|
||||||
Object * /*ob*/,
|
|
||||||
const float UNUSED(mouse[2]),
|
|
||||||
int mode) override
|
|
||||||
{
|
{
|
||||||
return paint_2d_new_stroke(C, op, mode);
|
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)[3];
|
||||||
int orco_tris_num;
|
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++) {
|
for (int i = 0; i < orco_tris_num; i++) {
|
||||||
const float *co_tri[3] = {
|
const float *co_tri[3] = {
|
||||||
|
@ -3265,7 +3265,7 @@ static void sculpt_topology_update(Sculpt *sd,
|
||||||
|
|
||||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
|
||||||
BKE_pbvh_node_mark_topology_update(nodes[n]);
|
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])
|
bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mval[2])
|
||||||
{
|
{
|
||||||
StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
|
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);
|
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||||
ViewContext *vc = paint_stroke_view_context(op->customdata);
|
ViewContext *vc = paint_stroke_view_context(op->customdata);
|
||||||
Object *ob = CTX_data_active_object(C);
|
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;
|
cache->first_time = true;
|
||||||
|
|
||||||
#define PIXEL_INPUT_THRESHHOLD 5
|
#define PIXEL_INPUT_THRESHHOLD 5
|
||||||
|
|
|
@ -503,7 +503,7 @@ float SCULPT_automasking_factor_get(AutomaskingCache *automasking,
|
||||||
PBVHVertRef vert,
|
PBVHVertRef vert,
|
||||||
AutomaskingNodeData *automask_data)
|
AutomaskingNodeData *automask_data)
|
||||||
{
|
{
|
||||||
if (!automasking) {
|
if (!automasking || vert.i == PBVH_REF_NONE) {
|
||||||
return 1.0f;
|
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) {
|
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||||
|
SCULPT_automasking_node_update(ss, &automask_data, &vd);
|
||||||
|
|
||||||
float final_disp[3];
|
float final_disp[3];
|
||||||
switch (brush->elastic_deform_type) {
|
switch (brush->elastic_deform_type) {
|
||||||
case BRUSH_ELASTIC_DEFORM_GRAB:
|
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 mode = RNA_enum_get(op->ptr, "mode");
|
||||||
const int tot_vert = SCULPT_vertex_count_get(ss);
|
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;
|
PBVH *pbvh = ob->sculpt->pbvh;
|
||||||
PBVHNode **nodes;
|
PBVHNode **nodes;
|
||||||
|
@ -842,62 +839,86 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
|
||||||
return OPERATOR_CANCELLED;
|
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) {
|
SCULPT_undo_push_begin(ob, op);
|
||||||
bool hidden_vertex = false;
|
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
|
switch (mode) {
|
||||||
* be synced from face sets to non-manifold vertices. */
|
case SCULPT_FACE_SET_VISIBILITY_TOGGLE: {
|
||||||
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
|
bool hidden_vertex = false;
|
||||||
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)) {
|
/* This can fail with regular meshes with non-manifold geometry as the visibility state can't
|
||||||
hidden_vertex = true;
|
* be synced from face sets to non-manifold vertices. */
|
||||||
break;
|
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) {
|
if (ss->hide_poly) {
|
||||||
for (int i = 0; i < ss->totfaces; i++) {
|
for (int i = 0; i < ss->totfaces; i++) {
|
||||||
if (ss->hide_poly[i]) {
|
if (ss->hide_poly[i]) {
|
||||||
hidden_vertex = true;
|
hidden_vertex = true;
|
||||||
break;
|
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) {
|
if (ss->face_sets) {
|
||||||
SCULPT_face_visibility_all_set(ss, true);
|
SCULPT_face_set_visibility_set(ss, active_face_set, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SCULPT_face_visibility_all_set(ss, false);
|
SCULPT_face_visibility_all_set(ss, false);
|
||||||
SCULPT_face_set_visibility_set(ss, active_face_set, true);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mode == SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE) {
|
break;
|
||||||
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
|
case SCULPT_FACE_SET_VISIBILITY_INVERT:
|
||||||
SCULPT_face_visibility_all_set(ss, false);
|
ss->hide_poly = BKE_sculpt_hide_poly_ensure(mesh);
|
||||||
SCULPT_face_set_visibility_set(ss, active_face_set, true);
|
SCULPT_face_visibility_all_invert(ss);
|
||||||
}
|
break;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For modes that use the cursor active vertex, update the rotation origin for viewport
|
/* 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)) {
|
if (ELEM(mode, SCULPT_FACE_SET_VISIBILITY_TOGGLE, SCULPT_FACE_SET_VISIBILITY_SHOW_ACTIVE)) {
|
||||||
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
||||||
float location[3];
|
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_visibility_sync_all_from_faces(ob);
|
||||||
|
|
||||||
SCULPT_undo_push_end(ob);
|
SCULPT_undo_push_end(ob);
|
||||||
|
|
||||||
for (int i = 0; i < totnode; i++) {
|
for (int i = 0; i < totnode; i++) {
|
||||||
BKE_pbvh_node_mark_update_visibility(nodes[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_undo_push_end(ob);
|
||||||
|
|
||||||
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
|
SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK);
|
||||||
|
SCULPT_tag_update_overlays(C);
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1611,7 +1611,9 @@ void CLIP_OT_mode_set(wmOperatorType *ot)
|
||||||
ot->poll = ED_space_clip_poll;
|
ot->poll = ED_space_clip_poll;
|
||||||
|
|
||||||
/* properties */
|
/* 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],
|
float grid_steps_y[SI_GRID_STEPS_LEN],
|
||||||
const int grid_dimension)
|
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++) {
|
for (int step = 0; step < SI_GRID_STEPS_LEN; step++) {
|
||||||
if (flag & SI_CUSTOM_GRID) {
|
switch (grid_shape_source) {
|
||||||
grid_steps_x[step] = 1.0f / sima->custom_grid_subdiv[0];
|
case SI_GRID_SHAPE_DYNAMIC:
|
||||||
grid_steps_y[step] = 1.0f / sima->custom_grid_subdiv[1];
|
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
|
||||||
}
|
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
|
||||||
else {
|
break;
|
||||||
grid_steps_x[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
|
case SI_GRID_SHAPE_FIXED:
|
||||||
grid_steps_y[step] = powf(grid_dimension, step - SI_GRID_STEPS_LEN);
|
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)
|
void NLA_OT_fmodifier_add(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
/* identifiers */
|
/* identifiers */
|
||||||
ot->name = "Add F-Modifier";
|
ot->name = "Add F-Modifier";
|
||||||
ot->idname = "NLA_OT_fmodifier_add";
|
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_property_translation_context(ot->prop, BLT_I18NCONTEXT_ID_ACTION);
|
||||||
RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
|
RNA_def_enum_funcs(ot->prop, nla_fmodifier_itemf);
|
||||||
|
|
||||||
RNA_def_boolean(ot->srna,
|
prop = RNA_def_boolean(ot->srna,
|
||||||
"only_active",
|
"only_active",
|
||||||
true,
|
true,
|
||||||
"Only Active",
|
"Only Active",
|
||||||
"Only add a F-Modifier of the specified type to the active strip");
|
"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;
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||||
|
|
||||||
/* properties */
|
/* properties */
|
||||||
RNA_def_boolean(
|
ot->prop = RNA_def_boolean(
|
||||||
ot->srna, "only_active", true, "Only Active", "Only paste F-Modifiers on active strip");
|
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(
|
RNA_def_boolean(
|
||||||
ot->srna,
|
ot->srna,
|
||||||
"replace",
|
"replace",
|
||||||
|
|
|
@ -64,6 +64,10 @@ struct NodeInsertOfsData {
|
||||||
float offset_x; /* offset to apply to node chain */
|
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)
|
static void clear_picking_highlight(ListBase *links)
|
||||||
{
|
{
|
||||||
LISTBASE_FOREACH (bNodeLink *, link, 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);
|
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) {
|
LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) {
|
||||||
if (node->flag & NODE_SELECT) {
|
if (!(node->flag & NODE_SELECT)) {
|
||||||
if (node->parent == nullptr) {
|
continue;
|
||||||
/* disallow moving a parent into its child */
|
}
|
||||||
if (nodeAttachNodeCheck(frame, node) == false) {
|
|
||||||
/* attach all unparented nodes */
|
if (node->parent == nullptr) {
|
||||||
nodeAttachNode(node, frame);
|
/* 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) {
|
if (parent) {
|
||||||
/* disallow moving a parent into its child */
|
/* disallow moving a parent into its child */
|
||||||
if (nodeAttachNodeCheck(frame, node) == false) {
|
if (nodeAttachNodeCheck(frame, node) == false) {
|
||||||
nodeDetachNode(node);
|
nodeDetachNode(node);
|
||||||
nodeAttachNode(node, frame);
|
nodeAttachNode(node, frame);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1881,100 +1885,55 @@ void NODE_OT_detach(wmOperatorType *ot)
|
||||||
/** \name Automatic Node Insert on Dragging
|
/** \name Automatic Node Insert on Dragging
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
/* prevent duplicate testing code below */
|
static bNode *get_selected_node_for_insertion(bNodeTree &node_tree)
|
||||||
static bool ed_node_link_conditions(ScrArea *area,
|
|
||||||
bool test,
|
|
||||||
SpaceNode **r_snode,
|
|
||||||
bNode **r_select)
|
|
||||||
{
|
{
|
||||||
SpaceNode *snode = area ? (SpaceNode *)area->spacedata.first : nullptr;
|
bNode *selected_node = nullptr;
|
||||||
|
int selected_node_count = 0;
|
||||||
*r_snode = snode;
|
for (bNode *node : node_tree.all_nodes()) {
|
||||||
*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) {
|
|
||||||
if (node->flag & SELECT) {
|
if (node->flag & SELECT) {
|
||||||
if (select) {
|
selected_node = node;
|
||||||
break;
|
selected_node_count++;
|
||||||
}
|
}
|
||||||
select = node;
|
if (selected_node_count > 1) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* only one selected */
|
if (!selected_node) {
|
||||||
if (node || select == nullptr) {
|
return nullptr;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (selected_node->input_sockets().is_empty() || selected_node->output_sockets().is_empty()) {
|
||||||
/* correct node */
|
return nullptr;
|
||||||
if (BLI_listbase_is_empty(&select->inputs) || BLI_listbase_is_empty(&select->outputs)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (std::any_of(selected_node->input_sockets().begin(),
|
||||||
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW);
|
selected_node->input_sockets().end(),
|
||||||
|
[&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) {
|
||||||
/* test node for links */
|
return nullptr;
|
||||||
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->output_sockets().begin(),
|
||||||
*r_select = select;
|
selected_node->output_sockets().end(),
|
||||||
return true;
|
[&](const bNodeSocket *socket) { return socket->is_directly_linked(); })) {
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
return selected_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
void node_insert_on_link_flags_set(SpaceNode &snode, const ARegion ®ion)
|
||||||
|
|
||||||
} // namespace blender::ed::space_node
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
|
||||||
/** \name Node Line Intersection Test
|
|
||||||
* \{ */
|
|
||||||
|
|
||||||
void ED_node_link_intersect_test(ScrArea *area, int test)
|
|
||||||
{
|
{
|
||||||
using namespace blender;
|
bNodeTree &node_tree = *snode.edittree;
|
||||||
using namespace blender::ed::space_node;
|
node_tree.ensure_topology_cache();
|
||||||
|
|
||||||
bNode *select;
|
node_insert_on_link_flags_clear(node_tree);
|
||||||
SpaceNode *snode;
|
|
||||||
if (!ed_node_link_conditions(area, test, &snode, &select)) {
|
bNode *node_to_insert = get_selected_node_for_insertion(node_tree);
|
||||||
|
if (!node_to_insert) {
|
||||||
return;
|
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 */
|
/* find link to select/highlight */
|
||||||
bNodeLink *selink = nullptr;
|
bNodeLink *selink = nullptr;
|
||||||
float dist_best = FLT_MAX;
|
float dist_best = FLT_MAX;
|
||||||
LISTBASE_FOREACH (bNodeLink *, link, &snode->edittree->links) {
|
LISTBASE_FOREACH (bNodeLink *, link, &node_tree.links) {
|
||||||
|
if (node_link_is_hidden_or_dimmed(region.v2d, *link)) {
|
||||||
if (node_link_is_hidden_or_dimmed(region->v2d, *link)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1986,10 +1945,10 @@ void ED_node_link_intersect_test(ScrArea *area, int test)
|
||||||
* upper left node edge of a intersected line segment */
|
* upper left node edge of a intersected line segment */
|
||||||
for (int i = 0; i < NODE_LINK_RESOL; i++) {
|
for (int i = 0; i < NODE_LINK_RESOL; i++) {
|
||||||
/* Check if the node rectangle intersects the line from this point to next one. */
|
/* Check if the node rectangle intersects the line from this point to next one. */
|
||||||
if (BLI_rctf_isect_segment(&select->totr, 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
|
/* store the shortest distance to the upper left edge
|
||||||
* of all intersections found so far */
|
* 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,
|
/* to be precise coords should be clipped by select->totr,
|
||||||
* but not done since there's no real noticeable difference */
|
* 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
|
/** \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. */
|
/** 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;
|
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
|
} // 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*/,
|
static char *datastack_drop_tooltip(bContext * /*C*/,
|
||||||
wmDrag *drag,
|
wmDrag *drag,
|
||||||
const int UNUSED(xy[2]),
|
const int /*xy*/[2],
|
||||||
struct wmDropBox * /*drop*/)
|
struct wmDropBox * /*drop*/)
|
||||||
{
|
{
|
||||||
StackDropData *drop_data = static_cast<StackDropData *>(drag->poin);
|
StackDropData *drop_data = static_cast<StackDropData *>(drag->poin);
|
||||||
|
|
|
@ -487,37 +487,6 @@ GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspread
|
||||||
return geometry_set;
|
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)
|
std::unique_ptr<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval)
|
||||||
{
|
{
|
||||||
SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
|
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*/,
|
static char *view3d_object_data_drop_tooltip(bContext * /*C*/,
|
||||||
wmDrag * /*drag*/,
|
wmDrag * /*drag*/,
|
||||||
const int UNUSED(xy[2]),
|
const int /*xy*/[2],
|
||||||
wmDropBox * /*drop*/)
|
wmDropBox * /*drop*/)
|
||||||
{
|
{
|
||||||
return BLI_strdup(TIP_("Create object instance from object-data"));
|
return BLI_strdup(TIP_("Create object instance from object-data"));
|
||||||
|
|
|
@ -262,7 +262,7 @@ struct foreachScreenFace_userData {
|
||||||
static void meshobject_foreachScreenVert__mapFunc(void *userData,
|
static void meshobject_foreachScreenVert__mapFunc(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
foreachScreenObjectVert_userData *data = static_cast<foreachScreenObjectVert_userData *>(
|
foreachScreenObjectVert_userData *data = static_cast<foreachScreenObjectVert_userData *>(
|
||||||
userData);
|
userData);
|
||||||
|
@ -316,7 +316,7 @@ void meshobject_foreachScreenVert(
|
||||||
static void mesh_foreachScreenVert__mapFunc(void *userData,
|
static void mesh_foreachScreenVert__mapFunc(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float co[3],
|
const float co[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
foreachScreenVert_userData *data = static_cast<foreachScreenVert_userData *>(userData);
|
foreachScreenVert_userData *data = static_cast<foreachScreenVert_userData *>(userData);
|
||||||
BMVert *eve = BM_vert_at_index(data->vc.em->bm, index);
|
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,
|
static void mesh_foreachScreenFace__mapFunc(void *userData,
|
||||||
int index,
|
int index,
|
||||||
const float cent[3],
|
const float cent[3],
|
||||||
const float UNUSED(no[3]))
|
const float /*no*/[3])
|
||||||
{
|
{
|
||||||
foreachScreenFace_userData *data = static_cast<foreachScreenFace_userData *>(userData);
|
foreachScreenFace_userData *data = static_cast<foreachScreenFace_userData *>(userData);
|
||||||
BMFace *efa = BM_face_at_index(data->vc.em->bm, index);
|
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_uv.c
|
||||||
transform_convert_mesh_vert_cdata.c
|
transform_convert_mesh_vert_cdata.c
|
||||||
transform_convert_nla.c
|
transform_convert_nla.c
|
||||||
transform_convert_node.c
|
transform_convert_node.cc
|
||||||
transform_convert_object.c
|
transform_convert_object.c
|
||||||
transform_convert_object_texspace.c
|
transform_convert_object_texspace.c
|
||||||
transform_convert_paintcurve.c
|
transform_convert_paintcurve.c
|
||||||
|
|
|
@ -1518,26 +1518,26 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_prop_edit = false;
|
/* Save proportional edit settings.
|
||||||
int prop_edit_flag = 0;
|
* Skip saving proportional edit if it was not actually used. */
|
||||||
if (t->flag & T_PROP_EDIT_ALL) {
|
if (!(t->options & CTX_NO_PET)) {
|
||||||
if (t->flag & T_PROP_EDIT) {
|
bool use_prop_edit = false;
|
||||||
use_prop_edit = true;
|
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 modal, save settings back in scene if not set as operator argument */
|
||||||
if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
|
if ((t->flag & T_MODAL) || (op->flag & OP_IS_REPEAT)) {
|
||||||
/* save settings if not set in operator */
|
/* save settings if not set in operator */
|
||||||
|
|
||||||
/* skip saving proportional edit if it was not actually used */
|
|
||||||
if (!(t->options & CTX_NO_PET)) {
|
|
||||||
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) &&
|
if ((prop = RNA_struct_find_property(op->ptr, "use_proportional_edit")) &&
|
||||||
!RNA_property_is_set(op->ptr, prop)) {
|
!RNA_property_is_set(op->ptr, prop)) {
|
||||||
BKE_view_layer_synced_ensure(t->scene, t->view_layer);
|
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;
|
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. */
|
/* 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"))) {
|
if ((prop = RNA_struct_find_property(op->ptr, "mirror"))) {
|
||||||
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
|
RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
|
|
||||||
#include "transform_data.h"
|
#include "transform_data.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* use node center for transform instead of upper-left corner.
|
/* use node center for transform instead of upper-left corner.
|
||||||
* disabled since it makes absolute snapping not work so nicely
|
* disabled since it makes absolute snapping not work so nicely
|
||||||
*/
|
*/
|
||||||
|
@ -141,6 +145,7 @@ typedef enum {
|
||||||
/** No cursor wrapping on region bounds */
|
/** No cursor wrapping on region bounds */
|
||||||
T_NO_CURSOR_WRAP = 1 << 23,
|
T_NO_CURSOR_WRAP = 1 << 23,
|
||||||
} eTFlag;
|
} eTFlag;
|
||||||
|
ENUM_OPERATORS(eTFlag, T_NO_CURSOR_WRAP);
|
||||||
|
|
||||||
#define T_ALL_RESTRICTIONS (T_NO_CONSTRAINT | T_NULL_ONE)
|
#define T_ALL_RESTRICTIONS (T_NO_CONSTRAINT | T_NULL_ONE)
|
||||||
#define T_PROP_EDIT_ALL (T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED)
|
#define T_PROP_EDIT_ALL (T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED)
|
||||||
|
@ -864,3 +869,7 @@ bool checkUseAxisMatrix(TransInfo *t);
|
||||||
th++, i++)
|
th++, i++)
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
|
|
||||||
#include "RE_engine.h"
|
#include "RE_engine.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
struct BMEditMesh;
|
struct BMEditMesh;
|
||||||
struct BMesh;
|
struct BMesh;
|
||||||
struct BezTriple;
|
struct BezTriple;
|
||||||
|
@ -244,7 +248,7 @@ extern TransConvertTypeInfo TransConvertType_MeshVertCData;
|
||||||
|
|
||||||
extern TransConvertTypeInfo TransConvertType_NLA;
|
extern TransConvertTypeInfo TransConvertType_NLA;
|
||||||
|
|
||||||
/* transform_convert_node.c */
|
/* transform_convert_node.cc */
|
||||||
|
|
||||||
extern TransConvertTypeInfo TransConvertType_Node;
|
extern TransConvertTypeInfo TransConvertType_Node;
|
||||||
|
|
||||||
|
@ -279,3 +283,7 @@ extern TransConvertTypeInfo TransConvertType_SequencerImage;
|
||||||
/* transform_convert_tracking.c */
|
/* transform_convert_tracking.c */
|
||||||
|
|
||||||
extern TransConvertTypeInfo TransConvertType_Tracking;
|
extern TransConvertTypeInfo TransConvertType_Tracking;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -55,6 +55,29 @@ typedef struct TransDataNla {
|
||||||
int handle;
|
int handle;
|
||||||
} TransDataNla;
|
} 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
|
/** \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)
|
* this is done as a iterative procedure (done 5 times max for now)
|
||||||
*/
|
*/
|
||||||
NlaStrip *prev = strip->prev;
|
NlaStrip *prev = BKE_nlastrip_prev_in_track(strip, true);
|
||||||
while (prev != NULL && (prev->type & NLASTRIP_TYPE_TRANSITION)) {
|
NlaStrip *next = BKE_nlastrip_next_in_track(strip, true);
|
||||||
prev = prev->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
NlaStrip *next = strip->next;
|
|
||||||
while (next != NULL && (next->type & NLASTRIP_TYPE_TRANSITION)) {
|
|
||||||
next = next->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (short iter = 0; iter < 5; iter++) {
|
for (short iter = 0; iter < 5; iter++) {
|
||||||
const bool pExceeded = (prev != NULL) && (tdn->h1[0] < prev->end);
|
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
|
/* 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)
|
* (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_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||||
|
|
||||||
RNA_float_set(&strip_ptr, "frame_start", tdn->h1[0]);
|
applyTransformNLA_translation(&strip_ptr, tdn);
|
||||||
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]);
|
|
||||||
|
|
||||||
/* flush transforms to child strips (since this should be a meta) */
|
/* flush transforms to child strips (since this should be a meta) */
|
||||||
BKE_nlameta_flush_transforms(strip);
|
BKE_nlameta_flush_transforms(strip);
|
||||||
|
|
|
@ -96,13 +96,13 @@ static bool is_node_parent_select(bNode *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
|
static void createTransNodeData(bContext * /*C*/, TransInfo *t)
|
||||||
{
|
{
|
||||||
const float dpi_fac = UI_DPI_FAC;
|
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 */
|
/* 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,
|
UI_view2d_edge_pan_init(t->context,
|
||||||
&customdata->edgepan_data,
|
&customdata->edgepan_data,
|
||||||
NODE_EDGE_PAN_INSIDE_PAD,
|
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. */
|
/* 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 */
|
/* set transform flags on nodes */
|
||||||
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
|
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
|
||||||
|
@ -142,9 +142,8 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransData *td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransNode TransData");
|
TransData *td = tc->data = MEM_cnew_array<TransData>(tc->data_len, __func__);
|
||||||
TransData2D *td2d = tc->data_2d = MEM_callocN(tc->data_len * sizeof(TransData2D),
|
TransData2D *td2d = tc->data_2d = MEM_cnew_array<TransData2D>(tc->data_len, __func__);
|
||||||
"TransNode TransData2D");
|
|
||||||
|
|
||||||
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
|
LISTBASE_FOREACH (bNode *, node, &snode->edittree->nodes) {
|
||||||
if (node->flag & NODE_TRANSFORM) {
|
if (node->flag & NODE_TRANSFORM) {
|
||||||
|
@ -161,9 +160,11 @@ static void createTransNodeData(bContext *UNUSED(C), TransInfo *t)
|
||||||
|
|
||||||
static void flushTransNodes(TransInfo *t)
|
static void flushTransNodes(TransInfo *t)
|
||||||
{
|
{
|
||||||
|
using namespace blender::ed;
|
||||||
const float dpi_fac = UI_DPI_FAC;
|
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->options & CTX_VIEW2D_EDGE_PAN) {
|
||||||
if (t->state == TRANS_CANCEL) {
|
if (t->state == TRANS_CANCEL) {
|
||||||
|
@ -196,7 +197,7 @@ static void flushTransNodes(TransInfo *t)
|
||||||
for (int i = 0; i < tc->data_len; i++) {
|
for (int i = 0; i < tc->data_len; i++) {
|
||||||
TransData *td = &tc->data[i];
|
TransData *td = &tc->data[i];
|
||||||
TransData2D *td2d = &tc->data_2d[i];
|
TransData2D *td2d = &tc->data_2d[i];
|
||||||
bNode *node = td->extra;
|
bNode *node = static_cast<bNode *>(td->extra);
|
||||||
|
|
||||||
float loc[2];
|
float loc[2];
|
||||||
add_v2_v2v2(loc, td2d->loc, offset);
|
add_v2_v2v2(loc, td2d->loc, offset);
|
||||||
|
@ -221,7 +222,7 @@ static void flushTransNodes(TransInfo *t)
|
||||||
|
|
||||||
/* handle intersection with noodles */
|
/* handle intersection with noodles */
|
||||||
if (tc->data_len == 1) {
|
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)
|
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);
|
const bool canceled = (t->state == TRANS_CANCEL);
|
||||||
|
|
||||||
SpaceNode *snode = (SpaceNode *)t->area->spacedata.first;
|
|
||||||
if (canceled && t->remove_on_cancel) {
|
if (canceled && t->remove_on_cancel) {
|
||||||
/* remove selected nodes on cancel */
|
/* remove selected nodes on cancel */
|
||||||
bNodeTree *ntree = snode->edittree;
|
|
||||||
if (ntree) {
|
if (ntree) {
|
||||||
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
|
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
|
||||||
if (node->flag & NODE_SELECT) {
|
if (node->flag & NODE_SELECT) {
|
||||||
|
@ -253,11 +256,10 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t)
|
||||||
|
|
||||||
if (!canceled) {
|
if (!canceled) {
|
||||||
ED_node_post_apply_transform(C, snode->edittree);
|
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 */
|
space_node::node_insert_on_link_flags_clear(*ntree);
|
||||||
ED_node_link_intersect_test(t->area, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
|
@ -523,9 +523,7 @@ static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
return OPERATOR_RUNNING_MODAL;
|
return OPERATOR_RUNNING_MODAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool transform_poll_property(const bContext *UNUSED(C),
|
static bool transform_poll_property(const bContext *C, wmOperator *op, const PropertyRNA *prop)
|
||||||
wmOperator *op,
|
|
||||||
const PropertyRNA *prop)
|
|
||||||
{
|
{
|
||||||
const char *prop_id = RNA_property_identifier(prop);
|
const char *prop_id = RNA_property_identifier(prop);
|
||||||
|
|
||||||
|
@ -559,12 +557,21 @@ static bool transform_poll_property(const bContext *UNUSED(C),
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Proportional Editing. */
|
/* 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");
|
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 ((prop_pet != prop) && (RNA_property_boolean_get(op->ptr, prop_pet) == false)) {
|
||||||
if (STRPREFIX(prop_id, "proportional") || STRPREFIX(prop_id, "use_proportional")) {
|
/* If "use_proportional_edit" is false, hide:
|
||||||
return false;
|
* - "proportional_edit_falloff",
|
||||||
}
|
* - "proportional_size",
|
||||||
|
* - "use_proportional_connected",
|
||||||
|
* - "use_proportional_projected". */
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
/* For enum. */
|
/* For enum. */
|
||||||
#include "DNA_space_types.h"
|
#include "DNA_space_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
bool peelObjectsTransform(struct TransInfo *t,
|
bool peelObjectsTransform(struct TransInfo *t,
|
||||||
const float mval[2],
|
const float mval[2],
|
||||||
bool use_peel_object,
|
bool use_peel_object,
|
||||||
|
@ -92,3 +96,7 @@ void transform_snap_anim_flush_data(TransInfo *t,
|
||||||
TransData *td,
|
TransData *td,
|
||||||
eAnimEdit_AutoSnap autosnap,
|
eAnimEdit_AutoSnap autosnap,
|
||||||
float *r_val_final);
|
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