diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-12-02 03:40:58 +0300 |
commit | a35c635edb3db548e11555024ec3a384f93ce352 (patch) | |
tree | ae0c0c9435c2e7daed4cbd916e0be90df7898b51 | |
parent | 7164e63fefcfa26caf387a2ad04a8c51b533c32b (diff) | |
parent | f1ac64921b49eaea8658d144754a1a532198c720 (diff) |
Merge branch 'master' into tmp-overlay-enginetmp-overlay-engine
# Conflicts:
# source/blender/draw/modes/paint_texture_mode.c
191 files changed, 4005 insertions, 2026 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e6e0abe1ab8..0af6d200c6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,76 +131,6 @@ get_blender_version() #----------------------------------------------------------------------------- -# Platform Specific Defaults - -# list of var-names -set(_init_vars) - -# initialize to ON -macro(option_defaults_init) - foreach(_var ${ARGV}) - set(${_var} ON) - list(APPEND _init_vars "${_var}") - endforeach() - unset(_var) -endmacro() - -# remove from namespace -macro(option_defaults_clear) - foreach(_var ${_init_vars}) - unset(${_var}) - endforeach() - unset(_var) - unset(_init_vars) -endmacro() - - -# values to initialize WITH_**** -option_defaults_init( - _init_BUILDINFO - _init_CODEC_FFMPEG - _init_CYCLES_OSL - _init_IMAGE_OPENEXR - _init_INPUT_NDOF - _init_JACK - _init_OPENCOLLADA - _init_OPENCOLORIO - _init_SDL - _init_FFTW3 - _init_OPENSUBDIV -) - -# TBB malloc is only supported on for windows currently -if(WIN32) - set(_init_TBB_MALLOC_PROXY ON) -else() - set(_init_TBB_MALLOC_PROXY OFF) -endif() - - -# customize... -if(UNIX AND NOT APPLE) - # some of these libraries are problematic on Linux - # disable less important dependencies by default - set(_init_CODEC_FFMPEG OFF) - set(_init_CYCLES_OSL OFF) - set(_init_IMAGE_OPENEXR OFF) - set(_init_JACK OFF) - set(_init_OPENCOLLADA OFF) - set(_init_OPENCOLORIO OFF) - set(_init_SDL OFF) - set(_init_FFTW3 OFF) - set(_init_OPENSUBDIV OFF) - set(_init_OPENVDB OFF) - set(_init_OPENIMAGEDENOISE OFF) -elseif(WIN32) - set(_init_JACK OFF) -elseif(APPLE) - set(_init_JACK OFF) -endif() - - -#----------------------------------------------------------------------------- # Options # First platform specific non-cached vars @@ -226,7 +156,7 @@ if(APPLE) option(WITH_PYTHON_FRAMEWORK "Enable building using the Python available in the framework (OSX only)" OFF) endif() -option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ${_init_BUILDINFO}) +option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON) if(${CMAKE_VERSION} VERSION_LESS 2.8.8) # add_library OBJECT arg unsupported set(WITH_BUILDINFO OFF) @@ -240,20 +170,20 @@ mark_as_advanced(BUILDINFO_OVERRIDE_TIME) option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON) option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON) -option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ${_init_FFTW3}) +option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ON) option(WITH_BULLET "Enable Bullet (Physics Engine)" ON) option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" ) mark_as_advanced(WITH_SYSTEM_BULLET) -option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO}) +option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ON) # Compositor option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON) -option(WITH_OPENIMAGEDENOISE "Enable the OpenImageDenoise compositing node" ${_init_OPENIMAGEDENOISE}) +option(WITH_OPENIMAGEDENOISE "Enable the OpenImageDenoise compositing node" ON) -option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" ${_init_OPENSUBDIV}) +option(WITH_OPENSUBDIV "Enable OpenSubdiv for surface subdivision" ON) -option(WITH_OPENVDB "Enable features relying on OpenVDB" ${_init_OPENVDB}) -option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" ${_init_OPENVDB}) +option(WITH_OPENVDB "Enable features relying on OpenVDB" ON) +option(WITH_OPENVDB_BLOSC "Enable blosc compression for OpenVDB, only enable if OpenVDB was built with blosc support" ON) option(WITH_OPENVDB_3_ABI_COMPATIBLE "Assume OpenVDB library has been compiled with version 3 ABI compatibility" OFF) mark_as_advanced(WITH_OPENVDB_3_ABI_COMPATIBLE) @@ -315,11 +245,11 @@ endif() option(WITH_MOD_FLUID "Enable Elbeem Modifier (Fluid Simulation)" ON) option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON) option(WITH_MOD_REMESH "Enable Remesh Modifier" ON) -option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF) +option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" ON) # Image format support option(WITH_OPENIMAGEIO "Enable OpenImageIO Support (http://www.openimageio.org)" ON) -option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ${_init_IMAGE_OPENEXR}) +option(WITH_IMAGE_OPENEXR "Enable OpenEXR Support (http://www.openexr.com)" ON) option(WITH_IMAGE_OPENJPEG "Enable OpenJpeg Support (http://www.openjpeg.org)" ON) option(WITH_IMAGE_TIFF "Enable LibTIFF Support" ON) option(WITH_IMAGE_DDS "Enable DDS Image Support" ON) @@ -328,23 +258,25 @@ option(WITH_IMAGE_HDR "Enable HDR Image Support" ON) # Audio/Video format support option(WITH_CODEC_AVI "Enable Blenders own AVI file support (raw/jpeg)" ON) -option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ${_init_CODEC_FFMPEG}) -option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" OFF) +option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" ON) +option(WITH_CODEC_SNDFILE "Enable libsndfile Support (http://www.mega-nerd.com/libsndfile)" ON) # Alembic support -option(WITH_ALEMBIC "Enable Alembic Support" OFF) +option(WITH_ALEMBIC "Enable Alembic Support" ON) option(WITH_ALEMBIC_HDF5 "Enable Legacy Alembic Support (not officially supported)" OFF) # 3D format support # Disable opencollada when we don't have precompiled libs -option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ${_init_OPENCOLLADA}) +option(WITH_OPENCOLLADA "Enable OpenCollada Support (http://www.opencollada.org)" ON) # Sound output -option(WITH_SDL "Enable SDL for sound and joystick support" ${_init_SDL}) +option(WITH_SDL "Enable SDL for sound and joystick support" ON) option(WITH_OPENAL "Enable OpenAL Support (http://www.openal.org)" ON) -option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ${_init_JACK}) -if(UNIX AND NOT APPLE) - option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) +if(NOT WIN32) + option(WITH_JACK "Enable JACK Support (http://www.jackaudio.org)" ON) + if(UNIX AND NOT APPLE) + option(WITH_JACK_DYNLOAD "Enable runtime dynamic JACK libraries loading" OFF) + endif() endif() if(UNIX AND NOT APPLE) option(WITH_SDL_DYNLOAD "Enable runtime dynamic SDL libraries loading" OFF) @@ -360,7 +292,7 @@ option(WITH_DRACO "Enable Draco mesh compression Python module (used for # Camera/motion tracking option(WITH_LIBMV "Enable Libmv structure from motion library" ON) -option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." OFF) +option(WITH_LIBMV_SCHUR_SPECIALIZATIONS "Enable fixed-size schur specializations." ON) mark_as_advanced(WITH_LIBMV_SCHUR_SPECIALIZATIONS) # Logging/unbit test libraries. @@ -376,7 +308,7 @@ option(WITH_FREESTYLE "Enable Freestyle (advanced edges rendering)" ON) if(WIN32) option(WITH_INPUT_IME "Enable Input Method Editor (IME) for complex Asian character input" ON) endif() -option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ${_init_INPUT_NDOF}) +option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) option(WITH_STATIC_LIBS "Try to link with static libraries, as much as possible, to make blender more portable across distributions" OFF) @@ -412,7 +344,7 @@ mark_as_advanced(WITH_CPU_SSE) option(WITH_CYCLES "Enable Cycles Render Engine" ON) option(WITH_CYCLES_STANDALONE "Build Cycles standalone application" OFF) option(WITH_CYCLES_STANDALONE_GUI "Build Cycles standalone with GUI" OFF) -option(WITH_CYCLES_OSL "Build Cycles with OSL support" ${_init_CYCLES_OSL}) +option(WITH_CYCLES_OSL "Build Cycles with OSL support" ON) option(WITH_CYCLES_EMBREE "Build Cycles with Embree support" OFF) option(WITH_CYCLES_CUDA_BINARIES "Build Cycles CUDA binaries" OFF) option(WITH_CYCLES_CUBIN_COMPILER "Build cubins with nvrtc based compiler instead of nvcc" OFF) @@ -468,7 +400,11 @@ mark_as_advanced(WITH_ASSERT_ABORT) option(WITH_BOOST "Enable features depending on boost" ON) option(WITH_TBB "Enable features depending on TBB (OpenVDB, OpenImageDenoise, sculpt multithreading)" ON) -option(WITH_TBB_MALLOC_PROXY "Enable the TBB malloc replacement" ${_init_TBB_MALLOC_PROXY}) + +# TBB malloc is only supported on for windows currently +if(WIN32) + option(WITH_TBB_MALLOC_PROXY "Enable the TBB malloc replacement" ON) +endif() # Unit testsing option(WITH_GTESTS "Enable GTest unit testing" OFF) @@ -591,9 +527,6 @@ endif() option(POSTINSTALL_SCRIPT "Run given CMake script after installation process" OFF) mark_as_advanced(POSTINSTALL_SCRIPT) -# avoid using again -option_defaults_clear() - # end option(...) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 19dac236762..bbacedca0ce 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -64,7 +64,7 @@ def create_buildbot_upload_zip(builder, package_files): sys.stderr.write('Create buildbot_upload.zip failed: ' + str(ex) + '\n') sys.exit(1) -def create_tar_bz2(src, dest, package_name): +def create_tar_xz(src, dest, package_name): # One extra to remove leading os.sep when cleaning root for package_root ln = len(src) + 1 flist = list() @@ -75,9 +75,20 @@ def create_tar_bz2(src, dest, package_name): flist.extend([(os.path.join(root, file), os.path.join(package_root, file)) for file in files]) import tarfile - package = tarfile.open(dest, 'w:bz2') + + # Set UID/GID of archived files to 0, otherwise they'd be owned by whatever + # user compiled the package. If root then unpacks it to /usr/local/ you get + # a security issue. + def _fakeroot(tarinfo): + tarinfo.gid = 0 + tarinfo.gname = "root" + tarinfo.uid = 0 + tarinfo.uname = "root" + return tarinfo + + package = tarfile.open(dest, 'w:xz', preset=9) for entry in flist: - package.add(entry[0], entry[1], recursive=False) + package.add(entry[0], entry[1], recursive=False, filter=_fakeroot) package.close() def cleanup_files(dirpath, extension): @@ -163,11 +174,11 @@ def pack_linux(builder): # Construct package name platform_name = 'linux-' + blender_glibc + '-' + blender_arch package_name = get_package_name(builder, platform_name) - package_filename = package_name + ".tar.bz2" + package_filename = package_name + ".tar.xz" - print("Creating .tar.bz2 archive") - package_filepath = builder.install_dir + '.tar.bz2' - create_tar_bz2(builder.install_dir, package_filepath, package_name) + print("Creating .tar.xz archive") + package_filepath = builder.install_dir + '.tar.xz' + create_tar_xz(builder.install_dir, package_filepath, package_name) # Create buildbot_upload.zip create_buildbot_upload_zip(builder, [(package_filepath, package_filename)]) diff --git a/build_files/cmake/Modules/GTestTesting.cmake b/build_files/cmake/Modules/GTestTesting.cmake index a93e829e6b0..2a05b92ba3f 100644 --- a/build_files/cmake/Modules/GTestTesting.cmake +++ b/build_files/cmake/Modules/GTestTesting.cmake @@ -12,9 +12,14 @@ # #============================================================================= -macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) +macro(BLENDER_SRC_GTEST_EX) if(WITH_GTESTS) - set(TARGET_NAME ${NAME}_test) + set(options SKIP_ADD_TEST) + set(oneValueArgs NAME) + set(multiValueArgs SRC EXTRA_LIBS COMMAND_ARGS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + set(TARGET_NAME ${ARG_NAME}_test) get_property(_current_include_directories DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) @@ -30,11 +35,11 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) ) unset(_current_include_directories) - add_executable(${TARGET_NAME} ${SRC}) + add_executable(${TARGET_NAME} ${ARG_SRC}) target_include_directories(${TARGET_NAME} PUBLIC "${TEST_INC}") target_include_directories(${TARGET_NAME} SYSTEM PUBLIC "${TEST_INC_SYS}") target_link_libraries(${TARGET_NAME} - ${EXTRA_LIBS} + ${ARG_EXTRA_LIBS} ${PLATFORM_LINKLIBS} bf_testing_main bf_intern_eigen @@ -60,8 +65,11 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) RUNTIME_OUTPUT_DIRECTORY "${TESTS_OUTPUT_DIR}" RUNTIME_OUTPUT_DIRECTORY_RELEASE "${TESTS_OUTPUT_DIR}" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${TESTS_OUTPUT_DIR}") - if(${DO_ADD_TEST}) - add_test(NAME ${TARGET_NAME} COMMAND ${TESTS_OUTPUT_DIR}/${TARGET_NAME} WORKING_DIRECTORY ${TEST_INSTALL_DIR}) + if(NOT ARG_SKIP_ADD_TEST) + add_test( + NAME ${TARGET_NAME} + COMMAND ${TESTS_OUTPUT_DIR}/${TARGET_NAME} ${ARG_COMMAND_ARGS} + WORKING_DIRECTORY ${TEST_INSTALL_DIR}) # Don't fail tests on leaks since these often happen in external libraries # that we can't fix. @@ -74,13 +82,23 @@ macro(BLENDER_SRC_GTEST_EX NAME SRC EXTRA_LIBS DO_ADD_TEST) endmacro() macro(BLENDER_SRC_GTEST NAME SRC EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${SRC}" "${EXTRA_LIBS}" "TRUE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${SRC}" + EXTRA_LIBS "${EXTRA_LIBS}") endmacro() macro(BLENDER_TEST NAME EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "TRUE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${NAME}_test.cc" + EXTRA_LIBS "${EXTRA_LIBS}") endmacro() macro(BLENDER_TEST_PERFORMANCE NAME EXTRA_LIBS) - BLENDER_SRC_GTEST_EX("${NAME}" "${NAME}_test.cc" "${EXTRA_LIBS}" "FALSE") + BLENDER_SRC_GTEST_EX( + NAME "${NAME}" + SRC "${NAME}_test.cc" + EXTRA_LIBS "${EXTRA_LIBS}" + SKIP_ADD_TEST) endmacro() diff --git a/build_files/cmake/config/blender_full.cmake b/build_files/cmake/config/blender_full.cmake index 56b970c349d..fae15ea979b 100644 --- a/build_files/cmake/config/blender_full.cmake +++ b/build_files/cmake/config/blender_full.cmake @@ -18,7 +18,6 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) @@ -29,7 +28,6 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) -set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_LZMA ON CACHE BOOL "" FORCE) set(WITH_LZO ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) @@ -49,20 +47,17 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_TBB ON CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) # platform dependent options -if(UNIX AND NOT APPLE) +if(NOT WIN32) set(WITH_JACK ON CACHE BOOL "" FORCE) +endif() +if(UNIX AND NOT APPLE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) -elseif(WIN32) - set(WITH_JACK OFF CACHE BOOL "" FORCE) -elseif(APPLE) - set(WITH_JACK ON CACHE BOOL "" FORCE) - -# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake") + set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) endif() diff --git a/build_files/cmake/config/blender_lite.cmake b/build_files/cmake/config/blender_lite.cmake index 2a1f4a59c15..3a67836d253 100644 --- a/build_files/cmake/config/blender_lite.cmake +++ b/build_files/cmake/config/blender_lite.cmake @@ -24,7 +24,6 @@ set(WITH_LIBMV OFF CACHE BOOL "" FORCE) set(WITH_LLVM OFF CACHE BOOL "" FORCE) set(WITH_COMPOSITOR OFF CACHE BOOL "" FORCE) set(WITH_FREESTYLE OFF CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE) set(WITH_IK_SOLVER OFF CACHE BOOL "" FORCE) set(WITH_IK_ITASC OFF CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON OFF CACHE BOOL "" FORCE) @@ -54,5 +53,9 @@ set(WITH_OPENVDB OFF CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW OFF CACHE BOOL "" FORCE) set(WITH_SDL OFF CACHE BOOL "" FORCE) set(WITH_TBB OFF CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE) + +if(UNIX AND NOT APPLE) + set(WITH_GHOST_XDND OFF CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT OFF CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE OFF CACHE BOOL "" FORCE) +endif() diff --git a/build_files/cmake/config/blender_release.cmake b/build_files/cmake/config/blender_release.cmake index af089834295..07d95a84112 100644 --- a/build_files/cmake/config/blender_release.cmake +++ b/build_files/cmake/config/blender_release.cmake @@ -19,7 +19,6 @@ set(WITH_LIBMV ON CACHE BOOL "" FORCE) set(WITH_LIBMV_SCHUR_SPECIALIZATIONS ON CACHE BOOL "" FORCE) set(WITH_COMPOSITOR ON CACHE BOOL "" FORCE) set(WITH_FREESTYLE ON CACHE BOOL "" FORCE) -set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) set(WITH_IK_SOLVER ON CACHE BOOL "" FORCE) set(WITH_IK_ITASC ON CACHE BOOL "" FORCE) set(WITH_IMAGE_CINEON ON CACHE BOOL "" FORCE) @@ -30,7 +29,6 @@ set(WITH_IMAGE_OPENJPEG ON CACHE BOOL "" FORCE) set(WITH_IMAGE_TIFF ON CACHE BOOL "" FORCE) set(WITH_INPUT_NDOF ON CACHE BOOL "" FORCE) set(WITH_INTERNATIONAL ON CACHE BOOL "" FORCE) -set(WITH_JACK ON CACHE BOOL "" FORCE) set(WITH_LZMA ON CACHE BOOL "" FORCE) set(WITH_LZO ON CACHE BOOL "" FORCE) set(WITH_MOD_FLUID ON CACHE BOOL "" FORCE) @@ -50,8 +48,6 @@ set(WITH_PYTHON_INSTALL ON CACHE BOOL "" FORCE) set(WITH_QUADRIFLOW ON CACHE BOOL "" FORCE) set(WITH_SDL ON CACHE BOOL "" FORCE) set(WITH_TBB ON CACHE BOOL "" FORCE) -set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) -set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) set(WITH_MEM_JEMALLOC ON CACHE BOOL "" FORCE) set(WITH_CYCLES_CUDA_BINARIES ON CACHE BOOL "" FORCE) @@ -60,13 +56,12 @@ set(CYCLES_CUDA_BINARIES_ARCH sm_30;sm_35;sm_37;sm_50;sm_52;sm_60;sm_61;sm_70;sm set(WITH_CYCLES_DEVICE_OPTIX ON CACHE BOOL "" FORCE) # platform dependent options -if(UNIX AND NOT APPLE) +if(NOT WIN32) set(WITH_JACK ON CACHE BOOL "" FORCE) +endif() +if(UNIX AND NOT APPLE) set(WITH_DOC_MANPAGE ON CACHE BOOL "" FORCE) -elseif(WIN32) - set(WITH_JACK OFF CACHE BOOL "" FORCE) -elseif(APPLE) - set(WITH_JACK ON CACHE BOOL "" FORCE) - -# include("${CMAKE_CURRENT_SOURCE_DIR}/../platform/platform_apple_xcode.cmake") + set(WITH_GHOST_XDND ON CACHE BOOL "" FORCE) + set(WITH_X11_XINPUT ON CACHE BOOL "" FORCE) + set(WITH_X11_XF86VMODE ON CACHE BOOL "" FORCE) endif() diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake index 5ace42646c5..0e530463659 100644 --- a/build_files/cmake/packaging.cmake +++ b/build_files/cmake/packaging.cmake @@ -135,7 +135,7 @@ elseif(UNIX) add_package_archive( "${PROJECT_NAME}-${BLENDER_VERSION}-${BUILD_REV}-${PACKAGE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}" - "tar.bz2") + "tar.xz") endif() unset(MAJOR_VERSION) diff --git a/build_files/package_spec/build_archive.py b/build_files/package_spec/build_archive.py index 5ca2f319d87..d8d3c29ea48 100755 --- a/build_files/package_spec/build_archive.py +++ b/build_files/package_spec/build_archive.py @@ -49,15 +49,19 @@ try: if not os.path.exists(output_dir): os.mkdir(output_dir) + archive_env = os.environ.copy() + if extension == 'zip': archive_cmd = ['zip', '-9', '-r', package_archive, package_dir] - elif extension == 'tar.bz2': - archive_cmd = ['tar', 'cjf', package_archive, package_dir] + elif extension == 'tar.xz': + archive_cmd = ['tar', '-cf', package_archive, '--owner=0', '--group=0', + '--use-compress-program=xz', package_dir] + archive_env['XZ_OPT'] = '-9' else: sys.stderr.write('Unknown archive extension: ' + extension) sys.exit(-1) - subprocess.call(archive_cmd) + subprocess.check_call(archive_cmd, env=archive_env) except Exception as ex: sys.stderr.write('Failed to create package archive: ' + str(ex) + '\n') sys.exit(1) diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 3625dd45ae2..cbe61e367fa 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -159,7 +159,7 @@ static inline void curvemapping_to_array(BL::CurveMapping &cumap, array<float> & data.resize(size); for (int i = 0; i < size; i++) { float t = (float)i / (float)(size - 1); - data[i] = curve.evaluate(t); + data[i] = cumap.evaluate(curve, t); } } @@ -197,15 +197,16 @@ static inline void curvemapping_color_to_array(BL::CurveMapping &cumap, BL::CurveMap mapI = cumap.curves[3]; for (int i = 0; i < size; i++) { const float t = min_x + (float)i / (float)(size - 1) * range_x; - data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)), - mapG.evaluate(mapI.evaluate(t)), - mapB.evaluate(mapI.evaluate(t))); + data[i] = make_float3(cumap.evaluate(mapR, cumap.evaluate(mapI, t)), + cumap.evaluate(mapG, cumap.evaluate(mapI, t)), + cumap.evaluate(mapB, cumap.evaluate(mapI, t))); } } else { for (int i = 0; i < size; i++) { float t = min_x + (float)i / (float)(size - 1) * range_x; - data[i] = make_float3(mapR.evaluate(t), mapG.evaluate(t), mapB.evaluate(t)); + data[i] = make_float3( + cumap.evaluate(mapR, t), cumap.evaluate(mapG, t), cumap.evaluate(mapB, t)); } } } diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp index b3a9aab3266..86d755ab06a 100644 --- a/intern/cycles/bvh/bvh_optix.cpp +++ b/intern/cycles/bvh/bvh_optix.cpp @@ -49,7 +49,7 @@ void BVHOptiX::copy_to_device(Progress &progress, DeviceScene *dscene) progress.set_status("Updating Scene BVH", "Building OptiX acceleration structure"); Device *const device = dscene->bvh_nodes.device; - if (!device->build_optix_bvh(this, dscene->bvh_nodes)) + if (!device->build_optix_bvh(this)) progress.set_error("Failed to build OptiX acceleration structure"); } diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 672d93c2581..66fcac921d3 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -407,7 +407,7 @@ class Device { const DeviceDrawParams &draw_params); /* acceleration structure building */ - virtual bool build_optix_bvh(BVH *, device_memory &) + virtual bool build_optix_bvh(BVH *) { return false; } diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp index ac71be9dbea..b8587eb0a62 100644 --- a/intern/cycles/device/device_multi.cpp +++ b/intern/cycles/device/device_multi.cpp @@ -153,21 +153,13 @@ class MultiDevice : public Device { return result; } - bool build_optix_bvh(BVH *bvh, device_memory &mem) + bool build_optix_bvh(BVH *bvh) { - device_ptr key = unique_key++; - // Broadcast acceleration structure build to all devices foreach (SubDevice &sub, devices) { - mem.device = sub.device; - if (!sub.device->build_optix_bvh(bvh, mem)) + if (!sub.device->build_optix_bvh(bvh)) return false; - sub.ptr_map[key] = mem.device_pointer; } - - mem.device = this; - mem.device_pointer = key; - stats.mem_alloc(mem.device_size); return true; } diff --git a/intern/cycles/device/device_optix.cpp b/intern/cycles/device/device_optix.cpp index e10bab5a0d8..ae3ab7e1fc2 100644 --- a/intern/cycles/device/device_optix.cpp +++ b/intern/cycles/device/device_optix.cpp @@ -174,7 +174,7 @@ class OptiXDevice : public Device { device_vector<SbtRecord> sbt_data; device_vector<TextureInfo> texture_info; device_only_memory<KernelParams> launch_params; - vector<device_only_memory<uint8_t>> blas; + vector<device_only_memory<uint8_t>> as_mem; OptixTraversableHandle tlas_handle = 0; // TODO(pmours): This is copied from device_cuda.cpp, so move to common code eventually @@ -268,8 +268,8 @@ class OptiXDevice : public Device { // Stop processing any more tasks task_pool.stop(); - // Clean up all memory before destroying context - blas.clear(); + // Free all acceleration structures + as_mem.clear(); sbt_data.free(); texture_info.free(); @@ -290,8 +290,8 @@ class OptiXDevice : public Device { optixPipelineDestroy(pipelines[i]); // Destroy launch streams - for (int i = 0; i < info.cpu_threads; ++i) - cuStreamDestroy(cuda_stream[i]); + for (CUstream stream : cuda_stream) + cuStreamDestroy(stream); // Destroy OptiX and CUDA context optixDeviceContextDestroy(context); @@ -881,15 +881,16 @@ class OptiXDevice : public Device { return true; } - bool build_optix_bvh(BVH *bvh, device_memory &out_data) override + bool build_optix_bvh(BVH *bvh) override { assert(bvh->params.top_level); unsigned int num_instances = 0; unordered_map<Mesh *, vector<OptixTraversableHandle>> meshes; + meshes.reserve(bvh->meshes.size()); - // Clear all previous AS - blas.clear(); + // Free all previous acceleration structure + as_mem.clear(); // Build bottom level acceleration structures (BLAS) // Note: Always keep this logic in sync with bvh_optix.cpp! @@ -900,6 +901,7 @@ class OptiXDevice : public Device { Mesh *const mesh = ob->mesh; vector<OptixTraversableHandle> handles; + handles.reserve(2); // Build BLAS for curve primitives if (bvh->params.primitive_mask & PRIMITIVE_ALL_CURVE && mesh->num_curves() > 0) { @@ -966,9 +968,9 @@ class OptiXDevice : public Device { build_input.aabbArray.primitiveIndexOffset = mesh->prim_offset; // Allocate memory for new BLAS and build it - blas.emplace_back(this, "blas"); + as_mem.emplace_back(this, "blas"); handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, blas.back(), handles.back())) + if (!build_optix_bvh(build_input, num_motion_steps, as_mem.back(), handles.back())) return false; } @@ -1032,9 +1034,9 @@ class OptiXDevice : public Device { build_input.triangleArray.primitiveIndexOffset = mesh->prim_offset + mesh->num_segments(); // Allocate memory for new BLAS and build it - blas.emplace_back(this, "blas"); + as_mem.emplace_back(this, "blas"); handles.emplace_back(); - if (!build_optix_bvh(build_input, num_motion_steps, blas.back(), handles.back())) + if (!build_optix_bvh(build_input, num_motion_steps, as_mem.back(), handles.back())) return false; } @@ -1051,6 +1053,7 @@ class OptiXDevice : public Device { // Skip non-traceable objects if (!ob->is_traceable()) continue; + // Create separate instance for triangle/curve meshes of an object for (OptixTraversableHandle handle : meshes[ob->mesh]) { OptixAabb &aabb = aabbs[num_instances]; @@ -1078,8 +1081,8 @@ class OptiXDevice : public Device { // Insert motion traversable if object has motion if (motion_blur && ob->use_motion()) { - blas.emplace_back(this, "motion_transform"); - device_only_memory<uint8_t> &motion_transform_gpu = blas.back(); + as_mem.emplace_back(this, "motion_transform"); + device_only_memory<uint8_t> &motion_transform_gpu = as_mem.back(); motion_transform_gpu.alloc_to_device(sizeof(OptixSRTMotionTransform) + (max(ob->motion.size(), 2) - 2) * sizeof(OptixSRTData)); @@ -1157,7 +1160,7 @@ class OptiXDevice : public Device { instances.resize(num_instances); instances.copy_to_device(); - // Build top-level acceleration structure + // Build top-level acceleration structure (TLAS) OptixBuildInput build_input = {}; build_input.type = OPTIX_BUILD_INPUT_TYPE_INSTANCES; build_input.instanceArray.instances = instances.device_pointer; @@ -1165,7 +1168,8 @@ class OptiXDevice : public Device { build_input.instanceArray.aabbs = aabbs.device_pointer; build_input.instanceArray.numAabbs = num_instances; - return build_optix_bvh(build_input, 0 /* TLAS has no motion itself */, out_data, tlas_handle); + as_mem.emplace_back(this, "tlas"); + return build_optix_bvh(build_input, 0, as_mem.back(), tlas_handle); } void update_texture_info() diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 2f73434706c..2884ea62a18 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct MicrofacetExtra { float3 color, cspec0; + float3 fresnel_color; float clearcoat; } MicrofacetExtra; @@ -276,6 +277,22 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha) return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t); } +ccl_device_forceinline void bsdf_microfacet_fresnel_color(const ShaderData *sd, + MicrofacetBsdf *bsdf) +{ + kernel_assert(CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)); + + float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); + bsdf->extra->fresnel_color = interpolate_fresnel_color( + sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0); + + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + bsdf->extra->fresnel_color *= 0.25f * bsdf->extra->clearcoat; + } + + bsdf->sample_weight *= average(bsdf->extra->fresnel_color); +} + /* GGX microfacet with Smith shadow-masking from: * * Microfacet Models for Refraction through Rough Surfaces @@ -305,15 +322,13 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const Sha { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -321,15 +336,13 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const S { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -364,15 +377,13 @@ ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, con { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = saturate(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index 9780dd87415..a5fe989bcd1 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -402,9 +402,7 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -424,9 +422,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, con bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -582,9 +578,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index c1d74dddc2a..3e423e42573 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -145,7 +145,17 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) { - albedo += sc->weight; + float3 closure_albedo = sc->weight; + /* Closures that include a Fresnel term typically have weights close to 1 even though their + * actual contribution is significantly lower. + * To account for this, we scale their weight by the average fresnel factor (the same is also + * done for the sample weight in the BSDF setup, so we don't need to scale that here). */ + if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(sc->type)) { + MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc; + closure_albedo *= bsdf->extra->fresnel_color; + } + + albedo += closure_albedo; sum_nonspecular_weight += sc->sample_weight; } } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 01710f713ac..aa4dfdca2d1 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -552,6 +552,12 @@ typedef enum ClosureType { (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)) +#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \ + (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) #define CLOSURE_IS_BSSRDF(type) \ (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl index 04e96e8ed3c..9787398e2ae 100644 --- a/intern/opencolorio/gpu_shader_display_transform.glsl +++ b/intern/opencolorio/gpu_shader_display_transform.glsl @@ -16,7 +16,7 @@ out vec4 fragColor; */ uniform sampler1D curve_mapping_texture; uniform int curve_mapping_lut_size; -uniform ivec4 use_curve_mapping_extend_extrapolate; +uniform int use_curve_mapping_extend_extrapolate; uniform vec4 curve_mapping_mintable; uniform vec4 curve_mapping_range; uniform vec4 curve_mapping_ext_in_x; @@ -42,8 +42,8 @@ float read_curve_mapping(int table, int index) float curvemap_calc_extend(int table, float x, vec2 first, vec2 last) { if (x <= first[0]) { - if (use_curve_mapping_extend_extrapolate[table] == 0) { - /* no extrapolate */ + if (use_curve_mapping_extend_extrapolate == 0) { + /* horizontal extrapolation */ return first[1]; } else { @@ -55,8 +55,8 @@ float curvemap_calc_extend(int table, float x, vec2 first, vec2 last) } } else if (x >= last[0]) { - if (use_curve_mapping_extend_extrapolate[table] == 0) { - /* no extrapolate */ + if (use_curve_mapping_extend_extrapolate == 0) { + /* horizontal extrapolation */ return last[1]; } else { diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 9ba2d8fb8f9..5670b37f892 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -73,10 +73,10 @@ typedef struct OCIO_CurveMappingSettings { int lut_size; /* Extend extrapolation flags for all the tables. - * if use_extend_extrapolate[T] != 0 means extrapolation for - * table T is needed. + * if use_extend_extrapolate != 0 means extrapolation for + * curve. */ - int use_extend_extrapolate[4]; + int use_extend_extrapolate; /* Minimal X value of the curve mapping tables. */ float mintable[4]; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index 99d59c8d989..a80e29a2dec 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -499,8 +499,8 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, if (use_curve_mapping) { immUniform1i("curve_mapping_texture", 2); immUniform1i("curve_mapping_lut_size", curve_mapping_settings->lut_size); - immUniform4iv("use_curve_mapping_extend_extrapolate", - curve_mapping_settings->use_extend_extrapolate); + immUniform1i("use_curve_mapping_extend_extrapolate", + curve_mapping_settings->use_extend_extrapolate); immUniform4fv("curve_mapping_mintable", curve_mapping_settings->mintable); immUniform4fv("curve_mapping_range", curve_mapping_settings->range); immUniform4fv("curve_mapping_ext_in_x", curve_mapping_settings->ext_in_x); diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index f317b346eb8..6a87ac0adaa 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -1048,9 +1048,6 @@ </linearGradient> - <filter color-interpolation-filters="sRGB" inkscape:collect="always" id="filter15613" x="-0.092011765" width="1.1840235" y="-0.097762503" height="1.1955251"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.65175" id="feGaussianBlur15615"/> - </filter> <linearGradient id="linearGradient37542-55"> <stop id="stop37544-61" offset="0" style="stop-color:#000000;stop-opacity:1;"/> <stop id="stop37546-03" offset="1" style="stop-color:#ffffff;stop-opacity:1;"/> @@ -1065,9 +1062,6 @@ </linearGradient> - <filter color-interpolation-filters="sRGB" inkscape:collect="always" id="filter15613-8" x="-0.092011765" width="1.1840235" y="-0.097762503" height="1.1955251"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.65175" id="feGaussianBlur15615-1"/> - </filter> <filter color-interpolation-filters="sRGB" inkscape:label="Greyscale" id="filter15388"> @@ -1327,14 +1321,6 @@ <radialGradient inkscape:collect="always" xlink:href="#linearGradient16595" id="radialGradient52883-6-8-3" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.39420438,-0.08239205,0.27256031,1.3040635,-362.22886,-161.73912)" cx="-302.79681" cy="462.0358" fx="-302.79681" fy="462.0358" r="8"/> - <filter style="color-interpolation-filters:sRGB" inkscape:collect="always" id="filter15613-7" x="-0.092011765" width="1.1840235" y="-0.097762503" height="1.1955251"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.65175" id="feGaussianBlur15615-4"/> - </filter> - - - <filter style="color-interpolation-filters:sRGB" inkscape:collect="always" id="filter15613-8-8" x="-0.092011765" width="1.1840235" y="-0.097762503" height="1.1955251"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.65175" id="feGaussianBlur15615-1-5"/> - </filter> <filter style="color-interpolation-filters:sRGB" inkscape:label="Greyscale" id="filter15388-0"> @@ -3746,14 +3732,6 @@ <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 449.50391,369 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 11 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 H 455 c 1.08333,0 2.07323,-0.26796 2.8125,-0.85938 C 458.55177,379.54921 459,378.625 459,377.5 c 0,-1.125 -0.44823,-2.04921 -1.1875,-2.64062 -0.49098,-0.39279 -1.11527,-0.59695 -1.78125,-0.72071 C 456.61178,373.63193 457,372.89881 457,372 c 0,-0.96354 -0.41934,-1.76349 -1.07422,-2.26758 C 455.27091,369.22833 454.41324,369 453.5,369 Z m 0.5,1 H 453.5 c 0.74361,0 1.38549,0.19369 1.81641,0.52539 0.43091,0.3317 0.68359,0.7813 0.68359,1.47461 0,0.69331 -0.25268,1.14291 -0.68359,1.47461 C 454.88549,373.80631 454.24361,374 453.5,374 h -3.49609 z m 0,5 h 3.46093 0.0352 1.5 c 0.91667,0 1.67677,0.23204 2.1875,0.64062 0.51073,0.40859 0.8125,0.98438 0.8125,1.85938 0,0.875 -0.30177,1.45079 -0.8125,1.85938 C 456.67677,379.76796 455.91667,380 455,380 h -4.99609 z" id="path10949-7" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccscsccscsccscscscccccscscscc"/> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 408.50391,369 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 5.91992 a 0.50005,0.50005 0 0 0 0,0.16211 V 380.5 a 0.50005,0.50005 0 1 0 1,0 V 376 h 3.25586 l 3.84961,4.8125 a 0.50024018,0.50024018 0 1 0 0.78124,-0.625 l -3.49414,-4.36914 c 1.48603,-0.40423 2.60743,-1.70768 2.60743,-3.31836 0,-1.92707 -1.57293,-3.5 -3.5,-3.5 z m 0.5,1 h 3.5 c 1.38662,0 2.5,1.11337 2.5,2.5 0,1.38663 -1.11338,2.5 -2.5,2.5 a 0.50005,0.50005 0 0 0 -0.004,0 h -3.49609 z" id="path13132" inkscape:connector-curvature="0"/> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="M 431.51758,369.26562 C 429.42795,369.91461 428,371.85293 428,374.04102 V 376 c 0,1.78552 0.9537,3.43731 2.5,4.33008 1.54631,0.89277 3.45369,0.89277 5,0 1.5463,-0.89277 2.5,-2.54456 2.5,-4.33008 v -0.5 a 0.50004997,0.50004997 0 0 0 -0.5,-0.5 h -4 a 0.50004997,0.50004997 0 1 0 0,1 h 3.5 c 0,1.42986 -0.7617,2.74991 -2,3.46484 -1.23829,0.71494 -2.76171,0.71494 -4,0 -1.2383,-0.71493 -2,-2.03498 -2,-3.46484 v -1.95898 c 0,-1.75422 1.13918,-3.30002 2.81445,-3.82032 1.69498,-0.52641 3.36746,-0.003 4.25196,1.5293 a 0.50050004,0.50050004 0 1 0 0.86718,-0.5 c -1.1155,-1.93212 -3.34609,-2.62724 -5.41601,-1.98438 z" id="path13141" inkscape:connector-curvature="0"/> - <g style="display:inline;fill:#ffffff;enable-background:new" id="g13321" transform="translate(-42.000002,21.000005)"> - <g id="g13309" style="fill:#ffffff"> - <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 365.49219,94.992188 a 0.50005,0.50005 0 0 0 -0.38867,0.195312 0.50005,0.50005 0 0 0 -0.004,0.0059 l -1.95313,1.953125 a 0.50005,0.50005 0 1 0 0.70704,0.707032 L 365,96.707031 V 98.5 a 0.50005,0.50005 0 1 0 1,0 v -1.792969 l 1.14648,1.146485 a 0.50005,0.50005 0 1 0 0.70704,-0.707032 l -1.95704,-1.957031 a 0.50005,0.50005 0 0 0 -0.40429,-0.197265 z m 9.05859,1.941406 a 0.50005,0.50005 0 0 0 -0.0586,0.0059 h -2.93164 a 0.50005,0.50005 0 1 0 0,1 h 1.79297 l -3.14649,3.146486 a 0.50005,0.50005 0 1 0 0.70703,0.70703 l 3.14649,-3.146485 v 1.792965 a 0.50005,0.50005 0 1 0 1,0 v -2.931637 a 0.50005,0.50005 0 0 0 -0.50977,-0.574218 z m -0.0566,7.060546 a 0.50005,0.50005 0 0 0 -0.34766,0.85938 L 375.29297,106 H 371.5 a 0.50005,0.50005 0 1 0 0,1 h 3.79297 l -1.14649,1.14648 a 0.50005,0.50005 0 1 0 0.70704,0.70704 l 1.95703,-1.95704 a 0.50005,0.50005 0 0 0 0.002,-0.79296 0.50005,0.50005 0 0 0 -0.006,-0.004 l -1.95312,-1.95313 a 0.50005,0.50005 0 0 0 -0.35938,-0.15234 z" id="path13047-6" inkscape:connector-curvature="0"/> - </g> - <g id="g13313" style="fill:#ffffff"> - <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98000004;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 324.5,121 c -1.14583,0 -1.86235,0.56478 -2.18359,1.12695 C 321.99517,122.68912 322,123.25 322,123.25 V 125 h -0.5 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 4 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 6 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -4 c -3e-5,-0.27613 -0.22387,-0.49997 -0.5,-0.5 H 327 v -1.75 c 0,0 0.005,-0.56088 -0.31641,-1.12305 C 326.36235,121.56478 325.64583,121 324.5,121 Z m 0,1 c 0.85417,0 1.13765,0.31022 1.31641,0.62305 C 325.99517,122.93588 326,123.25 326,123.25 V 125 h -3 v -1.75 c 0,0 0.005,-0.31412 0.18359,-0.62695 C 323.36235,122.31022 323.64583,122 324.5,122 Z m -0.5,4 h 1 v 2 h -1 z" transform="translate(42.000002,-21.000005)" id="rect13261" inkscape:connector-curvature="0"/> - </g> - </g> <g inkscape:export-ydpi="96" inkscape:export-xdpi="96" inkscape:export-filename="C:\Users\Andrzej Ambroż\Desktop\mtrx.png" id="g13337" style="display:inline;opacity:0.98999999;fill:#ffffff;enable-background:new" transform="matrix(-1,0,0,1,1458,302.99979)"> <path style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.3;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 1262.5,-278.49979 h -13 v -13 h 13 v 13" id="path14450" inkscape:connector-curvature="0" sodipodi:nodetypes="ccccc"/> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 1257.5039,-287 c -0.191,-10e-4 -0.3661,0.1063 -0.4512,0.27734 l -3,6 c -0.1652,0.33223 0.076,0.72231 0.4473,0.72266 h 6 c 0.371,-3.5e-4 0.6125,-0.39043 0.4473,-0.72266 l -3,-6 c -0.084,-0.16853 -0.2552,-0.27571 -0.4434,-0.27734 z" id="path13331" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccc"/> @@ -3831,11 +3809,6 @@ <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 237.49219,305 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 2 a 0.50005,0.50005 0 1 0 1,0 V 306 h 3 v 12 h -1.5 a 0.50005,0.50005 0 1 0 0,1 h 4 a 0.50005,0.50005 0 1 0 0,-1 h -1.5 v -12 h 3 v 1.5 a 0.50005,0.50005 0 1 0 1,0 v -2 a 0.50005,0.50005 0 0 0 -0.5,-0.5 z m 7,6 a 0.50005,0.50005 0 0 0 -0.5,0.5 v 1 a 0.50005,0.50005 0 1 0 1,0 V 312 h 2 v 6 h -0.5 a 0.50005,0.50005 0 1 0 0,1 h 2 a 0.50005,0.50005 0 1 0 0,-1 h -0.5 v -6 h 2 v 0.5 a 0.50005,0.50005 0 1 0 1,0 v -1 a 0.50005,0.50005 0 0 0 -0.5,-0.5 z" id="path6924-7" inkscape:connector-curvature="0"/> </g> <path inkscape:connector-curvature="0" d="m 353,628 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z m 9,-3 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z m -3,0 h 1 v 1 h -1 z" style="display:inline;opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;enable-background:new" id="path14337"/> - <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 374.4375,121.17773 c -0.55229,-0.19531 -1.19407,-0.23097 -1.84766,0.002 -0.65359,0.23293 -1.30733,0.71399 -1.9707,1.49609 -0.28137,0.33173 -0.45085,0.79694 -0.61914,1.24219 -0.17701,-0.45587 -0.36207,-0.94012 -0.61914,-1.24219 -0.66249,-0.77846 -1.31558,-1.25837 -1.96875,-1.49023 -0.65317,-0.23186 -1.2953,-0.19616 -1.84766,-0.002 -1.10471,0.38842 -1.89002,1.32506 -2.44922,1.9961 a 0.50064603,0.50064603 0 1 0 0.76954,0.64062 c 0.54481,-0.65377 1.26345,-1.43095 2.00976,-1.69336 0.37316,-0.1312 0.7444,-0.1559 1.18359,0 0.4392,0.1559 0.95757,0.51168 1.54102,1.19727 0.19894,0.23376 0.56603,0.91963 0.64063,1.27734 A 0.50005,0.50005 0 0 0 369.75,125 h 0.5 a 0.50005,0.50005 0 0 0 0.49023,-0.40234 c 0.0736,-0.37229 0.37785,-0.96363 0.64063,-1.27344 0.58467,-0.68931 1.10595,-1.04668 1.54492,-1.20313 0.43897,-0.15644 0.80714,-0.13175 1.17969,0 0.74509,0.2635 1.46354,1.04375 2.00976,1.69922 a 0.50064603,0.50064603 0 1 0 0.76954,-0.64062 c -0.55904,-0.67084 -1.34269,-1.61133 -2.44727,-2.00196 z" id="path17826-1" inkscape:connector-curvature="0"/> - <g style="display:inline;fill:#ffffff;enable-background:new" id="g14433" transform="rotate(-90,380.52904,134)"> - <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 390.04688,140.46484 a 0.50005,0.50005 0 0 0 -0.41797,0.20704 l -2.95508,3.93945 a 0.50005,0.50005 0 0 0 -0.01,0.70703 l 2.96485,3.95312 a 0.50019216,0.50019216 0 1 0 0.80078,-0.5996 l -2.40039,-3.20118 h 7.1914 l -0.63867,1.27735 a 0.50005635,0.50005635 0 1 0 0.89453,0.44726 l 0.96875,-1.93554 a 0.50005,0.50005 0 0 0 -0.006,-0.58399 l -0.96289,-1.92773 a 0.50005635,0.50005635 0 1 0 -0.89453,0.44726 l 0.63867,1.27539 h -7.1914 l 2.40039,-3.19922 a 0.50005,0.50005 0 0 0 -0.38281,-0.80664 z" id="path17796-5" inkscape:connector-curvature="0"/> - </g> - <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:7.40000248;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 348.5,120 c -1.47879,0 -2.81353,0.43206 -3.80469,1.06641 C 343.70416,121.70075 343,122.54357 343,123.5 c 0,1.02778 0.79097,1.88608 1.87891,2.49805 1.08228,0.60878 2.52394,0.99597 4.09765,1 0.0129,9.4e-4 3.75669,0.27336 6.02344,-2.21094 V 127.5 a 0.50005,0.50005 0 1 0 1,0 v -4 a 0.50005,0.50005 0 0 0 -0.5,-0.5 h -4.25 a 0.50005,0.50005 0 1 0 0,1 h 3.10156 c -1.87731,2.16501 -5.32031,2 -5.32031,2 A 0.50005,0.50005 0 0 0 349,126 c -1.41667,0 -2.71684,-0.36001 -3.62891,-0.87305 C 344.45903,124.61392 344,123.97222 344,123.5 c 0,-0.41012 0.41561,-1.06779 1.23438,-1.5918 C 346.05313,121.38419 347.21846,121 348.5,121 a 0.50005,0.50005 0 1 0 0,-1 z" id="path18766-5" inkscape:connector-curvature="0"/> <g style="display:inline;fill:#ffffff;enable-background:new" id="g12950" transform="translate(-42.000002,4.4999696e-6)"> <g id="g12531-9" transform="translate(-209.00718,-44.00717)" style="display:inline;opacity:0.6;fill:#ffffff;enable-background:new"> <path style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 446.5,161 c -0.27613,3e-5 -0.49997,0.22387 -0.5,0.5 v 8 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 7 c 0.67616,0.01 0.67616,-1.00956 0,-1 H 447 v -7 h 0.5 4.9707 1.0293 c 0.67616,0.01 0.67616,-1.00956 0,-1 H 452.4707 447.5 Z m 4.50718,10.00717 L 451,173 h -1.5 c -0.67616,-0.01 -0.67616,1.00956 0,1 h 1.91992 c 0.0537,0.009 0.10843,0.009 0.16211,0 H 453.5 c 0.67616,0.01 0.67616,-1.00956 0,-1 H 452 l 0.007,-1.99283 z" id="path12529-5" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccccccccccccccccc"/> diff --git a/release/datafiles/blender_icons16/icon16_ndof_dom.dat b/release/datafiles/blender_icons16/icon16_ndof_dom.dat Binary files differdeleted file mode 100644 index e6ecd80d5a9..00000000000 --- a/release/datafiles/blender_icons16/icon16_ndof_dom.dat +++ /dev/null diff --git a/release/datafiles/blender_icons16/icon16_ndof_fly.dat b/release/datafiles/blender_icons16/icon16_ndof_fly.dat Binary files differdeleted file mode 100644 index 84b672bdf9f..00000000000 --- a/release/datafiles/blender_icons16/icon16_ndof_fly.dat +++ /dev/null diff --git a/release/datafiles/blender_icons16/icon16_ndof_trans.dat b/release/datafiles/blender_icons16/icon16_ndof_trans.dat Binary files differdeleted file mode 100644 index f74edd6f8b0..00000000000 --- a/release/datafiles/blender_icons16/icon16_ndof_trans.dat +++ /dev/null diff --git a/release/datafiles/blender_icons16/icon16_ndof_turn.dat b/release/datafiles/blender_icons16/icon16_ndof_turn.dat Binary files differdeleted file mode 100644 index 5b0cee02b49..00000000000 --- a/release/datafiles/blender_icons16/icon16_ndof_turn.dat +++ /dev/null diff --git a/release/datafiles/blender_icons32/icon32_ndof_dom.dat b/release/datafiles/blender_icons32/icon32_ndof_dom.dat Binary files differdeleted file mode 100644 index 9c7e6fdfc99..00000000000 --- a/release/datafiles/blender_icons32/icon32_ndof_dom.dat +++ /dev/null diff --git a/release/datafiles/blender_icons32/icon32_ndof_fly.dat b/release/datafiles/blender_icons32/icon32_ndof_fly.dat Binary files differdeleted file mode 100644 index a328f8dc1ca..00000000000 --- a/release/datafiles/blender_icons32/icon32_ndof_fly.dat +++ /dev/null diff --git a/release/datafiles/blender_icons32/icon32_ndof_trans.dat b/release/datafiles/blender_icons32/icon32_ndof_trans.dat Binary files differdeleted file mode 100644 index 553752dda40..00000000000 --- a/release/datafiles/blender_icons32/icon32_ndof_trans.dat +++ /dev/null diff --git a/release/datafiles/blender_icons32/icon32_ndof_turn.dat b/release/datafiles/blender_icons32/icon32_ndof_turn.dat Binary files differdeleted file mode 100644 index 3f43546cdbf..00000000000 --- a/release/datafiles/blender_icons32/icon32_ndof_turn.dat +++ /dev/null diff --git a/release/datafiles/userdef/userdef_default.c b/release/datafiles/userdef/userdef_default.c index d8b87480f29..3856a03b1ba 100644 --- a/release/datafiles/userdef/userdef_default.c +++ b/release/datafiles/userdef/userdef_default.c @@ -150,10 +150,16 @@ const UserDef U_default = { .tablet_api = USER_TABLET_AUTOMATIC, .pressure_threshold_max = 1.0, .pressure_softness = 0.0, - .ndof_sensitivity = 1.0, - .ndof_orbit_sensitivity = 1.0, + .ndof_sensitivity = 4.0, + .ndof_orbit_sensitivity = 4.0, .ndof_deadzone = 0.1, - .ndof_flag = (NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE), + .ndof_flag = (NDOF_MODE_ORBIT | NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | + NDOF_SHOULD_ROTATE | + /* Software from the driver authors follows this convention + * so invert this by default, see: T67579. */ + NDOF_ROTX_INVERT_AXIS | NDOF_ROTY_INVERT_AXIS | NDOF_ROTZ_INVERT_AXIS | + NDOF_PANX_INVERT_AXIS | NDOF_PANY_INVERT_AXIS | NDOF_PANZ_INVERT_AXIS | + NDOF_ZOOM_INVERT), .ogl_multisamples = 0, .image_draw_method = IMAGE_DRAW_METHOD_AUTO, .glalphaclip = 0.004, diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py index f264de5b140..5106010b555 100644 --- a/release/scripts/modules/console_python.py +++ b/release/scripts/modules/console_python.py @@ -341,23 +341,20 @@ def banner(context): sc = context.space_data version_string = sys.version.strip().replace('\n', ' ') - add_scrollback("PYTHON INTERACTIVE CONSOLE %s" % version_string, 'OUTPUT') - add_scrollback("", 'OUTPUT') - add_scrollback("Command History: Up/Down Arrow", 'OUTPUT') - add_scrollback("Cursor: Left/Right Home/End", 'OUTPUT') - add_scrollback("Remove: Backspace/Delete", 'OUTPUT') - add_scrollback("Execute: Enter", 'OUTPUT') - add_scrollback("Autocomplete: Ctrl-Space", 'OUTPUT') - add_scrollback("Zoom: Ctrl +/-, Ctrl-Wheel", 'OUTPUT') - add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, " - "bpy.props, bpy.types, bpy.context, bpy.utils, " - "bgl, blf, mathutils", - 'OUTPUT') - add_scrollback("Convenience Imports: from mathutils import *; " - "from math import *", 'OUTPUT') - add_scrollback("Convenience Variables: C = bpy.context, D = bpy.data", - 'OUTPUT') - add_scrollback("", 'OUTPUT') + message = ( + "PYTHON INTERACTIVE CONSOLE %s" % version_string, + "", + "Builtin Modules: " + "bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils", + + "Convenience Imports: from mathutils import *; from math import *", + "Convenience Variables: C = bpy.context, D = bpy.data", + "", + ) + + for line in message: + add_scrollback(line, 'OUTPUT') + sc.prompt = PROMPT return {'FINISHED'} diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 3a7a142e310..06fac16292d 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -392,7 +392,7 @@ def km_window(params): ), # NDOF settings - op_menu("USERPREF_MT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), + op_panel("USERPREF_PT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS'}, {"properties": [("data_path", 'preferences.inputs.ndof_sensitivity'), ("value", 1.1)]}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS'}, diff --git a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py index dc62b6bba68..6bf9a60a3d7 100644 --- a/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py +++ b/release/scripts/presets/keyconfig/keymap_data/industry_compatible_data.py @@ -196,7 +196,7 @@ def km_window(params): op_menu("SCREEN_MT_user_menu", {"type": 'TAB', "value": 'PRESS', "shift": True}), # NDOF settings - op_menu("USERPREF_MT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), + op_panel("USERPREF_PT_ndof_settings", {"type": 'NDOF_BUTTON_MENU', "value": 'PRESS'}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_PLUS', "value": 'PRESS'}, {"properties": [("data_path", 'preferences.inputs.ndof_sensitivity'), ("value", 1.1)]}), ("wm.context_scale_float", {"type": 'NDOF_BUTTON_MINUS', "value": 'PRESS'}, diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 98e812cf02d..7c28095259e 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -296,11 +296,11 @@ def brush_basic_wpaint_settings(layout, context, brush, *, compact=False): row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") layout.prop(brush, "blend", text="" if compact else "Blend") @@ -310,11 +310,11 @@ def brush_basic_vpaint_settings(layout, context, brush, *, compact=False): row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") if capabilities.has_color: layout.prop(brush, "blend", text="" if compact else "Blend") @@ -326,12 +326,12 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False): if capabilities.has_radius: row = layout.row(align=True) UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") row = layout.row(align=True) UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") if capabilities.has_color: layout.prop(brush, "blend", text="" if compact else "Blend") @@ -352,7 +352,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False): else: UnifiedPaintPanel.prop_unified_size(row, context, brush, "size", slider=True) - UnifiedPaintPanel.prop_unified_size(row, context, brush, "use_pressure_size", text="") + row.prop(brush, "use_pressure_size", text="") # strength, use_strength_pressure, and use_strength_attenuation row = layout.row(align=True) @@ -360,7 +360,7 @@ def brush_basic_sculpt_settings(layout, context, brush, *, compact=False): UnifiedPaintPanel.prop_unified_strength(row, context, brush, "strength") if capabilities.has_strength_pressure: - UnifiedPaintPanel.prop_unified_strength(row, context, brush, "use_pressure_strength", text="") + row.prop(brush, "use_pressure_strength", text="") # direction if not capabilities.has_direction: diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index fac8ff238c0..3b498b834bf 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -288,7 +288,8 @@ class DOPESHEET_MT_editor_menus(Menu): layout.menu("DOPESHEET_MT_view") layout.menu("DOPESHEET_MT_select") - layout.menu("DOPESHEET_MT_marker") + if st.show_markers: + layout.menu("DOPESHEET_MT_marker") if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action is not None): layout.menu("DOPESHEET_MT_channel") @@ -322,9 +323,12 @@ class DOPESHEET_MT_view(Menu): layout.prop(st, "show_group_colors") layout.prop(st, "show_interpolation") layout.prop(st, "show_extremes") - layout.prop(st, "show_marker_lines") layout.prop(st, "use_auto_merge_keyframes") + layout.separator() + layout.prop(st, "show_markers") + + layout.separator() layout.prop(st, "show_seconds") layout.prop(st, "show_locked_time") diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 15ef7b0ef82..188741956ab 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -94,10 +94,12 @@ class GRAPH_MT_editor_menus(Menu): bl_label = "" def draw(self, _context): + st = _context.space_data layout = self.layout layout.menu("GRAPH_MT_view") layout.menu("GRAPH_MT_select") - layout.menu("GRAPH_MT_marker") + if st.mode != 'DRIVERS' and st.show_markers: + layout.menu("GRAPH_MT_marker") layout.menu("GRAPH_MT_channel") layout.menu("GRAPH_MT_key") @@ -117,9 +119,12 @@ class GRAPH_MT_view(Menu): layout.prop(st, "show_cursor") layout.prop(st, "show_sliders") layout.prop(st, "show_group_colors") - layout.prop(st, "show_marker_lines") layout.prop(st, "use_auto_merge_keyframes") + if st.mode != 'DRIVERS': + layout.separator() + layout.prop(st, "show_markers") + layout.separator() layout.prop(st, "use_beauty_drawing") diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 825e4b41609..24d6f65d9b9 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -71,10 +71,12 @@ class NLA_MT_editor_menus(Menu): bl_label = "" def draw(self, _context): + st = _context.space_data layout = self.layout layout.menu("NLA_MT_view") layout.menu("NLA_MT_select") - layout.menu("NLA_MT_marker") + if st.show_markers: + layout.menu("NLA_MT_marker") layout.menu("NLA_MT_edit") layout.menu("NLA_MT_add") @@ -96,8 +98,10 @@ class NLA_MT_view(Menu): layout.prop(st, "show_locked_time") layout.prop(st, "show_strip_curves") + + layout.separator() + layout.prop(st, "show_markers") layout.prop(st, "show_local_markers") - layout.prop(st, "show_marker_lines") layout.separator() layout.operator("anim.previewrange_set") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 4d9a4646f5f..b4f841d2eb8 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -134,7 +134,8 @@ class SEQUENCER_MT_editor_menus(Menu): if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: layout.menu("SEQUENCER_MT_select") - layout.menu("SEQUENCER_MT_marker") + if st.show_markers: + layout.menu("SEQUENCER_MT_marker") layout.menu("SEQUENCER_MT_add") layout.menu("SEQUENCER_MT_strip") @@ -268,7 +269,8 @@ class SEQUENCER_MT_view(Menu): layout.prop(st, "show_seconds") layout.prop(st, "show_strip_offset") - layout.prop(st, "show_marker_lines") + layout.separator() + layout.prop(st, "show_markers") if is_preview: layout.separator() diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 04a904edde3..6d60c67ded0 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -90,6 +90,7 @@ class TIME_MT_editor_menus(Menu): def draw(self, _context): layout = self.layout horizontal = (layout.direction == 'VERTICAL') + st = _context.space_data if horizontal: row = layout.row() sub = row.row(align=True) @@ -109,7 +110,8 @@ class TIME_MT_editor_menus(Menu): sub = row.row(align=True) sub.menu("TIME_MT_view") - sub.menu("TIME_MT_marker") + if st.show_markers: + sub.menu("TIME_MT_marker") class TIME_MT_marker(Menu): @@ -135,7 +137,10 @@ class TIME_MT_view(Menu): layout.separator() - layout.prop(st, "show_marker_lines") + layout.prop(st, "show_markers") + + layout.separator() + layout.prop(scene, "show_keys_from_selected_only") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 7c6a7ecbcee..387acbec625 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1409,20 +1409,24 @@ class USERPREF_PT_saveload_file_browser(PreferencePanel, Panel): flow.prop(paths, "hide_system_bookmarks") -class USERPREF_MT_ndof_settings(Menu): - # accessed from the window key-bindings in C (only) +class USERPREF_PT_ndof_settings(Panel): bl_label = "3D Mouse Settings" + bl_space_type = 'TOPBAR' # dummy. + bl_region_type = 'HEADER' def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False # No animation. input_prefs = context.preferences.inputs is_view3d = context.space_data.type == 'VIEW_3D' - layout.prop(input_prefs, "ndof_sensitivity") - layout.prop(input_prefs, "ndof_orbit_sensitivity") - layout.prop(input_prefs, "ndof_deadzone") + col = layout.column(align=True) + col.prop(input_prefs, "ndof_sensitivity") + col.prop(input_prefs, "ndof_orbit_sensitivity") + col.prop(input_prefs, "ndof_deadzone") if is_view3d: layout.separator() @@ -1430,20 +1434,39 @@ class USERPREF_MT_ndof_settings(Menu): layout.separator() layout.label(text="Orbit Style") - layout.row().prop(input_prefs, "ndof_view_navigate_method", text="") - layout.row().prop(input_prefs, "ndof_view_rotate_method", text="") + layout.row().prop(input_prefs, "ndof_view_navigate_method", text="Navigate") + layout.row().prop(input_prefs, "ndof_view_rotate_method", text="Orbit") layout.separator() + layout.label(text="Orbit Options") - layout.prop(input_prefs, "ndof_rotx_invert_axis") - layout.prop(input_prefs, "ndof_roty_invert_axis") - layout.prop(input_prefs, "ndof_rotz_invert_axis") + split = layout.split(factor=0.6) + row = split.row() + row.alignment = 'RIGHT' + row.label(text="Invert Axis") + row = split.row(align=True) + for text, attr in ( + ("X", "ndof_rotx_invert_axis"), + ("Y", "ndof_roty_invert_axis"), + ("Z", "ndof_rotz_invert_axis"), + ): + row.prop(input_prefs, attr, text=text, toggle=True) # view2d use pan/zoom layout.separator() layout.label(text="Pan Options") - layout.prop(input_prefs, "ndof_panx_invert_axis") - layout.prop(input_prefs, "ndof_pany_invert_axis") - layout.prop(input_prefs, "ndof_panz_invert_axis") + + split = layout.split(factor=0.6) + row = split.row() + row.alignment = 'RIGHT' + row.label(text="Invert Axis") + row = split.row(align=True) + for text, attr in ( + ("X", "ndof_panx_invert_axis"), + ("Y", "ndof_pany_invert_axis"), + ("Z", "ndof_panz_invert_axis"), + ): + row.prop(input_prefs, attr, text=text, toggle=True) + layout.prop(input_prefs, "ndof_pan_yz_swap_axis") layout.label(text="Zoom Options") @@ -1452,8 +1475,8 @@ class USERPREF_MT_ndof_settings(Menu): if is_view3d: layout.separator() layout.label(text="Fly/Walk Options") - layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') - layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') + layout.prop(input_prefs, "ndof_fly_helicopter") + layout.prop(input_prefs, "ndof_lock_horizon") class USERPREF_PT_input_keyboard(PreferencePanel, Panel): @@ -2255,7 +2278,6 @@ classes = ( USERPREF_PT_saveload_autorun, USERPREF_PT_saveload_file_browser, - USERPREF_MT_ndof_settings, USERPREF_MT_keyconfigs, USERPREF_PT_input_keyboard, @@ -2278,6 +2300,9 @@ classes = ( USERPREF_PT_experimental_all, + # Popovers. + USERPREF_PT_ndof_settings, + # Add dynamically generated editor theme panels last, # so they show up last in the theme section. *ThemeGenericClassGenerator.generate_panel_classes_from_theme_areas(), diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 113274ce166..9f04dc4627a 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -5466,6 +5466,26 @@ class VIEW3D_PT_shading_options_ssao(Panel): col.prop(scene.display, "matcap_ssao_attenuation") +class VIEW3D_PT_shading_render_pass(Panel): + bl_space_type = 'VIEW_3D' + bl_region_type = 'HEADER' + bl_label = "Render Pass" + bl_parent_id = 'VIEW3D_PT_shading' + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + return (context.space_data.shading.type == 'MATERIAL' + or (context.engine in cls.COMPAT_ENGINES + and context.space_data.shading.type == 'RENDERED')) + + def draw(self, context): + shading = context.space_data.shading + + layout = self.layout + layout.prop(shading, "render_pass", text="") + + class VIEW3D_PT_gizmo_display(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' @@ -6909,6 +6929,7 @@ classes = ( VIEW3D_PT_shading_options, VIEW3D_PT_shading_options_shadow, VIEW3D_PT_shading_options_ssao, + VIEW3D_PT_shading_render_pass, VIEW3D_PT_gizmo_display, VIEW3D_PT_overlay, VIEW3D_PT_overlay_guides, diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 724264fe494..718365ec99d 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -1193,7 +1193,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel): if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}: row = sub.row(align=True) row.prop(sculpt, "constant_detail_resolution") - row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props.mode = 'DYNTOPO' elif (sculpt.detail_type_method == 'BRUSH'): sub.prop(sculpt, "detail_percent") else: @@ -1252,7 +1253,10 @@ class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel): col = layout.column() mesh = context.active_object.data - col.prop(mesh, "remesh_voxel_size") + row = col.row(align=True) + row.prop(mesh, "remesh_voxel_size") + props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') + props.mode = 'VOXEL' col.prop(mesh, "remesh_voxel_adaptivity") col.prop(mesh, "use_remesh_fix_poles") col.prop(mesh, "use_remesh_smooth_normals") diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h index 7c5efaf309d..878dbfc2a53 100644 --- a/source/blender/alembic/ABC_alembic.h +++ b/source/blender/alembic/ABC_alembic.h @@ -59,7 +59,7 @@ struct AlembicExportParams { bool apply_subdiv; bool curves_as_mesh; bool flatten_hierarchy; - bool visible_layers_only; + bool visible_objects_only; bool renderable_only; bool face_sets; bool use_subdiv_schema; diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index cbc8fd769b7..d422a3c023e 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -74,7 +74,7 @@ ExportSettings::ExportSettings() depsgraph(NULL), logger(), selected_only(false), - visible_layers_only(false), + visible_objects_only(false), renderable_only(false), frame_start(1), frame_end(1), @@ -161,7 +161,7 @@ static bool export_object(const ExportSettings *const settings, } // FIXME Sybren: handle these cleanly (maybe just remove code), // now using active scene layer instead. - if (settings->visible_layers_only && !BASE_VISIBLE(v3d, base)) { + if (settings->visible_objects_only && !BASE_VISIBLE(v3d, base)) { return false; } } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index a73289fcf95..923fe0ca29f 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -49,7 +49,7 @@ struct ExportSettings { SimpleLogger logger; bool selected_only; - bool visible_layers_only; + bool visible_objects_only; bool renderable_only; double frame_start, frame_end; diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc index 9b12fe86d59..585d4178e41 100644 --- a/source/blender/alembic/intern/abc_transform.cc +++ b/source/blender/alembic/intern/abc_transform.cc @@ -27,6 +27,7 @@ extern "C" { #include "DNA_object_types.h" +#include "BLI_listbase.h" #include "BLI_math.h" #include "BKE_animsys.h" @@ -131,9 +132,9 @@ Imath::Box3d AbcTransformWriter::bounds() return Imath::transform(bounds, m_matrix); } -bool AbcTransformWriter::hasAnimation(Object *ob) const +bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const { - return BKE_animdata_id_is_animated(&ob->id); + return true; } /* ************************************************************************** */ diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 1034c5b319f..5efa8c8a446 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -365,7 +365,7 @@ bool ABC_export(Scene *scene, /* TODO(Sybren): visible_layer & renderable only is ignored for now, * to be replaced with collections later in the 2.8 dev process * (also see note above). */ - job->settings.visible_layers_only = params->visible_layers_only; + job->settings.visible_objects_only = params->visible_objects_only; job->settings.renderable_only = params->renderable_only; job->settings.use_subdiv_schema = params->use_subdiv_schema; diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index b7139d5bbf6..fdfea95937b 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -25,6 +25,10 @@ * \brief Blender kernel action and pose functionality. */ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_listBase.h" /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ @@ -38,11 +42,6 @@ struct bPose; struct bPoseChannel; struct bPoseChannel_Runtime; -/* Kernel prototypes */ -#ifdef __cplusplus -extern "C" { -#endif - /* Action Lib Stuff ----------------- */ /* Allocate a new bAction with the given name */ diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index d0249cb2b38..963e3158d46 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -24,6 +24,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Depsgraph; struct FCurve; @@ -33,6 +37,7 @@ struct KeyingSet; struct ListBase; struct Main; struct NlaKeyframingContext; +struct PathResolvedRNA; struct PointerRNA; struct PropertyRNA; struct ReportList; @@ -244,6 +249,9 @@ typedef enum eAnimData_Recalc { ADT_RECALC_ALL = (ADT_RECALC_DRIVERS | ADT_RECALC_ANIM), } eAnimData_Recalc; +bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_value); +bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value); + /* Evaluation loop for evaluating animation data */ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, @@ -258,9 +266,6 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime); -/* TODO(sergey): This is mainly a temp public function. */ -bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct FCurve *fcu, float curval); - /* ------------ Specialized API --------------- */ /* There are a few special tools which require these following functions. They are NOT to be used * for standard animation evaluation UNDER ANY CIRCUMSTANCES! @@ -297,4 +302,8 @@ void BKE_animsys_update_driver_array(struct ID *id); /* ************************************* */ +#ifdef __cplusplus +} +#endif + #endif /* __BKE_ANIMSYS_H__*/ diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index dd1fff9ce47..f1c45ac0b45 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ * \note Use #STRINGIFY() rather than defining with quotes. */ #define BLENDER_VERSION 282 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 3 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index 70741831727..c7f6c09b886 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -111,8 +111,8 @@ float BKE_brush_weight_get(const struct Scene *scene, const struct Brush *brush) void BKE_brush_weight_set(const struct Scene *scene, struct Brush *brush, float value); bool BKE_brush_use_locked_size(const struct Scene *scene, const struct Brush *brush); -bool BKE_brush_use_alpha_pressure(const struct Scene *scene, const struct Brush *brush); -bool BKE_brush_use_size_pressure(const struct Scene *scene, const struct Brush *brush); +bool BKE_brush_use_alpha_pressure(const struct Brush *brush); +bool BKE_brush_use_size_pressure(const struct Brush *brush); bool BKE_brush_sculpt_has_secondary_color(const struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h index 643073b3470..e4ea1dad086 100644 --- a/source/blender/blenkernel/BKE_colortools.h +++ b/source/blender/blenkernel/BKE_colortools.h @@ -68,7 +68,9 @@ void BKE_curvemapping_initialize(struct CurveMapping *cumap); /* keep these (const CurveMap) - to help with thread safety */ /* single curve, no table check */ -float BKE_curvemap_evaluateF(const struct CurveMap *cuma, float value); +float BKE_curvemap_evaluateF(const struct CurveMapping *cumap, + const struct CurveMap *cuma, + float value); /* single curve, with table check */ float BKE_curvemapping_evaluateF(const struct CurveMapping *cumap, int cur, float value); void BKE_curvemapping_evaluate3F(const struct CurveMapping *cumap, diff --git a/source/blender/blenkernel/BKE_kelvinlet.h b/source/blender/blenkernel/BKE_kelvinlet.h new file mode 100644 index 00000000000..fbf7d3ede1f --- /dev/null +++ b/source/blender/blenkernel/BKE_kelvinlet.h @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + */ +#ifndef __BKE_KELVINLET_H__ +#define __BKE_KELVINLET_H__ + +/** \file + * \ingroup bke + */ + +#include "BLI_math.h" + +/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity + * Pixar Technical Memo #17-03 */ + +#define KELVINLET_MAX_ITERATIONS 3 + +typedef struct KelvinletParams { + float a; + float b; + float c; + + float f; + + float radius_scaled[KELVINLET_MAX_ITERATIONS]; +} KelvinletParams; + +/* Initialize KelvinletParams to store the parameters that will affect the deformation produced by + * a Kelvinlet */ +void BKE_kelvinlet_init_params( + KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio); + +/* Regularized Kelvinlets */ +/* All these functions output the displacement that should be applied to each element. */ +/* The initial coordinates of that element should not be modified during the transformation */ +void BKE_kelvinlet_grab(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_grab_biscale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_grab_triscale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]); +void BKE_kelvinlet_scale(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]); +void BKE_kelvinlet_twist(float r_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]); + +#endif diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 7ff9c4e6376..d7b037a8189 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -95,6 +95,7 @@ bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob); bool BKE_object_material_slot_used(struct ID *id, short actcol); struct Material *BKE_material_gpencil_get(struct Object *ob, short act); +struct Material *BKE_material_gpencil_default_get(void); struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act); void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 07dee83e5ca..1e549849989 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -20,6 +20,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_modifier_types.h" /* needed for all enum typdefs */ #include "BLI_compiler_attrs.h" #include "BKE_customdata.h" @@ -461,4 +465,8 @@ void modwrap_deformVertsEM(ModifierData *md, struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index c1bb60737ff..1ae1772e094 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -24,6 +24,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + struct Depsgraph; struct Editing; struct GPUOffScreen; @@ -599,4 +603,8 @@ void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int cfra); +#ifdef __cplusplus +} +#endif + #endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 1567985bd53..6807d81daa3 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -23,6 +23,10 @@ * \ingroup bke */ +#ifdef __cplusplus +extern "C" { +#endif + #define SOUND_WAVE_SAMPLES_PER_SECOND 250 #if defined(WITH_AUDASPACE) @@ -190,4 +194,8 @@ struct Depsgraph; void BKE_sound_evaluate(struct Depsgraph *depsgraph, struct Main *bmain, struct bSound *sound); +#ifdef __cplusplus +} +#endif + #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 883518b7a9d..88a3629ea3f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -129,6 +129,7 @@ set(SRC intern/image_gen.c intern/image_save.c intern/ipo.c + intern/kelvinlet.c intern/key.c intern/keyconfig.c intern/lattice.c @@ -292,6 +293,7 @@ set(SRC BKE_image.h BKE_image_save.h BKE_ipo.h + BKE_kelvinlet.h BKE_key.h BKE_keyconfig.h BKE_lattice.h diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index eea71d52ab6..32420e2e894 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -1717,7 +1717,7 @@ static bool animsys_store_rna_setting(PointerRNA *ptr, /* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) -static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) +bool BKE_animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) { PropertyRNA *prop = anim_rna->prop; PointerRNA *ptr = &anim_rna->ptr; @@ -1780,7 +1780,7 @@ static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) } /* Write the given value to a setting using RNA, and return success */ -static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) +bool BKE_animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) { PropertyRNA *prop = anim_rna->prop; PointerRNA *ptr = &anim_rna->ptr; @@ -1791,7 +1791,7 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val /* Check whether value is new. Otherwise we skip all the updates. */ float old_value; - if (!animsys_read_rna_setting(anim_rna, &old_value)) { + if (!BKE_animsys_read_rna_setting(anim_rna, &old_value)) { return false; } if (old_value == value) { @@ -1845,20 +1845,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val return true; } -/* Simple replacement based data-setting of the FCurve using RNA */ -bool BKE_animsys_execute_fcurve(PointerRNA *ptr, FCurve *fcu, float curval) -{ - PathResolvedRNA anim_rna; - bool ok = false; - - if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { - ok = animsys_write_rna_setting(&anim_rna, curval); - } - - /* return whether we were successful */ - return ok; -} - static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA *ptr_orig) { *ptr_orig = *ptr; @@ -1895,7 +1881,7 @@ static void animsys_write_orig_anim_rna(PointerRNA *ptr, PathResolvedRNA orig_anim_rna; /* TODO(sergey): Should be possible to cache resolved path in dependency graph somehow. */ if (animsys_store_rna_setting(&ptr_orig, rna_path, array_index, &orig_anim_rna)) { - animsys_write_rna_setting(&orig_anim_rna, value); + BKE_animsys_write_rna_setting(&orig_anim_rna, value); } } @@ -1926,7 +1912,7 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - animsys_write_rna_setting(&anim_rna, curval); + BKE_animsys_write_rna_setting(&anim_rna, curval); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, fcu->rna_path, fcu->array_index, curval); } @@ -1960,7 +1946,7 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - ok = animsys_write_rna_setting(&anim_rna, curval); + ok = BKE_animsys_write_rna_setting(&anim_rna, curval); } /* set error-flag if evaluation failed */ @@ -2039,7 +2025,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) { const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - animsys_write_rna_setting(&anim_rna, curval); + BKE_animsys_write_rna_setting(&anim_rna, curval); } } } @@ -3333,7 +3319,7 @@ void nladata_flush_channels(PointerRNA *ptr, if (nec->is_array) { rna.prop_index = i; } - animsys_write_rna_setting(&rna, value); + BKE_animsys_write_rna_setting(&rna, value); if (flush_to_original) { animsys_write_orig_anim_rna(ptr, nec->rna_path, rna.prop_index, value); } @@ -3818,7 +3804,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) for (aor = adt->overrides.first; aor; aor = aor->next) { PathResolvedRNA anim_rna; if (animsys_store_rna_setting(ptr, aor->rna_path, aor->array_index, &anim_rna)) { - animsys_write_rna_setting(&anim_rna, aor->value); + BKE_animsys_write_rna_setting(&anim_rna, aor->value); } } } @@ -4143,7 +4129,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, int driver_index, FCu /* Evaluate driver, and write results to COW-domain destination */ const float ctime = DEG_get_ctime(depsgraph); const float curval = calculate_fcurve(&anim_rna, fcu, ctime); - ok = animsys_write_rna_setting(&anim_rna, curval); + ok = BKE_animsys_write_rna_setting(&anim_rna, curval); /* Flush results & status codes to original data for UI (T59984) */ if (ok && DEG_is_active(depsgraph)) { diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 58b0c9b41ea..a694a335069 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -281,22 +281,22 @@ static void armature_transform_recurse(ListBase *bonebase, { for (Bone *bone = bonebase->first; bone; bone = bone->next) { - /* Transform the bone's roll. */ - if (bone_parent == NULL) { - - float roll_mat[3][3]; - { - float delta[3]; - sub_v3_v3v3(delta, bone->tail, bone->head); - vec_roll_to_mat3(delta, bone->roll, roll_mat); + /* Store the initial bone roll in a matrix, this is needed even for child bones + * so any change in head/tail doesn't cause the roll to change. + * + * Logic here is different to edit-mode because + * this is calculated in relative to the parent. */ + float roll_mat3_pre[3][3]; + { + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, bone->roll, roll_mat3_pre); + if (bone->parent == NULL) { + mul_m3_m3m3(roll_mat3_pre, mat3, roll_mat3_pre); } - - /* Transform the roll matrix. */ - mul_m3_m3m3(roll_mat, mat3, roll_mat); - - /* Apply the transformed roll back. */ - mat3_to_vec_roll(roll_mat, NULL, &bone->roll); } + /* Optional, use this for predictable results since the roll is re-calculated below anyway. */ + bone->roll = 0.0f; mul_m4_v3(mat, bone->arm_head); mul_m4_v3(mat, bone->arm_tail); @@ -314,6 +314,17 @@ static void armature_transform_recurse(ListBase *bonebase, copy_v3_v3(bone->tail, bone->arm_tail); } + /* Now the head/tail have been updated, set the roll back, matching 'roll_mat3_pre'. */ + { + float roll_mat3_post[3][3], delta_mat3[3][3]; + float delta[3]; + sub_v3_v3v3(delta, bone->tail, bone->head); + vec_roll_to_mat3(delta, 0.0f, roll_mat3_post); + invert_m3(roll_mat3_post); + mul_m3_m3m3(delta_mat3, roll_mat3_post, roll_mat3_pre); + bone->roll = atan2f(delta_mat3[2][0], delta_mat3[2][2]); + } + BKE_armature_where_is_bone(bone, bone_parent, false); { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 4d496fe758b..8b90eafdddf 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -931,7 +931,9 @@ void BKE_brush_sculpt_reset(Brush *br) br->alpha = 1.0f; break; case SCULPT_TOOL_CLAY: - br->spacing = 6; + br->flag |= BRUSH_SIZE_PRESSURE; + br->spacing = 3; + br->autosmooth_factor = 0.25f; br->normal_radius_factor = 0.75f; break; case SCULPT_TOOL_CLAY_STRIPS: @@ -1069,18 +1071,19 @@ void BKE_brush_sculpt_reset(Brush *br) */ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset) { - CurveMap *cm = NULL; + CurveMapping *cumap = NULL; + CurveMap *cuma = NULL; if (!b->curve) { b->curve = BKE_curvemapping_add(1, 0, 0, 1, 1); } + cumap = b->curve; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->preset = preset; - cm = b->curve->cm; - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - - b->curve->preset = preset; - BKE_curvemap_reset(cm, &b->curve->clipr, b->curve->preset, CURVEMAP_SLOPE_NEGATIVE); - BKE_curvemapping_changed(b->curve, false); + cuma = b->curve->cm; + BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_NEGATIVE); + BKE_curvemapping_changed(cumap, false); } /* Generic texture sampler for 3D painting systems. point has to be either in @@ -1398,20 +1401,14 @@ bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush) (brush->flag & BRUSH_LOCK_SIZE); } -bool BKE_brush_use_size_pressure(const Scene *scene, const Brush *brush) +bool BKE_brush_use_size_pressure(const Brush *brush) { - const short us_flag = scene->toolsettings->unified_paint_settings.flag; - - return (us_flag & UNIFIED_PAINT_SIZE) ? (us_flag & UNIFIED_PAINT_BRUSH_SIZE_PRESSURE) : - (brush->flag & BRUSH_SIZE_PRESSURE); + return brush->flag & BRUSH_SIZE_PRESSURE; } -bool BKE_brush_use_alpha_pressure(const Scene *scene, const Brush *brush) +bool BKE_brush_use_alpha_pressure(const Brush *brush) { - const short us_flag = scene->toolsettings->unified_paint_settings.flag; - - return (us_flag & UNIFIED_PAINT_ALPHA) ? (us_flag & UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE) : - (brush->flag & BRUSH_ALPHA_PRESSURE); + return brush->flag & BRUSH_ALPHA_PRESSURE; } bool BKE_brush_sculpt_has_secondary_color(const Brush *brush) diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 8166bbea962..2ec04ee2747 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -54,7 +54,7 @@ void BKE_curvemapping_set_defaults( int a; float clipminx, clipminy, clipmaxx, clipmaxy; - cumap->flag = CUMA_DO_CLIP; + cumap->flag = CUMA_DO_CLIP | CUMA_EXTEND_EXTRAPOLATE; if (tot == 4) { cumap->cur = 3; /* rhms, hack for 'col' curve? */ } @@ -71,7 +71,6 @@ void BKE_curvemapping_set_defaults( cumap->bwmul[0] = cumap->bwmul[1] = cumap->bwmul[2] = 1.0f; for (a = 0; a < tot; a++) { - cumap->cm[a].flag = CUMA_EXTEND_EXTRAPOLATE; cumap->cm[a].totpoint = 2; cumap->cm[a].curve = MEM_callocN(2 * sizeof(CurveMapPoint), "curve points"); @@ -591,14 +590,15 @@ static void calchandle_curvemap(BezTriple *bezt, const BezTriple *prev, const Be /* in X, out Y. * X is presumed to be outside first or last */ -static float curvemap_calc_extend(const CurveMap *cuma, +static float curvemap_calc_extend(const CurveMapping *cumap, + const CurveMap *cuma, float x, const float first[2], const float last[2]) { if (x <= first[0]) { - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - /* no extrapolate */ + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + /* extrapolate horizontally */ return first[1]; } else { @@ -611,8 +611,8 @@ static float curvemap_calc_extend(const CurveMap *cuma, } } else if (x >= last[0]) { - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { - /* no extrapolate */ + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + /* extrapolate horizontally */ return last[1]; } else { @@ -628,8 +628,9 @@ static float curvemap_calc_extend(const CurveMap *cuma, } /* only creates a table for a single channel in CurveMapping */ -static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) +static void curvemap_make_table(const CurveMapping *cumap, CurveMap *cuma) { + const rctf *clipr = &cumap->clipr; CurveMapPoint *cmp = cuma->curve; BezTriple *bezt; @@ -782,7 +783,7 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr) } else { /* Extrapolate values that lie outside the start and end point. */ - cmp[a].y = curvemap_calc_extend(cuma, cur_x, firstpoint, lastpoint); + cmp[a].y = curvemap_calc_extend(cumap, cuma, cur_x, firstpoint, lastpoint); } } else { @@ -829,7 +830,7 @@ void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore) /* verify and copy */ for (a = 0; a < 3; a++) { if (cumap->cm[a].table == NULL) { - curvemap_make_table(cumap->cm + a, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + a); } cumap->cm[a].premultable = cumap->cm[a].table; cumap->cm[a].table = MEM_mallocN((CM_TABLE + 1) * sizeof(CurveMapPoint), "premul table"); @@ -838,14 +839,15 @@ void BKE_curvemapping_premultiply(CurveMapping *cumap, int restore) } if (cumap->cm[3].table == NULL) { - curvemap_make_table(cumap->cm + 3, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + 3); } /* premul */ for (a = 0; a < 3; a++) { int b; for (b = 0; b <= CM_TABLE; b++) { - cumap->cm[a].table[b].y = BKE_curvemap_evaluateF(cumap->cm + 3, cumap->cm[a].table[b].y); + cumap->cm[a].table[b].y = BKE_curvemap_evaluateF( + cumap, cumap->cm + 3, cumap->cm[a].table[b].y); } copy_v2_v2(cumap->cm[a].premul_ext_in, cumap->cm[a].ext_in); @@ -949,7 +951,7 @@ void BKE_curvemapping_changed(CurveMapping *cumap, const bool rem_doubles) BKE_curvemap_remove(cuma, 2); } } - curvemap_make_table(cuma, clipr); + curvemap_make_table(cumap, cuma); } void BKE_curvemapping_changed_all(CurveMapping *cumap) @@ -967,7 +969,7 @@ void BKE_curvemapping_changed_all(CurveMapping *cumap) } /* table should be verified */ -float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) +float BKE_curvemap_evaluateF(const CurveMapping *cumap, const CurveMap *cuma, float value) { float fi; int i; @@ -978,7 +980,7 @@ float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) /* fi is table float index and should check against table range i.e. [0.0 CM_TABLE] */ if (fi < 0.0f || fi > CM_TABLE) { - return curvemap_calc_extend(cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x); + return curvemap_calc_extend(cumap, cuma, value, &cuma->table[0].x, &cuma->table[CM_TABLE].x); } else { if (i < 0) { @@ -997,7 +999,7 @@ float BKE_curvemap_evaluateF(const CurveMap *cuma, float value) float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value) { const CurveMap *cuma = cumap->cm + cur; - float val = BKE_curvemap_evaluateF(cuma, value); + float val = BKE_curvemap_evaluateF(cumap, cuma, value); /* account for clipping */ if (cumap->flag & CUMA_DO_CLIP) { @@ -1015,9 +1017,9 @@ float BKE_curvemapping_evaluateF(const CurveMapping *cumap, int cur, float value /* vector case */ void BKE_curvemapping_evaluate3F(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], vecin[0]); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], vecin[1]); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], vecin[2]); + vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], vecin[0]); + vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], vecin[1]); + vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], vecin[2]); } /* RGB case, no black/white points, no premult */ @@ -1025,12 +1027,12 @@ void BKE_curvemapping_evaluateRGBF(const CurveMapping *cumap, float vecout[3], const float vecin[3]) { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[0])); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[1])); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], - BKE_curvemap_evaluateF(&cumap->cm[3], vecin[2])); + vecout[0] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[0], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[0])); + vecout[1] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[1], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[1])); + vecout[2] = BKE_curvemap_evaluateF( + cumap, &cumap->cm[2], BKE_curvemap_evaluateF(cumap, &cumap->cm[3], vecin[2])); } static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap, @@ -1042,8 +1044,8 @@ static void curvemapping_evaluateRGBF_filmlike(const CurveMapping *cumap, const float v1in = vecin[channel_offset[1]]; const float v2in = vecin[channel_offset[2]]; - const float v0 = BKE_curvemap_evaluateF(&cumap->cm[channel_offset[0]], v0in); - const float v2 = BKE_curvemap_evaluateF(&cumap->cm[channel_offset[2]], v2in); + const float v0 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[0]], v0in); + const float v2 = BKE_curvemap_evaluateF(cumap, &cumap->cm[channel_offset[2]], v2in); const float v1 = v2 + ((v0 - v2) * (v1in - v2in) / (v0in - v2in)); vecout[channel_offset[0]] = v0; @@ -1074,9 +1076,9 @@ void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, switch (cumap->tone) { default: case CURVE_TONE_STANDARD: { - vecout[0] = BKE_curvemap_evaluateF(&cumap->cm[0], r); - vecout[1] = BKE_curvemap_evaluateF(&cumap->cm[1], g); - vecout[2] = BKE_curvemap_evaluateF(&cumap->cm[2], b); + vecout[0] = BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r); + vecout[1] = BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g); + vecout[2] = BKE_curvemap_evaluateF(cumap, &cumap->cm[2], b); break; } case CURVE_TONE_FILMLIKE: { @@ -1099,8 +1101,8 @@ void BKE_curvemapping_evaluate_premulRGBF_ex(const CurveMapping *cumap, else { /* Case 4: r >= g == b */ copy_v2_fl2(vecout, - BKE_curvemap_evaluateF(&cumap->cm[0], r), - BKE_curvemap_evaluateF(&cumap->cm[1], g)); + BKE_curvemap_evaluateF(cumap, &cumap->cm[0], r), + BKE_curvemap_evaluateF(cumap, &cumap->cm[1], g)); vecout[2] = vecout[1]; } } @@ -1208,7 +1210,7 @@ void BKE_curvemapping_initialize(CurveMapping *cumap) for (a = 0; a < CM_TOT; a++) { if (cumap->cm[a].table == NULL) { - curvemap_make_table(cumap->cm + a, &cumap->clipr); + curvemap_make_table(cumap, cumap->cm + a); } } } diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 9618ef8c78e..33f9b5b1012 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -417,12 +417,12 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, mti->deformMatrices(md, &mectx, me_eval, deformedVerts, defmats, me_eval->totvert); } else { + /* More complex handling will continue in BKE_crazyspace_build_sculpt. + * Exiting the loop on a non-deform modifier causes issues - T71213. */ + BLI_assert(crazyspace_modifier_supports_deform(md)); break; } } - else { - break; - } } for (; md; md = md->next) { diff --git a/source/blender/blenkernel/intern/kelvinlet.c b/source/blender/blenkernel/intern/kelvinlet.c new file mode 100644 index 00000000000..a7b48107873 --- /dev/null +++ b/source/blender/blenkernel/intern/kelvinlet.c @@ -0,0 +1,215 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "BKE_kelvinlet.h" + +/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity + * Pixar Technical Memo #17-03 */ + +void BKE_kelvinlet_init_params( + KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio) +{ + params->a = 1.0f / (4.0f * (float)M_PI * shear_modulus); + params->b = params->a / (4.0f * (1.0f - poisson_ratio)); + params->c = 2 * (3.0f * params->a - 2.0f * params->b); + + /* Used in scale and twist. */ + params->f = force; + + /* This can be exposed if needed */ + const float radius_e[KELVINLET_MAX_ITERATIONS] = {1.0f, 2.0f, 2.0f}; + params->radius_scaled[0] = radius * radius_e[0]; + params->radius_scaled[1] = params->radius_scaled[0] * radius_e[1]; + params->radius_scaled[2] = params->radius_scaled[1] * radius_e[2]; +} + +static void init_kelvinlet_grab(float radius_e[3], + float kelvinlet[3], + const float radius, + const KelvinletParams *params, + const int num_iterations) +{ + const float a = params->a; + const float b = params->b; + const float *radius_scaled = params->radius_scaled; + + for (int i = 0; i < num_iterations; i++) { + radius_e[i] = sqrtf(pow2f(radius) + pow2f(params->radius_scaled[i])); + } + + /* Regularized Kelvinlets: Formula (6) */ + for (int i = 0; i < num_iterations; i++) { + kelvinlet[i] = ((a - b) / radius_e[i]) + ((b * pow2f(radius)) / pow3f(radius_e[i])) + + ((a * pow2f(radius_scaled[i])) / (2.0f * pow3f(radius_e[i]))); + } +} + +void BKE_kelvinlet_grab(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3]; + const float c = params->c; + const float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 1); + + const float fade = kelvinlet[0] * c; + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3]; + const float c = params->c; + const float *radius_scaled = params->radius_scaled; + float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 2); + + const float u = kelvinlet[0] - kelvinlet[1]; + const float fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1])); + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float brush_delta[3]) +{ + float radius_e[3], kelvinlet[3], weights[3]; + const float c = params->c; + const float *radius_scaled = params->radius_scaled; + const float radius = len_v3v3(brush_location, elem_orig_co); + + init_kelvinlet_grab(radius_e, kelvinlet, radius, params, 3); + + weights[0] = 1.0f; + weights[1] = -((pow2f(radius_scaled[2]) - pow2f(radius_scaled[0])) / + (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1]))); + weights[2] = ((pow2f(radius_scaled[1]) - pow2f(radius_scaled[0])) / + (pow2f(radius_scaled[2]) - pow2f(radius_scaled[1]))); + + const float u = weights[0] * kelvinlet[0] + weights[1] * kelvinlet[1] + + weights[2] * kelvinlet[2]; + const float fade = u * c / + (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] + + weights[2] / radius_scaled[2]); + + mul_v3_v3fl(radius_elem_disp, brush_delta, fade); +} + +typedef void (*kelvinlet_fn)( + float[3], const float *, const float *, const float *, const KelvinletParams *); + +static void sculpt_kelvinet_integrate(kelvinlet_fn kelvinlet, + float r_disp[3], + const float vertex_co[3], + const float location[3], + const float normal[3], + const KelvinletParams *p) +{ + float k[4][3], k_it[4][3]; + kelvinlet(k[0], vertex_co, location, normal, p); + copy_v3_v3(k_it[0], k[0]); + mul_v3_fl(k_it[0], 0.5f); + add_v3_v3v3(k_it[0], vertex_co, k_it[0]); + kelvinlet(k[1], k_it[0], location, normal, p); + copy_v3_v3(k_it[1], k[1]); + mul_v3_fl(k_it[1], 0.5f); + add_v3_v3v3(k_it[1], vertex_co, k_it[1]); + kelvinlet(k[2], k_it[1], location, normal, p); + copy_v3_v3(k_it[2], k[2]); + add_v3_v3v3(k_it[2], vertex_co, k_it[2]); + sub_v3_v3v3(k_it[2], k_it[2], location); + kelvinlet(k[3], k_it[2], location, normal, p); + copy_v3_v3(r_disp, k[0]); + madd_v3_v3fl(r_disp, k[1], 2.0f); + madd_v3_v3fl(r_disp, k[2], 2.0f); + add_v3_v3(r_disp, k[3]); + mul_v3_fl(r_disp, 1.0f / 6.0f); +} + +/* Regularized Kelvinlets: Formula (16) */ +static void kelvinlet_scale(float disp[3], + const float vertex_co[3], + const float location[3], + const float UNUSED(normal[3]), + const KelvinletParams *p) +{ + float radius_vertex[3]; + sub_v3_v3v3(radius_vertex, vertex_co, location); + const float radius = len_v3(radius_vertex); + const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0])); + const float u = (2.0f * p->b - p->a) * ((1.0f / pow3f(radius_e))) + + ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e))); + const float fade = u * p->c; + mul_v3_v3fl(disp, radius_vertex, fade * p->f); +} + +void BKE_kelvinlet_scale(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]) +{ + sculpt_kelvinet_integrate( + kelvinlet_scale, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params); +} + +/* Regularized Kelvinlets: Formula (15) */ +static void kelvinlet_twist(float disp[3], + const float vertex_co[3], + const float location[3], + const float normal[3], + const KelvinletParams *p) +{ + float radius_vertex[3], q_r[3]; + sub_v3_v3v3(radius_vertex, vertex_co, location); + const float radius = len_v3(radius_vertex); + const float radius_e = sqrtf(pow2f(radius) + pow2f(p->radius_scaled[0])); + const float u = -p->a * ((1.0f / pow3f(radius_e))) + + ((3.0f * pow2f(p->radius_scaled[0])) / (2.0f * pow5f(radius_e))); + const float fade = u * p->c; + cross_v3_v3v3(q_r, normal, radius_vertex); + mul_v3_v3fl(disp, q_r, fade * p->f); +} + +void BKE_kelvinlet_twist(float radius_elem_disp[3], + const KelvinletParams *params, + const float elem_orig_co[3], + const float brush_location[3], + const float surface_normal[3]) +{ + sculpt_kelvinet_integrate( + kelvinlet_twist, radius_elem_disp, elem_orig_co, brush_location, surface_normal, params); +} diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 73c278a0ab6..54432c8da74 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -598,6 +598,11 @@ Material *BKE_material_gpencil_get(Object *ob, short act) } } +struct Material *BKE_material_gpencil_default_get(void) +{ + return &defgpencil_material; +} + MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act) { Material *ma = give_current_material(ob, act); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 46ef24be5e9..e7c20ca4fb2 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -655,19 +655,19 @@ bool BKE_paint_select_elem_test(Object *ob) void BKE_paint_cavity_curve_preset(Paint *p, int preset) { - CurveMap *cm = NULL; + CurveMapping *cumap = NULL; + CurveMap *cuma = NULL; if (!p->cavity_curve) { p->cavity_curve = BKE_curvemapping_add(1, 0, 0, 1, 1); } + cumap = p->cavity_curve; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->preset = preset; - cm = p->cavity_curve->cm; - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; - - p->cavity_curve->preset = preset; - BKE_curvemap_reset( - cm, &p->cavity_curve->clipr, p->cavity_curve->preset, CURVEMAP_SLOPE_POSITIVE); - BKE_curvemapping_changed(p->cavity_curve, false); + cuma = cumap->cm; + BKE_curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE); + BKE_curvemapping_changed(cumap, false); } eObjectMode BKE_paint_object_mode_from_paintmode(ePaintMode mode) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9dcebbba56e..ab72b7d3b0d 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1284,6 +1284,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_ mesh, (&(struct BMeshToMeshParams){ .calc_object_remap = true, + .update_shapekey_indices = true, })); DEG_id_tag_update(&mesh->id, 0); } diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index f4e89160487..b1ae71c609f 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -558,7 +558,7 @@ void BKE_texture_pointdensity_init_data(PointDensity *pd) pd->falloff_curve = BKE_curvemapping_add(1, 0, 0, 1, 1); pd->falloff_curve->preset = CURVE_PRESET_LINE; - pd->falloff_curve->cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + pd->falloff_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemap_reset(pd->falloff_curve->cm, &pd->falloff_curve->clipr, pd->falloff_curve->preset, diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c index dd2b182474e..3e449fa6b25 100644 --- a/source/blender/blenkernel/intern/workspace.c +++ b/source/blender/blenkernel/intern/workspace.c @@ -26,6 +26,7 @@ #include "BLI_string_utils.h" #include "BLI_listbase.h" +#include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_main.h" @@ -202,8 +203,10 @@ WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain) } void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook) { - /* workspaces should never be freed before wm (during which we call this function) */ - BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces)); + /* workspaces should never be freed before wm (during which we call this function). + * However, when running in background mode, loading a blend file may allocate windows (that need + * to be freed) without creating workspaces. This happens in BlendfileLoadingBaseTest. */ + BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces) || G.background); /* Free relations for this hook */ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 4c86b9d3396..85c6425bb2f 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -58,6 +58,10 @@ MINLINE float pow4f(float x) { return pow2f(pow2f(x)); } +MINLINE float pow5f(float x) +{ + return pow4f(x) * x; +} MINLINE float pow7f(float x) { return pow2f(pow3f(x)) * x; diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 0cb68cfd7fe..6c8b14ad5c7 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -37,10 +37,14 @@ #include "DNA_collection_types.h" #include "DNA_constraint_types.h" #include "DNA_curveprofile_types.h" +#include "DNA_freestyle_types.h" #include "DNA_gpu_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_gpencil_modifier_types.h" #include "DNA_light_types.h" #include "DNA_layer_types.h" #include "DNA_lightprobe_types.h" +#include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" @@ -50,12 +54,12 @@ #include "DNA_screen_types.h" #include "DNA_view3d_types.h" #include "DNA_genfile.h" -#include "DNA_gpencil_types.h" #include "DNA_workspace_types.h" #include "DNA_key_types.h" #include "DNA_curve_types.h" #include "DNA_armature_types.h" #include "DNA_text_types.h" +#include "DNA_texture_types.h" #include "DNA_world_types.h" #include "BKE_animsys.h" @@ -861,6 +865,232 @@ static void do_versions_local_collection_bits_set(LayerCollection *layer_collect } } +static void do_version_curvemapping_flag_extend_extrapolate(CurveMapping *cumap) +{ +#define CUMA_EXTEND_EXTRAPOLATE_OLD 1 + for (int curve_map_index = 0; curve_map_index < 4; curve_map_index++) { + CurveMap *cuma = &cumap->cm[curve_map_index]; + if (cuma->flag & CUMA_EXTEND_EXTRAPOLATE_OLD) { + cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; + return; + } + } +#undef CUMA_EXTEND_EXTRAPOLATE_OLD +} + +/* Util version to walk over all CurveMappings in the given `bmain` */ +static void do_version_curvemapping_walker(Main *bmain, void (*callback)(CurveMapping *cumap)) +{ + LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) { + callback(&scene->r.mblur_shutter_curve); + + if (scene->view_settings.curve_mapping) { + callback(scene->view_settings.curve_mapping); + } + + if (scene->ed != NULL) { + LISTBASE_FOREACH (Sequence *, seq, &scene->ed->seqbase) { + LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { + const SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type); + + if (smti) { + if (smd->type == seqModifierType_Curves) { + CurvesModifierData *cmd = (CurvesModifierData *)smd; + callback(&cmd->curve_mapping); + } + else if (smd->type == seqModifierType_HueCorrect) { + HueCorrectModifierData *hcmd = (HueCorrectModifierData *)smd; + callback(&hcmd->curve_mapping); + } + } + } + } + } + + // toolsettings + ToolSettings *ts = scene->toolsettings; + if (ts->vpaint) { + callback(ts->vpaint->paint.cavity_curve); + } + if (ts->wpaint) { + callback(ts->wpaint->paint.cavity_curve); + } + if (ts->sculpt) { + callback(ts->sculpt->paint.cavity_curve); + } + if (ts->uvsculpt) { + callback(ts->uvsculpt->paint.cavity_curve); + } + if (ts->gp_paint) { + callback(ts->gp_paint->paint.cavity_curve); + } + if (ts->gp_interpolate.custom_ipo) { + callback(ts->gp_interpolate.custom_ipo); + } + if (ts->gp_sculpt.cur_falloff) { + callback(ts->gp_sculpt.cur_falloff); + } + if (ts->gp_sculpt.cur_primitive) { + callback(ts->gp_sculpt.cur_primitive); + } + callback(ts->imapaint.paint.cavity_curve); + } + + FOREACH_NODETREE_BEGIN (bmain, node_tree, id) { + LISTBASE_FOREACH (bNode *, node, &node_tree->nodes) { + if (ELEM(node->type, + SH_NODE_CURVE_VEC, + SH_NODE_CURVE_RGB, + CMP_NODE_CURVE_VEC, + CMP_NODE_CURVE_RGB, + CMP_NODE_TIME, + CMP_NODE_HUECORRECT, + TEX_NODE_CURVE_RGB, + TEX_NODE_CURVE_TIME)) { + callback((CurveMapping *)node->storage); + } + } + } + FOREACH_NODETREE_END; + + LISTBASE_FOREACH (Light *, light, &bmain->lights) { + if (light->curfalloff) { + callback(light->curfalloff); + } + } + + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if (brush->curve) { + callback(brush->curve); + } + if (brush->gpencil_settings) { + if (brush->gpencil_settings->curve_sensitivity) { + callback(brush->gpencil_settings->curve_sensitivity); + } + if (brush->gpencil_settings->curve_strength) { + callback(brush->gpencil_settings->curve_strength); + } + if (brush->gpencil_settings->curve_jitter) { + callback(brush->gpencil_settings->curve_jitter); + } + } + } + + LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) { + if (part->clumpcurve) { + callback(part->clumpcurve); + } + if (part->roughcurve) { + callback(part->roughcurve); + } + if (part->twistcurve) { + callback(part->twistcurve); + } + } + + /* Object */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + /* Object modifiers */ + LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + + if (hmd->curfalloff) { + callback(hmd->curfalloff); + } + } + else if (md->type == eModifierType_Warp) { + WarpModifierData *tmd = (WarpModifierData *)md; + if (tmd->curfalloff) { + callback(tmd->curfalloff); + } + } + else if (md->type == eModifierType_WeightVGEdit) { + WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; + + if (wmd->cmap_curve) { + callback(wmd->cmap_curve); + } + } + } + /* Grease pencil modifiers */ + LISTBASE_FOREACH (ModifierData *, md, &ob->greasepencil_modifiers) { + if (md->type == eGpencilModifierType_Thick) { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + + if (gpmd->curve_thickness) { + callback(gpmd->curve_thickness); + } + } + else if (md->type == eGpencilModifierType_Hook) { + HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; + + if (gpmd->curfalloff) { + callback(gpmd->curfalloff); + } + } + } + } + + /* Free Style */ + LISTBASE_FOREACH (struct FreestyleLineStyle *, linestyle, &bmain->linestyles) { + LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->thickness_modifiers) { + switch (m->type) { + case LS_MODIFIER_ALONG_STROKE: + callback(((LineStyleAlphaModifier_AlongStroke *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_CAMERA: + callback(((LineStyleAlphaModifier_DistanceFromCamera *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_OBJECT: + callback(((LineStyleAlphaModifier_DistanceFromObject *)m)->curve); + break; + case LS_MODIFIER_MATERIAL: + callback(((LineStyleAlphaModifier_Material *)m)->curve); + break; + case LS_MODIFIER_TANGENT: + callback(((LineStyleAlphaModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_NOISE: + callback(((LineStyleAlphaModifier_Noise *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + callback(((LineStyleAlphaModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + callback(((LineStyleAlphaModifier_Curvature_3D *)m)->curve); + break; + } + } + + LISTBASE_FOREACH (LineStyleModifier *, m, &linestyle->thickness_modifiers) { + switch (m->type) { + case LS_MODIFIER_ALONG_STROKE: + callback(((LineStyleThicknessModifier_AlongStroke *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_CAMERA: + callback(((LineStyleThicknessModifier_DistanceFromCamera *)m)->curve); + break; + case LS_MODIFIER_DISTANCE_FROM_OBJECT: + callback(((LineStyleThicknessModifier_DistanceFromObject *)m)->curve); + break; + case LS_MODIFIER_MATERIAL: + callback(((LineStyleThicknessModifier_Material *)m)->curve); + break; + case LS_MODIFIER_TANGENT: + callback(((LineStyleThicknessModifier_Tangent *)m)->curve); + break; + case LS_MODIFIER_CREASE_ANGLE: + callback(((LineStyleThicknessModifier_CreaseAngle *)m)->curve); + break; + case LS_MODIFIER_CURVATURE_3D: + callback(((LineStyleThicknessModifier_Curvature_3D *)m)->curve); + break; + } + } + } +} + void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) { bool use_collection_compat_28 = true; @@ -910,11 +1140,10 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } } - /* We need to assign lib pointer to generated hidden collections *after* all have been created, - * otherwise we'll end up with several data-blocks sharing same name/library, - * which is FORBIDDEN! - * Note: we need this to be recursive, - * since a child collection may be sorted before its parent in bmain. */ + /* We need to assign lib pointer to generated hidden collections *after* all have been + * created, otherwise we'll end up with several data-blocks sharing same name/library, + * which is FORBIDDEN! Note: we need this to be recursive, since a child collection may be + * sorted before its parent in bmain. */ for (Collection *collection = bmain->collections.first; collection != NULL; collection = collection->id.next) { do_version_collection_propagate_lib_to_children(collection); @@ -1218,7 +1447,8 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } if (!MAIN_VERSION_ATLEAST(bmain, 280, 38)) { - /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects. */ + /* Ensure we get valid rigidbody object/constraint data in relevant collections' objects. + */ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1431,7 +1661,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (error & NTREE_DOVERSION_NEED_OUTPUT) { BKE_report(fd->reports, RPT_ERROR, "Eevee material conversion problem. Error in console"); printf( - "You need to connect Principled and Eevee Specular shader nodes to new material output " + "You need to connect Principled and Eevee Specular shader nodes to new material " + "output " "nodes.\n"); } @@ -3163,19 +3394,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - if (!MAIN_VERSION_ATLEAST(bmain, 280, 45)) { - for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { - for (ScrArea *area = screen->areabase.first; area; area = area->next) { - for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_SEQ) { - SpaceSeq *sseq = (SpaceSeq *)sl; - sseq->flag |= SEQ_SHOW_MARKER_LINES; - } - } - } - } - } - if (!MAIN_VERSION_ATLEAST(bmain, 280, 46)) { /* Add wireframe color. */ if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "char", "wire_color_type")) { @@ -3931,8 +4149,9 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } - { - /* Versioning code until next subversion bump goes here. */ + if (!MAIN_VERSION_ATLEAST(bmain, 282, 2)) { + do_version_curvemapping_walker(bmain, do_version_curvemapping_flag_extend_extrapolate); + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { sa->flag &= ~AREA_FLAG_UNUSED_6; @@ -3972,11 +4191,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } /* Pose brush smooth iterations */ - if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_itereations")) { + if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_iterations")) { for (Brush *br = bmain->brushes.first; br; br = br->id.next) { br->pose_smooth_iterations = 4; } } + /* Cloth pressure */ for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) { for (ModifierData *md = ob->modifiers.first; md; md = md->next) { @@ -3988,4 +4208,65 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + if (!MAIN_VERSION_ATLEAST(bmain, 282, 3)) { + /* Remove Unified pressure/size and pressure/alpha */ + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + ToolSettings *ts = scene->toolsettings; + UnifiedPaintSettings *ups = &ts->unified_paint_settings; + ups->flag &= ~(UNIFIED_PAINT_FLAG_UNUSED_0 | UNIFIED_PAINT_FLAG_UNUSED_1); + } + + /* Set the default render pass in the viewport to Combined. */ + if (!DNA_struct_elem_find(fd->filesdna, "View3DShading", "int", "render_pass")) { + for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { + scene->display.shading.render_pass = SCE_PASS_COMBINED; + } + + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->shading.render_pass = SCE_PASS_COMBINED; + } + } + } + } + } + + /* Make markers region visible by default. */ + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { + switch (sl->spacetype) { + case SPACE_SEQ: { + SpaceSeq *sseq = (SpaceSeq *)sl; + sseq->flag |= SEQ_SHOW_MARKERS; + break; + } + case SPACE_ACTION: { + SpaceAction *saction = (SpaceAction *)sl; + saction->flag |= SACTION_SHOW_MARKERS; + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = (SpaceGraph *)sl; + sipo->flag |= SIPO_SHOW_MARKERS; + break; + } + case SPACE_NLA: { + SpaceNla *snla = (SpaceNla *)sl; + snla->flag |= SNLA_SHOW_MARKERS; + break; + } + } + } + } + } + } + + { + /* Versioning code until next subversion bump goes here. */ + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index f2d6db886d3..1c88f6b00af 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -150,10 +150,9 @@ static void blo_update_defaults_screen(bScreen *screen, } } else if (sa->spacetype == SPACE_ACTION) { - /* Show marker lines, hide channels and collapse summary in timelines. */ + /* Show markers region, hide channels and collapse summary in timelines. */ SpaceAction *saction = sa->spacedata.first; - saction->flag |= SACTION_SHOW_MARKER_LINES; - + saction->flag |= SACTION_SHOW_MARKERS; if (saction->mode == SACTCONT_TIMELINE) { saction->ads.flag |= ADS_FLAG_SUMMARY_COLLAPSED; @@ -166,11 +165,15 @@ static void blo_update_defaults_screen(bScreen *screen, } else if (sa->spacetype == SPACE_GRAPH) { SpaceGraph *sipo = sa->spacedata.first; - sipo->flag |= SIPO_MARKER_LINES; + sipo->flag |= SIPO_SHOW_MARKERS; } else if (sa->spacetype == SPACE_NLA) { SpaceNla *snla = sa->spacedata.first; - snla->flag |= SNLA_SHOW_MARKER_LINES; + snla->flag |= SNLA_SHOW_MARKERS; + } + else if (sa->spacetype == SPACE_SEQ) { + SpaceSeq *seq = sa->spacedata.first; + seq->flag |= SEQ_SHOW_MARKERS; } else if (sa->spacetype == SPACE_TEXT) { /* Show syntax and line numbers in Script workspace text editor. */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 9bab959f0a2..1ecbfccab74 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -91,7 +91,7 @@ #include "BKE_key.h" #include "bmesh.h" -#include "intern/bmesh_private.h" /* for element checking */ +#include "intern/bmesh_private.h" /* For element checking. */ void BM_mesh_cd_flag_ensure(BMesh *bm, Mesh *mesh, const char cd_flag) { @@ -202,7 +202,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_MeshMasks_update(&mask, ¶ms->cd_mask_extra); if (!me || !me->totvert) { - if (me && is_new) { /*no verts? still copy customdata layout*/ + if (me && is_new) { /* No verts? still copy custom-data layout. */ CustomData_copy(&me->vdata, &bm->vdata, mask.vmask, CD_ASSIGN, 0); CustomData_copy(&me->edata, &bm->edata, mask.emask, CD_ASSIGN, 0); CustomData_copy(&me->ldata, &bm->ldata, mask.lmask, CD_ASSIGN, 0); @@ -213,7 +213,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP); CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE); } - return; /* sanity check */ + return; /* Sanity check. */ } if (is_new) { @@ -254,9 +254,8 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar if (tot_shape_keys) { if (is_new) { - /* check if we need to generate unique ids for the shapekeys. - * this also exists in the file reading code, but is here for - * a sanity check */ + /* Check if we need to generate unique ids for the shape-keys. + * This also exists in the file reading code, but is here for a sanity check. */ if (!me->key->uidgen) { fprintf(stderr, "%s had to generate shape key uid's in a situation we shouldn't need to! " @@ -310,10 +309,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar v = vtable[i] = BM_vert_create(bm, keyco ? keyco[i] : mvert->co, NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(v, i); /* set_ok */ - /* transfer flag */ + /* Transfer flag. */ v->head.hflag = BM_vert_flag_from_mflag(mvert->flag & ~SELECT); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (mvert->flag & SELECT) { BM_vert_select_set(bm, v, true); } @@ -327,12 +326,12 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert->bweight / 255.0f); } - /* set shape key original index */ + /* Set shape key original index. */ if (cd_shape_keyindex_offset != -1) { BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); } - /* set shapekey data */ + /* Set shape-key data. */ if (tot_shape_keys) { float(*co_dst)[3] = BM_ELEM_CD_GET_VOID_P(v, cd_shape_key_offset); for (int j = 0; j < tot_shape_keys; j++, co_dst++) { @@ -341,7 +340,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~BM_VERT; /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~BM_VERT; /* Added in order, clear dirty flag. */ } etable = MEM_mallocN(sizeof(BMEdge **) * me->totedge, __func__); @@ -352,10 +351,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar bm, vtable[medge->v1], vtable[medge->v2], NULL, BM_CREATE_SKIP_CD); BM_elem_index_set(e, i); /* set_ok */ - /* transfer flags */ + /* Transfer flags. */ e->head.hflag = BM_edge_flag_from_mflag(medge->flag & ~SELECT); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (medge->flag & SELECT) { BM_edge_select_set(bm, e, true); } @@ -371,10 +370,10 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~BM_EDGE; /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~BM_EDGE; /* Added in order, clear dirty flag. */ } - /* only needed for selection. */ + /* Only needed for selection. */ if (me->mselect && me->totselect != 0) { ftable = MEM_mallocN(sizeof(BMFace **) * me->totpoly, __func__); } @@ -400,13 +399,13 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar continue; } - /* don't use 'i' since we may have skipped the face */ + /* Don't use 'i' since we may have skipped the face. */ BM_elem_index_set(f, bm->totface - 1); /* set_ok */ - /* transfer flag */ + /* Transfer flag. */ f->head.hflag = BM_face_flag_from_mflag(mp->flag & ~ME_FACE_SEL); - /* this is necessary for selection counts to work properly */ + /* This is necessary for selection counts to work properly. */ if (mp->flag & ME_FACE_SEL) { BM_face_select_set(bm, f, true); } @@ -419,7 +418,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar int j = mp->loopstart; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - /* don't use 'j' since we may have skipped some faces, hence some loops. */ + /* Don't use 'j' since we may have skipped some faces, hence some loops. */ BM_elem_index_set(l_iter, totloops++); /* set_ok */ /* Save index of corresponding #MLoop. */ @@ -434,7 +433,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar } } if (is_new) { - bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* added in order, clear dirty flag */ + bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* Added in order, clear dirty flag. */ } /* -------------------------------------------------------------------- */ @@ -489,7 +488,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) int i = 0; BMIter iter; - /* caller needs to ensure this */ + /* Caller needs to ensure this. */ BLI_assert(ototvert > 0); vertMap = MEM_callocN(sizeof(*vertMap) * ototvert, "vertMap"); @@ -497,7 +496,7 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); if ((keyi != ORIGINDEX_NONE) && (keyi < ototvert) && - /* not fool-proof, but chances are if we have many verts with the same index, + /* Not fool-proof, but chances are if we have many verts with the same index, * we will want to use the first one, * since the second is more likely to be a duplicate. */ (vertMap[keyi] == NULL)) { @@ -520,8 +519,9 @@ static BMVert **bm_to_mesh_vertex_map(BMesh *bm, int ototvert) } /** - * returns customdata shapekey index from a keyblock or -1 - * \note could split this out into a more generic function */ + * Returns custom-data shapekey index from a keyblock or -1 + * \note could split this out into a more generic function. + */ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) { int i; @@ -540,12 +540,12 @@ static int bm_to_mesh_shape_layer_index_from_kb(BMesh *bm, KeyBlock *currkey) BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) { - /* this is a cheap way to set the edge draw, its not precise and will + /* This is a cheap way to set the edge draw, its not precise and will * pick the first 2 faces an edge uses. * The dot comparison is a little arbitrary, but set so that a 5 subd - * IcoSphere won't vanish but subd 6 will (as with pre-bmesh blender) */ + * IcoSphere won't vanish but subd 6 will (as with pre-bmesh Blender). */ - if (/* (med->flag & ME_EDGEDRAW) && */ /* assume to be true */ + if (/* (med->flag & ME_EDGEDRAW) && */ /* Assume to be true. */ (e->l && (e->l != e->l->radial_next)) && (dot_v3v3(e->l->f->no, e->l->radial_next->f->no) > 0.9995f)) { med->flag &= ~ME_EDGEDRAW; @@ -561,73 +561,49 @@ BLI_INLINE void bmesh_quick_edgedraw_flag(MEdge *med, BMEdge *e) */ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMeshParams *params) { - MLoop *mloop; - MPoly *mpoly; - MVert *mvert, *oldverts; - MEdge *med, *medge; + MEdge *med; BMVert *v, *eve; BMEdge *e; BMFace *f; BMIter iter; - int i, j, ototvert; + int i, j; const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); + const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - ototvert = me->totvert; - - /* new vertex block */ - if (bm->totvert == 0) { - mvert = NULL; - } - else { - mvert = MEM_callocN(bm->totvert * sizeof(MVert), "loadeditbMesh vert"); - } - - /* new edge block */ - if (bm->totedge == 0) { - medge = NULL; - } - else { - medge = MEM_callocN(bm->totedge * sizeof(MEdge), "loadeditbMesh edge"); - } + MVert *oldverts = NULL; + const int ototvert = me->totvert; - /* new ngon face block */ - if (bm->totface == 0) { - mpoly = NULL; - } - else { - mpoly = MEM_callocN(bm->totface * sizeof(MPoly), "loadeditbMesh poly"); - } + if (me->key && (cd_shape_keyindex_offset != -1)) { + /* Keep the old verts in case we are working on* a key, which is done at the end. */ - /* new loop block */ - if (bm->totloop == 0) { - mloop = NULL; - } - else { - mloop = MEM_callocN(bm->totloop * sizeof(MLoop), "loadeditbMesh loop"); - } - - /* lets save the old verts just in case we are actually working on - * a key ... we now do processing of the keys at the end */ + /* Use the array in-place instead of duplicating the array. */ +#if 0 oldverts = MEM_dupallocN(me->mvert); +#else + oldverts = me->mvert; + me->mvert = NULL; + CustomData_update_typemap(&me->vdata); + CustomData_set_layer(&me->vdata, CD_MVERT, NULL); +#endif + } - /* free custom data */ + /* Free custom data. */ CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); CustomData_free(&me->ldata, me->totloop); CustomData_free(&me->pdata, me->totpoly); - /* add new custom data */ + /* Add new custom data. */ me->totvert = bm->totvert; me->totedge = bm->totedge; me->totloop = bm->totloop; me->totpoly = bm->totface; - /* will be overwritten with a valid value if 'dotess' is set, otherwise we - * end up with 'me->totface' and me->mface == NULL which can crash [#28625] - */ + /* Will be overwritten with a valid value if 'dotess' is set, otherwise we + * end up with 'me->totface' and me->mface == NULL which can crash T28625. */ me->totface = 0; me->act_face = -1; @@ -640,6 +616,11 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh CustomData_copy(&bm->pdata, &me->pdata, mask.pmask, CD_CALLOC, me->totpoly); } + MVert *mvert = bm->totvert ? MEM_callocN(sizeof(MVert) * bm->totvert, "bm_to_me.vert") : NULL; + MEdge *medge = bm->totedge ? MEM_callocN(sizeof(MEdge) * bm->totedge, "bm_to_me.edge") : NULL; + MLoop *mloop = bm->totloop ? MEM_callocN(sizeof(MLoop) * bm->totloop, "bm_to_me.loop") : NULL; + MPoly *mpoly = bm->totface ? MEM_callocN(sizeof(MPoly) * bm->totface, "bm_to_me.poly") : NULL; + CustomData_add_layer(&me->vdata, CD_MVERT, CD_ASSIGN, mvert, me->totvert); CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, me->totedge); CustomData_add_layer(&me->ldata, CD_MLOOP, CD_ASSIGN, mloop, me->totloop); @@ -647,7 +628,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->cd_flag = BM_mesh_cd_flag_from_bmesh(bm); - /* this is called again, 'dotess' arg is used there */ + /* This is called again, 'dotess' arg is used there. */ BKE_mesh_update_customdata_pointers(me, 0); i = 0; @@ -659,7 +640,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(v, i); /* set_inline */ - /* copy over customdat */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); if (cd_vert_bweight_offset != -1) { @@ -683,7 +664,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_elem_index_set(e, i); /* set_inline */ - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->edata, &me->edata, e->head.data, i); bmesh_quick_edgedraw_flag(med, e); @@ -715,7 +696,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh mloop->e = BM_elem_index_get(l_iter->e); mloop->v = BM_elem_index_get(l_iter->v); - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->ldata, &me->ldata, l_iter->head.data, j); j++; @@ -729,7 +710,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh me->act_face = i; } - /* copy over customdata */ + /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->pdata, &me->pdata, f->head.data, i); i++; @@ -737,7 +718,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BM_CHECK_ELEMENT(f); } - /* patch hook indices and vertex parents */ + /* Patch hook indices and vertex parents. */ if (params->calc_object_remap && (ototvert > 0)) { BLI_assert(bmain != NULL); Object *ob; @@ -829,19 +810,16 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } - /* see comment below, this logic is in twice */ + /* See comment below, this logic is in twice. */ if (me->key) { - const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); - KeyBlock *currkey; KeyBlock *actkey = BLI_findlink(&me->key->block, bm->shapenr - 1); float(*ofs)[3] = NULL; - /* go through and find any shapekey customdata layers - * that might not have corresponding KeyBlocks, and add them if - * necessary */ + /* Go through and find any shape-key custom-data layers + * that might not have corresponding KeyBlocks, and add them if necessary. */ j = 0; for (i = 0; i < bm->vdata.totlayer; i++) { if (bm->vdata.layers[i].type != CD_SHAPEKEY) { @@ -862,30 +840,39 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh j++; } - /* editing the base key should update others */ - if ((me->key->type == KEY_RELATIVE) && /* only need offsets for relative shape keys */ - (actkey != NULL) && /* unlikely, but the active key may not be valid if the - * bmesh and the mesh are out of sync */ - (oldverts != NULL)) /* not used here, but 'oldverts' is used later for applying 'ofs' */ - { + /* Editing the base key should update others. */ + if (/* Only need offsets for relative shape keys. */ + (me->key->type == KEY_RELATIVE) && + + /* Unlikely, but the active key may not be valid if the + * BMesh and the mesh are out of sync. */ + (actkey != NULL) && + + /* Not used here, but 'oldverts' is used later for applying 'ofs'. */ + (oldverts != NULL) && + + /* Needed for referencing oldverts. */ + (cd_shape_keyindex_offset != -1)) { + const bool act_is_basis = BKE_keyblock_is_basis(me->key, bm->shapenr - 1); - /* active key is a base */ - if (act_is_basis && (cd_shape_keyindex_offset != -1)) { - float(*fp)[3] = actkey->data; + /* Active key is a base. */ + if (act_is_basis) { + const float(*fp)[3] = actkey->data; ofs = MEM_callocN(sizeof(float) * 3 * bm->totvert, "currkey->data"); mvert = me->mvert; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { const int keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if (keyi != ORIGINDEX_NONE) { + /* Could use 'eve->co' or 'mvert->co', they're the same at this point. */ + if (keyi != ORIGINDEX_NONE && keyi < actkey->totelem) { sub_v3_v3v3(ofs[i], mvert->co, fp[keyi]); } else { - /* if there are new vertices in the mesh, we can't propagate the offset + /* If there are new vertices in the mesh, we can't propagate the offset * because it will only work for the existing vertices and not the new - * ones, creating a mess when doing e.g. subdivide + translate */ + * ones, creating a mess when doing e.g. subdivide + translate. */ MEM_freeN(ofs); ofs = NULL; break; @@ -901,7 +888,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh (bm->shapenr - 1 == currkey->relative)); int cd_shape_offset; int keyi; - float(*ofs_pt)[3] = ofs; + const float(*ofs_pt)[3] = ofs; float *newkey, (*oldkey)[3], *fp; j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); @@ -916,11 +903,11 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (currkey == actkey) { copy_v3_v3(fp, eve->co); - if (actkey != me->key->refkey) { /* important see bug [#30771] */ + if (actkey != me->key->refkey) { /* Important see bug T30771. */ if (cd_shape_keyindex_offset != -1) { if (oldverts) { keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset); - if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* valid old vertex */ + if (keyi != ORIGINDEX_NONE && keyi < currkey->totelem) { /* Valid old vertex. */ copy_v3_v3(mvert->co, oldverts[keyi].co); } } @@ -928,29 +915,29 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } else if (j != -1) { - /* in most cases this runs */ + /* In most cases this runs. */ copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset)); } else if ((oldkey != NULL) && (cd_shape_keyindex_offset != -1) && ((keyi = BM_ELEM_CD_GET_INT(eve, cd_shape_keyindex_offset)) != ORIGINDEX_NONE) && (keyi < currkey->totelem)) { - /* old method of reconstructing keys via vertice's original key indices, - * currently used if the new method above fails (which is theoretically - * possible in certain cases of undo) */ + /* Old method of reconstructing keys via vertice's original key indices, + * currently used if the new method above fails + * (which is theoretically possible in certain cases of undo). */ copy_v3_v3(fp, oldkey[keyi]); } else { - /* fail! fill in with dummy value */ + /* Fail! fill in with dummy value. */ copy_v3_v3(fp, mvert->co); } - /* propagate edited basis offsets to other shapes */ + /* Propagate edited basis offsets to other shapes. */ if (apply_offset) { add_v3_v3(fp, *ofs_pt++); - /* Apply back new coordinates of offsetted shapekeys into BMesh. + /* Apply back new coordinates of offsetted shape-keys into BMesh. * Otherwise, in case we call again BM_mesh_bm_to_me on same BMesh, * we'll apply diff from previous call to BM_mesh_bm_to_me, - * to shapekey values from *original creation of the BMesh*. See T50524. */ + * to shape-key values from *original creation of the BMesh*. See T50524. */ copy_v3_v3(BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset), fp); } @@ -970,14 +957,25 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh } } + /* Run this even when shape keys aren't used since it may be used for hooks or vertex parents. */ + if (params->update_shapekey_indices) { + /* We have written a new shape key, if this mesh is _not_ going to be freed, + * update the shape key indices to match the newly updated. */ + if (cd_shape_keyindex_offset != -1) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + BM_ELEM_CD_SET_INT(eve, cd_shape_keyindex_offset, i); + } + } + } + if (oldverts != NULL) { MEM_freeN(oldverts); } - /* topology could be changed, ensure mdisps are ok */ + /* Topology could be changed, ensure mdisps are ok. */ multires_topology_changed(me); - /* to be removed as soon as COW is enabled by default. */ + /* To be removed as soon as COW is enabled by default.. */ BKE_mesh_runtime_clear_geometry(me); } @@ -1000,7 +998,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh */ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks *cd_mask_extra) { - /* must be an empty mesh. */ + /* Must be an empty mesh. */ BLI_assert(me->totvert == 0); BLI_assert(cd_mask_extra == NULL || (cd_mask_extra->vmask & CD_MASK_SHAPEKEY) == 0); @@ -1019,8 +1017,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * CustomData_add_layer(&me->ldata, CD_MLOOP, CD_CALLOC, NULL, bm->totloop); CustomData_add_layer(&me->pdata, CD_MPOLY, CD_CALLOC, NULL, bm->totface); - /* don't process shapekeys, we only feed them through the modifier stack as needed, - * e.g. for applying modifiers or the like*/ + /* Don't process shape-keys, we only feed them through the modifier stack as needed, + * e.g. for applying modifiers or the like. */ CustomData_MeshMasks mask = CD_MASK_DERIVEDMESH; if (cd_mask_extra != NULL) { CustomData_MeshMasks_update(&mask, cd_mask_extra); @@ -1050,7 +1048,7 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * me->runtime.deformed_only = true; - /* don't add origindex layer if one already exists */ + /* Don't add origindex layer if one already exists. */ add_orig = !CustomData_has_layer(&bm->pdata, CD_ORIGINDEX); index = CustomData_get_layer(&me->vdata, CD_ORIGINDEX); @@ -1089,8 +1087,8 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * med->flag = BM_edge_flag_to_mflag(eed); - /* handle this differently to editmode switching, - * only enable draw for single user edges rather then calculating angle */ + /* Handle this differently to editmode switching, + * only enable draw for single user edges rather then calculating angle. */ if ((med->flag & ME_EDGEDRAW) == 0) { if (eed->l && eed->l == eed->l->radial_next) { med->flag |= ME_EDGEDRAW; diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.h b/source/blender/bmesh/intern/bmesh_mesh_conv.h index f0302764a5f..65d5c6d5494 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.h +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.h @@ -48,6 +48,16 @@ void BM_mesh_bm_from_me(BMesh *bm, const struct Mesh *me, const struct BMeshFrom struct BMeshToMeshParams { /** Update object hook indices & vertex parents. */ uint calc_object_remap : 1; + /** + * This re-assigns shape-key indices. Only do if the BMesh will have continued use + * to update the mesh & shape key in the future. + * In the case the BMesh is freed immediately, this can be left false. + * + * This is needed when flushing changes from edit-mode into object mode, + * so a second flush or edit-mode exit doesn't run with indices + * that have become invalid from updating the shape-key, see T71865. + */ + uint update_shapekey_indices : 1; struct CustomData_MeshMasks cd_mask_extra; }; void BM_mesh_bm_to_me(struct Main *bmain, diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 21ab148496c..4abeec19645 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -58,6 +58,15 @@ set(SRC intern/eval/deg_eval.cc intern/eval/deg_eval_copy_on_write.cc intern/eval/deg_eval_flush.cc + intern/eval/deg_eval_runtime_backup.cc + intern/eval/deg_eval_runtime_backup_modifier.cc + intern/eval/deg_eval_runtime_backup_movieclip.cc + intern/eval/deg_eval_runtime_backup_object.cc + intern/eval/deg_eval_runtime_backup_pose.cc + intern/eval/deg_eval_runtime_backup_scene.cc + intern/eval/deg_eval_runtime_backup_sequence.cc + intern/eval/deg_eval_runtime_backup_sequencer.cc + intern/eval/deg_eval_runtime_backup_sound.cc intern/eval/deg_eval_stats.cc intern/node/deg_node.cc intern/node/deg_node_component.cc @@ -98,6 +107,15 @@ set(SRC intern/eval/deg_eval.h intern/eval/deg_eval_copy_on_write.h intern/eval/deg_eval_flush.h + intern/eval/deg_eval_runtime_backup.h + intern/eval/deg_eval_runtime_backup_modifier.h + intern/eval/deg_eval_runtime_backup_movieclip.h + intern/eval/deg_eval_runtime_backup_object.h + intern/eval/deg_eval_runtime_backup_pose.h + intern/eval/deg_eval_runtime_backup_scene.h + intern/eval/deg_eval_runtime_backup_sequence.h + intern/eval/deg_eval_runtime_backup_sequencer.h + intern/eval/deg_eval_runtime_backup_sound.h intern/eval/deg_eval_stats.h intern/node/deg_node.h intern/node/deg_node_component.h diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 8a33453b923..3a2cf35f4d5 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -21,7 +21,7 @@ * \ingroup depsgraph */ -/* Enable special; trickery to treat nested owned IDs (such as nodetree of +/* Enable special trickery to treat nested owned IDs (such as nodetree of * material) to be handled in same way as "real" data-blocks, even tho some * internal BKE routines doesn't treat them like that. * @@ -95,6 +95,7 @@ extern "C" { #include "intern/depsgraph.h" #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" +#include "intern/eval/deg_eval_runtime_backup.h" #include "intern/node/deg_node.h" #include "intern/node/deg_node_id.h" @@ -945,545 +946,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph, return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders); } -namespace { - -/* Backup of sequencer strips runtime data. */ - -/* Backup of a single strip. */ -class SequenceBackup { - public: - SequenceBackup() - { - reset(); - } - - inline void reset() - { - scene_sound = NULL; - } - - void init_from_sequence(Sequence *sequence) - { - scene_sound = sequence->scene_sound; - - sequence->scene_sound = NULL; - } - - void restore_to_sequence(Sequence *sequence) - { - sequence->scene_sound = scene_sound; - reset(); - } - - inline bool isEmpty() const - { - return (scene_sound == NULL); - } - - void *scene_sound; -}; - -class SequencerBackup { - public: - SequencerBackup(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - typedef map<Sequence *, SequenceBackup> SequencesBackupMap; - SequencesBackupMap sequences_backup; -}; - -SequencerBackup::SequencerBackup() -{ -} - -void SequencerBackup::init_from_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequenceBackup sequence_backup; - sequence_backup.init_from_sequence(sequence); - if (!sequence_backup.isEmpty()) { - sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); - } - } - SEQ_END; -} - -void SequencerBackup::restore_to_scene(Scene *scene) -{ - Sequence *sequence; - SEQ_BEGIN (scene->ed, sequence) { - SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); - if (it == sequences_backup.end()) { - continue; - } - SequenceBackup &sequence_backup = it->second; - sequence_backup.restore_to_sequence(sequence); - } - SEQ_END; - /* Cleanup audio while the scene is still known. */ - for (SequencesBackupMap::value_type &it : sequences_backup) { - SequenceBackup &sequence_backup = it.second; - if (sequence_backup.scene_sound != NULL) { - BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); - } - } -} - -/* Backup of scene runtime data. */ - -class SceneBackup { - public: - SceneBackup(); - - void reset(); - - void init_from_scene(Scene *scene); - void restore_to_scene(Scene *scene); - - /* Sound/audio related pointers of the scene itself. - * - * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency - * graph will be gone. This means we don't need to compare original scene pointer, or worry about - * freeing those if they cant' be restored: we just copy them over to a new scene. */ - void *sound_scene; - void *playback_handle; - void *sound_scrub_handle; - void *speaker_handles; - float rigidbody_last_time; - - SequencerBackup sequencer_backup; -}; - -SceneBackup::SceneBackup() -{ - reset(); -} - -void SceneBackup::reset() -{ - sound_scene = NULL; - playback_handle = NULL; - sound_scrub_handle = NULL; - speaker_handles = NULL; - rigidbody_last_time = -1; -} - -void SceneBackup::init_from_scene(Scene *scene) -{ - sound_scene = scene->sound_scene; - playback_handle = scene->playback_handle; - sound_scrub_handle = scene->sound_scrub_handle; - speaker_handles = scene->speaker_handles; - - if (scene->rigidbody_world != NULL) { - rigidbody_last_time = scene->rigidbody_world->ltime; - } - - /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock - * is freed for re-allocation. */ - scene->sound_scene = NULL; - scene->playback_handle = NULL; - scene->sound_scrub_handle = NULL; - scene->speaker_handles = NULL; - - sequencer_backup.init_from_scene(scene); -} - -void SceneBackup::restore_to_scene(Scene *scene) -{ - scene->sound_scene = sound_scene; - scene->playback_handle = playback_handle; - scene->sound_scrub_handle = sound_scrub_handle; - scene->speaker_handles = speaker_handles; - - if (scene->rigidbody_world != NULL) { - scene->rigidbody_world->ltime = rigidbody_last_time; - } - - sequencer_backup.restore_to_scene(scene); - - reset(); -} - -/* Backup of sound datablocks runtime data. */ - -class SoundBackup { - public: - SoundBackup(); - - void reset(); - - void init_from_sound(bSound *sound); - void restore_to_sound(bSound *sound); - - void *cache; - void *waveform; - void *playback_handle; -}; - -SoundBackup::SoundBackup() -{ - reset(); -} - -void SoundBackup::reset() -{ - cache = NULL; - waveform = NULL; - playback_handle = NULL; -} - -void SoundBackup::init_from_sound(bSound *sound) -{ - cache = sound->cache; - waveform = sound->waveform; - playback_handle = sound->playback_handle; - - sound->cache = NULL; - sound->waveform = NULL; - sound->playback_handle = NULL; -} - -void SoundBackup::restore_to_sound(bSound *sound) -{ - sound->cache = cache; - sound->waveform = waveform; - sound->playback_handle = playback_handle; - - reset(); -} - -/* Identifier used to match modifiers to backup/restore their runtime data. - * Identification is happening using original modifier data pointer and the - * modifier type. - * It is not enough to only pointer, since it's possible to have a situation - * when modifier is removed and a new one added, and due to memory allocation - * policy they might have same pointer. - * By adding type into matching we are at least ensuring that modifier will not - * try to interpret runtime data created by another modifier type. */ -class ModifierDataBackupID { - public: - ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None) - { - } - - ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) - : modifier_data(modifier_data), type(type) - { - } - - bool operator<(const ModifierDataBackupID &other) const - { - if (modifier_data < other.modifier_data) { - return true; - } - if (modifier_data == other.modifier_data) { - return static_cast<int>(type) < static_cast<int>(other.type); - } - return false; - } - - ModifierData *modifier_data; - ModifierType type; -}; - -/* Storage for backed up runtime modifier data. */ -typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; - -/* Storage for backed up pose channel runtime data. */ -typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; - -class ObjectRuntimeBackup { - public: - ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0) - { - /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ - memset(&runtime, 0, sizeof(runtime)); - } - - /* Make a backup of object's evaluation runtime data, additionally - * make object to be safe for free without invalidating backed up - * pointers. */ - void init_from_object(Object *object); - void backup_modifier_runtime_data(Object *object); - void backup_pose_channel_runtime_data(Object *object); - - /* Restore all fields to the given object. */ - void restore_to_object(Object *object); - /* NOTE: Will free all runtime data which has not been restored. */ - void restore_modifier_runtime_data(Object *object); - void restore_pose_channel_runtime_data(Object *object); - - Object_Runtime runtime; - short base_flag; - unsigned short base_local_view_bits; - ModifierRuntimeDataBackup modifier_runtime_data; - PoseChannelRuntimeDataBackup pose_channel_runtime_data; -}; - -void ObjectRuntimeBackup::init_from_object(Object *object) -{ - /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ - Mesh *mesh_eval = object->runtime.mesh_eval; - runtime = object->runtime; - BKE_object_runtime_reset(object); - /* Keep bbox (for now at least). */ - object->runtime.bb = runtime.bb; - /* Object update will override actual object->data to an evaluated version. - * Need to make sure we don't have data set to evaluated one before free - * anything. */ - if (mesh_eval != NULL && object->data == mesh_eval) { - object->data = runtime.mesh_orig; - } - /* Make a backup of base flags. */ - base_flag = object->base_flag; - base_local_view_bits = object->base_local_view_bits; - /* Backup tuntime data of all modifiers. */ - backup_modifier_runtime_data(object); - /* Backup runtime data of all pose channels. */ - backup_pose_channel_runtime_data(object); -} - -inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) -{ - return ModifierDataBackupID(modifier_data->orig_modifier_data, - static_cast<ModifierType>(modifier_data->type)); -} - -void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - if (modifier_data->runtime == NULL) { - continue; - } - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); - modifier_data->runtime = NULL; - } -} - -void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; - BKE_pose_channel_runtime_reset(&pchan->runtime); - } - } - } -} - -void ObjectRuntimeBackup::restore_to_object(Object *object) -{ - Mesh *mesh_orig = object->runtime.mesh_orig; - BoundBox *bb = object->runtime.bb; - object->runtime = runtime; - object->runtime.mesh_orig = mesh_orig; - object->runtime.bb = bb; - if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { - if (object->id.recalc & ID_RECALC_GEOMETRY) { - /* If geometry is tagged for update it means, that part of - * evaluated mesh are not valid anymore. In this case we can not - * have any "persistent" pointers to point to an invalid data. - * - * We restore object's data datablock to an original copy of - * that datablock. */ - object->data = mesh_orig; - - /* After that, immediately free the invalidated caches. */ - BKE_object_free_derived_caches(object); - } - else { - Mesh *mesh_eval = object->runtime.mesh_eval; - /* Do same thing as object update: override actual object data - * pointer with evaluated datablock. */ - object->data = mesh_eval; - /* Evaluated mesh simply copied edit_mesh pointer from - * original mesh during update, need to make sure no dead - * pointers are left behind. */ - mesh_eval->edit_mesh = mesh_orig->edit_mesh; - } - } - object->base_flag = base_flag; - object->base_local_view_bits = base_local_view_bits; - /* Restore modifier's runtime data. - * NOTE: Data of unused modifiers will be freed there. */ - restore_modifier_runtime_data(object); - restore_pose_channel_runtime_data(object); -} - -void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) -{ - LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { - BLI_assert(modifier_data->orig_modifier_data != NULL); - ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); - ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( - modifier_data_id); - if (runtime_data_iterator != modifier_runtime_data.end()) { - modifier_data->runtime = runtime_data_iterator->second; - runtime_data_iterator->second = NULL; - } - } - for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { - const ModifierDataBackupID modifier_data_id = value.first; - void *runtime = value.second; - if (value.second == NULL) { - continue; - } - const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); - BLI_assert(modifier_type_info != NULL); - modifier_type_info->freeRuntimeData(runtime); - } -} - -void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) -{ - if (object->pose != NULL) { - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is NULL in Edit mode. */ - if (pchan->orig_pchan != NULL) { - PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = - pose_channel_runtime_data.find(pchan->orig_pchan); - if (runtime_data_iterator != pose_channel_runtime_data.end()) { - pchan->runtime = runtime_data_iterator->second; - pose_channel_runtime_data.erase(runtime_data_iterator); - } - } - } - } - for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { - BKE_pose_channel_runtime_free(&value.second); - } -} - -/* Backup of movie clip runtime data. */ - -class MovieClipBackup { - public: - MovieClipBackup(); - - void reset(); - - void init_from_movieclip(MovieClip *movieclip); - void restore_to_movieclip(MovieClip *movieclip); - - struct anim *anim; - struct MovieClipCache *cache; -}; - -MovieClipBackup::MovieClipBackup() -{ - reset(); -} - -void MovieClipBackup::reset() -{ - anim = NULL; - cache = NULL; -} - -void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) -{ - anim = movieclip->anim; - cache = movieclip->cache; - /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written - * datablock is freed for re-allocation. */ - movieclip->anim = NULL; - movieclip->cache = NULL; -} - -void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) -{ - movieclip->anim = anim; - movieclip->cache = cache; - - reset(); -} - -class RuntimeBackup { - public: - RuntimeBackup() : drawdata_ptr(NULL) - { - drawdata_backup.first = drawdata_backup.last = NULL; - } - - /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */ - void init_from_id(ID *id); - - /* Restore fields to the given ID. */ - void restore_to_id(ID *id); - - SceneBackup scene_backup; - SoundBackup sound_backup; - ObjectRuntimeBackup object_backup; - DrawDataList drawdata_backup; - DrawDataList *drawdata_ptr; - MovieClipBackup movieclip_backup; -}; - -void RuntimeBackup::init_from_id(ID *id) -{ - if (!check_datablock_expanded(id)) { - return; - } - const ID_Type id_type = GS(id->name); - switch (id_type) { - case ID_OB: - object_backup.init_from_object(reinterpret_cast<Object *>(id)); - break; - case ID_SCE: - scene_backup.init_from_scene(reinterpret_cast<Scene *>(id)); - break; - case ID_SO: - sound_backup.init_from_sound(reinterpret_cast<bSound *>(id)); - break; - case ID_MC: - movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id)); - break; - default: - break; - } - /* Note that we never free GPU draw data from here since that's not - * safe for threading and draw data is likely to be re-used. */ - drawdata_ptr = DRW_drawdatalist_from_id(id); - if (drawdata_ptr != NULL) { - drawdata_backup = *drawdata_ptr; - drawdata_ptr->first = drawdata_ptr->last = NULL; - } -} - -void RuntimeBackup::restore_to_id(ID *id) -{ - const ID_Type id_type = GS(id->name); - switch (id_type) { - case ID_OB: - object_backup.restore_to_object(reinterpret_cast<Object *>(id)); - break; - case ID_SCE: - scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id)); - break; - case ID_SO: - sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id)); - break; - case ID_MC: - movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id)); - break; - default: - break; - } - if (drawdata_ptr != NULL) { - *drawdata_ptr = drawdata_backup; - } -} - -} // namespace - ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node) { const ID *id_orig = id_node->id_orig; @@ -1492,7 +954,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode if (!deg_copy_on_write_is_needed(id_orig)) { return id_cow; } - RuntimeBackup backup; + RuntimeBackup backup(depsgraph); backup.init_from_id(id_cow); deg_free_copy_on_write_datablock(id_cow); deg_expand_copy_on_write_datablock(depsgraph, id_node); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc new file mode 100644 index 00000000000..88390ab412f --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.cc @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup.h" + +#include "intern/eval/deg_eval_copy_on_write.h" + +#include "BLI_utildefines.h" + +#include "DRW_engine.h" + +namespace DEG { + +RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph) + : scene_backup(depsgraph), + sound_backup(depsgraph), + object_backup(depsgraph), + drawdata_ptr(NULL), + movieclip_backup(depsgraph) +{ + drawdata_backup.first = drawdata_backup.last = NULL; +} + +void RuntimeBackup::init_from_id(ID *id) +{ + if (!deg_copy_on_write_is_expanded(id)) { + return; + } + + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + object_backup.init_from_object(reinterpret_cast<Object *>(id)); + break; + case ID_SCE: + scene_backup.init_from_scene(reinterpret_cast<Scene *>(id)); + break; + case ID_SO: + sound_backup.init_from_sound(reinterpret_cast<bSound *>(id)); + break; + case ID_MC: + movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id)); + break; + default: + break; + } + + /* Note that we never free GPU draw data from here since that's not + * safe for threading and draw data is likely to be re-used. */ + drawdata_ptr = DRW_drawdatalist_from_id(id); + if (drawdata_ptr != NULL) { + drawdata_backup = *drawdata_ptr; + drawdata_ptr->first = drawdata_ptr->last = NULL; + } +} + +void RuntimeBackup::restore_to_id(ID *id) +{ + const ID_Type id_type = GS(id->name); + switch (id_type) { + case ID_OB: + object_backup.restore_to_object(reinterpret_cast<Object *>(id)); + break; + case ID_SCE: + scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id)); + break; + case ID_SO: + sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id)); + break; + case ID_MC: + movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id)); + break; + default: + break; + } + if (drawdata_ptr != NULL) { + *drawdata_ptr = drawdata_backup; + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h new file mode 100644 index 00000000000..31ae3164e37 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_ID.h" + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" +#include "intern/eval/deg_eval_runtime_backup_object.h" +#include "intern/eval/deg_eval_runtime_backup_scene.h" +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +namespace DEG { + +struct Depsgraph; + +class RuntimeBackup { + public: + explicit RuntimeBackup(const Depsgraph *depsgraph); + + /* NOTE: Will reset all runtime fields which has been backed up to NULL. */ + void init_from_id(ID *id); + + /* Restore fields to the given ID. */ + void restore_to_id(ID *id); + + SceneBackup scene_backup; + SoundBackup sound_backup; + ObjectRuntimeBackup object_backup; + DrawDataList drawdata_backup; + DrawDataList *drawdata_ptr; + MovieClipBackup movieclip_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc new file mode 100644 index 00000000000..c5744533083 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.cc @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" + +namespace DEG { + +ModifierDataBackupID::ModifierDataBackupID(const Depsgraph * /*depsgraph*/) + : ModifierDataBackupID(NULL, eModifierType_None) +{ +} + +ModifierDataBackupID::ModifierDataBackupID(ModifierData *modifier_data, ModifierType type) + : modifier_data(modifier_data), type(type) +{ +} + +bool ModifierDataBackupID::operator<(const ModifierDataBackupID &other) const +{ + if (modifier_data < other.modifier_data) { + return true; + } + if (modifier_data == other.modifier_data) { + return static_cast<int>(type) < static_cast<int>(other.type); + } + return false; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h new file mode 100644 index 00000000000..4b3d46126f3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_modifier.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "BKE_modifier.h" + +#include "intern/depsgraph_type.h" + +struct ModifierData; + +namespace DEG { + +struct Depsgraph; + +/* Identifier used to match modifiers to backup/restore their runtime data. + * Identification is happening using original modifier data pointer and the + * modifier type. + * It is not enough to only pointer, since it's possible to have a situation + * when modifier is removed and a new one added, and due to memory allocation + * policy they might have same pointer. + * By adding type into matching we are at least ensuring that modifier will not + * try to interpret runtime data created by another modifier type. */ +class ModifierDataBackupID { + public: + ModifierDataBackupID(const Depsgraph *depsgraph); + ModifierDataBackupID(ModifierData *modifier_data, ModifierType type); + + bool operator<(const ModifierDataBackupID &other) const; + + ModifierData *modifier_data; + ModifierType type; +}; + +/* Storage for backed up runtime modifier data. */ +typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc new file mode 100644 index 00000000000..54838475bbf --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.cc @@ -0,0 +1,61 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_movieclip.h" + +#include "DNA_movieclip_types.h" + +#include "BLI_utildefines.h" + +namespace DEG { + +MovieClipBackup::MovieClipBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void MovieClipBackup::reset() +{ + anim = NULL; + cache = NULL; +} + +void MovieClipBackup::init_from_movieclip(MovieClip *movieclip) +{ + anim = movieclip->anim; + cache = movieclip->cache; + /* Clear pointers stored in the movie clip, so they are not freed when copied-on-written + * datablock is freed for re-allocation. */ + movieclip->anim = NULL; + movieclip->cache = NULL; +} + +void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip) +{ + movieclip->anim = anim; + movieclip->cache = cache; + + reset(); +} + +} // namespace DEG diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h index 84820c3c564..a9d528a254c 100644 --- a/source/blender/editors/include/BIF_gl.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_movieclip.h @@ -13,32 +13,36 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * The Original Code is Copyright (C) 2019 Blender Foundation. * All rights reserved. - * os dependent include locations of gl.h */ /** \file - * \ingroup editorui + * \ingroup depsgraph */ -#ifndef __BIF_GL_H__ -#define __BIF_GL_H__ +#pragma once -#include "GPU_glew.h" -#include "BLI_utildefines.h" +struct anim; +struct MovieClip; +struct MovieClipCache; -/* hacking pointsize and linewidth */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -# define glPointSize(f) \ - glPointSize(U.pixelsize *_Generic((f), double : (float)(f), default : (f))) -# define glLineWidth(f) \ - glLineWidth(U.pixelsize *_Generic((f), double : (float)(f), default : (f))) -#else -# define glPointSize(f) glPointSize(U.pixelsize *(f)) -# define glLineWidth(f) glLineWidth(U.pixelsize *(f)) -#endif /* C11 */ +namespace DEG { -#define GLA_PIXEL_OFS 0.375f +struct Depsgraph; -#endif /* #ifdef __BIF_GL_H__ */ +/* Backup of movie clip runtime data. */ +class MovieClipBackup { + public: + MovieClipBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_movieclip(MovieClip *movieclip); + void restore_to_movieclip(MovieClip *movieclip); + + struct anim *anim; + struct MovieClipCache *cache; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc new file mode 100644 index 00000000000..a6a042f3e7b --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -0,0 +1,182 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_object.h" + +#include <cstring> + +#include "DNA_mesh_types.h" + +#include "BLI_listbase.h" + +#include "BKE_action.h" +#include "BKE_object.h" + +namespace DEG { + +ObjectRuntimeBackup::ObjectRuntimeBackup(const Depsgraph * /*depsgraph*/) + : base_flag(0), base_local_view_bits(0) +{ + /* TODO(sergey): Use something like BKE_object_runtime_reset(). */ + memset(&runtime, 0, sizeof(runtime)); +} + +void ObjectRuntimeBackup::init_from_object(Object *object) +{ + /* Store evaluated mesh and curve_cache, and make sure we don't free it. */ + Mesh *mesh_eval = object->runtime.mesh_eval; + runtime = object->runtime; + BKE_object_runtime_reset(object); + /* Keep bbox (for now at least). */ + object->runtime.bb = runtime.bb; + /* Object update will override actual object->data to an evaluated version. + * Need to make sure we don't have data set to evaluated one before free + * anything. */ + if (mesh_eval != NULL && object->data == mesh_eval) { + object->data = runtime.mesh_orig; + } + /* Make a backup of base flags. */ + base_flag = object->base_flag; + base_local_view_bits = object->base_local_view_bits; + /* Backup tuntime data of all modifiers. */ + backup_modifier_runtime_data(object); + /* Backup runtime data of all pose channels. */ + backup_pose_channel_runtime_data(object); +} + +inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data) +{ + return ModifierDataBackupID(modifier_data->orig_modifier_data, + static_cast<ModifierType>(modifier_data->type)); +} + +void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + if (modifier_data->runtime == NULL) { + continue; + } + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime)); + modifier_data->runtime = NULL; + } +} + +void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime; + BKE_pose_channel_runtime_reset(&pchan->runtime); + } + } + } +} + +void ObjectRuntimeBackup::restore_to_object(Object *object) +{ + Mesh *mesh_orig = object->runtime.mesh_orig; + BoundBox *bb = object->runtime.bb; + object->runtime = runtime; + object->runtime.mesh_orig = mesh_orig; + object->runtime.bb = bb; + if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) { + if (object->id.recalc & ID_RECALC_GEOMETRY) { + /* If geometry is tagged for update it means, that part of + * evaluated mesh are not valid anymore. In this case we can not + * have any "persistent" pointers to point to an invalid data. + * + * We restore object's data datablock to an original copy of + * that datablock. */ + object->data = mesh_orig; + + /* After that, immediately free the invalidated caches. */ + BKE_object_free_derived_caches(object); + } + else { + Mesh *mesh_eval = object->runtime.mesh_eval; + /* Do same thing as object update: override actual object data + * pointer with evaluated datablock. */ + object->data = mesh_eval; + /* Evaluated mesh simply copied edit_mesh pointer from + * original mesh during update, need to make sure no dead + * pointers are left behind. */ + mesh_eval->edit_mesh = mesh_orig->edit_mesh; + } + } + object->base_flag = base_flag; + object->base_local_view_bits = base_local_view_bits; + /* Restore modifier's runtime data. + * NOTE: Data of unused modifiers will be freed there. */ + restore_modifier_runtime_data(object); + restore_pose_channel_runtime_data(object); +} + +void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) +{ + LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) { + BLI_assert(modifier_data->orig_modifier_data != NULL); + ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data); + ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find( + modifier_data_id); + if (runtime_data_iterator != modifier_runtime_data.end()) { + modifier_data->runtime = runtime_data_iterator->second; + runtime_data_iterator->second = NULL; + } + } + for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) { + const ModifierDataBackupID modifier_data_id = value.first; + void *runtime = value.second; + if (value.second == NULL) { + continue; + } + const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); + BLI_assert(modifier_type_info != NULL); + modifier_type_info->freeRuntimeData(runtime); + } +} + +void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) +{ + if (object->pose != NULL) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + /* This is NULL in Edit mode. */ + if (pchan->orig_pchan != NULL) { + PoseChannelRuntimeDataBackup::iterator runtime_data_iterator = + pose_channel_runtime_data.find(pchan->orig_pchan); + if (runtime_data_iterator != pose_channel_runtime_data.end()) { + pchan->runtime = runtime_data_iterator->second; + pose_channel_runtime_data.erase(runtime_data_iterator); + } + } + } + } + for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) { + BKE_pose_channel_runtime_free(&value.second); + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h new file mode 100644 index 00000000000..e5c3d6a967a --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "DNA_object_types.h" + +#include "intern/eval/deg_eval_runtime_backup_modifier.h" +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +struct Object; + +namespace DEG { + +class ObjectRuntimeBackup { + public: + ObjectRuntimeBackup(const Depsgraph *depsgraph); + + /* Make a backup of object's evaluation runtime data, additionally + * make object to be safe for free without invalidating backed up + * pointers. */ + void init_from_object(Object *object); + void backup_modifier_runtime_data(Object *object); + void backup_pose_channel_runtime_data(Object *object); + + /* Restore all fields to the given object. */ + void restore_to_object(Object *object); + /* NOTE: Will free all runtime data which has not been restored. */ + void restore_modifier_runtime_data(Object *object); + void restore_pose_channel_runtime_data(Object *object); + + Object_Runtime runtime; + short base_flag; + unsigned short base_local_view_bits; + ModifierRuntimeDataBackup modifier_runtime_data; + PoseChannelRuntimeDataBackup pose_channel_runtime_data; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc new file mode 100644 index 00000000000..821cc21f359 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.cc @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_pose.h" + +namespace DEG { + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h new file mode 100644 index 00000000000..53a2c4c0784 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_pose.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/depsgraph_type.h" + +#include "DNA_action_types.h" + +struct bPoseChannel; + +namespace DEG { + +/* Storage for backed up pose channel runtime data. */ +typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc new file mode 100644 index 00000000000..a288fb6ab92 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.cc @@ -0,0 +1,82 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_scene.h" + +#include "DNA_scene_types.h" +#include "DNA_rigidbody_types.h" + +namespace DEG { + +SceneBackup::SceneBackup(const Depsgraph *depsgraph) : sequencer_backup(depsgraph) +{ + reset(); +} + +void SceneBackup::reset() +{ + sound_scene = NULL; + playback_handle = NULL; + sound_scrub_handle = NULL; + speaker_handles = NULL; + rigidbody_last_time = -1; +} + +void SceneBackup::init_from_scene(Scene *scene) +{ + sound_scene = scene->sound_scene; + playback_handle = scene->playback_handle; + sound_scrub_handle = scene->sound_scrub_handle; + speaker_handles = scene->speaker_handles; + + if (scene->rigidbody_world != NULL) { + rigidbody_last_time = scene->rigidbody_world->ltime; + } + + /* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock + * is freed for re-allocation. */ + scene->sound_scene = NULL; + scene->playback_handle = NULL; + scene->sound_scrub_handle = NULL; + scene->speaker_handles = NULL; + + sequencer_backup.init_from_scene(scene); +} + +void SceneBackup::restore_to_scene(Scene *scene) +{ + scene->sound_scene = sound_scene; + scene->playback_handle = playback_handle; + scene->sound_scrub_handle = sound_scrub_handle; + scene->speaker_handles = speaker_handles; + + if (scene->rigidbody_world != NULL) { + scene->rigidbody_world->ltime = rigidbody_last_time; + } + + sequencer_backup.restore_to_scene(scene); + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h new file mode 100644 index 00000000000..751bc4208d2 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_scene.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of scene runtime data. */ +class SceneBackup { + public: + SceneBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + /* Sound/audio related pointers of the scene itself. + * + * NOTE: Scene can not disappear after relations update, because otherwise the entire dependency + * graph will be gone. This means we don't need to compare original scene pointer, or worry about + * freeing those if they cant' be restored: we just copy them over to a new scene. */ + void *sound_scene; + void *playback_handle; + void *sound_scrub_handle; + void *speaker_handles; + float rigidbody_last_time; + + SequencerBackup sequencer_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc new file mode 100644 index 00000000000..0150281a4ef --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.cc @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" + +#include "DNA_sequence_types.h" + +namespace DEG { + +SequenceBackup::SequenceBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void SequenceBackup::reset() +{ + scene_sound = NULL; +} + +void SequenceBackup::init_from_sequence(Sequence *sequence) +{ + scene_sound = sequence->scene_sound; + + sequence->scene_sound = NULL; +} + +void SequenceBackup::restore_to_sequence(Sequence *sequence) +{ + sequence->scene_sound = scene_sound; + reset(); +} + +bool SequenceBackup::isEmpty() const +{ + return (scene_sound == NULL); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h new file mode 100644 index 00000000000..8a762a2785e --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequence.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct Sequence; + +namespace DEG { + +struct Depsgraph; + +/* Backup of a single strip. */ +class SequenceBackup { + public: + SequenceBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sequence(Sequence *sequence); + void restore_to_sequence(Sequence *sequence); + + bool isEmpty() const; + + void *scene_sound; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc new file mode 100644 index 00000000000..08c2697aab3 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.cc @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sequencer.h" + +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "BKE_sequencer.h" +#include "BKE_sound.h" + +namespace DEG { + +SequencerBackup::SequencerBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph) +{ +} + +void SequencerBackup::init_from_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequenceBackup sequence_backup(depsgraph); + sequence_backup.init_from_sequence(sequence); + if (!sequence_backup.isEmpty()) { + sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup)); + } + } + SEQ_END; +} + +void SequencerBackup::restore_to_scene(Scene *scene) +{ + Sequence *sequence; + SEQ_BEGIN (scene->ed, sequence) { + SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence); + if (it == sequences_backup.end()) { + continue; + } + SequenceBackup &sequence_backup = it->second; + sequence_backup.restore_to_sequence(sequence); + } + SEQ_END; + /* Cleanup audio while the scene is still known. */ + for (SequencesBackupMap::value_type &it : sequences_backup) { + SequenceBackup &sequence_backup = it.second; + if (sequence_backup.scene_sound != NULL) { + BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound); + } + } +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h new file mode 100644 index 00000000000..57b533a1b84 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sequencer.h @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "intern/eval/deg_eval_runtime_backup_sequence.h" +#include "intern/depsgraph_type.h" + +struct Scene; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sequencer strips runtime data. */ +class SequencerBackup { + public: + SequencerBackup(const Depsgraph *depsgraph); + + void init_from_scene(Scene *scene); + void restore_to_scene(Scene *scene); + + const Depsgraph *depsgraph; + + typedef map<Sequence *, SequenceBackup> SequencesBackupMap; + SequencesBackupMap sequences_backup; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc new file mode 100644 index 00000000000..0c54032e32c --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.cc @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#include "intern/eval/deg_eval_runtime_backup_sound.h" + +#include "BLI_utildefines.h" + +#include "DNA_sound_types.h" + +namespace DEG { + +SoundBackup::SoundBackup(const Depsgraph * /*depsgraph*/) +{ + reset(); +} + +void SoundBackup::reset() +{ + cache = NULL; + waveform = NULL; + playback_handle = NULL; +} + +void SoundBackup::init_from_sound(bSound *sound) +{ + cache = sound->cache; + waveform = sound->waveform; + playback_handle = sound->playback_handle; + + sound->cache = NULL; + sound->waveform = NULL; + sound->playback_handle = NULL; +} + +void SoundBackup::restore_to_sound(bSound *sound) +{ + sound->cache = cache; + sound->waveform = waveform; + sound->playback_handle = playback_handle; + + reset(); +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h new file mode 100644 index 00000000000..87783146701 --- /dev/null +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_sound.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +struct bSound; + +namespace DEG { + +struct Depsgraph; + +/* Backup of sound datablocks runtime data. */ +class SoundBackup { + public: + SoundBackup(const Depsgraph *depsgraph); + + void reset(); + + void init_from_sound(bSound *sound); + void restore_to_sound(bSound *sound); + + void *cache; + void *waveform; + void *playback_handle; +}; + +} // namespace DEG diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 9527c6c9612..7d996f3c535 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -85,6 +85,7 @@ set(SRC engines/eevee/eevee_motion_blur.c engines/eevee/eevee_occlusion.c engines/eevee/eevee_render.c + engines/eevee/eevee_renderpasses.c engines/eevee/eevee_sampling.c engines/eevee/eevee_screen_raytrace.c engines/eevee/eevee_shaders.c @@ -224,6 +225,7 @@ data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC) +data_to_c_simple(engines/eevee/shaders/renderpass_postprocess_frag.glsl SRC) data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/ssr_lib.glsl SRC) data_to_c_simple(engines/eevee/shaders/update_noise_frag.glsl SRC) diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index c5ee4e12b40..5edfadd7f41 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -23,6 +23,10 @@ #ifndef __DRW_ENGINE_H__ #define __DRW_ENGINE_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "BLI_sys_types.h" /* for bool */ struct ARegion; @@ -168,4 +172,8 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat); struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id); void DRW_drawdata_free(struct ID *id); +#ifdef __cplusplus +} +#endif + #endif /* __DRW_ENGINE_H__ */ diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index d59d1f56e92..824ea69ea73 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -136,8 +136,6 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; const float *viewport_size = DRW_viewport_size_get(); int size_fs[2] = {(int)viewport_size[0], (int)viewport_size[1]}; @@ -172,7 +170,7 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_subsurface_init(sldata, vedata); /* Force normal buffer creation. */ - if (DRW_state_is_image_render() && !minimal && (view_layer->passflag & SCE_PASS_NORMAL) != 0) { + if (!minimal && (stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { effects->enabled_effects |= EFFECT_NORMAL_BUFFER; } diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a1096390bce..603a4787dba 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -27,6 +27,8 @@ #include "BKE_object.h" #include "BKE_global.h" /* for G.debug_value */ +#include "DEG_depsgraph_query.h" + #include "DNA_world_types.h" #include "eevee_private.h" @@ -81,7 +83,9 @@ static void eevee_engine_init(void *ved) &sldata->common_data); } - /* EEVEE_effects_init needs to go first for TAA */ + /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. + * `EEVEE_effects_init` needs to go second for TAA. */ + EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, camera, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -147,6 +151,8 @@ static void eevee_cache_finish(void *vedata) { EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); EEVEE_PrivateData *g_data = ((EEVEE_Data *)vedata)->stl->g_data; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); EEVEE_volumes_cache_finish(sldata, vedata); EEVEE_materials_cache_finish(sldata, vedata); @@ -156,6 +162,14 @@ static void eevee_cache_finish(void *vedata) EEVEE_effects_draw_init(sldata, vedata); EEVEE_volumes_draw_init(sldata, vedata); + uint tot_samples = scene_eval->eevee.taa_render_samples; + if (tot_samples == 0) { + /* use a high number of samples so the outputs accum buffers + * will have the highest possible precision */ + tot_samples = 1024; + } + EEVEE_renderpasses_output_init(sldata, vedata, tot_samples); + /* Restart taa if a shader has finish compiling. */ /* HACK We should use notification of some sort from the compilation job instead. */ if (g_data->queued_shaders_count != g_data->queued_shaders_count_prev) { @@ -306,6 +320,8 @@ static void eevee_draw_background(void *vedata) EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); + EEVEE_renderpasses_output_accumulate(sldata, vedata); + DRW_view_set_active(NULL); if (DRW_state_is_image_render() && (stl->effects->enabled_effects & EFFECT_SSR) && @@ -319,14 +335,19 @@ static void eevee_draw_background(void *vedata) } } - /* Tonemapping and transfer result to default framebuffer. */ - bool use_render_settings = stl->g_data->use_color_render_settings; + if ((stl->g_data->render_passes & SCE_PASS_COMBINED) > 0) { + /* Tonemapping and transfer result to default framebuffer. */ + bool use_render_settings = stl->g_data->use_color_render_settings; - GPU_framebuffer_bind(dfbl->default_fb); - DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(stl->effects->final_tx, true, use_render_settings); - /* Draw checkerboard with alpha under. */ - EEVEE_draw_alpha_checker(vedata); + /* Draw checkerboard with alpha under. */ + EEVEE_draw_alpha_checker(vedata); + } + else { + EEVEE_renderpasses_draw(sldata, vedata); + } /* Debug : Output buffer to view. */ switch (G.debug_value) { @@ -483,6 +504,7 @@ static void eevee_engine_free(void) EEVEE_screen_raytrace_free(); EEVEE_subsurface_free(); EEVEE_volumes_free(); + EEVEE_renderpasses_free(); } static const DrawEngineDataSize eevee_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data); diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c index 7209651a1d4..c9b56a6d551 100644 --- a/source/blender/draw/engines/eevee/eevee_mist.c +++ b/source/blender/draw/engines/eevee/eevee_mist.c @@ -49,6 +49,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_TextureList *txl = vedata->txl; EEVEE_StorageList *stl = vedata->stl; EEVEE_PassList *psl = vedata->psl; + EEVEE_EffectsInfo *effects = stl->effects; EEVEE_PrivateData *g_data = stl->g_data; Scene *scene = draw_ctx->scene; @@ -74,8 +75,10 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->mist_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->mist_accum_fb); - GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->mist_accum_fb); + GPU_framebuffer_clear_color(fbl->mist_accum_fb, clear); + } /* Mist settings. */ if (scene && scene->world) { diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index 48e9b5bcc13..6ba518b3a28 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -131,7 +131,7 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) return 0; } -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -143,18 +143,22 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); if (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) { + const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_R32F : GPU_R16F; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; /* Should be enough precision for many samples. */ - DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, GPU_R32F, 0); + DRW_texture_ensure_fullscreen_2d(&txl->ao_accum, texture_format, 0); GPU_framebuffer_ensure_config(&fbl->ao_accum_fb, {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->ao_accum)}); /* Clear texture. */ - GPU_framebuffer_bind(fbl->ao_accum_fb); - GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + GPU_framebuffer_bind(fbl->ao_accum_fb); + GPU_framebuffer_clear_color(fbl->ao_accum_fb, clear); + } /* Accumulation pass */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD; diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 7d02aacfac7..97bde2e5f2e 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -271,6 +271,7 @@ typedef struct EEVEE_PassList { struct DRWPass *update_noise_pass; struct DRWPass *lookdev_glossy_pass; struct DRWPass *lookdev_diffuse_pass; + struct DRWPass *renderpass_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -295,6 +296,7 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; struct GPUFrameBuffer *mist_accum_fb; + struct GPUFrameBuffer *renderpass_fb; struct GPUFrameBuffer *ao_accum_fb; struct GPUFrameBuffer *velocity_resolve_fb; @@ -341,6 +343,8 @@ typedef struct EEVEE_TextureList { struct GPUTexture *maxzbuffer; + struct GPUTexture *renderpass; + struct GPUTexture *color; /* R16_G16_B16 */ struct GPUTexture *color_double_buffer; struct GPUTexture *depth_double_buffer; @@ -799,6 +803,10 @@ typedef struct EEVEE_PrivateData { float studiolight_glossy_clamp; float studiolight_filter_quality; + /* Renderpasses */ + /* Bitmask containing the active render_passes */ + eScenePassType render_passes; + /** For rendering shadows. */ struct DRWView *cube_views[6]; /** For rendering probes. */ @@ -988,7 +996,9 @@ void EEVEE_bloom_free(void); /* eevee_occlusion.c */ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_occlusion_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, @@ -1009,7 +1019,9 @@ void EEVEE_screen_raytrace_free(void); void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_draw_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint sss_id, @@ -1035,6 +1047,19 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_mist_free(void); +/* eevee_renderpasses.c */ +void EEVEE_renderpasses_init(EEVEE_Data *vedata); +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples); +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type); +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_renderpasses_free(void); +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata); + /* eevee_temporal_sampling.c */ void EEVEE_temporal_sampling_reset(EEVEE_Data *vedata); int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 75e837f140b..ba5704f14e5 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -130,7 +130,9 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph * DRW_view_default_set(view); DRW_view_set_active(view); - /* EEVEE_effects_init needs to go first for TAA */ + /* `EEVEE_renderpasses_init` will set the active render passes used by `EEVEE_effects_init`. + * `EEVEE_effects_init` needs to go second for TAA. */ + EEVEE_renderpasses_init(vedata); EEVEE_effects_init(sldata, vedata, ob_camera_eval, false); EEVEE_materials_init(sldata, stl, fbl); EEVEE_shadows_init(sldata); @@ -202,79 +204,60 @@ void EEVEE_render_cache(void *vedata, } } -static void eevee_render_result_combined(RenderLayer *rl, - const char *viewname, - const rcti *rect, - EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) +static void eevee_render_color_result(RenderLayer *rl, + const char *viewname, + const rcti *rect, + const char *render_pass_name, + int num_channels, + GPUFrameBuffer *framebuffer, + EEVEE_Data *vedata) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); - - GPU_framebuffer_bind(vedata->stl->effects->final_fb); - GPU_framebuffer_read_color(vedata->stl->effects->final_fb, + RenderPass *rp = RE_pass_find_by_name(rl, render_pass_name, viewname); + GPU_framebuffer_bind(framebuffer); + GPU_framebuffer_read_color(framebuffer, vedata->stl->g_data->overscan_pixels + rect->xmin, vedata->stl->g_data->overscan_pixels + rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - 4, + num_channels, 0, rp->rect); } +static void eevee_render_result_combined(RenderLayer *rl, + const char *viewname, + const rcti *rect, + EEVEE_Data *vedata, + EEVEE_ViewLayerData *UNUSED(sldata)) +{ + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_COMBINED, 4, vedata->stl->effects->final_fb, vedata); +} + static void eevee_render_result_subsurface(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->sss_accum_fb == NULL) { /* SSS is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_COLOR, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_COLOR) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_COLOR); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_COLOR, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_SUBSURFACE_DIRECT, viewname); - - GPU_framebuffer_bind(vedata->fbl->sss_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_DIRECT) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_SUBSURFACE_DIRECT); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_SUBSURFACE_DIRECT, 3, vedata->fbl->renderpass_fb, vedata); } - if ((view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { + if ((vedata->stl->g_data->render_passes & SCE_PASS_SUBSURFACE_INDIRECT) != 0) { /* Do nothing as all the lighting is in the direct pass. * TODO : Separate Direct from indirect lighting. */ } @@ -284,54 +267,19 @@ static void eevee_render_result_normal(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata)) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_NORMAL) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_NORMAL, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_color(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 1, - rp->rect); - - float viewinv[4][4]; - DRW_view_viewmat_get(NULL, viewinv, true); - - /* Convert Eevee encoded normals to Blender normals. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - if (rp->rect[i] == 0.0f && rp->rect[i + 1] == 0.0f) { - /* If normal is not correct then do not produce NANs. */ - continue; - } - - float fenc[2]; - fenc[0] = rp->rect[i + 0] * 4.0f - 2.0f; - fenc[1] = rp->rect[i + 1] * 4.0f - 2.0f; - - float f = dot_v2v2(fenc, fenc); - float g = sqrtf(1.0f - f / 4.0f); - - rp->rect[i + 0] = fenc[0] * g; - rp->rect[i + 1] = fenc[1] * g; - rp->rect[i + 2] = 1.0f - f / 2.0f; - - mul_mat3_m4_v3(viewinv, &rp->rect[i]); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_NORMAL) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_NORMAL); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_NORMAL, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -341,49 +289,17 @@ static void eevee_render_result_z(RenderLayer *rl, EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; - EEVEE_StorageList *stl = vedata->stl; - EEVEE_PrivateData *g_data = stl->g_data; + const int current_sample = vedata->stl->effects->taa_current_sample; /* Only read the center texel. */ - if (stl->effects->taa_current_sample > 1) { + if (current_sample > 1) { return; } - if ((view_layer->passflag & SCE_PASS_Z) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); - - GPU_framebuffer_bind(vedata->fbl->main_fb); - GPU_framebuffer_read_depth(vedata->fbl->main_fb, - g_data->overscan_pixels + rect->xmin, - g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - rp->rect); - - bool is_persp = DRW_view_is_persp_get(NULL); - - float winmat[4][4]; - DRW_view_winmat_get(NULL, winmat, false); - - /* Convert ogl depth [0..1] to view Z [near..far] */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - if (rp->rect[i] == 1.0f) { - rp->rect[i] = 1e10f; /* Background */ - } - else { - if (is_persp) { - rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; - rp->rect[i] = winmat[3][2] / (rp->rect[i] + winmat[2][2]); - } - else { - rp->rect[i] = -common_data->view_vecs[0][2] + - rp->rect[i] * -common_data->view_vecs[1][2]; - } - } - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_Z) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_Z); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_Z, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -391,29 +307,12 @@ static void eevee_render_result_mist(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_MIST, viewname); - - GPU_framebuffer_bind(vedata->fbl->mist_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 1, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty; i++) { - rp->rect[i] /= (float)render_samples; - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_MIST); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_MIST, 1, vedata->fbl->renderpass_fb, vedata); } } @@ -421,35 +320,17 @@ static void eevee_render_result_occlusion(RenderLayer *rl, const char *viewname, const rcti *rect, EEVEE_Data *vedata, - EEVEE_ViewLayerData *UNUSED(sldata), - int render_samples) + EEVEE_ViewLayerData *sldata) { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - if (vedata->fbl->ao_accum_fb == NULL) { /* AO is not enabled. */ return; } - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_AO, viewname); - - GPU_framebuffer_bind(vedata->fbl->ao_accum_fb); - GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb, - vedata->stl->g_data->overscan_pixels + rect->xmin, - vedata->stl->g_data->overscan_pixels + rect->ymin, - BLI_rcti_size_x(rect), - BLI_rcti_size_y(rect), - 3, - 0, - rp->rect); - - /* This is the accumulated color. Divide by the number of samples. */ - for (int i = 0; i < rp->rectx * rp->recty * 3; i += 3) { - rp->rect[i] = rp->rect[i + 1] = rp->rect[i + 2] = min_ff( - 1.0f, rp->rect[i] / (float)render_samples); - } + if ((vedata->stl->g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_renderpasses_postprocess(sldata, vedata, SCE_PASS_AO); + eevee_render_color_result( + rl, viewname, rect, RE_PASSNAME_AO, 3, vedata->fbl->renderpass_fb, vedata); } } @@ -488,7 +369,6 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl { const DRWContextState *draw_ctx = DRW_context_state_get(); const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); - ViewLayer *view_layer = draw_ctx->view_layer; const char *viewname = RE_GetActiveRenderView(engine->re); EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; @@ -517,31 +397,20 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl GPU_framebuffer_bind(fbl->main_fb); DRW_hair_update(); - if ((view_layer->passflag & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | - SCE_PASS_SUBSURFACE_INDIRECT)) != 0) { - EEVEE_subsurface_output_init(sldata, vedata); - } - - if ((view_layer->passflag & SCE_PASS_MIST) != 0) { - EEVEE_mist_output_init(sldata, vedata); - } - - if ((view_layer->passflag & SCE_PASS_AO) != 0) { - EEVEE_occlusion_output_init(sldata, vedata); - } - uint tot_sample = scene_eval->eevee.taa_render_samples; uint render_samples = 0; - if (RE_engine_test_break(engine)) { - return; - } - /* SSR needs one iteration to start properly. */ if (stl->effects->enabled_effects & EFFECT_SSR) { tot_sample += 1; } + EEVEE_renderpasses_output_init(sldata, vedata, tot_sample); + + if (RE_engine_test_break(engine)) { + return; + } + while (render_samples < tot_sample && !RE_engine_test_break(engine)) { float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; float clear_depth = 1.0f; @@ -616,16 +485,12 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl DRW_draw_pass(psl->refract_depth_pass); DRW_draw_pass(psl->refract_depth_pass_cull); DRW_draw_pass(psl->refract_pass); - /* Subsurface output */ - EEVEE_subsurface_output_accumulate(sldata, vedata); - /* Occlusion output */ - EEVEE_occlusion_output_accumulate(sldata, vedata); /* Result NORMAL */ eevee_render_result_normal(rl, viewname, rect, vedata, sldata); /* Volumetrics Resolve Opaque */ EEVEE_volumes_resolve(sldata, vedata); - /* Mist output */ - EEVEE_mist_output_accumulate(sldata, vedata); + /* Subsurface output, Occlusion output, Mist output */ + EEVEE_renderpasses_output_accumulate(sldata, vedata); /* Transparent */ GPU_framebuffer_texture_attach(fbl->main_color_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(fbl->main_color_fb); @@ -644,9 +509,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl } eevee_render_result_combined(rl, viewname, rect, vedata, sldata); - eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples); - eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples); + eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata); + eevee_render_result_mist(rl, viewname, rect, vedata, sldata); + eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata); /* Restore original viewport size. */ DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]}); diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c new file mode 100644 index 00000000000..927ff70a52b --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c @@ -0,0 +1,278 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BLI_string_utils.h" + +#include "DEG_depsgraph_query.h" + +#include "eevee_private.h" + +extern char datatoc_common_view_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_renderpass_postprocess_frag_glsl[]; + +static struct { + struct GPUShader *postprocess_sh; +} e_data = {NULL}; /* Engine data */ + +/* bitmask containing all renderpasses that need post-processing */ +#define EEVEE_RENDERPASSES_WITH_POST_PROCESSING \ + (SCE_PASS_Z | SCE_PASS_MIST | SCE_PASS_NORMAL | SCE_PASS_AO | SCE_PASS_SUBSURFACE_COLOR | \ + SCE_PASS_SUBSURFACE_DIRECT) + +#define EEVEE_RENDERPASSES_SUBSURFACE \ + (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_INDIRECT) + +#define EEVEE_RENDERPASSES_ALL (EEVEE_RENDERPASSES_WITH_POST_PROCESSING | SCE_PASS_COMBINED) + +#define EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE (SCE_PASS_Z | SCE_PASS_NORMAL) + +#define EEVEE_RENDERPASSES_COLOR_PASS (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT) + +bool EEVEE_renderpasses_only_first_sample_pass_active(EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + return (g_data->render_passes & ~EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) == 0; +} + +void EEVEE_renderpasses_init(EEVEE_Data *vedata) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + ViewLayer *view_layer = draw_ctx->view_layer; + View3D *v3d = draw_ctx->v3d; + + if (v3d) { + g_data->render_passes = v3d->shading.render_pass; + } + else { + g_data->render_passes = (view_layer->passflag & EEVEE_RENDERPASSES_ALL) | SCE_PASS_COMBINED; + } +} + +void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + uint tot_samples) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + + const bool needs_post_processing = (g_data->render_passes & + EEVEE_RENDERPASSES_WITH_POST_PROCESSING) > 0; + if (needs_post_processing) { + if (e_data.postprocess_sh == NULL) { + char *frag_str = BLI_string_joinN(datatoc_common_view_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_renderpass_postprocess_frag_glsl); + e_data.postprocess_sh = DRW_shader_create_fullscreen(frag_str, NULL); + MEM_freeN(frag_str); + } + + /* Create FrameBuffer. */ + + /* Should be enough to store the data needs for a single pass. + * Some passes will use less, but it is only relevant for final renderings and + * when renderpasses other than `SCE_PASS_COMBINED` are requested */ + DRW_texture_ensure_fullscreen_2d(&txl->renderpass, GPU_RGBA16F, 0); + GPU_framebuffer_ensure_config(&fbl->renderpass_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->renderpass)}); + + if ((g_data->render_passes & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_init(sldata, vedata, tot_samples); + } + + if ((g_data->render_passes & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_init(sldata, vedata); + } + + if ((g_data->render_passes & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_init(sldata, vedata, tot_samples); + } + + /* Create Pass. */ + DRW_PASS_CREATE(psl->renderpass_pass, DRW_STATE_WRITE_COLOR); + } + else { + /* Free unneeded memory */ + DRW_TEXTURE_FREE_SAFE(txl->renderpass); + GPU_FRAMEBUFFER_FREE_SAFE(fbl->renderpass_fb); + psl->renderpass_pass = NULL; + } +} + +/* Postprocess data to construct a specific renderpass + * + * This method will create a shading group to perform the post-processing for the given + * `renderpass_type`. The post-processing will be done and the result will be stored in the + * `vedata->txl->renderpass` texture. + * + * Only invoke this function for passes that need post-processing. + * + * After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */ +void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata, + EEVEE_Data *vedata, + eScenePassType renderpass_type) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + const int current_sample = effects->taa_current_sample; + + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.postprocess_sh, psl->renderpass_pass); + DRW_shgroup_uniform_int_copy(shgrp, "renderpassType", renderpass_type); + + switch (renderpass_type) { + case SCE_PASS_Z: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); + break; + } + + case SCE_PASS_AO: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->ao_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_NORMAL: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &effects->ssr_normal_input); + DRW_shgroup_uniform_texture_ref(shgrp, "depthBuffer", &dtxl->depth); + break; + } + + case SCE_PASS_MIST: { + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->mist_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_DIRECT: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_dir_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + case SCE_PASS_SUBSURFACE_COLOR: { + DRW_shgroup_uniform_texture_ref(shgrp, "inputBuffer", &txl->sss_col_accum); + DRW_shgroup_uniform_int_copy(shgrp, "currentSample", current_sample); + break; + } + + default: { + break; + } + } + + DRW_shgroup_call(shgrp, DRW_cache_fullscreen_quad_get(), NULL); + + /* only draw the shading group that has been added. This function can be called multiple times + * and the pass still hold the previous shading groups.*/ + GPU_framebuffer_bind(fbl->renderpass_fb); + DRW_draw_pass_subset(psl->renderpass_pass, shgrp, shgrp); +} + +void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + eScenePassType render_pass = stl->g_data->render_passes; + + if ((render_pass & SCE_PASS_MIST) != 0) { + EEVEE_mist_output_accumulate(sldata, vedata); + } + if ((effects->enabled_effects & EFFECT_SSS) && + (render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0) { + EEVEE_subsurface_output_accumulate(sldata, vedata); + } + if ((render_pass & SCE_PASS_AO) != 0) { + EEVEE_occlusion_output_accumulate(sldata, vedata); + } +} + +void EEVEE_renderpasses_draw(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +{ + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_EffectsInfo *effects = stl->effects; + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + eScenePassType render_pass = stl->g_data->render_passes; + const DRWContextState *draw_ctx = DRW_context_state_get(); + const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph); + + bool is_valid = (render_pass & EEVEE_RENDERPASSES_ALL) > 0; + bool needs_color_transfer = (render_pass & EEVEE_RENDERPASSES_COLOR_PASS) > 0 && + DRW_state_is_opengl_render(); + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & EEVEE_RENDERPASSES_SUBSURFACE) != 0 && + (effects->enabled_effects & EFFECT_SSS) == 0) { + is_valid = false; + } + + /* When SSS isn't available, but the pass is requested, we mark it as invalid */ + if ((render_pass & SCE_PASS_AO) != 0 && (scene_eval->eevee.flag & SCE_EEVEE_GTAO_ENABLED) == 0) { + is_valid = false; + } + + const int current_sample = stl->effects->taa_current_sample; + const int total_samples = stl->effects->taa_total_sample; + if ((render_pass & EEVEE_RENDERPASSES_POST_PROCESS_ON_FIRST_SAMPLE) && + (current_sample > 1 && total_samples != 1)) { + return; + } + + if (is_valid) { + EEVEE_renderpasses_postprocess(sldata, vedata, render_pass); + GPU_framebuffer_bind(dfbl->default_fb); + DRW_transform_to_display(txl->renderpass, needs_color_transfer, false); + } + else { + /* Draw state is not valid for this pass, clear the buffer */ + static float clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(dfbl->default_fb); + GPU_framebuffer_clear_color(dfbl->default_fb, clear_color); + } + GPU_framebuffer_bind(fbl->main_fb); +} + +void EEVEE_renderpasses_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.postprocess_sh); +} diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 8376b8c67b8..e94fc903694 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -156,7 +156,9 @@ static void set_shgrp_stencil(void *UNUSED(userData), DRWShadingGroup *shgrp) DRW_shgroup_stencil_mask(shgrp, 255); } -void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), + EEVEE_Data *vedata, + uint tot_samples) { EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -164,8 +166,10 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat EEVEE_EffectsInfo *effects = stl->effects; if (effects->enabled_effects & EFFECT_SSS) { - DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, GPU_RGBA16F, 0); - DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, GPU_RGBA16F, 0); + const eGPUTextureFormat texture_format_light = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F; + const eGPUTextureFormat texture_format_color = (tot_samples > 512) ? GPU_RGBA32F : GPU_RGBA16F; + DRW_texture_ensure_fullscreen_2d(&txl->sss_dir_accum, texture_format_light, 0); + DRW_texture_ensure_fullscreen_2d(&txl->sss_col_accum, texture_format_color, 0); GPUTexture *stencil_tex = effects->sss_stencil; @@ -183,9 +187,11 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat GPU_ATTACHMENT_TEXTURE(txl->sss_col_accum)}); /* Clear texture. */ - float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - GPU_framebuffer_bind(fbl->sss_accum_fb); - GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + if (DRW_state_is_image_render() || effects->taa_current_sample == 1) { + float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + GPU_framebuffer_bind(fbl->sss_accum_fb); + GPU_framebuffer_clear_color(fbl->sss_accum_fb, clear); + } /* Make the opaque refraction pass mask the sss. */ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES | @@ -253,7 +259,8 @@ void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata, DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call(grp, quad, NULL); - if (DRW_state_is_image_render()) { + if ((stl->g_data->render_passes & (SCE_PASS_SUBSURFACE_COLOR | SCE_PASS_SUBSURFACE_DIRECT)) != + 0) { grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_accum_ps); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index e5f89aab4d1..0f0b4a3e0a9 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -234,7 +234,9 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data view_is_valid = view_is_valid && (ED_screen_animation_no_scrub(wm) == NULL); } - effects->taa_total_sample = scene_eval->eevee.taa_samples; + effects->taa_total_sample = EEVEE_renderpasses_only_first_sample_pass_active(vedata) ? + 1 : + scene_eval->eevee.taa_samples; MAX2(effects->taa_total_sample, 0); DRW_view_persmat_get(NULL, persmat, false); diff --git a/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl new file mode 100644 index 00000000000..5a738d0f130 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/renderpass_postprocess_frag.glsl @@ -0,0 +1,64 @@ +#define SCE_PASS_Z (1 << 1) +#define SCE_PASS_AO (1 << 6) +#define SCE_PASS_NORMAL (1 << 8) +#define SCE_PASS_MIST (1 << 14) +#define SCE_PASS_SUBSURFACE_DIRECT (1 << 28) +#define SCE_PASS_SUBSURFACE_COLOR (1 << 30) + +#define ACCUMULATED_COLOR_PASSES (SCE_PASS_SUBSURFACE_DIRECT | SCE_PASS_SUBSURFACE_COLOR) +#define ACCUMULATED_VALUE_PASSES (SCE_PASS_MIST) +uniform int renderpassType; +uniform int currentSample; +uniform sampler2D inputBuffer; + +out vec4 fragColor; + +void main() +{ + ivec2 texel = ivec2(gl_FragCoord.xy); + + if (renderpassType == SCE_PASS_Z) { + float depth = texelFetch(depthBuffer, texel, 0).r; + if (depth == 1.0f) { + depth = 1e10; + } + else { + depth = -get_view_z_from_depth(depth); + } + fragColor.r = depth; + } + + else if (renderpassType == SCE_PASS_AO) { + float ao_accum = texelFetch(inputBuffer, texel, 0).r; + fragColor = vec4(vec3(min(1.0, ao_accum / currentSample)), 1.0); + } + + else if (renderpassType == SCE_PASS_NORMAL) { + float depth = texelFetch(depthBuffer, texel, 0).r; + vec2 encoded_normal = texelFetch(inputBuffer, texel, 0).rg; + /* decode the normals only when they are valid. otherwise the result buffer will be filled with + * NaN's */ + if (depth != 1.0 && any(notEqual(encoded_normal, vec2(0.0)))) { + vec3 decoded_normal = normal_decode(texelFetch(inputBuffer, texel, 0).rg, vec3(0.0)); + vec3 world_normal = mat3(ViewMatrixInverse) * decoded_normal; + fragColor = vec4(world_normal, 1.0); + } + else { + fragColor = vec4(0.0, 0.0, 0.0, 1.0); + } + } + + else if ((renderpassType & ACCUMULATED_VALUE_PASSES) != 0) { + float accumulated_value = texelFetch(inputBuffer, texel, 0).r; + fragColor = vec4(vec3(accumulated_value / currentSample), 1.0); + } + + else if ((renderpassType & ACCUMULATED_COLOR_PASSES) != 0) { + vec3 accumulated_color = texelFetch(inputBuffer, texel, 0).rgb; + fragColor = vec4(accumulated_color / currentSample, 1.0); + } + + else { + fragColor = vec4(1.0, 0.0, 1.0, 1.0); + } +}
\ No newline at end of file diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 48912a914dc..cd96b21280f 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -1816,7 +1816,6 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, for (int i = 0; i < cache->grp_used; i++) { elm = &cache->grp_cache[i]; array_elm = &cache_ob->shgrp_array[idx]; - const float scale = cache_ob->scale; /* Limit stencil id */ if (stencil_id > 255) { @@ -1858,6 +1857,8 @@ static void gpencil_shgroups_create(GPENCIL_e_data *e_data, break; } + const float scale = (!cache_ob->is_dup_ob) ? mat4_to_scale(gpf->runtime.parent_obmat) : + cache_ob->scale; float(*obmat)[4] = (!cache_ob->is_dup_ob) ? gpf->runtime.parent_obmat : cache_ob->obmat; switch (elm->type) { case eGpencilBatchGroupType_Stroke: { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl index 0c290260b20..8285541e0b4 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl @@ -51,6 +51,7 @@ uniform float fade_ob_factor; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 in vec4 finalColor; in vec2 texCoord_interp; @@ -210,7 +211,8 @@ void main() /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { fragColor = wire_color; } if (viewport_xray == 1) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl index 87963c66858..33d7d714231 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_vert.glsl @@ -26,6 +26,7 @@ out vec4 finalprev_pos; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -52,7 +53,8 @@ void main() /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { finalColor = wire_color; } if (viewport_xray == 1) { diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl index 582b9a7f249..8df08f0bf68 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_vert.glsl @@ -24,6 +24,7 @@ out vec2 finaluvdata; #define V3D_SHADING_MATERIAL_COLOR 0 #define V3D_SHADING_TEXTURE_COLOR 3 +#define V3D_SHADING_VERTEX_COLOR 5 float defaultpixsize = pixsize * (1000.0 / pixfactor); @@ -49,7 +50,8 @@ void main(void) /* for solid override color */ if (shading_type[0] == OB_SOLID) { if ((shading_type[1] != V3D_SHADING_MATERIAL_COLOR) && - (shading_type[1] != V3D_SHADING_TEXTURE_COLOR)) { + (shading_type[1] != V3D_SHADING_TEXTURE_COLOR) && + (shading_type[1] != V3D_SHADING_VERTEX_COLOR)) { finalColor = wire_color; } if (viewport_xray == 1) { diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 3e63f05ca64..42375f29d4d 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -30,6 +30,77 @@ #include "GPU_batch.h" +/* -------------------------------------------------------------------- */ +/** \name World Data + * \{ */ + +static void workbench_world_data_free(DrawData *dd) +{ + WORKBENCH_WorldData *data = (WORKBENCH_WorldData *)dd; + DRW_UBO_FREE_SAFE(data->world_ubo); +} + +/* Ensure the availability of the world_ubo in the given WORKBENCH_PrivateData + * + * See T70167: Some platforms create threads to upload ubo's. + * + * Reuses the last previous created `world_ubo`. Due to limitations of + * DrawData it will only be reused when there is a world attached to the Scene. + * Future development: The best location would be to store it in the View3D. + * + * We don't cache the data itself as there was no indication that that lead to + * an improvement. + * + * This functions also sets the `WORKBENCH_PrivateData.is_world_ubo_owner` that must + * be respected. + */ +static void workbench_world_data_ubo_ensure(const Scene *scene, WORKBENCH_PrivateData *wpd) +{ + World *world = scene->world; + if (world) { + WORKBENCH_WorldData *engine_world_data = (WORKBENCH_WorldData *)DRW_drawdata_ensure( + &world->id, + &draw_engine_workbench_solid, + sizeof(WORKBENCH_WorldData), + NULL, + &workbench_world_data_free); + + if (engine_world_data->world_ubo == NULL) { + engine_world_data->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), + &wpd->world_data); + } + else { + DRW_uniformbuffer_update(engine_world_data->world_ubo, &wpd->world_data); + } + + /* Borrow world data ubo */ + wpd->is_world_ubo_owner = false; + wpd->world_ubo = engine_world_data->world_ubo; + } + else { + /* there is no world so we cannot cache the UBO. */ + BLI_assert(!wpd->world_ubo || wpd->is_world_ubo_owner); + if (!wpd->world_ubo) { + wpd->is_world_ubo_owner = true; + wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); + } + } +} + +static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateData *wpd) +{ + WORKBENCH_UBO_World *wd = &wpd->world_data; + float light_direction[3]; + float view_matrix[4][4]; + DRW_view_viewmat_get(NULL, view_matrix, false); + + workbench_private_data_get_light_direction(light_direction); + + /* Shadow direction. */ + mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, light_direction); +} +/* \} */ + void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info) { effect_info->jitter_index = 0; @@ -139,7 +210,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) } } - wpd->world_ubo = DRW_uniformbuffer_create(sizeof(WORKBENCH_UBO_World), &wpd->world_data); + workbench_world_data_update_shadow_direction_vs(wpd); + workbench_world_data_ubo_ensure(scene, wpd); /* Cavity settings */ { @@ -203,31 +275,29 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) BLI_listbase_clear(&wpd->smoke_domains); } -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, - float r_light_direction[3]) +void workbench_private_data_get_light_direction(float r_light_direction[3]) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - WORKBENCH_UBO_World *wd = &wpd->world_data; - float view_matrix[4][4]; - DRW_view_viewmat_get(NULL, view_matrix, false); copy_v3_v3(r_light_direction, scene->display.light_direction); SWAP(float, r_light_direction[2], r_light_direction[1]); r_light_direction[2] = -r_light_direction[2]; r_light_direction[0] = -r_light_direction[0]; - - /* Shadow direction. */ - mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, r_light_direction); - - DRW_uniformbuffer_update(wpd->world_ubo, wd); } void workbench_private_data_free(WORKBENCH_PrivateData *wpd) { BLI_ghash_free(wpd->material_hash, NULL, MEM_freeN); BLI_ghash_free(wpd->material_transp_hash, NULL, MEM_freeN); - DRW_UBO_FREE_SAFE(wpd->world_ubo); + + if (wpd->is_world_ubo_owner) { + DRW_UBO_FREE_SAFE(wpd->world_ubo); + } + else { + wpd->world_ubo = NULL; + } + DRW_UBO_FREE_SAFE(wpd->dof_ubo); GPU_BATCH_DISCARD_SAFE(wpd->world_clip_planes_batch); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 9a7e1a5a782..e5872dbac50 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -728,7 +728,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata) /* Deferred Mix Pass */ { - workbench_private_data_get_light_direction(wpd, e_data.display.light_direction); + workbench_private_data_get_light_direction(e_data.display.light_direction); studiolight_update_light(wpd, e_data.display.light_direction); if (SHADOW_ENABLED(wpd)) { diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index d731b167c06..80b274e9b76 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -22,8 +22,6 @@ #include "workbench_private.h" -#include "BIF_gl.h" - #include "BLI_alloca.h" #include "BLI_dynstr.h" #include "BLI_string_utils.h" @@ -337,8 +335,6 @@ void workbench_forward_engine_init(WORKBENCH_Data *vedata) } WORKBENCH_PrivateData *wpd = stl->g_data; workbench_private_data_init(wpd); - float light_direction[3]; - workbench_private_data_get_light_direction(wpd, light_direction); if (!e_data.checker_depth_sh) { e_data.checker_depth_sh = DRW_shader_create_fullscreen( diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index 0f9551a8cc9..45d49448490 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -22,8 +22,6 @@ #include "workbench_private.h" -#include "BIF_gl.h" - #include "BKE_image.h" #include "BKE_node.h" diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 595b92d19d0..9fcd9651f94 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -217,6 +217,11 @@ typedef struct WORKBENCH_PrivateData { View3DShading shading; StudioLight *studio_light; const UserDef *preferences; + /* Does this instance owns the `world_ubo` field. + * Normally the field is borrowed from `WORKBENCH_WorldData`. In case that + * there is no World attached to the scene the UBO cannot be cached and should + * be freed after using. */ + bool is_world_ubo_owner; struct GPUUniformBuffer *world_ubo; struct DRWShadingGroup *shadow_shgrp; struct DRWShadingGroup *depth_shgrp; @@ -307,6 +312,12 @@ typedef struct WORKBENCH_ObjectData { bool shadow_bbox_dirty; } WORKBENCH_ObjectData; +typedef struct WORKBENCH_WorldData { + DrawData dd; + /* The cached `GPUUniformBuffer`, that is reused between draw calls. */ + struct GPUUniformBuffer *world_ubo; +} WORKBENCH_WorldData; + /* inline helper functions */ BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd) { @@ -526,8 +537,7 @@ bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, void workbench_effect_info_init(WORKBENCH_EffectInfo *effect_info); void workbench_private_data_init(WORKBENCH_PrivateData *wpd); void workbench_private_data_free(WORKBENCH_PrivateData *wpd); -void workbench_private_data_get_light_direction(WORKBENCH_PrivateData *wpd, - float r_light_direction[3]); +void workbench_private_data_get_light_direction(float r_light_direction[3]); /* workbench_volume.c */ void workbench_volume_engine_init(void); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 98a9ea965de..4bfae75848b 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2576,6 +2576,9 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) RegionView3D *rv3d = ar->regiondata; DRW_opengl_context_enable(); + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); + GPU_matrix_mul(object->obmat); /* Setup framebuffer */ DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); @@ -2583,7 +2586,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object) GPU_framebuffer_bind(fbl->depth_only_fb); GPU_framebuffer_clear_depth(fbl->depth_only_fb, 1.0f); GPU_depth_test(true); - GPU_matrix_mul(object->obmat); const float(*world_clip_planes)[4] = NULL; if (rv3d->rflag & RV3D_CLIPPING) { diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 36583ecf060..13358808a23 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -228,6 +228,47 @@ void ED_markers_get_minmax(ListBase *markers, short sel, float *first, float *la *last = max; } +/** + * Function used in operator polls, checks whether the markers region is currently drawn in the + * editor in which the operator is called. + */ +static bool ED_operator_markers_region_active(bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + + switch (sa->spacetype) { + case SPACE_ACTION: { + SpaceAction *saction = sa->spacedata.first; + if (saction->flag & SACTION_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_GRAPH: { + SpaceGraph *sipo = sa->spacedata.first; + if (sipo->mode != SIPO_MODE_DRIVERS && sipo->flag & SIPO_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_NLA: { + SpaceNla *snla = sa->spacedata.first; + if (snla->flag & SNLA_SHOW_MARKERS) { + return true; + } + break; + } + case SPACE_SEQ: { + SpaceSeq *seq = sa->spacedata.first; + if (seq->flag & SEQ_SHOW_MARKERS) { + return true; + } + break; + } + } + return false; +} + static bool region_position_is_over_marker(View2D *v2d, ListBase *markers, float region_x) { if (markers == NULL || BLI_listbase_is_empty(markers)) { @@ -409,7 +450,7 @@ static void draw_marker_name(const uiFontStyle *fstyle, UI_fontstyle_draw_simple(fstyle, name_x, text_y, name, text_color); } -static void draw_marker_line(const float color[4], float x, float ymin, float ymax) +static void draw_marker_line(const float color[4], int xpos, int ymin, int ymax) { GPUVertFormat *format = immVertexFormat(); uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); @@ -426,8 +467,8 @@ static void draw_marker_line(const float color[4], float x, float ymin, float ym immUniform1f("dash_factor", 0.5f); immBegin(GPU_PRIM_LINES, 2); - immVertex2f(pos, x, ymin); - immVertex2f(pos, x, ymax); + immVertex2f(pos, xpos, ymin); + immVertex2f(pos, xpos, ymax); immEnd(); immUnbindProgram(); @@ -449,26 +490,6 @@ static int marker_get_icon_id(TimeMarker *marker, int flag) } } -static void draw_marker_line_if_necessary(TimeMarker *marker, int flag, int xpos, int height) -{ -#ifdef DURIAN_CAMERA_SWITCH - if ((marker->camera) || (flag & DRAW_MARKERS_LINES)) -#else - if (flag & DRAW_MARKERS_LINES) -#endif - { - float color[4]; - if (marker->flag & SELECT) { - copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f); - } - else { - copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f); - } - - draw_marker_line(color, xpos, UI_DPI_FAC * 20, height); - } -} - static void draw_marker( const uiFontStyle *fstyle, TimeMarker *marker, int cfra, int xpos, int flag, int region_height) { @@ -476,7 +497,15 @@ static void draw_marker( GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - draw_marker_line_if_necessary(marker, flag, xpos, region_height); + float color[4]; + if (marker->flag & SELECT) { + copy_v4_fl4(color, 1.0f, 1.0f, 1.0f, 0.38f); + } + else { + copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 0.38f); + } + + draw_marker_line(color, xpos, UI_DPI_FAC * 20, region_height); int icon_id = marker_get_icon_id(marker, flag); UI_icon_draw(xpos - 0.55f * UI_DPI_ICON_SIZE, UI_DPI_FAC * 18, icon_id); @@ -599,8 +628,7 @@ static bool ed_markers_poll_selected_markers(bContext *C) { ListBase *markers = ED_context_get_markers(C); - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (!ED_operator_markers_region_active(C)) { return 0; } @@ -613,12 +641,7 @@ static bool ed_markers_poll_selected_no_locked_markers(bContext *C) ListBase *markers = ED_context_get_markers(C); ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->lock_markers) { - return 0; - } - - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (ts->lock_markers || !ED_operator_markers_region_active(C)) { return 0; } @@ -632,12 +655,7 @@ static bool ed_markers_poll_markers_exist(bContext *C) ListBase *markers = ED_context_get_markers(C); ToolSettings *ts = CTX_data_tool_settings(C); - if (ts->lock_markers) { - return 0; - } - - /* first things first: markers can only exist in timeline views */ - if (ED_operator_animview_active(C) == 0) { + if (ts->lock_markers || !ED_operator_markers_region_active(C)) { return 0; } @@ -692,7 +710,7 @@ static void MARKER_OT_add(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_add_exec; - ot->poll = ED_operator_animview_active; + ot->poll = ED_operator_markers_region_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1661,7 +1679,7 @@ static void MARKER_OT_camera_bind(wmOperatorType *ot) /* api callbacks */ ot->exec = ed_marker_camera_bind_exec; - ot->poll = ED_operator_animview_active; + ot->poll = ED_operator_markers_region_active; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 92957c51c08..c9206e8df4a 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1320,20 +1320,36 @@ static int change_spacing_exec(bContext *C, wmOperator *op) Curve *cu = obedit->data; EditFont *ef = cu->editfont; int kern, delta = RNA_int_get(op->ptr, "delta"); + int selstart, selend; + bool changed = false; - kern = ef->textbufinfo[ef->pos - 1].kern; - kern += delta; - CLAMP(kern, -20, 20); - - if (ef->textbufinfo[ef->pos - 1].kern == kern) { - return OPERATOR_CANCELLED; + const bool has_select = BKE_vfont_select_get(obedit, &selstart, &selend); + if (has_select) { + selstart -= 1; + } + else { + selstart = selend = ef->pos - 1; } + selstart = max_ii(0, selstart); - ef->textbufinfo[ef->pos - 1].kern = kern; + for (int i = selstart; i <= selend; i++) { + kern = ef->textbufinfo[i].kern + delta; + CLAMP(kern, -20, 20); - text_update_edited(C, obedit, FO_EDIT); + if (ef->textbufinfo[i].kern != kern) { + ef->textbufinfo[i].kern = kern; + changed = true; + } + } - return OPERATOR_FINISHED; + if (changed) { + text_update_edited(C, obedit, FO_EDIT); + + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } void FONT_OT_change_spacing(wmOperatorType *ot) diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 680fe3a00e5..fd8fe103a2d 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -529,10 +529,6 @@ set(ICON_NAMES axis_side axis_front axis_top - ndof_dom - ndof_turn - ndof_fly - ndof_trans layer_used layer_active sortalpha diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c index 80795b825b0..06e5f36637b 100644 --- a/source/blender/editors/gpencil/drawgpencil.c +++ b/source/blender/editors/gpencil/drawgpencil.c @@ -51,6 +51,7 @@ #include "BKE_context.h" #include "BKE_brush.h" #include "BKE_global.h" +#include "BKE_material.h" #include "BKE_paint.h" #include "BKE_gpencil.h" #include "BKE_image.h" @@ -427,7 +428,9 @@ static void gp_draw_stroke_fill(bGPdata *gpd, const float color[4]) { BLI_assert(gps->totpoints >= 3); - Material *ma = gpd->mat[gps->mat_nr]; + const bool use_mat = (gpd->mat != NULL); + + Material *ma = (use_mat) ? gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get(); MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; /* Calculate triangles cache for filling area (must be done only after changes) */ @@ -869,6 +872,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) short sthickness; float ink[4]; const bool is_unique = (tgpw->gps != NULL); + const bool use_mat = (tgpw->gpd->mat != NULL); GPU_program_point_size(true); @@ -880,7 +884,7 @@ static void gp_draw_strokes(tGPDdraw *tgpw) continue; } /* check if the color is visible */ - Material *ma = tgpw->gpd->mat[gps->mat_nr]; + Material *ma = (use_mat) ? tgpw->gpd->mat[gps->mat_nr] : BKE_material_gpencil_default_get(); MaterialGPencilStyle *gp_style = (ma) ? ma->gp_style : NULL; if ((gp_style == NULL) || (gp_style->flag & GP_STYLE_COLOR_HIDE) || @@ -1159,6 +1163,9 @@ void ED_gp_draw_interpolation(const bContext *C, tGPDinterpolate *tgpi, const in copy_v4_v4(tgpw.tintcolor, color); tgpw.onion = true; tgpw.custonion = true; + if (obact->totcol == 0) { + tgpw.gpd->mat = NULL; + } gp_draw_strokes(&tgpw); } diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c index 3c4d43b5f53..ec26006eb06 100644 --- a/source/blender/editors/gpencil/gpencil_interpolate.c +++ b/source/blender/editors/gpencil/gpencil_interpolate.c @@ -1052,8 +1052,8 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op) /* if destination stroke is smaller, resize new_stroke to size of gps_to stroke */ if (gps_from->totpoints > gps_to->totpoints) { /* free weights of removed points */ - if (gps_from->dvert != NULL) { - BKE_defvert_array_free_elems(gps_from->dvert + gps_to->totpoints, + if (new_stroke->dvert != NULL) { + BKE_defvert_array_free_elems(new_stroke->dvert + gps_to->totpoints, gps_from->totpoints - gps_to->totpoints); } diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index fc7b0d8be8f..4bf43a2034a 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -83,6 +83,7 @@ void EDBM_mesh_clear(struct BMEditMesh *em); void EDBM_selectmode_to_scene(struct bContext *C); void EDBM_mesh_make(struct Object *ob, const int select_mode, const bool add_key_index); void EDBM_mesh_free(struct BMEditMesh *em); +void EDBM_mesh_load_ex(struct Main *bmain, struct Object *ob, bool free_data); void EDBM_mesh_load(struct Main *bmain, struct Object *ob); /* flushes based on the current select mode. if in vertex select mode, @@ -236,6 +237,14 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* rename bool EDBM_mesh_deselect_all_multi_ex(struct Base **bases, const uint bases_len); bool EDBM_mesh_deselect_all_multi(struct bContext *C); +bool EDBM_selectmode_disable_multi_ex(struct Scene *scene, + struct Base **bases, + const uint bases_len, + const short selectmode_disable, + const short selectmode_fallback); +bool EDBM_selectmode_disable_multi(struct bContext *C, + const short selectmode_disable, + const short selectmode_fallback); /* editmesh_preselect_edgering.c */ struct EditMesh_PreSelEdgeRing; diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index c15f299bca8..2bf50d3b4b8 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -739,10 +739,10 @@ DEF_ICON_BLANK(251) DEF_ICON(AXIS_SIDE) DEF_ICON(AXIS_FRONT) DEF_ICON(AXIS_TOP) -DEF_ICON(NDOF_DOM) -DEF_ICON(NDOF_TURN) -DEF_ICON(NDOF_FLY) -DEF_ICON(NDOF_TRANS) +DEF_ICON_BLANK(252) +DEF_ICON_BLANK(252a) +DEF_ICON_BLANK(252b) +DEF_ICON_BLANK(252c) DEF_ICON(LAYER_USED) DEF_ICON(LAYER_ACTIVE) /* available */ diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 499842a570b..31cbd2a3831 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -2019,7 +2019,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons rctf line_range; /* First curve point. */ - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { line_range.xmin = rect->xmin; line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy); } @@ -2028,7 +2028,7 @@ void ui_draw_but_CURVE(ARegion *ar, uiBut *but, const uiWidgetColors *wcol, cons line_range.ymin = rect->ymin + zoomy * (cmp[0].y - offsy + cuma->ext_in[1]); } /* Last curve point. */ - if ((cuma->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) == 0) { line_range.xmax = rect->xmax; line_range.ymax = rect->ymin + zoomy * (cmp[CM_TABLE].y - offsy); } diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c index 0cf357c508b..2b5cf2ed6b9 100644 --- a/source/blender/editors/interface/interface_eyedropper_color.c +++ b/source/blender/editors/interface/interface_eyedropper_color.c @@ -39,7 +39,7 @@ #include "RNA_access.h" -#include "BIF_gl.h" +#include "GPU_glew.h" #include "UI_interface.h" diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 11106dd403f..b34188684e6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -294,6 +294,7 @@ typedef struct uiHandleButtonMulti { typedef struct uiHandleButtonData { wmWindowManager *wm; wmWindow *window; + ScrArea *area; ARegion *region; bool interactive; @@ -7721,7 +7722,8 @@ static void button_tooltip_timer_reset(bContext *C, uiBut *but) if (!wm->drags.first) { bool is_label = UI_but_has_tooltip_label(but); double delay = is_label ? UI_TOOLTIP_DELAY_LABEL : UI_TOOLTIP_DELAY; - WM_tooltip_timer_init_ex(C, data->window, data->region, ui_but_tooltip_init, delay); + WM_tooltip_timer_init_ex( + C, data->window, data->area, data->region, ui_but_tooltip_init, delay); if (is_label) { bScreen *sc = WM_window_get_active_screen(data->window); if (sc->tool_tip) { @@ -7927,6 +7929,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA data = MEM_callocN(sizeof(uiHandleButtonData), "uiHandleButtonData"); data->wm = CTX_wm_manager(C); data->window = CTX_wm_window(C); + data->area = CTX_wm_area(C); BLI_assert(ar != NULL); data->region = ar; @@ -8009,7 +8012,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA /* Show a label for this button. */ bScreen *sc = WM_window_get_active_screen(data->window); if ((PIL_check_seconds_timer() - WM_tooltip_time_closed()) < 0.1) { - WM_tooltip_immediate_init(C, CTX_wm_window(C), ar, ui_but_tooltip_init); + WM_tooltip_immediate_init(C, CTX_wm_window(C), data->area, ar, ui_but_tooltip_init); if (sc->tool_tip) { sc->tool_tip->pass = 1; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 956fd4514af..17247736d3b 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -3992,11 +3992,11 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) BKE_curvemapping_changed(cumap, false); break; case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */ - cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; case UICURVE_FUNC_EXTEND_EXP: /* extend extrapolate */ - cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; + cumap->flag |= CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); break; } diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index 573dfcde88a..7582ef3f41d 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -127,7 +127,7 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op) .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"), .curves_as_mesh = RNA_boolean_get(op->ptr, "curves_as_mesh"), .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"), - .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"), + .visible_objects_only = RNA_boolean_get(op->ptr, "visible_objects_only"), .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"), .face_sets = RNA_boolean_get(op->ptr, "face_sets"), .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"), @@ -209,7 +209,7 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); - uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE); + uiItemR(row, imfptr, "visible_objects_only", 0, NULL, ICON_NONE); row = uiLayoutRow(box, false); uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE); @@ -392,10 +392,10 @@ void WM_OT_alembic_export(wmOperatorType *ot) "Export only objects marked renderable in the outliner"); RNA_def_boolean(ot->srna, - "visible_layers_only", + "visible_objects_only", 0, - "Visible Layers Only", - "Export only objects in visible layers"); + "Visible Objects Only", + "Export only objects that are visible"); RNA_def_boolean(ot->srna, "flatten", diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index b7f506a8a41..5c9fb866df7 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -36,8 +36,6 @@ #include "BKE_global.h" #include "BKE_mesh.h" -#include "BIF_gl.h" - #include "ED_mesh.h" #include "ED_screen.h" #include "ED_select_utils.h" diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c index a709bd010aa..ebd1e62e596 100644 --- a/source/blender/editors/mesh/editmesh_knife_project.c +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -22,7 +22,6 @@ */ #include "DNA_curve_types.h" -#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BLI_math.h" @@ -143,21 +142,7 @@ static int knifeproject_exec(bContext *C, wmOperator *op) /* select only tagged faces */ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); - CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { - if (ob->type == OB_MESH) { - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - if (embm) { - /* not essential, but switch out of vertex mode since the - * selected regions wont be nicely isolated after flushing. - * note: call after de-select to avoid selection flushing. - * note: do this on all participating meshes so this is in sync - * e.g. for later selection picking, see T68852.*/ - EDBM_selectmode_disable(scene, embm, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); - } - } - } - CTX_DATA_END; + EDBM_selectmode_disable_multi(C, SCE_SELECT_VERTEX, SCE_SELECT_EDGE); BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, false, BM_ELEM_TAG); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 7955ccc0977..40d57af97aa 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2653,6 +2653,41 @@ bool EDBM_mesh_deselect_all_multi(struct bContext *C) return changed_multi; } +bool EDBM_selectmode_disable_multi_ex(Scene *scene, + struct Base **bases, + const uint bases_len, + const short selectmode_disable, + const short selectmode_fallback) +{ + bool changed_multi = false; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base_iter = bases[base_index]; + Object *ob_iter = base_iter->object; + BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter); + + EDBM_selectmode_disable(scene, em_iter, selectmode_disable, selectmode_fallback); + changed_multi = true; + } + return changed_multi; +} + +bool EDBM_selectmode_disable_multi(struct bContext *C, + const short selectmode_disable, + const short selectmode_fallback) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc, depsgraph); + uint bases_len = 0; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc.view_layer, NULL, &bases_len); + bool changed_multi = EDBM_selectmode_disable_multi_ex( + scene, bases, bases_len, selectmode_disable, selectmode_fallback); + MEM_freeN(bases); + return changed_multi; +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 8df392fb04b..59090acf433 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4197,7 +4197,12 @@ static bool mesh_separate_loose( BM_mesh_elem_hflag_disable_all(bm_old, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); if (clear_object_data) { - BM_mesh_bm_to_me(NULL, bm_old, me_old, (&(struct BMeshToMeshParams){0})); + BM_mesh_bm_to_me(NULL, + bm_old, + me_old, + (&(struct BMeshToMeshParams){ + .update_shapekey_indices = true, + })); } finally: diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 44984251243..d07ba05de20 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -521,6 +521,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) (&(struct BMeshToMeshParams){ /* Undo code should not be manipulating 'G_MAIN->object' hooks/vertex-parent. */ .calc_object_remap = false, + .update_shapekey_indices = false, .cd_mask_extra = {.vmask = CD_MASK_SHAPE_KEYINDEX}, })); diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 522c2f32d27..42404554ed8 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -325,7 +325,7 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index) * \warning This can invalidate the #Mesh runtime cache of other objects (for linked duplicates). * Most callers should run #DEG_id_tag_update on \a ob->data, see: T46738, T46913 */ -void EDBM_mesh_load(Main *bmain, Object *ob) +void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data) { Mesh *me = ob->data; BMesh *bm = me->edit_mesh->bm; @@ -341,6 +341,7 @@ void EDBM_mesh_load(Main *bmain, Object *ob) me, (&(struct BMeshToMeshParams){ .calc_object_remap = true, + .update_shapekey_indices = !free_data, })); /* Free derived mesh. usually this would happen through depsgraph but there @@ -380,6 +381,11 @@ void EDBM_mesh_clear(BMEditMesh *em) } } +void EDBM_mesh_load(Main *bmain, Object *ob) +{ + EDBM_mesh_load_ex(bmain, ob, true); +} + /** * Should only be called on the active editmesh, otherwise call #BKE_editmesh_free */ diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index be815fb0d10..b7c9579e277 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -445,7 +445,7 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f return false; } - EDBM_mesh_load(bmain, obedit); + EDBM_mesh_load_ex(bmain, obedit, freedata); if (freedata) { EDBM_mesh_free(me->edit_mesh); diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 7106af25a82..5740dacd05f 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1173,7 +1173,7 @@ static int render_shutter_curve_preset_exec(bContext *C, wmOperator *op) CurveMap *cm = mblur_shutter_curve->cm; int preset = RNA_enum_get(op->ptr, "shape"); - cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + mblur_shutter_curve->flag &= ~CUMA_EXTEND_EXTRAPOLATE; mblur_shutter_curve->preset = preset; BKE_curvemap_reset( cm, &mblur_shutter_curve->clipr, mblur_shutter_curve->preset, CURVEMAP_SLOPE_POS_NEG); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f419d30a17e..0d0e183e480 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -18,7 +18,7 @@ */ /** \file - * \ingroup edrend + * \ingroup render */ #include <math.h> @@ -77,7 +77,7 @@ #include "render_intern.h" /* Define this to get timing information. */ -// #undef DEBUG_TIME +// #define DEBUG_TIME #ifdef DEBUG_TIME # include "PIL_time.h" @@ -138,6 +138,8 @@ typedef struct OGLRender { TaskPool *task_pool; bool pool_ok; bool is_animation; + + eImageFormatDepth color_depth; SpinLock reports_lock; unsigned int num_scheduled_frames; ThreadMutex task_mutex; @@ -356,6 +358,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R char err_out[256] = "unknown"; ImBuf *ibuf_view; const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL; + int output_flags = oglrender->color_depth <= R_IMF_CHAN_DEPTH_8 ? IB_rect : IB_rectfloat; if (view_context) { ibuf_view = ED_view3d_draw_offscreen_imbuf(depsgraph, @@ -365,7 +368,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R ar, sizex, sizey, - IB_rectfloat, + output_flags, alpha_mode, oglrender->ofs_samples, viewname, @@ -385,7 +388,7 @@ static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, R scene->camera, oglrender->sizex, oglrender->sizey, - IB_rectfloat, + output_flags, V3D_OFSDRAW_SHOW_ANNOTATION, alpha_mode, oglrender->ofs_samples, @@ -528,6 +531,8 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) const bool is_animation = RNA_boolean_get(op->ptr, "animation"); const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer"); const bool is_write_still = RNA_boolean_get(op->ptr, "write_still"); + const eImageFormatDepth color_depth = (is_animation) ? scene->r.im_format.depth : + R_IMF_CHAN_DEPTH_32; const int samples = U.ogl_multisamples; char err_out[256] = "unknown"; @@ -600,6 +605,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) oglrender->write_still = is_write_still && !is_animation; oglrender->is_animation = is_animation; + oglrender->color_depth = color_depth; oglrender->views_len = BKE_scene_multiview_num_views_get(&scene->r); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 6dc3a1ec1ac..1fe299e58a9 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -80,10 +80,10 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "GPU_shader.h" +#include "GPU_glew.h" #include "RE_pipeline.h" #include "RE_engine.h" diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 78c9980134f..856072ec47a 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -648,7 +648,7 @@ static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups, GPU_matrix_translate_2f(-x, -y); /* scale based on tablet pressure */ - if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (primary && ups->stroke_active && BKE_brush_use_size_pressure(brush)) { const float scale = ups->size_pressure_value; GPU_matrix_translate_2f(x, y); GPU_matrix_scale_2f(scale, scale); @@ -778,7 +778,7 @@ static bool paint_draw_cursor_overlay( } /* scale based on tablet pressure */ - if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { do_pop = true; GPU_matrix_push(); GPU_matrix_translate_2fv(center); @@ -1075,7 +1075,7 @@ static void paint_cursor_on_hit(UnifiedPaintSettings *ups, unprojected_radius = paint_calc_object_space_radius(vc, location, projected_radius); /* scale 3D brush radius by pressure */ - if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { unprojected_radius *= ups->size_pressure_value; } @@ -1362,7 +1362,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) immUniformColor3fvAlpha(outline_col, outline_alpha); /* draw brush outline */ - if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush)) { imm_draw_circle_wire_2d( pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40); /* outer at half alpha */ @@ -1407,8 +1407,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) immUniformColor3fvAlpha(outline_col, outline_alpha); - if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush) && - mode != PAINT_MODE_SCULPT) { + if (ups->stroke_active && BKE_brush_use_size_pressure(brush) && mode != PAINT_MODE_SCULPT) { imm_draw_circle_wire_3d( pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40); /* outer at half alpha */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 9acc189ae95..0b770f17314 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -548,7 +548,7 @@ static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, Po return; } - if (BKE_brush_use_alpha_pressure(scene, brush)) { + if (BKE_brush_use_alpha_pressure(brush)) { BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure * alphafac)); } else { diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index ee359def68c..fc0c6d748cb 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -336,7 +336,7 @@ static bool paint_brush_update(bContext *C, ups->pixel_radius = BKE_brush_size_get(scene, brush); - if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) { + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, mode)) { ups->pixel_radius *= stroke->cached_size_pressure; } @@ -527,8 +527,8 @@ static void paint_brush_stroke_add_step(bContext *C, * windows for some tablets, then we just skip first touch .. */ if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || - BKE_brush_use_alpha_pressure(scene, pop->s.brush) || - BKE_brush_use_size_pressure(scene, pop->s.brush))) { + BKE_brush_use_alpha_pressure(pop->s.brush) || + BKE_brush_use_size_pressure(pop->s.brush))) { return; } @@ -540,8 +540,8 @@ static void paint_brush_stroke_add_step(bContext *C, * which is the sensitivity of the most sensitive pen tablet available */ if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || - BKE_brush_use_alpha_pressure(scene, pop->s.brush) || - BKE_brush_use_size_pressure(scene, pop->s.brush))) { + BKE_brush_use_alpha_pressure(pop->s.brush) || + BKE_brush_use_size_pressure(pop->s.brush))) { return; } #endif @@ -756,7 +756,7 @@ static float paint_space_stroke_spacing_variable(bContext *C, float dpressure, float length) { - if (BKE_brush_use_size_pressure(scene, stroke->brush)) { + if (BKE_brush_use_size_pressure(stroke->brush)) { /* use pressure to modify size. set spacing so that at 100%, the circles * are aligned nicely with no overlap. for this the spacing needs to be * the average of the previous and next size. */ diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index ac7cf310099..536d93cac29 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1522,7 +1522,7 @@ static void vwpaint_update_cache_variants(bContext *C, VPaint *vp, Object *ob, P } } - if (BKE_brush_use_size_pressure(scene, brush) && + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) { cache->radius = cache->initial_radius * cache->pressure; } @@ -1684,11 +1684,9 @@ static void get_brush_alpha_data(const Scene *scene, float *r_brush_alpha_pressure) { *r_brush_size_pressure = BKE_brush_size_get(scene, brush) * - (BKE_brush_use_size_pressure(scene, brush) ? ss->cache->pressure : - 1.0f); + (BKE_brush_use_size_pressure(brush) ? ss->cache->pressure : 1.0f); *r_brush_alpha_value = BKE_brush_alpha_get(scene, brush); - *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(scene, brush) ? ss->cache->pressure : - 1.0f); + *r_brush_alpha_pressure = (BKE_brush_use_alpha_pressure(brush) ? ss->cache->pressure : 1.0f); } static float wpaint_get_active_weight(const MDeformVert *dv, const WeightPaintInfo *wpi) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2e98d463945..9eb32a9f731 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -48,6 +48,7 @@ #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_image.h" +#include "BKE_kelvinlet.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_main.h" @@ -1723,7 +1724,7 @@ static float brush_strength(const Sculpt *sd, const float root_alpha = BKE_brush_alpha_get(scene, brush); float alpha = root_alpha * root_alpha; float dir = (brush->flag & BRUSH_DIR_IN) ? -1 : 1; - float pressure = BKE_brush_use_alpha_pressure(scene, brush) ? cache->pressure : 1; + float pressure = BKE_brush_use_alpha_pressure(brush) ? cache->pressure : 1; float pen_flip = cache->pen_flip ? -1 : 1; float invert = cache->invert ? -1 : 1; float overlap = ups->overlap_factor; @@ -1740,8 +1741,9 @@ static float brush_strength(const Sculpt *sd, switch (brush->sculpt_tool) { case SCULPT_TOOL_CLAY: + final_pressure = pow4f(pressure); overlap = (1.0f + overlap) / 2.0f; - return 0.25f * alpha * flip * pressure * overlap * feather; + return 0.25f * alpha * flip * final_pressure * overlap * feather; case SCULPT_TOOL_DRAW: case SCULPT_TOOL_DRAW_SHARP: case SCULPT_TOOL_LAYER: @@ -2631,152 +2633,48 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, const TaskParallelTLS *__restrict tls) { SculptThreadedTaskData *data = userdata; - SculptDoBrushSmoothGridDataChunk *data_chunk = tls->userdata_chunk; SculptSession *ss = data->ob->sculpt; Sculpt *sd = data->sd; const Brush *brush = data->brush; const bool smooth_mask = data->smooth_mask; float bstrength = data->strength; - CCGElem **griddata, *gddata; - - float(*tmpgrid_co)[3] = NULL; - float tmprow_co[2][3]; - float *tmpgrid_mask = NULL; - float tmprow_mask[2]; + PBVHVertexIter vd; - BLI_bitmap *const *grid_hidden; - int *grid_indices, totgrid, gridsize; - int i, x, y; + CLAMP(bstrength, 0.0f, 1.0f); SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); - CLAMP(bstrength, 0.0f, 1.0f); - - BKE_pbvh_node_get_grids( - ss->pbvh, data->nodes[n], &grid_indices, &totgrid, NULL, &gridsize, &griddata); - CCGKey key = *BKE_pbvh_get_grid_key(ss->pbvh); - - grid_hidden = BKE_pbvh_grid_hidden(ss->pbvh); - - if (smooth_mask) { - tmpgrid_mask = (void *)(data_chunk + 1); - } - else { - tmpgrid_co = (void *)(data_chunk + 1); - } - - for (i = 0; i < totgrid; i++) { - int gi = grid_indices[i]; - const BLI_bitmap *gh = grid_hidden[gi]; - gddata = griddata[gi]; - - if (smooth_mask) { - memset(tmpgrid_mask, 0, data_chunk->tmpgrid_size); - } - else { - memset(tmpgrid_co, 0, data_chunk->tmpgrid_size); - } - - for (y = 0; y < gridsize - 1; y++) { - const int v = y * gridsize; + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + if (sculpt_brush_test_sq_fn(&test, vd.co)) { + const float fade = bstrength * tex_strength(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), + vd.index, + tls->thread_id); if (smooth_mask) { - tmprow_mask[0] = (*CCG_elem_offset_mask(&key, gddata, v) + - *CCG_elem_offset_mask(&key, gddata, v + gridsize)); + float val = grids_neighbor_average_mask(ss, vd.index) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0.0f, 1.0f); } else { - add_v3_v3v3(tmprow_co[0], - CCG_elem_offset_co(&key, gddata, v), - CCG_elem_offset_co(&key, gddata, v + gridsize)); - } - - for (x = 0; x < gridsize - 1; x++) { - const int v1 = x + y * gridsize; - const int v2 = v1 + 1; - const int v3 = v1 + gridsize; - const int v4 = v3 + 1; - - if (smooth_mask) { - float tmp; - - tmprow_mask[(x + 1) % 2] = (*CCG_elem_offset_mask(&key, gddata, v2) + - *CCG_elem_offset_mask(&key, gddata, v4)); - tmp = tmprow_mask[(x + 1) % 2] + tmprow_mask[x % 2]; - - tmpgrid_mask[v1] += tmp; - tmpgrid_mask[v2] += tmp; - tmpgrid_mask[v3] += tmp; - tmpgrid_mask[v4] += tmp; - } - else { - float tmp[3]; - - add_v3_v3v3(tmprow_co[(x + 1) % 2], - CCG_elem_offset_co(&key, gddata, v2), - CCG_elem_offset_co(&key, gddata, v4)); - add_v3_v3v3(tmp, tmprow_co[(x + 1) % 2], tmprow_co[x % 2]); - - add_v3_v3(tmpgrid_co[v1], tmp); - add_v3_v3(tmpgrid_co[v2], tmp); - add_v3_v3(tmpgrid_co[v3], tmp); - add_v3_v3(tmpgrid_co[v4], tmp); - } - } - } - - /* blend with existing coordinates */ - for (y = 0; y < gridsize; y++) { - for (x = 0; x < gridsize; x++) { - float *co; - const float *fno; - float *mask; - const int index = y * gridsize + x; - - if (gh) { - if (BLI_BITMAP_TEST(gh, index)) { - continue; - } - } - - co = CCG_elem_offset_co(&key, gddata, index); - fno = CCG_elem_offset_no(&key, gddata, index); - mask = CCG_elem_offset_mask(&key, gddata, index); - - if (sculpt_brush_test_sq_fn(&test, co)) { - const float strength_mask = (smooth_mask ? 0.0f : *mask); - const float fade = - bstrength * - tex_strength( - ss, brush, co, sqrtf(test.dist), NULL, fno, strength_mask, 0, tls->thread_id); - float f = 1.0f / 16.0f; - - if (x == 0 || x == gridsize - 1) { - f *= 2.0f; - } - - if (y == 0 || y == gridsize - 1) { - f *= 2.0f; - } - - if (smooth_mask) { - *mask += ((tmpgrid_mask[index] * f) - *mask) * fade; - } - else { - float *avg = tmpgrid_co[index]; - float val[3]; - - mul_v3_fl(avg, f); - sub_v3_v3v3(val, avg, co); - madd_v3_v3v3fl(val, co, val, fade); - - sculpt_clip(sd, ss, co, val); - } - } + float avg[3], val[3]; + grids_neighbor_average(ss, avg, vd.index); + sub_v3_v3v3(val, avg, vd.co); + madd_v3_v3v3fl(val, vd.co, val, fade); + sculpt_clip(sd, ss, vd.co, val); } } } + BKE_pbvh_vertex_iter_end; } static void smooth(Sculpt *sd, @@ -2821,25 +2719,9 @@ static void smooth(Sculpt *sd, BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); switch (type) { - case PBVH_GRIDS: { - int gridsize; - size_t size; - SculptDoBrushSmoothGridDataChunk *data_chunk; - - BKE_pbvh_node_get_grids(ss->pbvh, NULL, NULL, NULL, NULL, &gridsize, NULL); - size = (size_t)gridsize; - size = sizeof(float) * size * size * (smooth_mask ? 1 : 3); - data_chunk = MEM_mallocN(sizeof(*data_chunk) + size, __func__); - data_chunk->tmpgrid_size = size; - size += sizeof(*data_chunk); - - settings.userdata_chunk = data_chunk; - settings.userdata_chunk_size = size; + case PBVH_GRIDS: BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); - - MEM_freeN(data_chunk); break; - } case PBVH_FACES: BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); break; @@ -2847,10 +2729,6 @@ static void smooth(Sculpt *sd, BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); break; } - - if (ss->multires) { - multires_stitch_grids(ob); - } } } @@ -3528,98 +3406,6 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); } -/* Regularized Kelvinlets: Sculpting Brushes based on Fundamental Solutions of Elasticity - * Pixar Technical Memo #17-03 */ - -typedef struct KelvinletParams { - float f; - float a; - float b; - float c; - float radius_scaled; -} KelvinletParams; - -static int sculpt_kelvinlet_get_scale_iteration_count(eBrushElasticDeformType type) -{ - if (type == BRUSH_ELASTIC_DEFORM_GRAB) { - return 1; - } - if (type == BRUSH_ELASTIC_DEFORM_GRAB_BISCALE) { - return 2; - } - if (type == BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE) { - return 3; - } - return 0; -} - -static void sculpt_kelvinet_integrate(void (*kelvinlet)(float disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p), - float r_disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p) -{ - float k[4][3], k_it[4][3]; - kelvinlet(k[0], vertex_co, location, normal, p); - copy_v3_v3(k_it[0], k[0]); - mul_v3_fl(k_it[0], 0.5f); - add_v3_v3v3(k_it[0], vertex_co, k_it[0]); - kelvinlet(k[1], k_it[0], location, normal, p); - copy_v3_v3(k_it[1], k[1]); - mul_v3_fl(k_it[1], 0.5f); - add_v3_v3v3(k_it[1], vertex_co, k_it[1]); - kelvinlet(k[2], k_it[1], location, normal, p); - copy_v3_v3(k_it[2], k[2]); - add_v3_v3v3(k_it[2], vertex_co, k_it[2]); - sub_v3_v3v3(k_it[2], k_it[2], location); - kelvinlet(k[3], k_it[2], location, normal, p); - copy_v3_v3(r_disp, k[0]); - madd_v3_v3fl(r_disp, k[1], 2); - madd_v3_v3fl(r_disp, k[2], 2); - add_v3_v3(r_disp, k[3]); - mul_v3_fl(r_disp, 1.0f / 6.0f); -} - -/* Regularized Kelvinlets: Formula (16) */ -static void sculpt_kelvinlet_scale(float disp[3], - const float vertex_co[3], - const float location[3], - float UNUSED(normal[3]), - KelvinletParams *p) -{ - float r_v[3]; - sub_v3_v3v3(r_v, vertex_co, location); - float r = len_v3(r_v); - float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled); - float u = (2.0f * p->b - p->a) * ((1.0f / (r_e * r_e * r_e))) + - ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e)); - float fade = u * p->c; - mul_v3_v3fl(disp, r_v, fade * p->f); -} - -/* Regularized Kelvinlets: Formula (15) */ -static void sculpt_kelvinlet_twist(float disp[3], - const float vertex_co[3], - const float location[3], - float normal[3], - KelvinletParams *p) -{ - float r_v[3], q_r[3]; - sub_v3_v3v3(r_v, vertex_co, location); - float r = len_v3(r_v); - float r_e = sqrtf(r * r + p->radius_scaled * p->radius_scaled); - float u = -p->a * ((1.0f / (r_e * r_e * r_e))) + - ((3.0f * p->radius_scaled * p->radius_scaled) / (2.0f * r_e * r_e * r_e * r_e * r_e)); - float fade = u * p->c; - cross_v3_v3v3(q_r, normal, r_v); - mul_v3_v3fl(disp, q_r, fade * p->f); -} - static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -3640,23 +3426,6 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co; - /* Maybe this can be exposed to the user */ - float radius_e[3] = {1.0f, 2.0f, 2.0f}; - float r_e[3]; - float kvl[3]; - float radius_scaled[3]; - - radius_scaled[0] = ss->cache->radius * radius_e[0]; - radius_scaled[1] = radius_scaled[0] * radius_e[1]; - radius_scaled[2] = radius_scaled[1] * radius_e[2]; - - float shear_modulus = 1.0f; - float poisson_ratio = brush->elastic_deform_volume_preservation; - - float a = 1.0f / (4.0f * (float)M_PI * shear_modulus); - float b = a / (4.0f * (1.0f - poisson_ratio)); - float c = 2 * (3.0f * a - 2.0f * b); - float dir; if (ss->cache->mouse[0] > ss->cache->initial_mouse[0]) { dir = 1.0f; @@ -3671,73 +3440,38 @@ static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, dir = -dir; } } + + KelvinletParams params; + float force = len_v3(grab_delta) * dir * bstrength; + BKE_kelvinlet_init_params( + ¶ms, ss->cache->radius, force, 1.0f, brush->elastic_deform_volume_preservation); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { sculpt_orig_vert_data_update(&orig_data, &vd); - float fade, final_disp[3], weights[3]; - float r = len_v3v3(location, orig_data.co); - KelvinletParams params; - params.a = a; - params.b = b; - params.c = c; - params.radius_scaled = radius_scaled[0]; - - int multi_scale_it = sculpt_kelvinlet_get_scale_iteration_count(brush->elastic_deform_type); - for (int it = 0; it < max_ii(1, multi_scale_it); it++) { - r_e[it] = sqrtf(r * r + radius_scaled[it] * radius_scaled[it]); - } - - /* Regularized Kelvinlets: Formula (6) */ - for (int s_it = 0; s_it < multi_scale_it; s_it++) { - kvl[s_it] = ((a - b) / r_e[s_it]) + ((b * r * r) / (r_e[s_it] * r_e[s_it] * r_e[s_it])) + - ((a * radius_scaled[s_it] * radius_scaled[s_it]) / - (2.0f * r_e[s_it] * r_e[s_it] * r_e[s_it])); - } - + float final_disp[3]; switch (brush->elastic_deform_type) { - /* Regularized Kelvinlets: Multi-scale extrapolation. Formula (11) */ case BRUSH_ELASTIC_DEFORM_GRAB: - fade = kvl[0] * c; - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.f); + BKE_kelvinlet_grab(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; case BRUSH_ELASTIC_DEFORM_GRAB_BISCALE: { - const float u = kvl[0] - kvl[1]; - fade = u * c / ((1.0f / radius_scaled[0]) - (1.0f / radius_scaled[1])); - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f); + BKE_kelvinlet_grab_biscale(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; } case BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE: { - weights[0] = 1.0f; - weights[1] = -( - (radius_scaled[2] * radius_scaled[2] - radius_scaled[0] * radius_scaled[0]) / - (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1])); - weights[2] = ((radius_scaled[1] * radius_scaled[1] - radius_scaled[0] * radius_scaled[0]) / - (radius_scaled[2] * radius_scaled[2] - radius_scaled[1] * radius_scaled[1])); - - const float u = weights[0] * kvl[0] + weights[1] * kvl[1] + weights[2] * kvl[2]; - fade = u * c / - (weights[0] / radius_scaled[0] + weights[1] / radius_scaled[1] + - weights[2] / radius_scaled[2]); - mul_v3_v3fl(final_disp, grab_delta, fade * bstrength * 20.0f); + BKE_kelvinlet_grab_triscale(final_disp, ¶ms, orig_data.co, location, grab_delta); + mul_v3_fl(final_disp, bstrength * 20.0f); break; } case BRUSH_ELASTIC_DEFORM_SCALE: - params.f = len_v3(grab_delta) * dir * bstrength; - sculpt_kelvinet_integrate(sculpt_kelvinlet_scale, - final_disp, - orig_data.co, - location, - ss->cache->sculpt_normal_symm, - ¶ms); + BKE_kelvinlet_scale( + final_disp, ¶ms, orig_data.co, location, ss->cache->sculpt_normal_symm); break; case BRUSH_ELASTIC_DEFORM_TWIST: - params.f = len_v3(grab_delta) * dir * bstrength; - sculpt_kelvinet_integrate(sculpt_kelvinlet_twist, - final_disp, - orig_data.co, - location, - ss->cache->sculpt_normal_symm, - ¶ms); + BKE_kelvinlet_twist( + final_disp, ¶ms, orig_data.co, location, ss->cache->sculpt_normal_symm); break; } @@ -4926,7 +4660,6 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, if (sculpt_brush_test_sq_fn(&test, vd.co)) { float intr[3]; float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); sub_v3_v3v3(val, intr, vd.co); @@ -4962,6 +4695,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) Brush *brush = BKE_paint_brush(&sd->paint); const float radius = fabsf(ss->cache->radius); + const float initial_radius = fabsf(ss->cache->initial_radius); bool flip = ss->cache->bstrength < 0.0f; float offset = get_offset(sd, ss); @@ -4997,7 +4731,7 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) d_offset = min_ff(radius, d_offset); d_offset = d_offset / radius; d_offset = 1.0f - d_offset; - displace = fabsf(radius * (0.25f + offset + (d_offset * 0.15f))); + displace = fabsf(initial_radius * (0.25f + offset + (d_offset * 0.15f))); if (flip) { displace = -displace; } @@ -6781,8 +6515,10 @@ static void sculpt_update_cache_invariants( static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, float initial_size) { switch (brush->sculpt_tool) { + case SCULPT_TOOL_CLAY: + return max_ff(initial_size * 0.20f, initial_size * pow3f(cache->pressure)); case SCULPT_TOOL_CLAY_STRIPS: - return max_ff(initial_size * 0.35f, initial_size * cache->pressure * cache->pressure); + return max_ff(initial_size * 0.35f, initial_size * pow2f(cache->pressure)); default: return initial_size * cache->pressure; } @@ -6986,12 +6722,14 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po } } - if (BKE_brush_use_size_pressure(scene, brush) && + if (BKE_brush_use_size_pressure(brush) && paint_supports_dynamic_size(brush, PAINT_MODE_SCULPT)) { cache->radius = sculpt_brush_dynamic_size_get(brush, cache, cache->initial_radius); + cache->dyntopo_radius = cache->initial_radius * cache->pressure; } else { cache->radius = cache->initial_radius; + cache->dyntopo_radius = cache->initial_radius; } cache->radius_squared = cache->radius * cache->radius; @@ -7402,14 +7140,13 @@ static void sculpt_brush_stroke_init(bContext *C, wmOperator *op) static void sculpt_restore_mesh(Sculpt *sd, Object *ob) { - SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); /* Restore the mesh before continuing with anchored stroke */ if ((brush->flag & BRUSH_ANCHORED) || ((brush->sculpt_tool == SCULPT_TOOL_GRAB || brush->sculpt_tool == SCULPT_TOOL_ELASTIC_DEFORM) && - BKE_brush_use_size_pressure(ss->cache->vc->scene, brush)) || + BKE_brush_use_size_pressure(brush)) || (brush->flag & BRUSH_DRAG_DOT)) { paint_mesh_restore_co(sd, ob); } @@ -7603,11 +7340,12 @@ static void sculpt_stroke_update_step(bContext *C, BKE_pbvh_bmesh_detail_size_set(ss->pbvh, object_space_constant_detail); } else if (sd->flags & SCULPT_DYNTOPO_DETAIL_BRUSH) { - BKE_pbvh_bmesh_detail_size_set(ss->pbvh, ss->cache->radius * sd->detail_percent / 100.0f); + BKE_pbvh_bmesh_detail_size_set(ss->pbvh, + ss->cache->dyntopo_radius * sd->detail_percent / 100.0f); } else { BKE_pbvh_bmesh_detail_size_set(ss->pbvh, - (ss->cache->radius / (float)ups->pixel_radius) * + (ss->cache->dyntopo_radius / (float)ups->pixel_radius) * (float)(sd->detail_size * U.pixelsize) / 0.4f); } @@ -8710,36 +8448,60 @@ static void SCULPT_OT_detail_flood_fill(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static void sample_detail(bContext *C, int mx, int my) +typedef enum eSculptSampleDetailModeTypes { + SAMPLE_DETAIL_DYNTOPO = 0, + SAMPLE_DETAIL_VOXEL = 1, +} eSculptSampleDetailModeTypes; + +static EnumPropertyItem prop_sculpt_sample_detail_mode_types[] = { + {SAMPLE_DETAIL_DYNTOPO, "DYNTOPO", 0, "Dyntopo", "Sample dyntopo detail"}, + {SAMPLE_DETAIL_VOXEL, "VOXEL", 0, "Voxel", "Sample mesh voxel size"}, + {0, NULL, 0, NULL, NULL}, +}; + +static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my) { - /* Find 3D view to pick from. */ - bScreen *screen = CTX_wm_screen(C); - ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my); - ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL; - if (ar == NULL) { - return; - } + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *ob = vc->obact; + Mesh *mesh = ob->data; - /* Set context to 3D view. */ - ScrArea *prev_sa = CTX_wm_area(C); - ARegion *prev_ar = CTX_wm_region(C); - CTX_wm_area_set(C, sa); - CTX_wm_region_set(C, ar); + SculptSession *ss = ob->sculpt; + SculptCursorGeometryInfo sgi; + sculpt_vertex_random_access_init(ss); - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - ViewContext vc; - ED_view3d_viewcontext_init(C, &vc, depsgraph); + /* Update the active vertex */ + float mouse[2] = {mx, my}; + sculpt_cursor_geometry_info_update(C, &sgi, mouse, false); + BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false); - /* Pick sample detail. */ + /* Average the edge length of the connected edges to the active vertex */ + int active_vertex = sculpt_active_vertex_get(ss); + const float *active_vertex_co = sculpt_active_vertex_co_get(ss); + float edge_length = 0.0f; + int tot = 0; + SculptVertexNeighborIter ni; + sculpt_vertex_neighbors_iter_begin(ss, active_vertex, ni) + { + edge_length += len_v3v3(active_vertex_co, sculpt_vertex_co_get(ss, ni.index)); + tot += 1; + } + sculpt_vertex_neighbors_iter_end(ni); + if (tot > 0) { + mesh->remesh_voxel_size = edge_length / (float)tot; + } +} + +static void sample_detail_dyntopo(bContext *C, ViewContext *vc, ARegion *ar, int mx, int my) +{ Sculpt *sd = CTX_data_tool_settings(C)->sculpt; - Object *ob = vc.obact; + Object *ob = vc->obact; Brush *brush = BKE_paint_brush(&sd->paint); sculpt_stroke_modifiers_check(C, ob, brush); float mouse[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin}; float ray_start[3], ray_end[3], ray_normal[3]; - float depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, false); + float depth = sculpt_raycast_init(vc, mouse, ray_start, ray_end, ray_normal, false); SculptDetailRaycastData srd; srd.hit = 0; @@ -8754,6 +8516,37 @@ static void sample_detail(bContext *C, int mx, int my) /* Convert edge length to world space detail resolution. */ sd->constant_detail = 1 / (srd.edge_length * mat4_to_scale(ob->obmat)); } +} + +static void sample_detail(bContext *C, int mx, int my, int mode) +{ + /* Find 3D view to pick from. */ + bScreen *screen = CTX_wm_screen(C); + ScrArea *sa = BKE_screen_find_area_xy(screen, SPACE_VIEW3D, mx, my); + ARegion *ar = (sa) ? BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my) : NULL; + if (ar == NULL) { + return; + } + + /* Set context to 3D view. */ + ScrArea *prev_sa = CTX_wm_area(C); + ARegion *prev_ar = CTX_wm_region(C); + CTX_wm_area_set(C, sa); + CTX_wm_region_set(C, ar); + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ViewContext vc; + ED_view3d_viewcontext_init(C, &vc, depsgraph); + + /* Pick sample detail. */ + switch (mode) { + case SAMPLE_DETAIL_DYNTOPO: + sample_detail_dyntopo(C, &vc, ar, mx, my); + break; + case SAMPLE_DETAIL_VOXEL: + sample_detail_voxel(C, &vc, mx, my); + break; + } /* Restore context. */ CTX_wm_area_set(C, prev_sa); @@ -8764,7 +8557,8 @@ static int sculpt_sample_detail_size_exec(bContext *C, wmOperator *op) { int ss_co[2]; RNA_int_get_array(op->ptr, "location", ss_co); - sample_detail(C, ss_co[0], ss_co[1]); + int mode = RNA_enum_get(op->ptr, "mode"); + sample_detail(C, ss_co[0], ss_co[1], mode); return OPERATOR_FINISHED; } @@ -8783,7 +8577,8 @@ static int sculpt_sample_detail_size_modal(bContext *C, wmOperator *op, const wm if (event->val == KM_PRESS) { int ss_co[2] = {event->x, event->y}; - sample_detail(C, ss_co[0], ss_co[1]); + int mode = RNA_enum_get(op->ptr, "mode"); + sample_detail(C, ss_co[0], ss_co[1], mode); RNA_int_set_array(op->ptr, "location", ss_co); WM_cursor_modal_restore(CTX_wm_window(C)); @@ -8816,7 +8611,7 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) ot->invoke = sculpt_sample_detail_size_invoke; ot->exec = sculpt_sample_detail_size_exec; ot->modal = sculpt_sample_detail_size_modal; - ot->poll = sculpt_and_constant_or_manual_detail_poll; + ot->poll = sculpt_mode_poll; ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -8830,6 +8625,12 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) "Screen Coordinates of sampling", 0, SHRT_MAX); + RNA_def_enum(ot->srna, + "mode", + prop_sculpt_sample_detail_mode_types, + SAMPLE_DETAIL_DYNTOPO, + "Detail Mode", + "Target sculpting workflow that is going to use the sampled size"); } /* Dynamic-topology detail size diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 0b25ab31ce0..324ca250c86 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -318,6 +318,10 @@ typedef struct StrokeCache { float true_last_location[3]; float location[3]; float last_location[3]; + + /* This radius variable is not affected by pressure curves */ + float dyntopo_radius; + bool is_last_valid; bool pen_flip; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 1685852dd02..901efbdf0ff 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -71,7 +71,7 @@ static SpaceLink *action_new(const ScrArea *sa, const Scene *scene) saction->autosnap = SACTSNAP_FRAME; saction->mode = SACTCONT_DOPESHEET; saction->mode_prev = SACTCONT_DOPESHEET; - saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKER_LINES; + saction->flag = SACTION_SHOW_INTERPOLATION | SACTION_SHOW_MARKERS; saction->ads.filterflag |= ADS_FILTER_SUMMARY; @@ -215,10 +215,10 @@ static void action_main_region_draw(const bContext *C, ARegion *ar) marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN; - if (saction->flag & SACTION_SHOW_MARKER_LINES) { - marker_flag |= DRAW_MARKERS_LINES; + + if (saction->flag & SACTION_SHOW_MARKERS) { + ED_markers_draw(C, marker_flag); } - ED_markers_draw(C, marker_flag); /* caches */ if (saction->mode == SACTCONT_TIMELINE) { diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index b8d9d3b791f..eb7ba480296 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -81,7 +81,7 @@ static SpaceLink *graph_new(const ScrArea *UNUSED(sa), const Scene *scene) /* settings for making it easier by default to just see what you're interested in tweaking */ sipo->ads->filterflag |= ADS_FILTER_ONLYSEL; - sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_MARKER_LINES; + sipo->flag |= SIPO_SELVHANDLESONLY | SIPO_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for graphedit"); @@ -296,10 +296,9 @@ static void graph_main_region_draw(const bContext *C, ARegion *ar) if (sipo->mode != SIPO_MODE_DRIVERS) { UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sipo->flag & SIPO_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (sipo->flag & SIPO_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); } /* preview range */ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index b51aec90e4f..225ca72a7d0 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -123,6 +123,10 @@ static bool stats_mesheval(Mesh *me_eval, bool is_selected, SceneStats *stats) static void stats_object(Object *ob, SceneStats *stats, GSet *objects_gset) { + if ((ob->base_flag & BASE_VISIBLE_VIEWLAYER) == 0) { + return; + } + const bool is_selected = (ob->base_flag & BASE_SELECTED) != 0; stats->totobj++; diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index f274f3c93ec..5cd2a86adf8 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -71,7 +71,7 @@ static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene) /* set auto-snapping settings */ snla->autosnap = SACTSNAP_FRAME; - snla->flag = SNLA_SHOW_MARKER_LINES; + snla->flag = SNLA_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for nla"); @@ -274,10 +274,9 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar) /* markers */ UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (snla->flag & SNLA_SHOW_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (snla->flag & SNLA_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); /* preview range */ UI_view2d_view_ortho(v2d); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 5ca4ae7b666..70cb28fa937 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -2067,10 +2067,9 @@ void draw_timeline_seq(const bContext *C, ARegion *ar) /* markers */ UI_view2d_view_orthoSpecial(ar, v2d, 1); int marker_draw_flag = DRAW_MARKERS_MARGIN; - if (sseq->flag & SEQ_SHOW_MARKER_LINES) { - marker_draw_flag |= DRAW_MARKERS_LINES; + if (sseq->flag & SEQ_SHOW_MARKERS) { + ED_markers_draw(C, marker_draw_flag); } - ED_markers_draw(C, marker_draw_flag); UI_view2d_view_ortho(v2d); /* draw cache on top of markers area */ diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index e1cf6d00b90..6e1b9d62f0e 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -93,7 +93,7 @@ static SpaceLink *sequencer_new(const ScrArea *UNUSED(sa), const Scene *scene) sseq->chanshown = 0; sseq->view = SEQ_VIEW_SEQUENCE; sseq->mainb = SEQ_DRAW_IMG_IMBUF; - sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKER_LINES; + sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA | SEQ_SHOW_MARKERS; /* header */ ar = MEM_callocN(sizeof(ARegion), "header for sequencer"); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 3ee9755cb06..5f029e840d3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1121,13 +1121,6 @@ static void draw_rotation_guide(const RegionView3D *rv3d) immEnd(); immUnbindProgram(); -# if 0 - /* find screen coordinates for rotation center, then draw pretty icon */ - mul_m4_v3(rv3d->persinv, rot_center); - UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); - /* ^^ just playing around, does not work */ -# endif - GPU_blend(false); glDepthMask(GL_TRUE); } @@ -1866,9 +1859,11 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph, if (drawtype == OB_MATERIAL) { v3d.shading.flag = V3D_SHADING_SCENE_WORLD | V3D_SHADING_SCENE_LIGHTS; + v3d.shading.render_pass = SCE_PASS_COMBINED; } else if (drawtype == OB_RENDER) { v3d.shading.flag = V3D_SHADING_SCENE_WORLD_RENDER | V3D_SHADING_SCENE_LIGHTS_RENDER; + v3d.shading.render_pass = SCE_PASS_COMBINED; } v3d.flag2 = V3D_HIDE_OVERLAYS; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 3ad194a5d2b..d40f79cea3f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -992,8 +992,17 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) * \{ */ #ifdef WITH_INPUT_NDOF -# define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec)) -# define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec)) +static bool ndof_has_translate(const wmNDOFMotionData *ndof, + const View3D *v3d, + const RegionView3D *rv3d) +{ + return !is_zero_v3(ndof->tvec) && (!ED_view3d_offset_lock_check(v3d, rv3d)); +} + +static bool ndof_has_rotate(const wmNDOFMotionData *ndof, const RegionView3D *rv3d) +{ + return !is_zero_v3(ndof->rvec) && ((rv3d->viewlock & RV3D_LOCKED) == 0); +} /** * \param depth_pt: A point to calculate the depth (in perspective mode) @@ -1189,8 +1198,8 @@ void view3d_ndof_fly(const wmNDOFMotionData *ndof, bool *r_has_translate, bool *r_has_rotate) { - bool has_translate = NDOF_HAS_TRANSLATE; - bool has_rotate = NDOF_HAS_ROTATE; + bool has_translate = ndof_has_translate(ndof, v3d, rv3d); + bool has_rotate = ndof_has_rotate(ndof, rv3d); float view_inv[4]; invert_qt_qt_normalized(view_inv, rv3d->viewquat); @@ -1338,9 +1347,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) ED_view3d_camera_lock_init_ex(depsgraph, v3d, rv3d, false); if (ndof->progress != P_FINISHING) { - const bool has_rotation = NDOF_HAS_ROTATE; + const bool has_rotation = ndof_has_rotate(ndof, rv3d); /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE && (rv3d->viewlock & RV3D_LOCKED); + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d) && + (rv3d->viewlock & RV3D_LOCKED); const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; if (has_translate || has_zoom) { @@ -1423,7 +1433,7 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev } else if ((rv3d->persp == RV3D_ORTHO) && RV3D_VIEW_IS_AXIS(rv3d->view)) { /* if we can't rotate, fallback to translate (locked axis views) */ - const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f) && ED_view3d_offset_lock_check(v3d, rv3d); if (has_translate || has_zoom) { @@ -1431,41 +1441,33 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev xform_flag |= HAS_TRANSLATE; } } - else if ((U.ndof_flag & NDOF_MODE_ORBIT) || ED_view3d_offset_lock_check(v3d, rv3d)) { - const bool has_rotation = NDOF_HAS_ROTATE; + else { + /* Note: based on feedback from T67579, users want to have pan and orbit enabled at once. + * It's arguable that orbit shouldn't pan (since we have a pan only operator), + * so if there are users who like to separate orbit/pan operations - it can be a preference. */ + const bool is_orbit_around_pivot = (U.ndof_flag & NDOF_MODE_ORBIT) || + ED_view3d_offset_lock_check(v3d, rv3d); + const bool has_rotation = ndof_has_rotate(ndof, rv3d); + const bool has_translate = !is_zero_v2(ndof->tvec) && ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f); - if (has_zoom) { - view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, false, has_zoom); - xform_flag |= HAS_TRANSLATE; - } - + /* Rotation first because dynamic offset resets offset otherwise (and disasbles panning). */ if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, true); + const float dist_backup = rv3d->dist; + if (!is_orbit_around_pivot) { + ED_view3d_distance_set(rv3d, 0.0f); + } + view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, is_orbit_around_pivot); xform_flag |= HAS_ROTATE; + if (!is_orbit_around_pivot) { + ED_view3d_distance_set(rv3d, dist_backup); + } } - } - else { /* free/explore (like fly mode) */ - const bool has_rotation = NDOF_HAS_ROTATE; - const bool has_translate = NDOF_HAS_TRANSLATE; - const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; - - float dist_backup; if (has_translate || has_zoom) { view3d_ndof_pan_zoom(ndof, vod->sa, vod->ar, has_translate, has_zoom); xform_flag |= HAS_TRANSLATE; } - - dist_backup = rv3d->dist; - ED_view3d_distance_set(rv3d, 0.0f); - - if (has_rotation) { - view3d_ndof_orbit(ndof, vod->sa, vod->ar, vod, false); - xform_flag |= HAS_ROTATE; - } - - ED_view3d_distance_set(rv3d, dist_backup); } ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d); @@ -1514,7 +1516,7 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *e const wmNDOFMotionData *ndof = event->customdata; char xform_flag = 0; - const bool has_translate = NDOF_HAS_TRANSLATE; + const bool has_translate = ndof_has_translate(ndof, v3d, rv3d); const bool has_zoom = (ndof->tvec[2] != 0.0f) && !rv3d->is_persp; /* we're panning here! so erase any leftover rotation from other operators */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index f3d26f85471..74fc1406795 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -5262,12 +5262,12 @@ static void applyTranslationValue(TransInfo *t, const float vec[3]) copy_v3_v3(tvec, vec); } + mul_m3_v3(td->smtx, tvec); + if (use_rotate_offset) { add_v3_v3(tvec, rotate_offset); } - mul_m3_v3(td->smtx, tvec); - if (t->options & CTX_GPENCIL_STROKES) { /* grease pencil multiframe falloff */ bGPDstroke *gps = (bGPDstroke *)td->extra; diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index 0c52dd15092..987327eefc1 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -44,7 +44,6 @@ set(SRC select_utils.c # general includes - ../include/BIF_gl.h ../include/BIF_glutil.h ../include/ED_anim_api.h ../include/ED_armature.h diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index 367ad556d02..a6512a64776 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -266,8 +266,8 @@ static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject * cumap = (CurveMapping *)py_srna->ptr.data; BKE_curvemapping_initialize(cumap); /* disable extrapolation if enabled */ - if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) { - cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE); + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE)) { + cumap->flag &= ~(CUMA_EXTEND_EXTRAPOLATE); BKE_curvemapping_changed(cumap, 0); } return PyFloat_FromDouble(BKE_curvemapping_evaluateF(cumap, cur, value)); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c index 01bb0ae2b93..e3ad5a64ac3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c @@ -71,8 +71,14 @@ static int remapTime(struct GpencilModifierData *md, const bool invpass = mmd->flag & GP_TIME_INVERT_LAYERPASS; int sfra = custom ? mmd->sfra : scene->r.sfra; int efra = custom ? mmd->efra : scene->r.efra; - CLAMP_MIN(sfra, 1); - CLAMP_MIN(efra, 1); + CLAMP_MIN(sfra, 0); + CLAMP_MIN(efra, 0); + + /* Avoid inverse ranges. */ + if (efra < sfra) { + return cfra; + } + const int time_range = efra - sfra + 1; int offset = mmd->offset; int segments = 0; diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 4bbcb6a4335..e692262358b 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -32,6 +32,7 @@ #include "GPU_texture.h" #define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */ +#define GLA_PIXEL_OFS 0.375f typedef struct GPUViewport GPUViewport; diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 8b372c0b110..717983f94d8 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -696,11 +696,24 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi // BLI_assert(v_first + v_count <= // (batch->elem ? batch->elem->index_len : batch->verts[0]->vertex_len)); +#ifdef __APPLE__ + GLuint vao = 0; +#endif + if (!GPU_arb_base_instance_is_supported()) { if (i_first > 0) { +#ifdef __APPLE__ + /** + * There seems to be a nasty bug when drawing using the same VAO reconfiguring. (see T71147) + * We just use a throwaway VAO for that. Note that this is likely to degrade performance. + **/ + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#else /* If using offset drawing with instancing, we must * use the default VAO and redo bindings. */ glBindVertexArray(GPU_vao_default()); +#endif batch_update_program_bindings(batch, i_first); } else { @@ -739,6 +752,12 @@ void GPU_batch_draw_advanced(GPUBatch *batch, int v_first, int v_count, int i_fi glEnable(GL_PRIMITIVE_RESTART); #endif } + +#ifdef __APPLE__ + if (vao != 0) { + glDeleteVertexArrays(1, &vao); + } +#endif } /* just draw some vertices and let shader place them where we want. */ diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 1a7b999514c..972ff87ebcf 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -29,8 +29,6 @@ #include "BLI_rect.h" #include "BLI_memblock.h" -#include "BIF_gl.h" - #include "DNA_vec_types.h" #include "DNA_userdef_types.h" diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 1b911226c6f..71e9da70c35 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -1029,11 +1029,11 @@ void IMB_colormanagement_init_default_view_settings( static void curve_mapping_apply_pixel(CurveMapping *curve_mapping, float *pixel, int channels) { if (channels == 1) { - pixel[0] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[0]); + pixel[0] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[0]); } else if (channels == 2) { - pixel[0] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[0]); - pixel[1] = BKE_curvemap_evaluateF(curve_mapping->cm, pixel[1]); + pixel[0] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[0]); + pixel[1] = BKE_curvemap_evaluateF(curve_mapping, curve_mapping->cm, pixel[1]); } else { BKE_curvemapping_evaluate_premulRGBF(curve_mapping, pixel, pixel); @@ -3904,10 +3904,11 @@ static void curve_mapping_to_ocio_settings(CurveMapping *curve_mapping, BKE_curvemapping_table_RGBA( curve_mapping, &curve_mapping_settings->lut, &curve_mapping_settings->lut_size); + curve_mapping_settings->use_extend_extrapolate = (curve_mapping->flag & + CUMA_EXTEND_EXTRAPOLATE) != 0; + for (i = 0; i < 4; i++) { CurveMap *cuma = curve_mapping->cm + i; - curve_mapping_settings->use_extend_extrapolate[i] = (cuma->flag & CUMA_EXTEND_EXTRAPOLATE) != - 0; curve_mapping_settings->range[i] = cuma->range; curve_mapping_settings->mintable[i] = cuma->mintable; curve_mapping_settings->ext_in_x[i] = cuma->ext_in[0]; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index b7834e2c7e0..b95a4ca3d96 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -28,6 +28,10 @@ #ifndef __DNA_ACTION_TYPES_H__ #define __DNA_ACTION_TYPES_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_listBase.h" #include "DNA_ID.h" #include "DNA_view2d_types.h" @@ -856,8 +860,8 @@ typedef enum eSAction_Flag { SACTION_SHOW_INTERPOLATION = (1 << 12), /* show extremes */ SACTION_SHOW_EXTREMES = (1 << 13), - /* show vertical line markers */ - SACTION_SHOW_MARKER_LINES = (1 << 14), + /* show markers region */ + SACTION_SHOW_MARKERS = (1 << 14), } eSAction_Flag; /* SpaceAction_Runtime.flag */ @@ -955,4 +959,8 @@ typedef enum eActionChannelFlag { ACHAN_MOVED = (1u << 31), } eActionChannelFlag; +#ifdef __cplusplus +} +#endif + #endif /* __DNA_ACTION_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index 219fc96554a..66adc547cf2 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -24,6 +24,7 @@ #ifndef __DNA_COLOR_TYPES_H__ #define __DNA_COLOR_TYPES_H__ +#include "DNA_defs.h" #include "DNA_vec_types.h" /* general defines for kernel functions */ @@ -47,7 +48,8 @@ enum { }; typedef struct CurveMap { - short totpoint, flag; + short totpoint; + short flag DNA_DEPRECATED; /** Quick multiply value for reading table. */ float range; @@ -67,9 +69,6 @@ typedef struct CurveMap { float premul_ext_out[2]; } CurveMap; -/* cuma->flag */ -#define CUMA_EXTEND_EXTRAPOLATE 1 - typedef struct CurveMapping { /** Cur; for buttons, to show active curve. */ int flag, cur; @@ -93,11 +92,17 @@ typedef struct CurveMapping { char _pad[6]; } CurveMapping; -/* cumapping->flag */ -#define CUMA_DO_CLIP (1 << 0) -#define CUMA_PREMULLED (1 << 1) -#define CUMA_DRAW_CFRA (1 << 2) -#define CUMA_DRAW_SAMPLE (1 << 3) +/* CurveMapping.flag */ +typedef enum eCurveMappingFlags { + CUMA_DO_CLIP = (1 << 0), + CUMA_PREMULLED = (1 << 1), + CUMA_DRAW_CFRA = (1 << 2), + CUMA_DRAW_SAMPLE = (1 << 3), + + /* The curve is extended by extrapolation. When not set the curve is extended + * Horizontally */ + CUMA_EXTEND_EXTRAPOLATE = (1 << 4), +} eCurveMappingFlags; /* cumapping->preset */ typedef enum eCurveMappingPreset { diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index fb9e522dfa9..60e0eb2976e 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -28,6 +28,10 @@ #include "DNA_ID.h" #include "DNA_customdata_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Ipo; struct Key; @@ -277,4 +281,8 @@ enum { #define MESH_MAX_VERTS 2000000000L +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 8de79d9ea2b..2e0c43bdb51 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -24,6 +24,10 @@ #ifndef __DNA_MOVIECLIP_TYPES_H__ #define __DNA_MOVIECLIP_TYPES_H__ +#ifdef __cplusplus +extern "C" { +#endif + #include "DNA_ID.h" #include "DNA_tracking_types.h" #include "DNA_color_types.h" /* for color management */ @@ -207,4 +211,8 @@ enum { MCLIP_PROXY_RENDER_USE_FALLBACK_RENDER = 2, }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 0de43c1632f..54ae38f608c 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -483,13 +483,23 @@ typedef struct ImageFormatData { #define R_IMF_FLAG_PREVIEW_JPG (1 << 1) /* was R_PREVIEW_JPG */ /* return values from BKE_imtype_valid_depths, note this is depts per channel */ -#define R_IMF_CHAN_DEPTH_1 (1 << 0) /* 1bits (unused) */ -#define R_IMF_CHAN_DEPTH_8 (1 << 1) /* 8bits (default) */ -#define R_IMF_CHAN_DEPTH_10 (1 << 2) /* 10bits (uncommon, Cineon/DPX support) */ -#define R_IMF_CHAN_DEPTH_12 (1 << 3) /* 12bits (uncommon, jp2/DPX support) */ -#define R_IMF_CHAN_DEPTH_16 (1 << 4) /* 16bits (tiff, halff float exr) */ -#define R_IMF_CHAN_DEPTH_24 (1 << 5) /* 24bits (unused) */ -#define R_IMF_CHAN_DEPTH_32 (1 << 6) /* 32bits (full float exr) */ +/* ImageFormatData.depth */ +typedef enum eImageFormatDepth { + /* 1bits (unused) */ + R_IMF_CHAN_DEPTH_1 = (1 << 0), + /* 8bits (default) */ + R_IMF_CHAN_DEPTH_8 = (1 << 1), + /* 10bits (uncommon, Cineon/DPX support) */ + R_IMF_CHAN_DEPTH_10 = (1 << 2), + /* 12bits (uncommon, jp2/DPX support) */ + R_IMF_CHAN_DEPTH_12 = (1 << 3), + /* 16bits (tiff, half float exr) */ + R_IMF_CHAN_DEPTH_16 = (1 << 4), + /* 24bits (unused) */ + R_IMF_CHAN_DEPTH_24 = (1 << 5), + /* 32bits (full float exr) */ + R_IMF_CHAN_DEPTH_32 = (1 << 6), +} eImageFormatDepth; /* ImageFormatData.planes */ #define R_IMF_PLANES_RGB 24 @@ -1288,14 +1298,11 @@ typedef enum { UNIFIED_PAINT_WEIGHT = (1 << 5), UNIFIED_PAINT_COLOR = (1 << 6), - /* only used if unified size is enabled, mirrors the brush flags - * BRUSH_LOCK_SIZE and BRUSH_SIZE_PRESSURE */ + /* only used if unified size is enabled, mirrors the brush flag BRUSH_LOCK_SIZE */ UNIFIED_PAINT_BRUSH_LOCK_SIZE = (1 << 2), - UNIFIED_PAINT_BRUSH_SIZE_PRESSURE = (1 << 3), + UNIFIED_PAINT_FLAG_UNUSED_0 = (1 << 3), - /* only used if unified alpha is enabled, mirrors the brush flag - * BRUSH_ALPHA_PRESSURE */ - UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE = (1 << 4), + UNIFIED_PAINT_FLAG_UNUSED_1 = (1 << 4), } eUnifiedPaintSettingsFlags; typedef struct CurvePaintSettings { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 8d9dc77c49b..fb941a61ae8 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -37,6 +37,10 @@ #include "DNA_vec_types.h" #include "DNA_vfont_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct Ipo; struct MovieClip; struct Scene; @@ -680,4 +684,8 @@ enum { SEQ_CACHE_PREFETCH_ENABLE = (1 << 10), }; +#ifdef __cplusplus +} +#endif + #endif /* __DNA_SEQUENCE_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 1ce282a5a91..7692a4b17bb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -466,8 +466,8 @@ typedef enum eGraphEdit_Flag { /* normalize curves on display */ SIPO_NORMALIZE = (1 << 14), SIPO_NORMALIZE_FREEZE = (1 << 15), - /* show vertical line for every marker */ - SIPO_MARKER_LINES = (1 << 16), + /* show markers region */ + SIPO_SHOW_MARKERS = (1 << 16), } eGraphEdit_Flag; /* SpaceGraph.mode (Graph Editor Mode) */ @@ -532,8 +532,8 @@ typedef enum eSpaceNla_Flag { SNLA_NOREALTIMEUPDATES = (1 << 6), /* don't show local strip marker indications */ SNLA_NOLOCALMARKERS = (1 << 7), - /* show vertical line for every marker */ - SNLA_SHOW_MARKER_LINES = (1 << 8), + /* show markers region */ + SNLA_SHOW_MARKERS = (1 << 8), } eSpaceNla_Flag; /** \} */ @@ -615,7 +615,7 @@ typedef enum eSpaceSeq_Flag { SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */ SEQ_SHOW_SAFE_CENTER = (1 << 9), SEQ_SHOW_METADATA = (1 << 10), - SEQ_SHOW_MARKER_LINES = (1 << 11), + SEQ_SHOW_MARKERS = (1 << 11), /* show markers region */ } eSpaceSeq_Flag; /* SpaceSeq.view */ diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index 365b1993d80..f6c8c0b1f6d 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -46,6 +46,7 @@ .single_color = {0.8f, 0.8f, 0.8f}, \ .background_color = {0.05f, 0.05f, 0.05f}, \ .studiolight_intensity = 1.0f, \ + .render_pass = SCE_PASS_COMBINED, \ } #define _DNA_DEFAULT_View3DOverlay \ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 7b832f1b646..a9a20980677 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -179,6 +179,10 @@ typedef struct View3DShading { float curvature_ridge_factor; float curvature_valley_factor; + /* Render pass displayed in the viewport. Is an `eScenePassType` where one bit is set */ + int render_pass; + char _pad2[4]; + struct IDProperty *prop; } View3DShading; diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 011e373cc61..679ccc9725b 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -123,6 +123,14 @@ static void rna_CurveMapping_tone_update(Main *UNUSED(bmain), WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } +static void rna_CurveMapping_extend_update(Main *UNUSED(bmain), + Scene *UNUSED(scene), + PointerRNA *UNUSED(ptr)) +{ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); +} + static void rna_CurveMapping_clipminx_range( PointerRNA *ptr, float *min, float *max, float *UNUSED(softmin), float *UNUSED(softmax)) { @@ -670,8 +678,17 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) } /* this function only exists because #BKE_curvemap_evaluateF uses a 'const' qualifier */ -static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, float value) +static float rna_CurveMapping_evaluateF(struct CurveMapping *cumap, + ReportList *reports, + struct CurveMap *cuma, + float value) { + if (&cumap->cm[0] != cuma && &cumap->cm[1] != cuma && &cumap->cm[2] != cuma && + &cumap->cm[3] != cuma) { + BKE_report(reports, RPT_ERROR, "CurveMapping does not own CurveMap"); + return 0.0f; + } + if (!cuma->table) { BKE_report( reports, @@ -679,7 +696,7 @@ static float rna_CurveMap_evaluateF(struct CurveMap *cuma, ReportList *reports, "CurveMap table not initialized, call initialize() on CurveMapping owner of the CurveMap"); return 0.0f; } - return BKE_curvemap_evaluateF(cuma, value); + return BKE_curvemap_evaluateF(cumap, cuma, value); } static void rna_CurveMap_initialize(struct CurveMapping *cumap) @@ -758,58 +775,22 @@ static void rna_def_curvemap_points_api(BlenderRNA *brna, PropertyRNA *cprop) static void rna_def_curvemap(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop, *parm; - FunctionRNA *func; - - static const EnumPropertyItem prop_extend_items[] = { - {0, "HORIZONTAL", 0, "Horizontal", ""}, - {CUMA_EXTEND_EXTRAPOLATE, "EXTRAPOLATED", 0, "Extrapolated", ""}, - {0, NULL, 0, NULL, NULL}, - }; + PropertyRNA *prop; srna = RNA_def_struct(brna, "CurveMap", NULL); RNA_def_struct_ui_text(srna, "CurveMap", "Curve in a curve mapping"); - prop = RNA_def_property(srna, "extend", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); - RNA_def_property_enum_items(prop, prop_extend_items); - RNA_def_property_ui_text(prop, "Extend", "Extrapolate the curve or extend it horizontally"); - prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "curve", "totpoint"); RNA_def_property_struct_type(prop, "CurveMapPoint"); RNA_def_property_ui_text(prop, "Points", ""); rna_def_curvemap_points_api(brna, prop); - - func = RNA_def_function(srna, "evaluate", "rna_CurveMap_evaluateF"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - RNA_def_function_ui_description(func, "Evaluate curve at given location"); - parm = RNA_def_float(func, - "position", - 0.0f, - -FLT_MAX, - FLT_MAX, - "Position", - "Position to evaluate curve at", - -FLT_MAX, - FLT_MAX); - RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); - parm = RNA_def_float(func, - "value", - 0.0f, - -FLT_MAX, - FLT_MAX, - "Value", - "Value of curve at given location", - -FLT_MAX, - FLT_MAX); - RNA_def_function_return(func, parm); } static void rna_def_curvemapping(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *parm; FunctionRNA *func; static const EnumPropertyItem tone_items[] = { @@ -818,6 +799,12 @@ static void rna_def_curvemapping(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem prop_extend_items[] = { + {0, "HORIZONTAL", 0, "Horizontal", ""}, + {CUMA_EXTEND_EXTRAPOLATE, "EXTRAPOLATED", 0, "Extrapolated", ""}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "CurveMapping", NULL); RNA_def_struct_ui_text( srna, @@ -860,6 +847,12 @@ static void rna_def_curvemapping(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip Max Y", ""); RNA_def_property_float_funcs(prop, NULL, NULL, "rna_CurveMapping_clipmaxy_range"); + prop = RNA_def_property(srna, "extend", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); + RNA_def_property_enum_items(prop, prop_extend_items); + RNA_def_property_ui_text(prop, "Extend", "Extrapolate the curve or extend it horizontally"); + RNA_def_property_update(prop, 0, "rna_CurveMapping_extend_update"); + prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_funcs(prop, "rna_CurveMapping_curves_begin", @@ -894,6 +887,32 @@ static void rna_def_curvemapping(BlenderRNA *brna) func = RNA_def_function(srna, "initialize", "rna_CurveMap_initialize"); RNA_def_function_ui_description(func, "Initialize curve"); + + func = RNA_def_function(srna, "evaluate", "rna_CurveMapping_evaluateF"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Evaluate curve at given location"); + parm = RNA_def_pointer(func, "curve", "CurveMap", "curve", "Curve to evaluate"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float(func, + "position", + 0.0f, + -FLT_MAX, + FLT_MAX, + "Position", + "Position to evaluate curve at", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "value", + 0.0f, + -FLT_MAX, + FLT_MAX, + "Value", + "Value of curve at given location", + -FLT_MAX, + FLT_MAX); + RNA_def_function_return(func, parm); } static void rna_def_color_ramp_element(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index d167c650683..997a5f5ca45 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -31,8 +31,6 @@ #include "BLI_utildefines.h" #include "BLI_path_util.h" -#include "BIF_gl.h" - #include "RNA_define.h" #include "RNA_enum_types.h" @@ -52,6 +50,8 @@ # include "DNA_image_types.h" # include "DNA_scene_types.h" +# include "GPU_glew.h" + # include "MEM_guardedalloc.h" static void rna_ImagePackedFile_save(ImagePackedFile *imapf, Main *bmain, ReportList *reports) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 2b47b1664d7..cca82abc9da 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3411,17 +3411,6 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Secondary Color", ""); RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update"); - prop = RNA_def_property(srna, "use_pressure_size", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_SIZE_PRESSURE); - RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); - RNA_def_property_ui_text(prop, "Size Pressure", "Enable tablet pressure sensitivity for size"); - - prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", UNIFIED_PAINT_BRUSH_ALPHA_PRESSURE); - RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); - RNA_def_property_ui_text( - prop, "Strength Pressure", "Enable tablet pressure sensitivity for strength"); - prop = RNA_def_property(srna, "use_locked_size", PROP_ENUM, PROP_NONE); /* as an enum */ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag"); RNA_def_property_enum_items(prop, brush_size_unit_items); diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index 8a06d594c1f..3562569acec 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -216,7 +216,7 @@ static void rna_Scene_alembic_export(Scene *scene, bool vcolors, bool apply_subdiv, bool flatten_hierarchy, - bool visible_layers_only, + bool visible_objects_only, bool renderable_only, bool face_sets, bool use_subdiv_schema, @@ -251,7 +251,7 @@ static void rna_Scene_alembic_export(Scene *scene, .vcolors = vcolors, .apply_subdiv = apply_subdiv, .flatten_hierarchy = flatten_hierarchy, - .visible_layers_only = visible_layers_only, + .visible_objects_only = visible_objects_only, .renderable_only = renderable_only, .face_sets = face_sets, .use_subdiv_schema = use_subdiv_schema, @@ -391,7 +391,7 @@ void RNA_api_scene(StructRNA *srna) func, "apply_subdiv", 1, "Subsurfs as meshes", "Export subdivision surfaces as meshes"); RNA_def_boolean(func, "flatten", 0, "Flatten hierarchy", "Flatten hierarchy"); RNA_def_boolean(func, - "visible_layers_only", + "visible_objects_only", 0, "Visible layers only", "Export only objects in visible layers"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index e14fff0220e..c97d19f47e5 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -374,6 +374,18 @@ static const EnumPropertyItem rna_enum_studio_light_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_view3dshading_render_pass_type_items[] = { + {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, + /* {SCE_PASS_Z, "Z", 0, "Z", ""},*/ + {SCE_PASS_AO, "AO", 0, "Ambient Occlusion", ""}, + {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, + {SCE_PASS_MIST, "MIST", 0, "Mist", ""}, + {SCE_PASS_SUBSURFACE_DIRECT, "SUBSURFACE_DIRECT", 0, "Subsurface Direct", ""}, + /* {SCE_PASS_SUBSURFACE_INDIRECT, "SUBSURFACE_INDIRECT", 0, "Subsurface Indirect", ""}, */ + {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE_COLOR", 0, "Subsurface Color", ""}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_clip_editor_mode_items[] = { {SC_MODE_TRACKING, "TRACKING", ICON_ANIM_DATA, "Tracking", "Show tracking and solving tools"}, {SC_MODE_MASKEDIT, "MASK", ICON_MOD_MASK, "Mask", "Show mask editing tools"}, @@ -3280,6 +3292,12 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna) RNA_def_property_ui_range(prop, 0.00f, 1.0f, 1, 3); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "render_pass", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "render_pass"); + RNA_def_property_enum_items(prop, rna_enum_view3dshading_render_pass_type_items); + RNA_def_property_ui_text(prop, "Render Pass", "Render Pass to show in the viewport"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); } static void rna_def_space_view3d_overlay(BlenderRNA *brna) @@ -4542,9 +4560,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Seconds", "Show timing in seconds not frames"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL); prop = RNA_def_property(srna, "show_annotation", PROP_BOOLEAN, PROP_NONE); @@ -4800,7 +4821,7 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) prop = RNA_def_property(srna, "show_pose_markers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_POSEMARKERS_SHOW); RNA_def_property_ui_text(prop, - "Show Pose Markers", + "Toggle Pose Markers", "Show markers belonging to the active action instead of Scene markers " "(Action and Shape Key Editors only)"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); @@ -4829,10 +4850,13 @@ static void rna_def_space_dopesheet(BlenderRNA *brna) "comparison with adjacent keys"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL); /* editing */ prop = RNA_def_property(srna, "use_auto_merge_keyframes", PROP_BOOLEAN, PROP_NONE); @@ -4986,9 +5010,12 @@ static void rna_def_space_graph(BlenderRNA *brna) "Display groups and channels with colors matching their corresponding groups"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); /* editing */ @@ -5097,10 +5124,13 @@ static void rna_def_space_nla(BlenderRNA *brna) "Show action-local markers on the strips, useful when synchronizing timing across strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); - prop = RNA_def_property(srna, "show_marker_lines", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_SHOW_MARKER_LINES); - RNA_def_property_ui_text(prop, "Show Marker Lines", "Show a vertical line for every marker"); - RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL); + prop = RNA_def_property(srna, "show_markers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SNLA_SHOW_MARKERS); + RNA_def_property_ui_text( + prop, + "Show Markers", + "If any exists, show markers in a separate row at the bottom of the editor"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); /* editing */ prop = RNA_def_property(srna, "use_realtime_update", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/nodes/shader/nodes/node_shader_curves.c b/source/blender/nodes/shader/nodes/node_shader_curves.c index f5c89e6ba41..6292d7b5062 100644 --- a/source/blender/nodes/shader/nodes/node_shader_curves.c +++ b/source/blender/nodes/shader/nodes/node_shader_curves.c @@ -147,7 +147,7 @@ static int gpu_shader_curve_rgb(GPUMaterial *mat, ext_rgba[a][2] = cm->maxtable; range_rgba[a] = 1.0f / max_ff(1e-8f, cm->maxtable - cm->mintable); /* Compute extrapolation gradients. */ - if ((cm->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { + if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE) != 0) { ext_rgba[a][1] = (cm->ext_in[0] != 0.0f) ? (cm->ext_in[1] / (cm->ext_in[0] * range_rgba[a])) : 1e8f; diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index af595de2ee4..b601a35f7f2 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -1091,7 +1091,9 @@ static PyObject *bpy_bmesh_to_mesh(BPy_BMesh *self, PyObject *args) bm = self->bm; struct Main *bmain = NULL; - struct BMeshToMeshParams params = {0}; + struct BMeshToMeshParams params = { + .update_shapekey_indices = true, + }; if (me->id.tag & LIB_TAG_NO_MAIN) { /* Mesh might be coming from a self-contained source like object.to_mesh(). No need to remap * anything in this case. */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6fb2b2fd7ee..d49e782c317 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -7818,7 +7818,7 @@ static int pyrna_deferred_register_props(StructRNA *srna, PyObject *class_dict) } } - { + if (ret == 0) { /* This block can be removed once 2.8x is released and annotations are in use. */ bool has_warning = false; while (PyDict_Next(class_dict, &pos, &key, &item)) { diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 44fd9158934..72ccbb0fb55 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -821,15 +821,18 @@ typedef struct ARegion *(*wmTooltipInitFn)(struct bContext *C, void WM_tooltip_immediate_init(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init); void WM_tooltip_timer_init_ex(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init, double delay); void WM_tooltip_timer_init(struct bContext *C, struct wmWindow *win, + struct ScrArea *sa, struct ARegion *ar, wmTooltipInitFn init); void WM_tooltip_timer_clear(struct bContext *C, struct wmWindow *win); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 15ad8cbedc4..0c3a5f92113 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -894,6 +894,8 @@ typedef struct wmDropBox { typedef struct wmTooltipState { /** Create tooltip on this event. */ struct wmTimer *timer; + /** The area the tooltip is created in. */ + struct ScrArea *area_from; /** The region the tooltip is created in. */ struct ARegion *region_from; /** The tooltip region. */ diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 901594850dd..e2462bb59b1 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -34,14 +34,15 @@ #include "BLI_blenlib.h" -#include "BIF_gl.h" #include "BIF_glutil.h" #include "BKE_context.h" #include "BKE_idcode.h" +#include "GPU_glew.h" #include "GPU_shader.h" #include "GPU_state.h" +#include "GPU_viewport.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 2f538a19ba2..09b7d89fc2b 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -39,8 +39,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -#include "BIF_gl.h" - #include "BKE_context.h" #include "BKE_image.h" #include "BKE_main.h" diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c63bc24d58e..180a518de2b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2850,7 +2850,7 @@ static int wm_handlers_do_intern(bContext *C, wmEvent *event, ListBase *handlers if (wm_gizmomap_highlight_set(gzmap, C, gz, part)) { if (gz != NULL) { if (U.flag & USER_TOOLTIPS) { - WM_tooltip_timer_init(C, CTX_wm_window(C), region, WM_gizmomap_tooltip_init); + WM_tooltip_timer_init(C, CTX_wm_window(C), area, region, WM_gizmomap_tooltip_init); } } } diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c index 9b62e532132..54953c097eb 100644 --- a/source/blender/windowmanager/intern/wm_stereo.c +++ b/source/blender/windowmanager/intern/wm_stereo.c @@ -32,8 +32,6 @@ #include "BLI_utildefines.h" -#include "BIF_gl.h" - #include "BKE_context.h" #include "BKE_global.h" #include "BKE_report.h" @@ -44,6 +42,7 @@ #include "GPU_immediate.h" #include "GPU_texture.h" +#include "GPU_viewport.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 2f40947b395..6a5de84ac31 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -29,9 +29,9 @@ #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" -#include "BIF_gl.h" - +#include "GPU_glew.h" #include "GPU_matrix.h" +#include "GPU_viewport.h" #include "WM_api.h" diff --git a/source/blender/windowmanager/intern/wm_tooltip.c b/source/blender/windowmanager/intern/wm_tooltip.c index 3a219d7a573..b192ea94010 100644 --- a/source/blender/windowmanager/intern/wm_tooltip.c +++ b/source/blender/windowmanager/intern/wm_tooltip.c @@ -42,7 +42,8 @@ double WM_tooltip_time_closed(void) return g_tooltip_time_closed; } -void WM_tooltip_immediate_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) +void WM_tooltip_immediate_init( + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init) { WM_tooltip_timer_clear(C, win); @@ -50,13 +51,14 @@ void WM_tooltip_immediate_init(bContext *C, wmWindow *win, ARegion *ar, wmToolti if (screen->tool_tip == NULL) { screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); } + screen->tool_tip->area_from = sa; screen->tool_tip->region_from = ar; screen->tool_tip->init = init; WM_tooltip_init(C, win); } void WM_tooltip_timer_init_ex( - bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init, double delay) + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init, double delay) { WM_tooltip_timer_clear(C, win); @@ -65,14 +67,16 @@ void WM_tooltip_timer_init_ex( if (screen->tool_tip == NULL) { screen->tool_tip = MEM_callocN(sizeof(*screen->tool_tip), __func__); } + screen->tool_tip->area_from = sa; screen->tool_tip->region_from = ar; screen->tool_tip->timer = WM_event_add_timer(wm, win, TIMER, delay); screen->tool_tip->init = init; } -void WM_tooltip_timer_init(bContext *C, wmWindow *win, ARegion *ar, wmTooltipInitFn init) +void WM_tooltip_timer_init( + bContext *C, wmWindow *win, ScrArea *sa, ARegion *ar, wmTooltipInitFn init) { - WM_tooltip_timer_init_ex(C, win, ar, init, UI_TOOLTIP_DELAY); + WM_tooltip_timer_init_ex(C, win, sa, ar, init, UI_TOOLTIP_DELAY); } void WM_tooltip_timer_clear(bContext *C, wmWindow *win) @@ -112,11 +116,21 @@ void WM_tooltip_init(bContext *C, wmWindow *win) } const int pass_prev = screen->tool_tip->pass; double pass_delay = 0.0; - screen->tool_tip->region = screen->tool_tip->init(C, - screen->tool_tip->region_from, - &screen->tool_tip->pass, - &pass_delay, - &screen->tool_tip->exit_on_event); + + { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_area_set(C, screen->tool_tip->area_from); + CTX_wm_region_set(C, screen->tool_tip->region_from); + screen->tool_tip->region = screen->tool_tip->init(C, + screen->tool_tip->region_from, + &screen->tool_tip->pass, + &pass_delay, + &screen->tool_tip->exit_on_event); + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, ar_prev); + } + copy_v2_v2_int(screen->tool_tip->event_xy, &win->eventstate->x); if (pass_prev != screen->tool_tip->pass) { /* The pass changed, add timer for next pass. */ diff --git a/tests/gtests/CMakeLists.txt b/tests/gtests/CMakeLists.txt index 285b414e997..54a1ee41198 100644 --- a/tests/gtests/CMakeLists.txt +++ b/tests/gtests/CMakeLists.txt @@ -13,6 +13,7 @@ if(WITH_GTESTS) add_subdirectory(testing) add_subdirectory(blenlib) + add_subdirectory(blenloader) add_subdirectory(guardedalloc) add_subdirectory(bmesh) if(WITH_ALEMBIC) diff --git a/tests/gtests/blenloader/CMakeLists.txt b/tests/gtests/blenloader/CMakeLists.txt new file mode 100644 index 00000000000..f8457e0164b --- /dev/null +++ b/tests/gtests/blenloader/CMakeLists.txt @@ -0,0 +1,90 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2019 by Blender Foundation. +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + .. + ../../../source/blender/blenkernel + ../../../source/blender/blenlib + ../../../source/blender/blenloader + ../../../source/blender/depsgraph + ../../../source/blender/imbuf + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../source/blender/windowmanager + ../../../intern/guardedalloc + ${GLOG_INCLUDE_DIRS} + ${GFLAGS_INCLUDE_DIRS} + ../../../extern/gtest/include +) + +set(SRC + blendfile_loading_base_test.cc + blendfile_loading_base_test.h +) + +set(LIB +) + +blender_add_lib(bf_blenloader_test "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") + + +set(INC + . + .. + ../../../source/blender/blenlib + ../../../source/blender/blenloader + ../../../source/blender/blenkernel + ../../../source/blender/makesdna + ../../../source/blender/makesrna + ../../../source/blender/depsgraph + ../../../intern/guardedalloc +) + +set(LIB + bf_blenloader_test + bf_blenloader + + # Should not be needed but gives windows linker errors if the ocio libs are linked before this: + bf_intern_opencolorio + bf_gpu +) + +include_directories(${INC}) + +setup_libdirs() +get_property(BLENDER_SORTED_LIBS GLOBAL PROPERTY BLENDER_SORTED_LIBS_PROP) + + +set(SRC + blendfile_load_test.cc +) +if(WITH_BUILDINFO) + list(APPEND SRC "$<TARGET_OBJECTS:buildinfoobj>") +endif() + +BLENDER_SRC_GTEST_EX( + NAME blenloader + SRC "${SRC}" + EXTRA_LIBS "${LIB}" + COMMAND_ARGS --test-assets-dir "${CMAKE_SOURCE_DIR}/../lib/tests") + +unset(_buildinfo_src) + +setup_liblinks(blenloader_test) diff --git a/tests/gtests/blenloader/blendfile_load_test.cc b/tests/gtests/blenloader/blendfile_load_test.cc new file mode 100644 index 00000000000..2ba3e3fcd88 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_load_test.cc @@ -0,0 +1,31 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#include "blendfile_loading_base_test.h" + +class BlendfileLoadingTest : public BlendfileLoadingBaseTest { +}; + +TEST_F(BlendfileLoadingTest, CanaryTest) +{ + /* Load the smallest blend file we have in the SVN lib/tests directory. */ + if (!blendfile_load("modifier_stack/array_test.blend")) { + return; + } + depsgraph_create(DAG_EVAL_RENDER); + EXPECT_NE(nullptr, this->depsgraph); +} diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.cc b/tests/gtests/blenloader/blendfile_loading_base_test.cc new file mode 100644 index 00000000000..5a1a7f9aae5 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_loading_base_test.cc @@ -0,0 +1,172 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#include "blendfile_loading_base_test.h" + +extern "C" { +#include "BKE_appdir.h" +#include "BKE_blender.h" +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_image.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_node.h" +#include "BKE_scene.h" + +#include "BLI_threads.h" +#include "BLI_path_util.h" + +#include "BLO_readfile.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph.h" + +#include "DNA_genfile.h" /* for DNA_sdna_current_init() */ +#include "DNA_windowmanager_types.h" + +#include "IMB_imbuf.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_define.h" + +#include "WM_api.h" +#include "wm.h" +} + +DEFINE_string(test_assets_dir, "", "lib/tests directory from SVN containing the test assets."); + +BlendfileLoadingBaseTest::~BlendfileLoadingBaseTest() +{ +} + +void BlendfileLoadingBaseTest::SetUpTestCase() +{ + testing::Test::SetUpTestCase(); + + /* Minimal code to make loading a blendfile and constructing a depsgraph not crash, copied from + * main() in creator.c. */ + BLI_threadapi_init(); + + DNA_sdna_current_init(); + BKE_blender_globals_init(); + IMB_init(); + BKE_images_init(); + BKE_modifier_init(); + DEG_register_node_types(); + RNA_init(); + init_nodesystem(); + + G.background = true; + G.factory_startup = true; + + /* Allocate a dummy window manager. The real window manager will try and load Python scripts from + * the release directory, which it won't be able to find. */ + ASSERT_EQ(G.main->wm.first, nullptr); + G.main->wm.first = MEM_callocN(sizeof(wmWindowManager), __func__); +} + +void BlendfileLoadingBaseTest::TearDownTestCase() +{ + if (G.main->wm.first != nullptr) { + MEM_freeN(G.main->wm.first); + G.main->wm.first = nullptr; + } + + /* Copied from WM_exit_ex() in wm_init_exit.c, and cherry-picked those lines that match the + * allocation/initialisation done in SetUpTestCase(). */ + BKE_blender_free(); + RNA_exit(); + + DEG_free_node_types(); + DNA_sdna_current_free(); + BLI_threadapi_exit(); + + BKE_blender_atexit(); + + if (MEM_get_memory_blocks_in_use() != 0) { + size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); + printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", + MEM_get_memory_blocks_in_use(), + (double)mem_in_use / 1024 / 1024); + MEM_printmemlist(); + } + + BKE_tempdir_session_purge(); + + testing::Test::TearDownTestCase(); +} + +void BlendfileLoadingBaseTest::TearDown() +{ + depsgraph_free(); + blendfile_free(); + + testing::Test::TearDown(); +} + +bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath) +{ + if (FLAGS_test_assets_dir.empty()) { + ADD_FAILURE() + << "Pass the flag --test-assets-dir and point to the lib/tests directory from SVN."; + return false; + } + + char abspath[FILENAME_MAX]; + BLI_path_join(abspath, sizeof(abspath), FLAGS_test_assets_dir.c_str(), filepath, NULL); + + bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, NULL /* reports */); + if (bfile == nullptr) { + ADD_FAILURE() << "Unable to load file '" << filepath << "' from test assets dir '" + << FLAGS_test_assets_dir << "'"; + return false; + } + return true; +} + +void BlendfileLoadingBaseTest::blendfile_free() +{ + if (bfile == nullptr) { + return; + } + + wmWindowManager *wm = static_cast<wmWindowManager *>(bfile->main->wm.first); + if (wm != nullptr) { + wm_close_and_free(NULL, wm); + } + BLO_blendfiledata_free(bfile); + bfile = nullptr; +} + +void BlendfileLoadingBaseTest::depsgraph_create(eEvaluationMode depsgraph_evaluation_mode) +{ + depsgraph = DEG_graph_new( + bfile->main, bfile->curscene, bfile->cur_view_layer, depsgraph_evaluation_mode); + DEG_graph_build_from_view_layer(depsgraph, bfile->main, bfile->curscene, bfile->cur_view_layer); + BKE_scene_graph_update_tagged(depsgraph, bfile->main); +} + +void BlendfileLoadingBaseTest::depsgraph_free() +{ + if (depsgraph == nullptr) { + return; + } + DEG_graph_free(depsgraph); + depsgraph = nullptr; +} diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.h b/tests/gtests/blenloader/blendfile_loading_base_test.h new file mode 100644 index 00000000000..466bbcd2392 --- /dev/null +++ b/tests/gtests/blenloader/blendfile_loading_base_test.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2019 by Blender Foundation. + */ +#ifndef __BLENDFILE_LOADING_BASE_TEST_H__ +#define __BLENDFILE_LOADING_BASE_TEST_H__ + +#include "testing/testing.h" +#include "DEG_depsgraph.h" + +struct BlendFileData; +struct Depsgraph; + +class BlendfileLoadingBaseTest : public testing::Test { + protected: + struct BlendFileData *bfile = nullptr; + struct Depsgraph *depsgraph = nullptr; + + public: + virtual ~BlendfileLoadingBaseTest(); + + /* Sets up Blender just enough to not crash on loading + * a blendfile and constructing a depsgraph. */ + static void SetUpTestCase(); + static void TearDownTestCase(); + + protected: + /* Frees the depsgraph & blendfile. */ + virtual void TearDown(); + + /* Loads a blend file from the lib/tests directory from SVN. + * Returns 'ok' flag (true=good, false=bad) and sets this->bfile. + * Fails the test if the file cannot be loaded (still returns though). + * Requires the CLI argument --test-asset-dir to point to ../../lib/tests. + * + * WARNING: only files saved with Blender 2.80+ can be loaded. Since Blender + * is only partially initialised (most importantly, without window manager), + * the space types are not registered, so any versioning code that handles + * those will SEGFAULT. + */ + bool blendfile_load(const char *filepath); + /* Free bfile if it is not nullptr. */ + void blendfile_free(); + + /* Create a depsgraph. Assumes a blend file has been loaded to this->bfile. */ + void depsgraph_create(eEvaluationMode depsgraph_evaluation_mode); + /* Free the depsgraph if it's not nullptr. */ + void depsgraph_free(); +}; + +#endif /* __BLENDFILE_LOADING_BASE_TEST_H__ */ diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py index 09e9b8981e3..9de1bc06d84 100755 --- a/tests/python/alembic_tests.py +++ b/tests/python/alembic_tests.py @@ -170,7 +170,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -188,7 +188,7 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'cubes_flat.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=True)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('cubes-hierarchy.blend', script) # Now check the resulting Alembic file. @@ -209,7 +209,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_hierarchical_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -227,7 +227,7 @@ class DupliGroupExportTest(AbstractAlembicTest): def test_flat_export(self, tempdir: pathlib.Path): abc = tempdir / 'dupligroup_hierarchical.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=True)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=True)" % abc.as_posix() self.run_blender('dupligroup-scene.blend', script) # Now check the resulting Alembic file. @@ -248,7 +248,7 @@ class CurveExportTest(AbstractAlembicTest): def test_export_single_curve(self, tempdir: pathlib.Path): abc = tempdir / 'single-curve.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False)" % abc.as_posix() + "renderable_only=True, visible_objects_only=True, flatten=False)" % abc.as_posix() self.run_blender('single-curve.blend', script) # Now check the resulting Alembic file. @@ -269,7 +269,7 @@ class HairParticlesExportTest(AbstractAlembicTest): def _do_test(self, tempdir: pathlib.Path, export_hair: bool, export_particles: bool) -> pathlib.Path: abc = tempdir / 'hair-particles.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=True, visible_layers_only=True, flatten=False, " \ + "renderable_only=True, visible_objects_only=True, flatten=False, " \ "export_hair=%r, export_particles=%r, as_background_job=False)" \ % (abc.as_posix(), export_hair, export_particles) self.run_blender('hair-particles.blend', script) @@ -330,7 +330,7 @@ class LongNamesExportTest(AbstractAlembicTest): def test_export_long_names(self, tempdir: pathlib.Path): abc = tempdir / 'long-names.abc' script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \ - "renderable_only=False, visible_layers_only=False, flatten=False)" % abc.as_posix() + "renderable_only=False, visible_objects_only=False, flatten=False)" % abc.as_posix() self.run_blender('long-names.blend', script) name_parts = [ |