Compare commits
3 Commits
spreadshee
...
temp-geome
Author | SHA1 | Date | |
---|---|---|---|
1da326f237 | |||
4ea3d24930 | |||
2495c0c539 |
@@ -2,7 +2,7 @@
|
||||
# Configuration of clang-format
|
||||
# =============================
|
||||
#
|
||||
# Tested to work with versions: 8 to 11.
|
||||
# Tested to work with versions: 6 to 8.
|
||||
|
||||
# This causes parameters on continuations to align to the opening brace.
|
||||
#
|
||||
@@ -255,6 +255,7 @@ ForEachMacros:
|
||||
- SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN
|
||||
- SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN
|
||||
- SEQ_ALL_BEGIN
|
||||
- SEQ_CURRENT_BEGIN
|
||||
- SURFACE_QUAD_ITER_BEGIN
|
||||
- foreach
|
||||
- ED_screen_areas_iter
|
||||
@@ -263,5 +264,8 @@ ForEachMacros:
|
||||
- MAP_SLOT_PROBING_BEGIN
|
||||
- VECTOR_SET_SLOT_PROBING_BEGIN
|
||||
|
||||
StatementMacros:
|
||||
- PyObject_VAR_HEAD
|
||||
# Use once we bump the minimum version to version 8.
|
||||
# # Without this string literals that in-line 'STRINGIFY' behave strangely (a bug?).
|
||||
# StatementMacros:
|
||||
# - PyObject_VAR_HEAD
|
||||
# - STRINGIFY
|
||||
|
@@ -43,6 +43,7 @@ Checks: >
|
||||
# the windows compiler currently.
|
||||
-modernize-raw-string-literal
|
||||
|
||||
WarningsAsErrors: '*'
|
||||
CheckOptions:
|
||||
- key: modernize-use-default-member-init.UseAssignment
|
||||
value: 1
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -46,6 +46,3 @@ Desktop.ini
|
||||
|
||||
# smoke simulation noise tile (generated)
|
||||
waveletNoiseTile.bin
|
||||
|
||||
# testing environment
|
||||
/Testing
|
||||
|
@@ -236,7 +236,9 @@ option(WITH_SYSTEM_AUDASPACE "Build with external audaspace library installed on
|
||||
mark_as_advanced(WITH_AUDASPACE)
|
||||
mark_as_advanced(WITH_SYSTEM_AUDASPACE)
|
||||
|
||||
set_and_warn_dependency(WITH_AUDASPACE WITH_SYSTEM_AUDASPACE OFF)
|
||||
if(NOT WITH_AUDASPACE)
|
||||
set(WITH_SYSTEM_AUDASPACE OFF)
|
||||
endif()
|
||||
|
||||
option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON)
|
||||
if(UNIX AND NOT APPLE)
|
||||
@@ -520,10 +522,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
mark_as_advanced(WITH_LINKER_LLD)
|
||||
endif()
|
||||
|
||||
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
||||
mark_as_advanced(WITH_COMPILER_ASAN)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
option(WITH_COMPILER_ASAN "Build and link against address sanitizer (only for Debug & RelWithDebInfo targets)." OFF)
|
||||
mark_as_advanced(WITH_COMPILER_ASAN)
|
||||
|
||||
if(WITH_COMPILER_ASAN)
|
||||
set(_asan_defaults "\
|
||||
-fsanitize=address \
|
||||
@@ -702,8 +704,10 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL)
|
||||
message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF")
|
||||
endif()
|
||||
|
||||
set_and_warn_dependency(WITH_PYTHON WITH_CYCLES OFF)
|
||||
set_and_warn_dependency(WITH_PYTHON WITH_DRACO OFF)
|
||||
if(NOT WITH_PYTHON)
|
||||
set(WITH_CYCLES OFF)
|
||||
set(WITH_DRACO OFF)
|
||||
endif()
|
||||
|
||||
if(WITH_DRACO AND NOT WITH_PYTHON_INSTALL)
|
||||
message(STATUS "WITH_DRACO requires WITH_PYTHON_INSTALL to be ON, disabling WITH_DRACO for now")
|
||||
@@ -775,7 +779,6 @@ if(WITH_INSTALL_PORTABLE)
|
||||
endif()
|
||||
|
||||
if(WITH_GHOST_SDL OR WITH_HEADLESS)
|
||||
message(STATUS "Disabling Ghost Wayland, X11, Input IME, and OpenXR")
|
||||
set(WITH_GHOST_WAYLAND OFF)
|
||||
set(WITH_GHOST_X11 OFF)
|
||||
set(WITH_X11_XINPUT OFF)
|
||||
@@ -806,7 +809,7 @@ endif()
|
||||
if(NOT WITH_CUDA_DYNLOAD)
|
||||
find_package(CUDA)
|
||||
if(NOT CUDA_FOUND)
|
||||
message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead")
|
||||
message("CUDA toolkit not found, using dynamic runtime loading of libraries instead")
|
||||
set(WITH_CUDA_DYNLOAD ON)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1232,7 +1235,6 @@ if(WITH_OPENMP)
|
||||
string(APPEND CMAKE_C_FLAGS " ${OpenMP_C_FLAGS}")
|
||||
string(APPEND CMAKE_CXX_FLAGS " ${OpenMP_CXX_FLAGS}")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
|
||||
string(APPEND CMAKE_MODULE_LINKER_FLAGS " ${OpenMP_LINKER_FLAGS}")
|
||||
else()
|
||||
# Typically avoid adding flags as defines but we can't
|
||||
# pass OpenMP flags to the linker for static builds, meaning
|
||||
@@ -1243,7 +1245,6 @@ if(WITH_OPENMP)
|
||||
find_library_static(OpenMP_LIBRARIES gomp ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "OpenMP not found, disabling WITH_OPENMP")
|
||||
set(WITH_OPENMP OFF)
|
||||
endif()
|
||||
|
||||
@@ -1319,7 +1320,6 @@ list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
|
||||
if(WITH_BULLET AND WITH_SYSTEM_BULLET)
|
||||
find_package(Bullet)
|
||||
if(NOT BULLET_FOUND)
|
||||
message(STATUS "Bullet not found, disabling WITH_BULLET")
|
||||
set(WITH_BULLET OFF)
|
||||
endif()
|
||||
else()
|
||||
|
@@ -129,10 +129,7 @@ Utilities
|
||||
Create a compressed archive of the source code.
|
||||
|
||||
* update:
|
||||
Updates git and all submodules and svn.
|
||||
|
||||
* update_code:
|
||||
Updates git and all submodules but not svn.
|
||||
updates git and all submodules
|
||||
|
||||
* format:
|
||||
Format source code using clang (uses PATHS if passed in). For example::
|
||||
@@ -525,9 +522,6 @@ icons_geom: .FORCE
|
||||
update: .FORCE
|
||||
$(PYTHON) ./build_files/utils/make_update.py
|
||||
|
||||
update_code: .FORCE
|
||||
$(PYTHON) ./build_files/utils/make_update.py --no-libraries
|
||||
|
||||
format: .FORCE
|
||||
PATH="../lib/${OS_NCASE}_${CPU}/llvm/bin/:../lib/${OS_NCASE}_centos7_${CPU}/llvm/bin/:../lib/${OS_NCASE}/llvm/bin/:$(PATH)" \
|
||||
$(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS)
|
||||
|
@@ -21,8 +21,7 @@ if(WIN32)
|
||||
endif()
|
||||
option(WITH_WEBP "Enable building of oiio with webp support" OFF)
|
||||
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
|
||||
cmake_host_system_information(RESULT NUM_CORES QUERY NUMBER_OF_LOGICAL_CORES)
|
||||
set(MAKE_THREADS ${NUM_CORES} CACHE STRING "Number of threads to run make with")
|
||||
set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
|
||||
|
||||
if(NOT BUILD_MODE)
|
||||
set(BUILD_MODE "Release")
|
||||
|
@@ -56,7 +56,6 @@ list(APPEND ZLIB_LIBRARIES ${BZIP2_LIBRARIES})
|
||||
if(WITH_OPENAL)
|
||||
find_package(OpenAL)
|
||||
if(NOT OPENAL_FOUND)
|
||||
message(WARNING "OpenAL not found, disabling WITH_OPENAL")
|
||||
set(WITH_OPENAL OFF)
|
||||
endif()
|
||||
endif()
|
||||
@@ -66,7 +65,6 @@ if(WITH_JACK)
|
||||
NAMES jackmp
|
||||
)
|
||||
if(NOT JACK_FRAMEWORK)
|
||||
message(STATUS "JACK not found, disabling WITH_JACK")
|
||||
set(WITH_JACK OFF)
|
||||
else()
|
||||
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
|
||||
@@ -104,7 +102,6 @@ endif()
|
||||
if(WITH_USD)
|
||||
find_package(USD)
|
||||
if(NOT USD_FOUND)
|
||||
message(STATUS "USD not found, disabling WITH_USD")
|
||||
set(WITH_USD OFF)
|
||||
endif()
|
||||
endif()
|
||||
@@ -149,7 +146,7 @@ if(WITH_PYTHON)
|
||||
|
||||
set(PYTHON_INCLUDE_DIR "${_py_framework}/include/python${PYTHON_VERSION}")
|
||||
set(PYTHON_EXECUTABLE "${_py_framework}/bin/python${PYTHON_VERSION}")
|
||||
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}")
|
||||
set(PYTHON_LIBPATH "${_py_framework}/lib/python${PYTHON_VERSION}/config-${PYTHON_VERSION}")
|
||||
# set(PYTHON_LIBRARY python${PYTHON_VERSION})
|
||||
# set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework Python") # won't build with this enabled
|
||||
|
||||
@@ -311,7 +308,7 @@ if(WITH_OPENCOLORIO)
|
||||
|
||||
if(NOT OPENCOLORIO_FOUND)
|
||||
set(WITH_OPENCOLORIO OFF)
|
||||
message(STATUS "OpenColorIO not found, disabling WITH_OPENCOLORIO")
|
||||
message(STATUS "OpenColorIO not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -360,7 +357,7 @@ if(WITH_CYCLES_OSL)
|
||||
if(OSL_INCLUDE_DIR AND OSL_LIBRARIES AND OSL_COMPILER AND OSL_SHADER_DIR)
|
||||
set(OSL_FOUND TRUE)
|
||||
else()
|
||||
message(WARNING "OSL not found, disabling WITH_CYCLES_OSL")
|
||||
message(STATUS "OSL not found")
|
||||
set(WITH_CYCLES_OSL OFF)
|
||||
endif()
|
||||
endif()
|
||||
@@ -388,7 +385,7 @@ if(WITH_OPENIMAGEDENOISE)
|
||||
|
||||
if(NOT OPENIMAGEDENOISE_FOUND)
|
||||
set(WITH_OPENIMAGEDENOISE OFF)
|
||||
message(STATUS "OpenImageDenoise not found, disabling WITH_OPENIMAGEDENOISE")
|
||||
message(STATUS "OpenImageDenoise not found")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -416,7 +413,7 @@ if(WITH_OPENMP)
|
||||
set(OpenMP_LINKER_FLAGS "-L'${LIBDIR}/openmp/lib' -lomp")
|
||||
|
||||
# Copy libomp.dylib to allow executables like datatoc and tests to work.
|
||||
# `@executable_path/../Resources/lib/` `LC_ID_DYLIB` is added by the deps builder.
|
||||
# `@executable_path/../Resources/lib/` `LC_ID_DYLIB`is added by the deps builder.
|
||||
# For single config generator datatoc, tests etc.
|
||||
execute_process(
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/Resources/lib
|
||||
|
@@ -149,6 +149,11 @@ add_definitions(-D_WIN32_WINNT=0x601)
|
||||
include(build_files/cmake/platform/platform_win32_bundle_crt.cmake)
|
||||
remove_cc_flag("/MDd" "/MD" "/Zi")
|
||||
|
||||
if(WITH_WINDOWS_PDB)
|
||||
set(PDB_INFO_OVERRIDE_FLAGS "/Z7")
|
||||
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
|
||||
endif()
|
||||
|
||||
if(MSVC_CLANG) # Clangs version of cl doesn't support all flags
|
||||
string(APPEND CMAKE_CXX_FLAGS " ${CXX_WARN_FLAGS} /nologo /J /Gd /EHsc -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference ")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd -Wno-unused-command-line-argument -Wno-microsoft-enum-forward-reference")
|
||||
@@ -157,21 +162,6 @@ else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /nologo /J /Gd /MP /bigobj")
|
||||
endif()
|
||||
|
||||
# X64 ASAN is available and usable on MSVC 16.9 preview 4 and up)
|
||||
if(WITH_COMPILER_ASAN AND MSVC AND NOT MSVC_CLANG)
|
||||
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.28.29828)
|
||||
#set a flag so we don't have to do this comparison all the time
|
||||
SET(MSVC_ASAN On)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fsanitize=address")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /fsanitize=address")
|
||||
string(APPEND CMAKE_EXE_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /INCREMENTAL:NO")
|
||||
else()
|
||||
message("-- ASAN not supported on MSVC ${CMAKE_CXX_COMPILER_VERSION}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
# C++ standards conformace (/permissive-) is available on msvc 15.5 (1912) and up
|
||||
if(MSVC_VERSION GREATER 1911 AND NOT MSVC_CLANG)
|
||||
string(APPEND CMAKE_CXX_FLAGS " /permissive-")
|
||||
@@ -184,41 +174,14 @@ if(WITH_WINDOWS_SCCACHE AND CMAKE_VS_MSBUILD_COMMAND)
|
||||
set(WITH_WINDOWS_SCCACHE Off)
|
||||
endif()
|
||||
|
||||
# Debug Symbol format
|
||||
# sccache # MSVC_ASAN # format # why
|
||||
# On # On # Z7 # sccache will only play nice with Z7
|
||||
# On # Off # Z7 # sccache will only play nice with Z7
|
||||
# Off # On # Zi # Asan will not play nice with Edit and Continue
|
||||
# Off # Off # ZI # Neither asan nor sscache is enabled Edit and Continue is available
|
||||
|
||||
# Release Symbol format
|
||||
# sccache # MSVC_ASAN # format # why
|
||||
# On # On # Z7 # sccache will only play nice with Z7
|
||||
# On # Off # Z7 # sccache will only play nice with Z7
|
||||
# Off # On # Zi # Asan will not play nice with Edit and Continue
|
||||
# Off # Off # Zi # Edit and Continue disables some optimizations
|
||||
|
||||
|
||||
if(WITH_WINDOWS_SCCACHE)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER sccache)
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER sccache)
|
||||
set(SYMBOL_FORMAT /Z7)
|
||||
set(SYMBOL_FORMAT_RELEASE /Z7)
|
||||
else()
|
||||
unset(CMAKE_C_COMPILER_LAUNCHER)
|
||||
unset(CMAKE_CXX_COMPILER_LAUNCHER)
|
||||
if(MSVC_ASAN)
|
||||
set(SYMBOL_FORMAT /Z7)
|
||||
set(SYMBOL_FORMAT_RELEASE /Z7)
|
||||
else()
|
||||
set(SYMBOL_FORMAT /ZI)
|
||||
set(SYMBOL_FORMAT_RELEASE /Zi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_WINDOWS_PDB)
|
||||
set(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}")
|
||||
set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO")
|
||||
set(SYMBOL_FORMAT /ZI)
|
||||
endif()
|
||||
|
||||
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}")
|
||||
@@ -227,11 +190,9 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
string(APPEND CMAKE_C_FLAGS_RELEASE " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
string(APPEND CMAKE_C_FLAGS_MINSIZEREL " /MD ${PDB_INFO_OVERRIDE_FLAGS}")
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}")
|
||||
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT_RELEASE}")
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
|
||||
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " /MD ${SYMBOL_FORMAT}")
|
||||
unset(SYMBOL_FORMAT)
|
||||
unset(SYMBOL_FORMAT_RELEASE)
|
||||
|
||||
# JMC is available on msvc 15.8 (1915) and up
|
||||
if(MSVC_VERSION GREATER 1914 AND NOT MSVC_CLANG)
|
||||
string(APPEND CMAKE_CXX_FLAGS_DEBUG " /JMC")
|
||||
|
@@ -9,10 +9,14 @@ if "%BUILD_WITH_SCCACHE%"=="1" (
|
||||
|
||||
if "%WITH_CLANG%"=="1" (
|
||||
set CLANG_CMAKE_ARGS=-T"llvm"
|
||||
)
|
||||
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
set ASAN_CMAKE_ARGS=-DWITH_COMPILER_ASAN=On
|
||||
)
|
||||
) else (
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
echo ASAN is only supported with clang.
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
if "%WITH_PYDEBUG%"=="1" (
|
||||
|
@@ -46,10 +46,16 @@ set LLVM_DIR=
|
||||
set CFLAGS=-m64 -fmsc-version=1914
|
||||
set CXXFLAGS=-m64 -fmsc-version=1914
|
||||
)
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
|
||||
)
|
||||
)
|
||||
|
||||
if "%WITH_ASAN%"=="1" (
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% -DWITH_COMPILER_ASAN=On
|
||||
if "%WITH_CLANG%" == "" (
|
||||
echo ASAN is only supported with clang.
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
if NOT "%verbose%" == "" (
|
||||
|
@@ -553,7 +553,7 @@ def example_extract_docstring(filepath):
|
||||
line_no += 1
|
||||
else:
|
||||
file.close()
|
||||
return "", 0, False
|
||||
return "", 0
|
||||
|
||||
for line in file:
|
||||
line_no += 1
|
||||
@@ -563,17 +563,15 @@ def example_extract_docstring(filepath):
|
||||
text.append(line.rstrip())
|
||||
|
||||
line_no += 1
|
||||
line_no_has_content = False
|
||||
|
||||
# Skip over blank lines so the Python code doesn't have blank lines at the top.
|
||||
for line in file:
|
||||
if line.strip():
|
||||
line_no_has_content = True
|
||||
break
|
||||
line_no += 1
|
||||
|
||||
file.close()
|
||||
return "\n".join(text), line_no, line_no_has_content
|
||||
return "\n".join(text), line_no
|
||||
|
||||
|
||||
def title_string(text, heading_char, double=False):
|
||||
@@ -592,18 +590,16 @@ def write_example_ref(ident, fw, example_id, ext="py"):
|
||||
filepath = os.path.join("..", "examples", "%s.%s" % (example_id, ext))
|
||||
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
|
||||
|
||||
text, line_no, line_no_has_content = example_extract_docstring(filepath_full)
|
||||
text, line_no = example_extract_docstring(filepath_full)
|
||||
|
||||
for line in text.split("\n"):
|
||||
fw("%s\n" % (ident + line).rstrip())
|
||||
fw("\n")
|
||||
|
||||
# Some files only contain a doc-string.
|
||||
if line_no_has_content:
|
||||
fw("%s.. literalinclude:: %s\n" % (ident, filepath))
|
||||
if line_no > 0:
|
||||
fw("%s :lines: %d-\n" % (ident, line_no))
|
||||
fw("\n")
|
||||
fw("%s.. literalinclude:: %s\n" % (ident, filepath))
|
||||
if line_no > 0:
|
||||
fw("%s :lines: %d-\n" % (ident, line_no))
|
||||
fw("\n")
|
||||
EXAMPLE_SET_USED.add(example_id)
|
||||
else:
|
||||
if bpy.app.debug:
|
||||
@@ -1412,8 +1408,7 @@ def pyrna2sphinx(basepath):
|
||||
else:
|
||||
fw(" .. attribute:: %s\n\n" % prop.identifier)
|
||||
if prop.description:
|
||||
write_indented_lines(" ", fw, prop.description, False)
|
||||
fw("\n")
|
||||
fw(" %s\n\n" % prop.description)
|
||||
|
||||
# special exception, can't use generic code here for enums
|
||||
if prop.type == "enum":
|
||||
|
4
extern/CMakeLists.txt
vendored
4
extern/CMakeLists.txt
vendored
@@ -109,7 +109,3 @@ endif()
|
||||
if(WITH_MOD_FLUID)
|
||||
add_subdirectory(mantaflow)
|
||||
endif()
|
||||
|
||||
if (WITH_COMPOSITOR)
|
||||
add_subdirectory(smaa_areatex)
|
||||
endif()
|
||||
|
2
extern/audaspace/CMakeLists.txt
vendored
2
extern/audaspace/CMakeLists.txt
vendored
@@ -42,7 +42,6 @@ set(SRC
|
||||
src/devices/NULLDevice.cpp
|
||||
src/devices/ReadDevice.cpp
|
||||
src/devices/SoftwareDevice.cpp
|
||||
src/devices/ThreadedDevice.cpp
|
||||
src/Exception.cpp
|
||||
src/file/File.cpp
|
||||
src/file/FileManager.cpp
|
||||
@@ -149,7 +148,6 @@ set(PUBLIC_HDR
|
||||
include/devices/NULLDevice.h
|
||||
include/devices/ReadDevice.h
|
||||
include/devices/SoftwareDevice.h
|
||||
include/devices/ThreadedDevice.h
|
||||
include/Exception.h
|
||||
include/file/File.h
|
||||
include/file/FileManager.h
|
||||
|
@@ -255,7 +255,6 @@ protected:
|
||||
/**
|
||||
* This function tells the device, to start or pause playback.
|
||||
* \param playing True if device should playback.
|
||||
* \note This method is only called when the device is locked.
|
||||
*/
|
||||
virtual void playing(bool playing)=0;
|
||||
|
||||
|
@@ -1,95 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file ThreadedDevice.h
|
||||
* @ingroup plugin
|
||||
* The ThreadedDevice class.
|
||||
*/
|
||||
|
||||
#include "devices/SoftwareDevice.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* This device extends the SoftwareDevice with code for running mixing in a separate thread.
|
||||
*/
|
||||
class AUD_PLUGIN_API ThreadedDevice : public SoftwareDevice
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Whether there is currently playback.
|
||||
*/
|
||||
bool m_playing;
|
||||
|
||||
/**
|
||||
* Whether the current playback should stop.
|
||||
*/
|
||||
bool m_stop;
|
||||
|
||||
/**
|
||||
* The streaming thread.
|
||||
*/
|
||||
std::thread m_thread;
|
||||
|
||||
/**
|
||||
* Starts the streaming thread.
|
||||
*/
|
||||
AUD_LOCAL void start();
|
||||
|
||||
/**
|
||||
* Streaming thread main function.
|
||||
*/
|
||||
AUD_LOCAL virtual void runMixingThread()=0;
|
||||
|
||||
// delete copy constructor and operator=
|
||||
ThreadedDevice(const ThreadedDevice&) = delete;
|
||||
ThreadedDevice& operator=(const ThreadedDevice&) = delete;
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
/**
|
||||
* Empty default constructor. To setup the device call the function create()
|
||||
* and to uninitialize call destroy().
|
||||
*/
|
||||
ThreadedDevice();
|
||||
|
||||
/**
|
||||
* Indicates that the mixing thread should be stopped.
|
||||
* \return Whether the mixing thread should be stopping.
|
||||
* \warning For thread safety, the device needs to be locked, when this method is called.
|
||||
*/
|
||||
inline bool shouldStop() { return m_stop; }
|
||||
|
||||
/**
|
||||
* This method needs to be called when the mixing thread is stopping.
|
||||
* \warning For thread safety, the device needs to be locked, when this method is called.
|
||||
*/
|
||||
inline void doStop() { m_stop = m_playing = false; }
|
||||
|
||||
/**
|
||||
* Stops all playback and notifies the mixing thread to stop.
|
||||
* \warning The device has to be unlocked to not run into a deadlock.
|
||||
*/
|
||||
void stopMixingThread();
|
||||
};
|
||||
|
||||
AUD_NAMESPACE_END
|
@@ -27,9 +27,9 @@ void PulseAudioDevice::PulseAudio_state_callback(pa_context *context, void *data
|
||||
{
|
||||
PulseAudioDevice* device = (PulseAudioDevice*)data;
|
||||
|
||||
std::lock_guard<ILockable> lock(*device);
|
||||
|
||||
device->m_state = AUD_pa_context_get_state(context);
|
||||
|
||||
AUD_pa_threaded_mainloop_signal(device->m_mainloop, 0);
|
||||
}
|
||||
|
||||
void PulseAudioDevice::PulseAudio_request(pa_stream *stream, size_t num_bytes, void *data)
|
||||
@@ -68,40 +68,29 @@ void PulseAudioDevice::PulseAudio_underflow(pa_stream *stream, void *data)
|
||||
}
|
||||
}
|
||||
|
||||
void PulseAudioDevice::runMixingThread()
|
||||
void PulseAudioDevice::playing(bool playing)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
{
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
m_playback = playing;
|
||||
|
||||
if(shouldStop())
|
||||
{
|
||||
AUD_pa_stream_cork(m_stream, 1, nullptr, nullptr);
|
||||
doStop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(AUD_pa_stream_is_corked(m_stream))
|
||||
AUD_pa_stream_cork(m_stream, 0, nullptr, nullptr);
|
||||
|
||||
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
|
||||
}
|
||||
AUD_pa_stream_cork(m_stream, playing ? 0 : 1, nullptr, nullptr);
|
||||
}
|
||||
|
||||
PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buffersize) :
|
||||
m_playback(false),
|
||||
m_state(PA_CONTEXT_UNCONNECTED),
|
||||
m_buffersize(buffersize),
|
||||
m_underflows(0)
|
||||
{
|
||||
m_mainloop = AUD_pa_mainloop_new();
|
||||
m_mainloop = AUD_pa_threaded_mainloop_new();
|
||||
|
||||
m_context = AUD_pa_context_new(AUD_pa_mainloop_get_api(m_mainloop), name.c_str());
|
||||
AUD_pa_threaded_mainloop_lock(m_mainloop);
|
||||
|
||||
m_context = AUD_pa_context_new(AUD_pa_threaded_mainloop_get_api(m_mainloop), name.c_str());
|
||||
|
||||
if(!m_context)
|
||||
{
|
||||
AUD_pa_mainloop_free(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_free(m_mainloop);
|
||||
|
||||
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
|
||||
}
|
||||
@@ -110,21 +99,26 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
|
||||
|
||||
AUD_pa_context_connect(m_context, nullptr, PA_CONTEXT_NOFLAGS, nullptr);
|
||||
|
||||
AUD_pa_threaded_mainloop_start(m_mainloop);
|
||||
|
||||
while(m_state != PA_CONTEXT_READY)
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case PA_CONTEXT_FAILED:
|
||||
case PA_CONTEXT_TERMINATED:
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_stop(m_mainloop);
|
||||
|
||||
AUD_pa_context_disconnect(m_context);
|
||||
AUD_pa_context_unref(m_context);
|
||||
|
||||
AUD_pa_mainloop_free(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_free(m_mainloop);
|
||||
|
||||
AUD_THROW(DeviceException, "Could not connect to PulseAudio.");
|
||||
break;
|
||||
default:
|
||||
AUD_pa_mainloop_iterate(m_mainloop, true, nullptr);
|
||||
AUD_pa_threaded_mainloop_wait(m_mainloop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -172,10 +166,13 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
|
||||
|
||||
if(!m_stream)
|
||||
{
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_stop(m_mainloop);
|
||||
|
||||
AUD_pa_context_disconnect(m_context);
|
||||
AUD_pa_context_unref(m_context);
|
||||
|
||||
AUD_pa_mainloop_free(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_free(m_mainloop);
|
||||
|
||||
AUD_THROW(DeviceException, "Could not create PulseAudio stream.");
|
||||
}
|
||||
@@ -191,27 +188,32 @@ PulseAudioDevice::PulseAudioDevice(std::string name, DeviceSpecs specs, int buff
|
||||
buffer_attr.prebuf = -1U;
|
||||
buffer_attr.tlength = buffersize;
|
||||
|
||||
if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
|
||||
if(AUD_pa_stream_connect_playback(m_stream, nullptr, &buffer_attr, static_cast<pa_stream_flags_t>(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE), nullptr, nullptr) < 0)
|
||||
{
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_stop(m_mainloop);
|
||||
|
||||
AUD_pa_context_disconnect(m_context);
|
||||
AUD_pa_context_unref(m_context);
|
||||
|
||||
AUD_pa_mainloop_free(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_free(m_mainloop);
|
||||
|
||||
AUD_THROW(DeviceException, "Could not connect PulseAudio stream.");
|
||||
}
|
||||
|
||||
AUD_pa_threaded_mainloop_unlock(m_mainloop);
|
||||
|
||||
create();
|
||||
}
|
||||
|
||||
PulseAudioDevice::~PulseAudioDevice()
|
||||
{
|
||||
stopMixingThread();
|
||||
AUD_pa_threaded_mainloop_stop(m_mainloop);
|
||||
|
||||
AUD_pa_context_disconnect(m_context);
|
||||
AUD_pa_context_unref(m_context);
|
||||
|
||||
AUD_pa_mainloop_free(m_mainloop);
|
||||
AUD_pa_threaded_mainloop_free(m_mainloop);
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@
|
||||
* The PulseAudioDevice class.
|
||||
*/
|
||||
|
||||
#include "devices/ThreadedDevice.h"
|
||||
#include "devices/SoftwareDevice.h"
|
||||
|
||||
#include <pulse/pulseaudio.h>
|
||||
|
||||
@@ -35,10 +35,15 @@ AUD_NAMESPACE_BEGIN
|
||||
/**
|
||||
* This device plays back through PulseAudio, the simple direct media layer.
|
||||
*/
|
||||
class AUD_PLUGIN_API PulseAudioDevice : public ThreadedDevice
|
||||
class AUD_PLUGIN_API PulseAudioDevice : public SoftwareDevice
|
||||
{
|
||||
private:
|
||||
pa_mainloop* m_mainloop;
|
||||
/**
|
||||
* Whether there is currently playback.
|
||||
*/
|
||||
volatile bool m_playback;
|
||||
|
||||
pa_threaded_mainloop* m_mainloop;
|
||||
pa_context* m_context;
|
||||
pa_stream* m_stream;
|
||||
pa_context_state_t m_state;
|
||||
@@ -69,15 +74,13 @@ private:
|
||||
*/
|
||||
AUD_LOCAL static void PulseAudio_underflow(pa_stream* stream, void* data);
|
||||
|
||||
/**
|
||||
* Streaming thread main function.
|
||||
*/
|
||||
AUD_LOCAL void runMixingThread();
|
||||
|
||||
// delete copy constructor and operator=
|
||||
PulseAudioDevice(const PulseAudioDevice&) = delete;
|
||||
PulseAudioDevice& operator=(const PulseAudioDevice&) = delete;
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Opens the PulseAudio audio device for playback.
|
||||
|
@@ -24,14 +24,18 @@ PULSEAUDIO_SYMBOL(pa_context_unref);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_begin_write);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_connect_playback);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_cork);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_is_corked);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_new);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_set_buffer_attr);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_set_underflow_callback);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_set_write_callback);
|
||||
PULSEAUDIO_SYMBOL(pa_stream_write);
|
||||
|
||||
PULSEAUDIO_SYMBOL(pa_mainloop_free);
|
||||
PULSEAUDIO_SYMBOL(pa_mainloop_get_api);
|
||||
PULSEAUDIO_SYMBOL(pa_mainloop_new);
|
||||
PULSEAUDIO_SYMBOL(pa_mainloop_iterate);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_free);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_get_api);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_lock);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_new);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_signal);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_start);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_stop);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_unlock);
|
||||
PULSEAUDIO_SYMBOL(pa_threaded_mainloop_wait);
|
||||
|
195
extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
vendored
195
extern/audaspace/plugins/wasapi/WASAPIDevice.cpp
vendored
@@ -31,83 +31,159 @@ template <class T> void SafeRelease(T **ppT)
|
||||
}
|
||||
}
|
||||
|
||||
void WASAPIDevice::runMixingThread()
|
||||
void WASAPIDevice::start()
|
||||
{
|
||||
lock();
|
||||
|
||||
// thread is still running, we can abort stopping it
|
||||
if(m_stop)
|
||||
m_stop = false;
|
||||
// thread is not running, let's start it
|
||||
else if(!m_playing)
|
||||
{
|
||||
if(m_thread.joinable())
|
||||
m_thread.join();
|
||||
|
||||
m_playing = true;
|
||||
|
||||
m_thread = std::thread(&WASAPIDevice::updateStream, this);
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
void WASAPIDevice::updateStream()
|
||||
{
|
||||
UINT32 buffer_size;
|
||||
UINT32 padding;
|
||||
UINT32 length;
|
||||
data_t* buffer;
|
||||
|
||||
IAudioRenderClient* render_client = nullptr;
|
||||
lock();
|
||||
|
||||
if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
|
||||
{
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
|
||||
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
|
||||
|
||||
if(FAILED(m_audio_client->GetBufferSize(&buffer_size)))
|
||||
goto init_error;
|
||||
|
||||
if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
|
||||
goto init_error;
|
||||
|
||||
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
|
||||
goto init_error;
|
||||
|
||||
length = buffer_size - padding;
|
||||
|
||||
if(FAILED(render_client->GetBuffer(length, &buffer)))
|
||||
goto init_error;
|
||||
|
||||
mix((data_t*)buffer, length);
|
||||
|
||||
if(FAILED(render_client->ReleaseBuffer(length, 0)))
|
||||
{
|
||||
init_error:
|
||||
SafeRelease(&render_client);
|
||||
doStop();
|
||||
return;
|
||||
}
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
IAudioRenderClient* render_client = nullptr;
|
||||
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
|
||||
|
||||
if(FAILED(m_audio_client->GetService(IID_IAudioRenderClient, reinterpret_cast<void**>(&render_client))))
|
||||
{
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
UINT32 padding;
|
||||
|
||||
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
|
||||
{
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
UINT32 length = buffer_size - padding;
|
||||
|
||||
if(FAILED(render_client->GetBuffer(length, &buffer)))
|
||||
{
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
mix((data_t*)buffer, length);
|
||||
|
||||
if(FAILED(render_client->ReleaseBuffer(length, 0)))
|
||||
{
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
m_audio_client->Start();
|
||||
|
||||
auto sleepDuration = std::chrono::milliseconds(buffer_size * 1000 / int(m_specs.rate) / 2);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
lock();
|
||||
|
||||
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
|
||||
{
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
|
||||
if(FAILED(m_audio_client->GetCurrentPadding(&padding)))
|
||||
goto stop_thread;
|
||||
|
||||
length = buffer_size - padding;
|
||||
|
||||
if(FAILED(render_client->GetBuffer(length, &buffer)))
|
||||
goto stop_thread;
|
||||
|
||||
mix((data_t*)buffer, length);
|
||||
|
||||
if(FAILED(render_client->ReleaseBuffer(length, 0)))
|
||||
goto stop_thread;
|
||||
|
||||
// stop thread
|
||||
if(shouldStop())
|
||||
{
|
||||
stop_thread:
|
||||
m_audio_client->Stop();
|
||||
SafeRelease(&render_client);
|
||||
doStop();
|
||||
return;
|
||||
}
|
||||
m_audio_client->Stop();
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
length = buffer_size - padding;
|
||||
|
||||
if(FAILED(render_client->GetBuffer(length, &buffer)))
|
||||
{
|
||||
m_audio_client->Stop();
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
mix((data_t*)buffer, length);
|
||||
|
||||
if(FAILED(render_client->ReleaseBuffer(length, 0)))
|
||||
{
|
||||
m_audio_client->Stop();
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// stop thread
|
||||
if(m_stop)
|
||||
{
|
||||
m_audio_client->Stop();
|
||||
SafeRelease(&render_client);
|
||||
m_playing = false;
|
||||
m_stop = false;
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
unlock();
|
||||
|
||||
std::this_thread::sleep_for(sleepDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void WASAPIDevice::playing(bool playing)
|
||||
{
|
||||
if((!m_playing || m_stop) && playing)
|
||||
start();
|
||||
else
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
|
||||
m_playing(false),
|
||||
m_stop(false),
|
||||
|
||||
m_imm_device_enumerator(nullptr),
|
||||
m_imm_device(nullptr),
|
||||
m_audio_client(nullptr),
|
||||
@@ -285,7 +361,14 @@ WASAPIDevice::WASAPIDevice(DeviceSpecs specs, int buffersize) :
|
||||
|
||||
WASAPIDevice::~WASAPIDevice()
|
||||
{
|
||||
stopMixingThread();
|
||||
lock();
|
||||
|
||||
stopAll();
|
||||
|
||||
unlock();
|
||||
|
||||
if(m_thread.joinable())
|
||||
m_thread.join();
|
||||
|
||||
SafeRelease(&m_audio_client);
|
||||
SafeRelease(&m_imm_device);
|
||||
|
29
extern/audaspace/plugins/wasapi/WASAPIDevice.h
vendored
29
extern/audaspace/plugins/wasapi/WASAPIDevice.h
vendored
@@ -26,7 +26,7 @@
|
||||
* The WASAPIDevice class.
|
||||
*/
|
||||
|
||||
#include "devices/ThreadedDevice.h"
|
||||
#include "devices/SoftwareDevice.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
@@ -40,23 +40,46 @@ AUD_NAMESPACE_BEGIN
|
||||
/**
|
||||
* This device plays back through WASAPI, the Windows audio API.
|
||||
*/
|
||||
class AUD_PLUGIN_API WASAPIDevice : public ThreadedDevice
|
||||
class AUD_PLUGIN_API WASAPIDevice : public SoftwareDevice
|
||||
{
|
||||
private:
|
||||
/**
|
||||
* Whether there is currently playback.
|
||||
*/
|
||||
bool m_playing;
|
||||
|
||||
/**
|
||||
* Whether the current playback should stop.
|
||||
*/
|
||||
bool m_stop;
|
||||
|
||||
IMMDeviceEnumerator* m_imm_device_enumerator;
|
||||
IMMDevice* m_imm_device;
|
||||
IAudioClient* m_audio_client;
|
||||
WAVEFORMATEXTENSIBLE m_wave_format_extensible;
|
||||
|
||||
/**
|
||||
* The streaming thread.
|
||||
*/
|
||||
std::thread m_thread;
|
||||
|
||||
/**
|
||||
* Starts the streaming thread.
|
||||
*/
|
||||
AUD_LOCAL void start();
|
||||
|
||||
/**
|
||||
* Streaming thread main function.
|
||||
*/
|
||||
AUD_LOCAL void runMixingThread();
|
||||
AUD_LOCAL void updateStream();
|
||||
|
||||
// delete copy constructor and operator=
|
||||
WASAPIDevice(const WASAPIDevice&) = delete;
|
||||
WASAPIDevice& operator=(const WASAPIDevice&) = delete;
|
||||
|
||||
protected:
|
||||
virtual void playing(bool playing);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Opens the WASAPI audio device for playback.
|
||||
|
@@ -737,7 +737,7 @@ void SoftwareDevice::mix(data_t* buffer, int length)
|
||||
{
|
||||
m_buffer.assureSize(length * AUD_SAMPLE_SIZE(m_specs));
|
||||
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
{
|
||||
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound;
|
||||
@@ -880,7 +880,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<IReader> reader, b
|
||||
// play sound
|
||||
std::shared_ptr<SoftwareDevice::SoftwareHandle> sound = std::shared_ptr<SoftwareDevice::SoftwareHandle>(new SoftwareDevice::SoftwareHandle(this, reader, pitch, resampler, mapper, keep));
|
||||
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
m_playingSounds.push_back(sound);
|
||||
|
||||
@@ -897,7 +897,7 @@ std::shared_ptr<IHandle> SoftwareDevice::play(std::shared_ptr<ISound> sound, boo
|
||||
|
||||
void SoftwareDevice::stopAll()
|
||||
{
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
std::lock_guard<std::recursive_mutex> lock(m_mutex);
|
||||
|
||||
while(!m_playingSounds.empty())
|
||||
m_playingSounds.front()->stop();
|
||||
|
65
extern/audaspace/src/devices/ThreadedDevice.cpp
vendored
65
extern/audaspace/src/devices/ThreadedDevice.cpp
vendored
@@ -1,65 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright 2009-2016 Jörg Müller
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
#include "devices/ThreadedDevice.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
AUD_NAMESPACE_BEGIN
|
||||
|
||||
void ThreadedDevice::start()
|
||||
{
|
||||
std::lock_guard<ILockable> lock(*this);
|
||||
|
||||
// thread is still running, we can abort stopping it
|
||||
if(m_stop)
|
||||
m_stop = false;
|
||||
|
||||
// thread is not running, let's start it
|
||||
else if(!m_playing)
|
||||
{
|
||||
if(m_thread.joinable())
|
||||
m_thread.join();
|
||||
|
||||
m_playing = true;
|
||||
|
||||
m_thread = std::thread(&ThreadedDevice::runMixingThread, this);
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadedDevice::playing(bool playing)
|
||||
{
|
||||
if((!m_playing || m_stop) && playing)
|
||||
start();
|
||||
else
|
||||
m_stop = true;
|
||||
}
|
||||
|
||||
ThreadedDevice::ThreadedDevice() :
|
||||
m_playing(false),
|
||||
m_stop(false)
|
||||
{
|
||||
}
|
||||
|
||||
void aud::ThreadedDevice::stopMixingThread()
|
||||
{
|
||||
stopAll();
|
||||
|
||||
if(m_thread.joinable())
|
||||
m_thread.join();
|
||||
}
|
||||
|
||||
AUD_NAMESPACE_END
|
26
extern/smaa_areatex/CMakeLists.txt
vendored
26
extern/smaa_areatex/CMakeLists.txt
vendored
@@ -1,26 +0,0 @@
|
||||
# ***** 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) 2017, Blender Foundation
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): IRIE Shinsuke
|
||||
#
|
||||
# ***** END GPL LICENSE BLOCK *****
|
||||
|
||||
add_executable(smaa_areatex smaa_areatex.cpp)
|
5
extern/smaa_areatex/README.blender
vendored
5
extern/smaa_areatex/README.blender
vendored
@@ -1,5 +0,0 @@
|
||||
Project: smaa-cpp
|
||||
URL: https://github.com/iRi-E/smaa-cpp
|
||||
License: MIT
|
||||
Upstream version: 0.4.0
|
||||
Local modifications:
|
1208
extern/smaa_areatex/smaa_areatex.cpp
vendored
1208
extern/smaa_areatex/smaa_areatex.cpp
vendored
File diff suppressed because it is too large
Load Diff
@@ -1409,15 +1409,15 @@ class CYCLES_LIGHT_PT_nodes(CyclesButtonsPanel, Panel):
|
||||
panel_node_draw(layout, light, 'OUTPUT_LIGHT', 'Surface')
|
||||
|
||||
|
||||
class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Beam Shape"
|
||||
class CYCLES_LIGHT_PT_spot(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Spot Shape"
|
||||
bl_parent_id = "CYCLES_LIGHT_PT_light"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if context.light.type in {'SPOT', 'AREA'}:
|
||||
return context.light and CyclesButtonsPanel.poll(context)
|
||||
light = context.light
|
||||
return (light and light.type == 'SPOT') and CyclesButtonsPanel.poll(context)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -1425,12 +1425,9 @@ class CYCLES_LIGHT_PT_beam_shape(CyclesButtonsPanel, Panel):
|
||||
layout.use_property_split = True
|
||||
|
||||
col = layout.column()
|
||||
if light.type == 'SPOT':
|
||||
col.prop(light, "spot_size", text="Spot Size")
|
||||
col.prop(light, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(light, "show_cone")
|
||||
elif light.type == 'AREA':
|
||||
col.prop(light, "spread", text="Spread")
|
||||
col.prop(light, "spot_size", text="Size")
|
||||
col.prop(light, "spot_blend", text="Blend", slider=True)
|
||||
col.prop(light, "show_cone")
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_preview(CyclesButtonsPanel, Panel):
|
||||
@@ -2287,7 +2284,7 @@ classes = (
|
||||
CYCLES_LIGHT_PT_preview,
|
||||
CYCLES_LIGHT_PT_light,
|
||||
CYCLES_LIGHT_PT_nodes,
|
||||
CYCLES_LIGHT_PT_beam_shape,
|
||||
CYCLES_LIGHT_PT_spot,
|
||||
CYCLES_WORLD_PT_preview,
|
||||
CYCLES_WORLD_PT_surface,
|
||||
CYCLES_WORLD_PT_volume,
|
||||
@@ -2317,7 +2314,7 @@ classes = (
|
||||
node_panel(CYCLES_WORLD_PT_settings_surface),
|
||||
node_panel(CYCLES_WORLD_PT_settings_volume),
|
||||
node_panel(CYCLES_LIGHT_PT_light),
|
||||
node_panel(CYCLES_LIGHT_PT_beam_shape)
|
||||
node_panel(CYCLES_LIGHT_PT_spot),
|
||||
)
|
||||
|
||||
|
||||
|
@@ -29,7 +29,7 @@ BlenderImageLoader::BlenderImageLoader(BL::Image b_image, int frame)
|
||||
{
|
||||
}
|
||||
|
||||
bool BlenderImageLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
|
||||
bool BlenderImageLoader::load_metadata(ImageMetaData &metadata)
|
||||
{
|
||||
metadata.width = b_image.size()[0];
|
||||
metadata.height = b_image.size()[1];
|
||||
@@ -171,7 +171,7 @@ BlenderPointDensityLoader::BlenderPointDensityLoader(BL::Depsgraph b_depsgraph,
|
||||
{
|
||||
}
|
||||
|
||||
bool BlenderPointDensityLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
|
||||
bool BlenderPointDensityLoader::load_metadata(ImageMetaData &metadata)
|
||||
{
|
||||
metadata.channels = 4;
|
||||
metadata.width = b_node.resolution();
|
||||
|
@@ -27,7 +27,7 @@ class BlenderImageLoader : public ImageLoader {
|
||||
public:
|
||||
BlenderImageLoader(BL::Image b_image, int frame);
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
|
||||
bool load_metadata(ImageMetaData &metadata) override;
|
||||
bool load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
const size_t pixels_size,
|
||||
@@ -44,7 +44,7 @@ class BlenderPointDensityLoader : public ImageLoader {
|
||||
public:
|
||||
BlenderPointDensityLoader(BL::Depsgraph depsgraph, BL::ShaderNodeTexPointDensity b_node);
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
|
||||
bool load_metadata(ImageMetaData &metadata) override;
|
||||
bool load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
const size_t pixels_size,
|
||||
|
@@ -82,7 +82,6 @@ void BlenderSync::sync_light(BL::Object &b_parent,
|
||||
light->set_axisu(transform_get_column(&tfm, 0));
|
||||
light->set_axisv(transform_get_column(&tfm, 1));
|
||||
light->set_sizeu(b_area_light.size());
|
||||
light->set_spread(b_area_light.spread());
|
||||
switch (b_area_light.shape()) {
|
||||
case BL::AreaLight::shape_SQUARE:
|
||||
light->set_sizev(light->get_sizeu());
|
||||
|
@@ -375,7 +375,7 @@ static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool
|
||||
case BL::Attribute::domain_POINT:
|
||||
element = ATTR_ELEMENT_VERTEX;
|
||||
break;
|
||||
case BL::Attribute::domain_FACE:
|
||||
case BL::Attribute::domain_POLYGON:
|
||||
element = ATTR_ELEMENT_FACE;
|
||||
break;
|
||||
default:
|
||||
|
@@ -41,7 +41,7 @@ class BlenderSmokeLoader : public ImageLoader {
|
||||
mesh_texture_space(b_mesh, texspace_loc, texspace_size);
|
||||
}
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override
|
||||
bool load_metadata(ImageMetaData &metadata) override
|
||||
{
|
||||
if (!b_domain) {
|
||||
return false;
|
||||
|
@@ -619,7 +619,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
||||
info.num = 0;
|
||||
|
||||
info.has_half_images = true;
|
||||
info.has_nanovdb = true;
|
||||
info.has_volume_decoupled = true;
|
||||
info.has_branched_path = true;
|
||||
info.has_adaptive_stop_per_sample = true;
|
||||
@@ -666,7 +665,6 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo> &subdevices,
|
||||
|
||||
/* Accumulate device info. */
|
||||
info.has_half_images &= device.has_half_images;
|
||||
info.has_nanovdb &= device.has_nanovdb;
|
||||
info.has_volume_decoupled &= device.has_volume_decoupled;
|
||||
info.has_branched_path &= device.has_branched_path;
|
||||
info.has_adaptive_stop_per_sample &= device.has_adaptive_stop_per_sample;
|
||||
|
@@ -78,7 +78,6 @@ class DeviceInfo {
|
||||
int num;
|
||||
bool display_device; /* GPU is used as a display device. */
|
||||
bool has_half_images; /* Support half-float textures. */
|
||||
bool has_nanovdb; /* Support NanoVDB volumes. */
|
||||
bool has_volume_decoupled; /* Decoupled volume shading. */
|
||||
bool has_branched_path; /* Supports branched path tracing. */
|
||||
bool has_adaptive_stop_per_sample; /* Per-sample adaptive sampling stopping. */
|
||||
@@ -100,7 +99,6 @@ class DeviceInfo {
|
||||
cpu_threads = 0;
|
||||
display_device = false;
|
||||
has_half_images = false;
|
||||
has_nanovdb = false;
|
||||
has_volume_decoupled = false;
|
||||
has_branched_path = true;
|
||||
has_adaptive_stop_per_sample = false;
|
||||
|
@@ -1654,7 +1654,6 @@ void device_cpu_info(vector<DeviceInfo> &devices)
|
||||
info.has_adaptive_stop_per_sample = true;
|
||||
info.has_osl = true;
|
||||
info.has_half_images = true;
|
||||
info.has_nanovdb = true;
|
||||
info.has_profiling = true;
|
||||
info.denoisers = DENOISER_NLM;
|
||||
if (openimagedenoise_supported()) {
|
||||
|
@@ -128,7 +128,6 @@ void device_cuda_info(vector<DeviceInfo> &devices)
|
||||
info.num = num;
|
||||
|
||||
info.has_half_images = (major >= 3);
|
||||
info.has_nanovdb = true;
|
||||
info.has_volume_decoupled = false;
|
||||
info.has_adaptive_stop_per_sample = false;
|
||||
info.denoisers = DENOISER_NLM;
|
||||
|
@@ -46,13 +46,10 @@ class MultiDevice : public Device {
|
||||
list<SubDevice> devices, denoising_devices;
|
||||
device_ptr unique_key;
|
||||
vector<vector<SubDevice *>> peer_islands;
|
||||
bool use_denoising;
|
||||
bool matching_rendering_and_denoising_devices;
|
||||
|
||||
MultiDevice(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background_)
|
||||
: Device(info, stats, profiler, background_),
|
||||
unique_key(1),
|
||||
use_denoising(!info.denoising_devices.empty())
|
||||
: Device(info, stats, profiler, background_), unique_key(1)
|
||||
{
|
||||
foreach (DeviceInfo &subinfo, info.multi_devices) {
|
||||
/* Always add CPU devices at the back since GPU devices can change
|
||||
@@ -197,7 +194,6 @@ class MultiDevice : public Device {
|
||||
if (!sub.device->load_kernels(requested_features))
|
||||
return false;
|
||||
|
||||
use_denoising = requested_features.use_denoising;
|
||||
if (requested_features.use_denoising) {
|
||||
/* Only need denoising feature, everything else is unused. */
|
||||
DeviceRequestedFeatures denoising_features;
|
||||
@@ -404,7 +400,7 @@ class MultiDevice : public Device {
|
||||
size_t existing_size = mem.device_size;
|
||||
|
||||
/* The tile buffers are allocated on each device (see below), so copy to all of them */
|
||||
if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) {
|
||||
if (strcmp(mem.name, "RenderBuffers") == 0) {
|
||||
foreach (SubDevice &sub, devices) {
|
||||
mem.device = sub.device;
|
||||
mem.device_pointer = (existing_key) ? sub.ptr_map[existing_key] : 0;
|
||||
@@ -470,7 +466,7 @@ class MultiDevice : public Device {
|
||||
/* This is a hack to only allocate the tile buffers on denoising devices
|
||||
* Similarly the tile buffers also need to be allocated separately on all devices so any
|
||||
* overlap rendered for denoising does not interfere with each other */
|
||||
if (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising) {
|
||||
if (strcmp(mem.name, "RenderBuffers") == 0) {
|
||||
vector<device_ptr> device_pointers;
|
||||
device_pointers.reserve(devices.size());
|
||||
|
||||
@@ -522,7 +518,7 @@ class MultiDevice : public Device {
|
||||
size_t existing_size = mem.device_size;
|
||||
|
||||
/* Free memory that was allocated for all devices (see above) on each device */
|
||||
if (mem.type == MEM_PIXELS || (strcmp(mem.name, "RenderBuffers") == 0 && use_denoising)) {
|
||||
if (strcmp(mem.name, "RenderBuffers") == 0 || mem.type == MEM_PIXELS) {
|
||||
foreach (SubDevice &sub, devices) {
|
||||
mem.device = sub.device;
|
||||
mem.device_pointer = sub.ptr_map[key];
|
||||
|
@@ -126,9 +126,6 @@ void device_opencl_info(vector<DeviceInfo> &devices)
|
||||
/* Check OpenCL extensions */
|
||||
info.has_half_images = platform_device.device_extensions.find("cl_khr_fp16") != string::npos;
|
||||
|
||||
/* Disabled for now due to apparent AMD driver bug. */
|
||||
info.has_nanovdb = platform_name != "AMD Accelerated Parallel Processing";
|
||||
|
||||
devices.push_back(info);
|
||||
num_devices++;
|
||||
}
|
||||
|
@@ -2036,9 +2036,7 @@ string OpenCLDevice::kernel_build_options(const string *debug_src)
|
||||
# endif
|
||||
|
||||
# ifdef WITH_NANOVDB
|
||||
if (info.has_nanovdb) {
|
||||
build_options += "-DWITH_NANOVDB ";
|
||||
}
|
||||
build_options += "-DWITH_NANOVDB ";
|
||||
# endif
|
||||
|
||||
return build_options;
|
||||
|
@@ -119,11 +119,11 @@ ccl_device_inline bool lamp_light_sample(
|
||||
klight->area.axisu[0], klight->area.axisu[1], klight->area.axisu[2]);
|
||||
float3 axisv = make_float3(
|
||||
klight->area.axisv[0], klight->area.axisv[1], klight->area.axisv[2]);
|
||||
float3 Ng = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
|
||||
float3 D = make_float3(klight->area.dir[0], klight->area.dir[1], klight->area.dir[2]);
|
||||
float invarea = fabsf(klight->area.invarea);
|
||||
bool is_round = (klight->area.invarea < 0.0f);
|
||||
|
||||
if (dot(ls->P - P, Ng) > 0.0f) {
|
||||
if (dot(ls->P - P, D) > 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,37 +135,20 @@ ccl_device_inline bool lamp_light_sample(
|
||||
ls->pdf = invarea;
|
||||
}
|
||||
else {
|
||||
float3 sample_axisu = axisu;
|
||||
float3 sample_axisv = axisv;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
if (!light_spread_clamp_area_light(
|
||||
P, Ng, &ls->P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inplane = ls->P;
|
||||
ls->pdf = rect_light_sample(P, &ls->P, sample_axisu, sample_axisv, randu, randv, true);
|
||||
ls->pdf = rect_light_sample(P, &ls->P, axisu, axisv, randu, randv, true);
|
||||
inplane = ls->P - inplane;
|
||||
}
|
||||
|
||||
ls->u = dot(inplane, axisu) * (1.0f / dot(axisu, axisu)) + 0.5f;
|
||||
ls->v = dot(inplane, axisv) * (1.0f / dot(axisv, axisv)) + 0.5f;
|
||||
|
||||
ls->Ng = Ng;
|
||||
ls->Ng = D;
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
|
||||
}
|
||||
|
||||
if (is_round) {
|
||||
ls->pdf *= lamp_light_pdf(kg, Ng, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, D, -ls->D, ls->t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -300,28 +283,9 @@ ccl_device bool lamp_light_eval(
|
||||
ls->pdf = invarea * lamp_light_pdf(kg, Ng, -D, ls->t);
|
||||
}
|
||||
else {
|
||||
float3 sample_axisu = axisu;
|
||||
float3 sample_axisv = axisv;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
if (!light_spread_clamp_area_light(
|
||||
P, Ng, &light_P, &sample_axisu, &sample_axisv, klight->area.tan_spread)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ls->pdf = rect_light_sample(P, &light_P, sample_axisu, sample_axisv, 0, 0, false);
|
||||
ls->pdf = rect_light_sample(P, &light_P, axisu, axisv, 0, 0, false);
|
||||
}
|
||||
ls->eval_fac = 0.25f * invarea;
|
||||
|
||||
if (klight->area.tan_spread > 0.0f) {
|
||||
/* Area Light spread angle attenuation */
|
||||
ls->eval_fac *= light_spread_attenuation(
|
||||
ls->D, ls->Ng, klight->area.tan_spread, klight->area.normalize_spread);
|
||||
if (ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
@@ -146,70 +146,6 @@ ccl_device float spot_light_attenuation(float3 dir, float spot_angle, float spot
|
||||
return attenuation;
|
||||
}
|
||||
|
||||
ccl_device float light_spread_attenuation(const float3 D,
|
||||
const float3 lightNg,
|
||||
const float tan_spread,
|
||||
const float normalize_spread)
|
||||
{
|
||||
/* Model a soft-box grid, computing the ratio of light not hidden by the
|
||||
* slats of the grid at a given angle. (see D10594). */
|
||||
const float cos_a = -dot(D, lightNg);
|
||||
const float sin_a = safe_sqrtf(1.0f - sqr(cos_a));
|
||||
const float tan_a = sin_a / cos_a;
|
||||
return max((1.0f - (tan_spread * tan_a)) * normalize_spread, 0.0f);
|
||||
}
|
||||
|
||||
/* Compute subset of area light that actually has an influence on the shading point, to
|
||||
* reduce noise with low spread. */
|
||||
ccl_device bool light_spread_clamp_area_light(const float3 P,
|
||||
const float3 lightNg,
|
||||
float3 *lightP,
|
||||
float3 *axisu,
|
||||
float3 *axisv,
|
||||
const float tan_spread)
|
||||
{
|
||||
/* Closest point in area light plane and distance to that plane. */
|
||||
const float3 closest_P = P - dot(lightNg, P - *lightP) * lightNg;
|
||||
const float t = len(closest_P - P);
|
||||
|
||||
/* Radius of circle on area light that actually affects the shading point. */
|
||||
const float radius = t / tan_spread;
|
||||
|
||||
/* TODO: would be faster to store as normalized vector + length, also in rect_light_sample. */
|
||||
float len_u, len_v;
|
||||
const float3 u = normalize_len(*axisu, &len_u);
|
||||
const float3 v = normalize_len(*axisv, &len_v);
|
||||
|
||||
/* Local uv coordinates of closest point. */
|
||||
const float closest_u = dot(u, closest_P - *lightP);
|
||||
const float closest_v = dot(v, closest_P - *lightP);
|
||||
|
||||
/* Compute rectangle encompassing the circle that affects the shading point,
|
||||
* clamped to the bounds of the area light. */
|
||||
const float min_u = max(closest_u - radius, -len_u * 0.5f);
|
||||
const float max_u = min(closest_u + radius, len_u * 0.5f);
|
||||
const float min_v = max(closest_v - radius, -len_v * 0.5f);
|
||||
const float max_v = min(closest_v + radius, len_v * 0.5f);
|
||||
|
||||
/* Skip if rectangle is empty. */
|
||||
if (min_u >= max_u || min_v >= max_v) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute new area light center position and axes from rectangle in local
|
||||
* uv coordinates. */
|
||||
const float new_center_u = 0.5f * (min_u + max_u);
|
||||
const float new_center_v = 0.5f * (min_v + max_v);
|
||||
const float new_len_u = 0.5f * (max_u - min_u);
|
||||
const float new_len_v = 0.5f * (max_v - min_v);
|
||||
|
||||
*lightP = *lightP + new_center_u * u + new_center_v * v;
|
||||
*axisu = u * new_len_u * 2.0f;
|
||||
*axisv = v * new_len_v * 2.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3 I, float t)
|
||||
{
|
||||
float cos_pi = dot(Ng, I);
|
||||
|
@@ -1501,9 +1501,9 @@ typedef struct KernelAreaLight {
|
||||
float axisu[3];
|
||||
float invarea;
|
||||
float axisv[3];
|
||||
float tan_spread;
|
||||
float pad1;
|
||||
float dir[3];
|
||||
float normalize_spread;
|
||||
float pad2;
|
||||
} KernelAreaLight;
|
||||
|
||||
typedef struct KernelDistantLight {
|
||||
|
@@ -242,15 +242,12 @@ ccl_device float3 svm_math_blackbody_color(float t)
|
||||
return make_float3(4.70366907f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
/* Manually align for readability. */
|
||||
/* clang-format off */
|
||||
int i = (t >= 6365.0f) ? 5 :
|
||||
(t >= 3315.0f) ? 4 :
|
||||
(t >= 1902.0f) ? 3 :
|
||||
(t >= 1449.0f) ? 2 :
|
||||
(t >= 1167.0f) ? 1 :
|
||||
0;
|
||||
/* clang-format on */
|
||||
|
||||
ccl_constant float *r = blackbody_table_r[i];
|
||||
ccl_constant float *g = blackbody_table_g[i];
|
||||
|
@@ -1407,15 +1407,6 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress)
|
||||
need_data_updates = true;
|
||||
}
|
||||
|
||||
/* Check if the shaders were modified. */
|
||||
if (object->used_shaders_is_modified() && object->get_object() &&
|
||||
object->get_object()->get_geometry()) {
|
||||
Geometry *geometry = object->get_object()->get_geometry();
|
||||
array<Node *> used_shaders = object->get_used_shaders();
|
||||
geometry->set_used_shaders(used_shaders);
|
||||
need_shader_updates = true;
|
||||
}
|
||||
|
||||
/* Check for changes in shaders (e.g. newly requested attributes). */
|
||||
foreach (Node *shader_node, object->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(shader_node);
|
||||
@@ -1595,11 +1586,6 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame
|
||||
|
||||
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
|
||||
|
||||
/* Make sure shader ids are also updated. */
|
||||
if (mesh->used_shaders_is_modified()) {
|
||||
mesh->tag_shader_modified();
|
||||
}
|
||||
|
||||
cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
|
||||
|
||||
cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
|
||||
@@ -1667,11 +1653,6 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame
|
||||
|
||||
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
|
||||
|
||||
/* Make sure shader ids are also updated. */
|
||||
if (mesh->used_shaders_is_modified()) {
|
||||
mesh->tag_shader_modified();
|
||||
}
|
||||
|
||||
/* Cycles overwrites the original triangles when computing displacement, so we always have to
|
||||
* repass the data if something is animated (vertices most likely) to avoid buffer overflows. */
|
||||
if (!cached_data.is_constant()) {
|
||||
@@ -1762,11 +1743,6 @@ void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t fra
|
||||
|
||||
Hair *hair = static_cast<Hair *>(object->get_geometry());
|
||||
|
||||
/* Make sure shader ids are also updated. */
|
||||
if (hair->used_shaders_is_modified()) {
|
||||
hair->tag_curve_shader_modified();
|
||||
}
|
||||
|
||||
cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
|
||||
|
||||
cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());
|
||||
|
@@ -239,7 +239,6 @@ template<typename T> class DataStore {
|
||||
{
|
||||
invalidate_last_loaded_time();
|
||||
data.clear();
|
||||
index_data_map.clear();
|
||||
}
|
||||
|
||||
void invalidate_last_loaded_time()
|
||||
@@ -481,23 +480,16 @@ class AlembicProcedural : public Procedural {
|
||||
* invocation, and updates the data on subsequent invocations if the frame changed. */
|
||||
void generate(Scene *scene, Progress &progress);
|
||||
|
||||
/* Tag for an update only if something was modified. */
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
/* This should be called by scene exporters to request the rendering of an object located
|
||||
* in the Alembic archive at the given path.
|
||||
*
|
||||
* Since we lazily load object, the function does not validate the existence of the object
|
||||
* in the archive. If no objects with such path if found in the archive during the next call
|
||||
* to `generate`, it will be ignored.
|
||||
*
|
||||
* Returns a pointer to an existing or a newly created AlembicObject for the given path. */
|
||||
AlembicObject *get_or_create_object(const ustring &path);
|
||||
|
||||
private:
|
||||
/* Add an object to our list of objects, and tag the socket as modified. */
|
||||
void add_object(AlembicObject *object);
|
||||
|
||||
/* Tag for an update only if something was modified. */
|
||||
void tag_update(Scene *scene);
|
||||
|
||||
/* Returns a pointer to an existing or a newly created AlembicObject for the given path. */
|
||||
AlembicObject *get_or_create_object(const ustring &path);
|
||||
|
||||
private:
|
||||
/* Load the data for all the objects whose data has not yet been loaded. */
|
||||
void load_objects(Progress &progress);
|
||||
|
||||
|
@@ -130,14 +130,6 @@ void Background::device_free(Device * /*device*/, DeviceScene * /*dscene*/)
|
||||
|
||||
void Background::tag_update(Scene *scene)
|
||||
{
|
||||
Shader *bg_shader = get_shader(scene);
|
||||
if (bg_shader && bg_shader->is_modified()) {
|
||||
/* Tag as modified to update the KernelBackground visibility information.
|
||||
* We only tag the use_shader socket as modified as it is related to the shader
|
||||
* and to avoid doing unnecessary updates anywhere else. */
|
||||
tag_use_shader_modified();
|
||||
}
|
||||
|
||||
if (ao_factor_is_modified() || use_ao_is_modified()) {
|
||||
scene->integrator->tag_update(scene, Integrator::BACKGROUND_AO_MODIFIED);
|
||||
}
|
||||
|
@@ -1584,6 +1584,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_vindex.tag_realloc();
|
||||
dscene->tri_patch.tag_realloc();
|
||||
dscene->tri_vnormal.tag_realloc();
|
||||
dscene->tri_patch_uv.tag_realloc();
|
||||
dscene->tri_shader.tag_realloc();
|
||||
dscene->patches.tag_realloc();
|
||||
|
@@ -303,8 +303,7 @@ ImageManager::ImageManager(const DeviceInfo &info)
|
||||
animation_frame = 0;
|
||||
|
||||
/* Set image limits */
|
||||
features.has_half_float = info.has_half_images;
|
||||
features.has_nanovdb = info.has_nanovdb;
|
||||
has_half_images = info.has_half_images;
|
||||
}
|
||||
|
||||
ImageManager::~ImageManager()
|
||||
@@ -348,7 +347,7 @@ void ImageManager::load_image_metadata(Image *img)
|
||||
metadata = ImageMetaData();
|
||||
metadata.colorspace = img->params.colorspace;
|
||||
|
||||
if (img->loader->load_metadata(features, metadata)) {
|
||||
if (img->loader->load_metadata(metadata)) {
|
||||
assert(metadata.type != IMAGE_DATA_NUM_TYPES);
|
||||
}
|
||||
else {
|
||||
@@ -357,10 +356,15 @@ void ImageManager::load_image_metadata(Image *img)
|
||||
|
||||
metadata.detect_colorspace();
|
||||
|
||||
assert(features.has_half_float ||
|
||||
(metadata.type != IMAGE_DATA_TYPE_HALF4 && metadata.type != IMAGE_DATA_TYPE_HALF));
|
||||
assert(features.has_nanovdb || (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
|
||||
metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3));
|
||||
/* No half textures on OpenCL, use full float instead. */
|
||||
if (!has_half_images) {
|
||||
if (metadata.type == IMAGE_DATA_TYPE_HALF4) {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
|
||||
}
|
||||
else if (metadata.type == IMAGE_DATA_TYPE_HALF) {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
img->need_metadata = false;
|
||||
}
|
||||
|
@@ -97,13 +97,6 @@ class ImageMetaData {
|
||||
void detect_colorspace();
|
||||
};
|
||||
|
||||
/* Information about supported features that Image loaders can use. */
|
||||
class ImageDeviceFeatures {
|
||||
public:
|
||||
bool has_half_float;
|
||||
bool has_nanovdb;
|
||||
};
|
||||
|
||||
/* Image loader base class, that can be subclassed to load image data
|
||||
* from custom sources (file, memory, procedurally generated, etc). */
|
||||
class ImageLoader {
|
||||
@@ -112,7 +105,7 @@ class ImageLoader {
|
||||
virtual ~ImageLoader(){};
|
||||
|
||||
/* Load metadata without actual image yet, should be fast. */
|
||||
virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) = 0;
|
||||
virtual bool load_metadata(ImageMetaData &metadata) = 0;
|
||||
|
||||
/* Load actual image contents. */
|
||||
virtual bool load_pixels(const ImageMetaData &metadata,
|
||||
@@ -219,8 +212,7 @@ class ImageManager {
|
||||
|
||||
private:
|
||||
bool need_update_;
|
||||
|
||||
ImageDeviceFeatures features;
|
||||
bool has_half_images;
|
||||
|
||||
thread_mutex device_mutex;
|
||||
thread_mutex images_mutex;
|
||||
|
@@ -30,7 +30,7 @@ OIIOImageLoader::~OIIOImageLoader()
|
||||
{
|
||||
}
|
||||
|
||||
bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata)
|
||||
bool OIIOImageLoader::load_metadata(ImageMetaData &metadata)
|
||||
{
|
||||
/* Perform preliminary checks, with meaningful logging. */
|
||||
if (!path_exists(filepath.string())) {
|
||||
@@ -76,7 +76,7 @@ bool OIIOImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMe
|
||||
}
|
||||
|
||||
/* check if it's half float */
|
||||
if (spec.format == TypeDesc::HALF && features.has_half_float) {
|
||||
if (spec.format == TypeDesc::HALF) {
|
||||
is_half = true;
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ class OIIOImageLoader : public ImageLoader {
|
||||
OIIOImageLoader(const string &filepath);
|
||||
~OIIOImageLoader();
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
|
||||
bool load_metadata(ImageMetaData &metadata) override;
|
||||
|
||||
bool load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
|
@@ -40,7 +40,7 @@ SkyLoader::SkyLoader(float sun_elevation,
|
||||
|
||||
SkyLoader::~SkyLoader(){};
|
||||
|
||||
bool SkyLoader::load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata)
|
||||
bool SkyLoader::load_metadata(ImageMetaData &metadata)
|
||||
{
|
||||
metadata.width = 512;
|
||||
metadata.height = 128;
|
||||
|
@@ -34,7 +34,7 @@ class SkyLoader : public ImageLoader {
|
||||
float ozone_density);
|
||||
~SkyLoader();
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override;
|
||||
bool load_metadata(ImageMetaData &metadata) override;
|
||||
|
||||
bool load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
|
@@ -34,7 +34,7 @@ VDBImageLoader::~VDBImageLoader()
|
||||
{
|
||||
}
|
||||
|
||||
bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata)
|
||||
bool VDBImageLoader::load_metadata(ImageMetaData &metadata)
|
||||
{
|
||||
#ifdef WITH_OPENVDB
|
||||
if (!grid) {
|
||||
@@ -56,71 +56,55 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
|
||||
if (grid->isType<openvdb::FloatGrid>()) {
|
||||
metadata.channels = 1;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3fGrid>()) {
|
||||
metadata.channels = 3;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::BoolGrid>()) {
|
||||
metadata.channels = 1;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::DoubleGrid>()) {
|
||||
metadata.channels = 1;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::Int32Grid>()) {
|
||||
metadata.channels = 1;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::Int64Grid>()) {
|
||||
metadata.channels = 1;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3IGrid>()) {
|
||||
metadata.channels = 3;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3dGrid>()) {
|
||||
metadata.channels = 3;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (features.has_nanovdb) {
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
|
||||
}
|
||||
nanogrid = nanovdb::openToNanoVDB(
|
||||
openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
|
||||
# endif
|
||||
}
|
||||
else if (grid->isType<openvdb::MaskGrid>()) {
|
||||
@@ -134,25 +118,21 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
|
||||
}
|
||||
|
||||
# ifdef WITH_NANOVDB
|
||||
if (nanogrid) {
|
||||
metadata.byte_size = nanogrid.size();
|
||||
if (metadata.channels == 1) {
|
||||
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
|
||||
}
|
||||
else {
|
||||
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
|
||||
}
|
||||
metadata.byte_size = nanogrid.size();
|
||||
if (metadata.channels == 1) {
|
||||
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT;
|
||||
}
|
||||
else {
|
||||
metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3;
|
||||
}
|
||||
# else
|
||||
if (metadata.channels == 1) {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT;
|
||||
}
|
||||
else {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
if (metadata.channels == 1) {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT;
|
||||
}
|
||||
else {
|
||||
metadata.type = IMAGE_DATA_TYPE_FLOAT4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set transform from object space to voxel index. */
|
||||
openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
|
||||
@@ -163,29 +143,20 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet
|
||||
}
|
||||
}
|
||||
|
||||
Transform texture_to_index;
|
||||
# ifdef WITH_NANOVDB
|
||||
if (nanogrid) {
|
||||
texture_to_index = transform_identity();
|
||||
}
|
||||
else
|
||||
Transform texture_to_index = transform_identity();
|
||||
# else
|
||||
openvdb::Coord min = bbox.min();
|
||||
Transform texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
|
||||
transform_scale(dim.x(), dim.y(), dim.z());
|
||||
# endif
|
||||
{
|
||||
openvdb::Coord min = bbox.min();
|
||||
texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
|
||||
transform_scale(dim.x(), dim.y(), dim.z());
|
||||
}
|
||||
|
||||
metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
|
||||
metadata.use_transform_3d = true;
|
||||
|
||||
# ifndef WITH_NANOVDB
|
||||
(void)features;
|
||||
# endif
|
||||
return true;
|
||||
#else
|
||||
(void)metadata;
|
||||
(void)features;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
@@ -194,52 +165,48 @@ bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size
|
||||
{
|
||||
#ifdef WITH_OPENVDB
|
||||
# ifdef WITH_NANOVDB
|
||||
if (nanogrid) {
|
||||
memcpy(pixels, nanogrid.data(), nanogrid.size());
|
||||
memcpy(pixels, nanogrid.data(), nanogrid.size());
|
||||
# else
|
||||
if (grid->isType<openvdb::FloatGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3fGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::BoolGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::DoubleGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Int32Grid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Int64Grid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3IGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3dGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::MaskGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
|
||||
}
|
||||
else
|
||||
# endif
|
||||
{
|
||||
if (grid->isType<openvdb::FloatGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3fGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::BoolGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::DoubleGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Int32Grid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Int64Grid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3IGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec3dGrid>()) {
|
||||
openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
|
||||
bbox, (openvdb::Vec3f *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
|
||||
}
|
||||
else if (grid->isType<openvdb::MaskGrid>()) {
|
||||
openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
|
||||
openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
(void)pixels;
|
||||
|
@@ -33,8 +33,7 @@ class VDBImageLoader : public ImageLoader {
|
||||
VDBImageLoader(const string &grid_name);
|
||||
~VDBImageLoader();
|
||||
|
||||
virtual bool load_metadata(const ImageDeviceFeatures &features,
|
||||
ImageMetaData &metadata) override;
|
||||
virtual bool load_metadata(ImageMetaData &metadata) override;
|
||||
|
||||
virtual bool load_pixels(const ImageMetaData &metadata,
|
||||
void *pixels,
|
||||
|
@@ -129,7 +129,6 @@ NODE_DEFINE(Light)
|
||||
SOCKET_VECTOR(axisv, "Axis V", zero_float3());
|
||||
SOCKET_FLOAT(sizev, "Size V", 1.0f);
|
||||
SOCKET_BOOLEAN(round, "Round", false);
|
||||
SOCKET_FLOAT(spread, "Spread", M_PI_F);
|
||||
|
||||
SOCKET_INT(map_resolution, "Map Resolution", 0);
|
||||
|
||||
@@ -859,15 +858,6 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
|
||||
float invarea = (area != 0.0f) ? 1.0f / area : 1.0f;
|
||||
float3 dir = light->dir;
|
||||
|
||||
/* Convert from spread angle 0..180 to 90..0, clamping to a minimum
|
||||
* angle to avoid excessive noise. */
|
||||
const float min_spread_angle = 1.0f * M_PI_F / 180.0f;
|
||||
const float spread_angle = 0.5f * (M_PI_F - max(light->spread, min_spread_angle));
|
||||
/* Normalization computed using:
|
||||
* integrate cos(x) (1 - tan(x) * tan(a)) * sin(x) from x = a to pi/2. */
|
||||
const float tan_spread = tanf(spread_angle);
|
||||
const float normalize_spread = 2.0f / (2.0f + (2.0f * spread_angle - M_PI_F) * tan_spread);
|
||||
|
||||
dir = safe_normalize(dir);
|
||||
|
||||
if (light->use_mis && area != 0.0f)
|
||||
@@ -887,8 +877,6 @@ void LightManager::device_update_points(Device *, DeviceScene *dscene, Scene *sc
|
||||
klights[light_index].area.dir[0] = dir.x;
|
||||
klights[light_index].area.dir[1] = dir.y;
|
||||
klights[light_index].area.dir[2] = dir.z;
|
||||
klights[light_index].area.tan_spread = tan_spread;
|
||||
klights[light_index].area.normalize_spread = normalize_spread;
|
||||
}
|
||||
else if (light->light_type == LIGHT_SPOT) {
|
||||
shader_id &= ~SHADER_AREA_LIGHT;
|
||||
|
@@ -58,7 +58,6 @@ class Light : public Node {
|
||||
NODE_SOCKET_API(float3, axisv)
|
||||
NODE_SOCKET_API(float, sizev)
|
||||
NODE_SOCKET_API(bool, round)
|
||||
NODE_SOCKET_API(float, spread)
|
||||
|
||||
NODE_SOCKET_API(Transform, tfm)
|
||||
|
||||
|
@@ -153,6 +153,10 @@ void Object::update_motion()
|
||||
|
||||
void Object::compute_bounds(bool motion_blur)
|
||||
{
|
||||
if (!is_modified() && !geometry->is_modified()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoundBox mbounds = geometry->bounds;
|
||||
|
||||
if (motion_blur && use_motion()) {
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
#define TEST_CATEGORY_NAME util_avx2
|
||||
|
||||
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
|
||||
defined(__AVX2__)
|
||||
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# include "util_avxf_test.h"
|
||||
#endif
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
#define TEST_CATEGORY_NAME util_avx
|
||||
|
||||
#if (defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) && \
|
||||
defined(__AVX__)
|
||||
#if defined(i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
|
||||
# include "util_avxf_test.h"
|
||||
#endif
|
||||
|
@@ -24,8 +24,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* \code{.py}
|
||||
/*
|
||||
* import bpy
|
||||
* import textwrap
|
||||
*
|
||||
@@ -43,7 +42,6 @@
|
||||
* print("%d,%d," % (w, h))
|
||||
* text = ", ".join(["0x%x" % p for p in pixels])
|
||||
* print(textwrap.fill(text, width=120), end=",\n")
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -533,18 +533,11 @@ GHOST_TSuccess GHOST_WindowWin32::setState(GHOST_TWindowState state)
|
||||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
wp.ptMaxPosition.x = 0;
|
||||
wp.ptMaxPosition.y = 0;
|
||||
style &= ~(WS_CAPTION | WS_MAXIMIZE);
|
||||
style &= ~WS_CAPTION;
|
||||
break;
|
||||
case GHOST_kWindowStateNormal:
|
||||
default:
|
||||
if (curstate == GHOST_kWindowStateFullScreen &&
|
||||
m_normal_state == GHOST_kWindowStateMaximized) {
|
||||
wp.showCmd = SW_SHOWMAXIMIZED;
|
||||
m_normal_state = GHOST_kWindowStateNormal;
|
||||
}
|
||||
else {
|
||||
wp.showCmd = SW_SHOWNORMAL;
|
||||
}
|
||||
wp.showCmd = SW_SHOWNORMAL;
|
||||
break;
|
||||
}
|
||||
::SetWindowLongPtr(m_hWnd, GWL_STYLE, style);
|
||||
|
2
intern/libmv/third_party/.clang-format
vendored
2
intern/libmv/third_party/.clang-format
vendored
@@ -1,2 +0,0 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
Submodule release/scripts/addons updated: 63492d3d03...bcd08a9506
@@ -349,10 +349,6 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
|
||||
# 1) try import
|
||||
try:
|
||||
mod = __import__(module_name)
|
||||
if mod.__file__ is None:
|
||||
# This can happen when the addon has been removed but there are
|
||||
# residual `.pyc` files left behind.
|
||||
raise ImportError(name=module_name)
|
||||
mod.__time__ = os.path.getmtime(mod.__file__)
|
||||
mod.__addon_enabled__ = False
|
||||
except Exception as ex:
|
||||
|
@@ -32,6 +32,12 @@ import bpy
|
||||
IS_TESTING = False
|
||||
|
||||
|
||||
def drepr(string):
|
||||
# is there a less crappy way to do this in python?, re.escape also escapes
|
||||
# single quotes strings so can't use it.
|
||||
return '"%s"' % repr(string)[1:-1].replace("\"", "\\\"").replace("\\'", "'")
|
||||
|
||||
|
||||
def classes_recursive(base_type, clss=None):
|
||||
if clss is None:
|
||||
clss = [base_type]
|
||||
@@ -60,7 +66,7 @@ class DataPathBuilder:
|
||||
if type(key) is int:
|
||||
str_value = '[%d]' % key
|
||||
elif type(key) is str:
|
||||
str_value = '["%s"]' % bpy.utils.escape_identifier(key)
|
||||
str_value = '[%s]' % drepr(key)
|
||||
else:
|
||||
raise Exception("unsupported accessor %r of type %r (internal error)" % (key, type(key)))
|
||||
return DataPathBuilder(self.data_path + (str_value, ))
|
||||
|
@@ -1,91 +0,0 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
__all__ = (
|
||||
"property_definition_from_data_path",
|
||||
"decompose_data_path",
|
||||
)
|
||||
|
||||
class _TokenizeDataPath:
|
||||
"""
|
||||
Class to split up tokens of a data-path.
|
||||
|
||||
Note that almost all access generates new objects with additional paths,
|
||||
with the exception of iteration which is the intended way to access the resulting data."""
|
||||
__slots__ = (
|
||||
"data_path",
|
||||
)
|
||||
|
||||
def __init__(self, attrs):
|
||||
self.data_path = attrs
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return _TokenizeDataPath(self.data_path + ((".%s" % attr),))
|
||||
|
||||
def __getitem__(self, key):
|
||||
return _TokenizeDataPath(self.data_path + (("[%r]" % (key,)),))
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
value_str = ", ".join([
|
||||
val for val in (
|
||||
", ".join(repr(value) for value in args),
|
||||
", ".join(["%s=%r" % (key, value) for key, value in kw.items()]),
|
||||
) if val])
|
||||
return _TokenizeDataPath(self.data_path + ('(%s)' % value_str, ))
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.data_path)
|
||||
|
||||
|
||||
def decompose_data_path(data_path):
|
||||
"""
|
||||
Return the components of a data path split into a list.
|
||||
"""
|
||||
ns = {"base": _TokenizeDataPath(())}
|
||||
return list(eval("base" + data_path, ns, ns))
|
||||
|
||||
|
||||
def property_definition_from_data_path(base, data_path):
|
||||
"""
|
||||
Return an RNA property definition from an object and a data path.
|
||||
|
||||
In Blender this is often used with ``context`` as the base and a
|
||||
path that it references, for example ``.space_data.lock_camera``.
|
||||
"""
|
||||
data = decompose_data_path(data_path)
|
||||
while data and (not data[-1].startswith(".")):
|
||||
data.pop()
|
||||
|
||||
if (not data) or (not data[-1].startswith(".")) or (len(data) < 2):
|
||||
return None
|
||||
|
||||
data_path_head = "".join(data[:-1])
|
||||
data_path_tail = data[-1]
|
||||
|
||||
value_head = eval("base" + data_path_head)
|
||||
value_head_rna = getattr(value_head, "bl_rna", None)
|
||||
if value_head_rna is None:
|
||||
return None
|
||||
|
||||
value_tail = value_head.bl_rna.properties.get(data_path_tail[1:])
|
||||
if not value_tail:
|
||||
return None
|
||||
|
||||
return value_tail
|
@@ -1694,7 +1694,6 @@ def km_image(params):
|
||||
("image.view_all", {"type": 'HOME', "value": 'PRESS', "shift": True},
|
||||
{"properties": [("fit_view", True)]}),
|
||||
("image.view_selected", {"type": 'NUMPAD_PERIOD', "value": 'PRESS'}, None),
|
||||
("image.view_cursor_center", {"type": 'C', "value": 'PRESS', "shift": True}, None),
|
||||
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS'}, None),
|
||||
("image.view_pan", {"type": 'MIDDLEMOUSE', "value": 'PRESS', "shift": True}, None),
|
||||
("image.view_pan", {"type": 'TRACKPADPAN', "value": 'ANY'}, None),
|
||||
|
@@ -355,8 +355,7 @@ class UpdateAnimatedTransformConstraint(Operator):
|
||||
|
||||
use_convert_to_radians: BoolProperty(
|
||||
name="Convert to Radians",
|
||||
description="Convert f-curves/drivers affecting rotations to radians.\n"
|
||||
"Warning: Use this only once",
|
||||
description="Convert fcurves/drivers affecting rotations to radians (Warning: use this only once!)",
|
||||
default=True,
|
||||
)
|
||||
|
||||
@@ -431,9 +430,22 @@ class UpdateAnimatedTransformConstraint(Operator):
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class ANIM_OT_show_group_colors_deprecated(Operator):
|
||||
"""This option moved to Preferences > Animation"""
|
||||
|
||||
bl_idname = "anim.show_group_colors_deprecated"
|
||||
bl_label = "Show Group Colors"
|
||||
bl_options = {'REGISTER'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, _context):
|
||||
return False
|
||||
|
||||
|
||||
classes = (
|
||||
ANIM_OT_keying_set_export,
|
||||
NLA_OT_bake,
|
||||
ClearUselessActions,
|
||||
UpdateAnimatedTransformConstraint,
|
||||
ANIM_OT_show_group_colors_deprecated,
|
||||
)
|
||||
|
@@ -95,76 +95,6 @@ def context_path_validate(context, data_path):
|
||||
return value
|
||||
|
||||
|
||||
def context_path_to_rna_property(context, data_path):
|
||||
from bl_rna_utils.data_path import property_definition_from_data_path
|
||||
rna_prop = property_definition_from_data_path(context, "." + data_path)
|
||||
if rna_prop is not None:
|
||||
return rna_prop
|
||||
return None
|
||||
|
||||
|
||||
def context_path_decompose(data_path):
|
||||
# Decompose a data_path into 3 components:
|
||||
# base_path, prop_attr, prop_item, where:
|
||||
# `"foo.bar["baz"].fiz().bob.buz[10][2]"`, returns...
|
||||
# `("foo.bar["baz"].fiz().bob", "buz", "[10][2]")`
|
||||
#
|
||||
# This is useful as we often want the base and the property, ignoring any item access.
|
||||
# Note that item access includes function calls since these aren't properties.
|
||||
#
|
||||
# Note that the `.` is removed from the start of the first and second values,
|
||||
# this is done because `.attr` isn't convenient to use as an argument,
|
||||
# also the convention is not to include this within the data paths or the operator logic for `bpy.ops.wm.*`.
|
||||
from bl_rna_utils.data_path import decompose_data_path
|
||||
path_split = decompose_data_path("." + data_path)
|
||||
|
||||
# Find the last property that isn't a function call.
|
||||
value_prev = ""
|
||||
i = len(path_split)
|
||||
while (i := i - 1) >= 0:
|
||||
value = path_split[i]
|
||||
if value.startswith("."):
|
||||
if not value_prev.startswith("("):
|
||||
break
|
||||
value_prev = value
|
||||
|
||||
if i != -1:
|
||||
base_path = "".join(path_split[:i])
|
||||
prop_attr = path_split[i]
|
||||
prop_item = "".join(path_split[i + 1:])
|
||||
|
||||
if base_path:
|
||||
assert(base_path.startswith("."))
|
||||
base_path= base_path[1:]
|
||||
if prop_attr:
|
||||
assert(prop_attr.startswith("."))
|
||||
prop_attr = prop_attr[1:]
|
||||
else:
|
||||
# If there are no properties, everything is an item.
|
||||
# Note that should not happen in practice with values which are added onto `context`,
|
||||
# include since it's correct to account for this case and not doing so will create a confusing exception.
|
||||
base_path = ""
|
||||
prop_attr = ""
|
||||
prop_item = "".join(path_split)
|
||||
|
||||
return (base_path, prop_attr, prop_item)
|
||||
|
||||
|
||||
def description_from_data_path(base, data_path, *, prefix, value=Ellipsis):
|
||||
if context_path_validate(base, data_path) is Ellipsis:
|
||||
return None
|
||||
|
||||
if (
|
||||
(rna_prop := context_path_to_rna_property(base, data_path)) and
|
||||
(description := rna_prop.description)
|
||||
):
|
||||
description = "%s: %s" % (prefix, description)
|
||||
if value != Ellipsis:
|
||||
description = "%s\n%s: %s" % (description, iface_("Value"), str(value))
|
||||
return description
|
||||
return None
|
||||
|
||||
|
||||
def operator_value_is_undo(value):
|
||||
if value in {None, Ellipsis}:
|
||||
return False
|
||||
@@ -190,9 +120,12 @@ def operator_value_is_undo(value):
|
||||
|
||||
|
||||
def operator_path_is_undo(context, data_path):
|
||||
data_path_head, _, _ = context_path_decompose(data_path)
|
||||
|
||||
# note that if we have data paths that use strings this could fail
|
||||
# luckily we don't do this!
|
||||
#
|
||||
# When we can't find the data owner assume no undo is needed.
|
||||
data_path_head = data_path.rpartition(".")[0]
|
||||
|
||||
if not data_path_head:
|
||||
return False
|
||||
|
||||
@@ -235,10 +168,6 @@ class WM_OT_context_set_boolean(Operator):
|
||||
default=True,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
|
||||
|
||||
execute = execute_context_assign
|
||||
|
||||
|
||||
@@ -256,10 +185,6 @@ class WM_OT_context_set_int(Operator): # same as enum
|
||||
)
|
||||
relative: rna_relative_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
|
||||
|
||||
execute = execute_context_assign
|
||||
|
||||
|
||||
@@ -276,10 +201,6 @@ class WM_OT_context_scale_float(Operator):
|
||||
default=1.0,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
if context_path_validate(context, data_path) is Ellipsis:
|
||||
@@ -314,10 +235,6 @@ class WM_OT_context_scale_int(Operator):
|
||||
options={'SKIP_SAVE'},
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
if context_path_validate(context, data_path) is Ellipsis:
|
||||
@@ -357,10 +274,6 @@ class WM_OT_context_set_float(Operator): # same as enum
|
||||
)
|
||||
relative: rna_relative_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
|
||||
|
||||
execute = execute_context_assign
|
||||
|
||||
|
||||
@@ -377,10 +290,6 @@ class WM_OT_context_set_string(Operator): # same as enum
|
||||
maxlen=1024,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
|
||||
|
||||
execute = execute_context_assign
|
||||
|
||||
|
||||
@@ -397,10 +306,6 @@ class WM_OT_context_set_enum(Operator):
|
||||
maxlen=1024,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
|
||||
|
||||
execute = execute_context_assign
|
||||
|
||||
|
||||
@@ -417,10 +322,6 @@ class WM_OT_context_set_value(Operator):
|
||||
maxlen=1024,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
if context_path_validate(context, data_path) is Ellipsis:
|
||||
@@ -438,13 +339,6 @@ class WM_OT_context_toggle(Operator):
|
||||
data_path: rna_path_prop
|
||||
module: rna_module_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
# Currently unsupported, it might be possible to extract this.
|
||||
if props.module:
|
||||
return None
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"))
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
|
||||
@@ -481,11 +375,6 @@ class WM_OT_context_toggle_enum(Operator):
|
||||
maxlen=1024,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
value = "(%r, %r)" % (props.value_1, props.value_2)
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"), value=value)
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
|
||||
@@ -517,10 +406,6 @@ class WM_OT_context_cycle_int(Operator):
|
||||
reverse: rna_reverse_prop
|
||||
wrap: rna_wrap_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
value = context_path_validate(context, data_path)
|
||||
@@ -557,10 +442,6 @@ class WM_OT_context_cycle_enum(Operator):
|
||||
reverse: rna_reverse_prop
|
||||
wrap: rna_wrap_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
value = context_path_validate(context, data_path)
|
||||
@@ -569,11 +450,22 @@ class WM_OT_context_cycle_enum(Operator):
|
||||
|
||||
orig_value = value
|
||||
|
||||
rna_prop = context_path_to_rna_property(context, data_path)
|
||||
# Have to get rna enum values
|
||||
rna_struct_str, rna_prop_str = data_path.rsplit('.', 1)
|
||||
i = rna_prop_str.find('[')
|
||||
|
||||
# just in case we get "context.foo.bar[0]"
|
||||
if i != -1:
|
||||
rna_prop_str = rna_prop_str[0:i]
|
||||
|
||||
rna_struct = eval("context.%s.rna_type" % rna_struct_str)
|
||||
|
||||
rna_prop = rna_struct.properties[rna_prop_str]
|
||||
|
||||
if type(rna_prop) != bpy.types.EnumProperty:
|
||||
raise Exception("expected an enum property")
|
||||
|
||||
enums = rna_prop.enum_items.keys()
|
||||
enums = rna_struct.properties[rna_prop_str].enum_items.keys()
|
||||
orig_index = enums.index(orig_value)
|
||||
|
||||
# Have the info we need, advance to the next item.
|
||||
@@ -606,10 +498,6 @@ class WM_OT_context_cycle_array(Operator):
|
||||
data_path: rna_path_prop
|
||||
reverse: rna_reverse_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
value = context_path_validate(context, data_path)
|
||||
@@ -635,10 +523,6 @@ class WM_OT_context_menu_enum(Operator):
|
||||
|
||||
data_path: rna_path_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Menu"))
|
||||
|
||||
def execute(self, context):
|
||||
data_path = self.data_path
|
||||
value = context_path_validate(context, data_path)
|
||||
@@ -646,15 +530,15 @@ class WM_OT_context_menu_enum(Operator):
|
||||
if value is Ellipsis:
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
base_path, prop_attr, _ = context_path_decompose(data_path)
|
||||
base_path, prop_string = data_path.rsplit(".", 1)
|
||||
value_base = context_path_validate(context, base_path)
|
||||
rna_prop = context_path_to_rna_property(context, data_path)
|
||||
prop = value_base.bl_rna.properties[prop_string]
|
||||
|
||||
def draw_cb(self, context):
|
||||
layout = self.layout
|
||||
layout.prop(value_base, prop_attr, expand=True)
|
||||
layout.prop(value_base, prop_string, expand=True)
|
||||
|
||||
context.window_manager.popup_menu(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon)
|
||||
context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -666,10 +550,6 @@ class WM_OT_context_pie_enum(Operator):
|
||||
|
||||
data_path: rna_path_prop
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
data_path = self.data_path
|
||||
@@ -678,15 +558,15 @@ class WM_OT_context_pie_enum(Operator):
|
||||
if value is Ellipsis:
|
||||
return {'PASS_THROUGH'}
|
||||
|
||||
base_path, prop_attr, _ = context_path_decompose(data_path)
|
||||
base_path, prop_string = data_path.rsplit(".", 1)
|
||||
value_base = context_path_validate(context, base_path)
|
||||
rna_prop = context_path_to_rna_property(context, data_path)
|
||||
prop = value_base.bl_rna.properties[prop_string]
|
||||
|
||||
def draw_cb(self, context):
|
||||
layout = self.layout
|
||||
layout.prop(value_base, prop_attr, expand=True)
|
||||
layout.prop(value_base, prop_string, expand=True)
|
||||
|
||||
wm.popup_menu_pie(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon, event=event)
|
||||
wm.popup_menu_pie(draw_func=draw_cb, title=prop.name, icon=prop.icon, event=event)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
@@ -707,15 +587,11 @@ class WM_OT_operator_pie_enum(Operator):
|
||||
maxlen=1024,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, props):
|
||||
return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
|
||||
|
||||
def invoke(self, context, event):
|
||||
wm = context.window_manager
|
||||
|
||||
data_path = self.data_path
|
||||
prop_attr = self.prop_string
|
||||
prop_string = self.prop_string
|
||||
|
||||
# same as eval("bpy.ops." + data_path)
|
||||
op_mod_str, ob_id_str = data_path.split(".", 1)
|
||||
@@ -731,7 +607,7 @@ class WM_OT_operator_pie_enum(Operator):
|
||||
def draw_cb(self, context):
|
||||
layout = self.layout
|
||||
pie = layout.menu_pie()
|
||||
pie.operator_enum(data_path, prop_attr)
|
||||
pie.operator_enum(data_path, prop_string)
|
||||
|
||||
wm.popup_menu_pie(draw_func=draw_cb, title=op_rna.name, event=event)
|
||||
|
||||
@@ -755,17 +631,17 @@ class WM_OT_context_set_id(Operator):
|
||||
value = self.value
|
||||
data_path = self.data_path
|
||||
|
||||
# Match the pointer type from the target property to `bpy.data.*`
|
||||
# match the pointer type from the target property to bpy.data.*
|
||||
# so we lookup the correct list.
|
||||
|
||||
rna_prop = context_path_to_rna_property(context, data_path)
|
||||
rna_prop_fixed_type = rna_prop.fixed_type
|
||||
data_path_base, data_path_prop = data_path.rsplit(".", 1)
|
||||
data_prop_rna = eval("context.%s" % data_path_base).rna_type.properties[data_path_prop]
|
||||
data_prop_rna_type = data_prop_rna.fixed_type
|
||||
|
||||
id_iter = None
|
||||
|
||||
for prop in bpy.data.rna_type.properties:
|
||||
if prop.rna_type.identifier == "CollectionProperty":
|
||||
if prop.fixed_type == rna_prop_fixed_type:
|
||||
if prop.fixed_type == data_prop_rna_type:
|
||||
id_iter = prop.identifier
|
||||
break
|
||||
|
||||
|
@@ -77,7 +77,6 @@ class COLLECTION_PT_instancing(CollectionButtonsPanel, Panel):
|
||||
|
||||
class COLLECTION_PT_lineart_collection(CollectionButtonsPanel, Panel):
|
||||
bl_label = "Line Art"
|
||||
bl_order = 10
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@@ -86,19 +86,12 @@ class DATA_PT_display(ArmatureButtonsPanel, Panel):
|
||||
|
||||
col = layout.column(heading="Show")
|
||||
col.prop(arm, "show_names", text="Names")
|
||||
col.prop(arm, "show_axes", text="Axes")
|
||||
col.prop(arm, "show_bone_custom_shapes", text="Shapes")
|
||||
col.prop(arm, "show_group_colors", text="Group Colors")
|
||||
|
||||
if ob:
|
||||
col.prop(ob, "show_in_front", text="In Front")
|
||||
|
||||
col = layout.column(align=False, heading="Axes")
|
||||
row = col.row(align=True)
|
||||
row.prop(arm, "show_axes", text="")
|
||||
sub = row.row(align=True)
|
||||
sub.active = arm.show_axes
|
||||
sub.prop(arm, "axes_position", text="Position")
|
||||
|
||||
|
||||
class DATA_MT_bone_group_context_menu(Menu):
|
||||
bl_label = "Bone Group Specials"
|
||||
|
@@ -277,7 +277,6 @@ class MATERIAL_PT_viewport(MaterialButtonsPanel, Panel):
|
||||
class MATERIAL_PT_lineart(MaterialButtonsPanel, Panel):
|
||||
bl_label = "Line Art"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_order = 10
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@@ -311,7 +311,6 @@ class OBJECT_PT_instancing_size(ObjectButtonsPanel, Panel):
|
||||
class OBJECT_PT_lineart(ObjectButtonsPanel, Panel):
|
||||
bl_label = "Line Art"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_order = 10
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
@@ -74,6 +74,10 @@ class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.alignment = 'LEFT'
|
||||
row.label(text="Enable physics for:")
|
||||
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
||||
|
||||
obj = context.object
|
||||
|
@@ -348,6 +348,8 @@ class DOPESHEET_MT_view(Menu):
|
||||
col.active = context.space_data.mode != 'SHAPEKEY'
|
||||
col.prop(st, "show_sliders")
|
||||
|
||||
if bpy.app.version < (2, 93):
|
||||
layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
|
||||
layout.prop(st, "show_interpolation")
|
||||
layout.prop(st, "show_extremes")
|
||||
layout.prop(st, "use_auto_merge_keyframes")
|
||||
|
@@ -18,6 +18,7 @@
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.types import Header, Menu, Panel
|
||||
from bl_ui.space_dopesheet import (
|
||||
DopesheetFilterPopoverBase,
|
||||
@@ -119,6 +120,10 @@ class GRAPH_MT_view(Menu):
|
||||
layout.prop(st, "use_realtime_update")
|
||||
layout.prop(st, "show_cursor")
|
||||
layout.prop(st, "show_sliders")
|
||||
|
||||
if bpy.app.version < (2, 93):
|
||||
layout.operator("anim.show_group_colors_deprecated", icon='CHECKBOX_HLT')
|
||||
|
||||
layout.prop(st, "use_auto_merge_keyframes")
|
||||
|
||||
if st.mode != 'DRIVERS':
|
||||
|
@@ -481,7 +481,7 @@ class NODE_MT_context_menu(Menu):
|
||||
class NODE_PT_active_node_generic(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_category = "Item"
|
||||
bl_label = "Node"
|
||||
|
||||
@classmethod
|
||||
@@ -499,7 +499,7 @@ class NODE_PT_active_node_generic(Panel):
|
||||
class NODE_PT_active_node_color(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_category = "Item"
|
||||
bl_label = "Color"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
bl_parent_id = 'NODE_PT_active_node_generic'
|
||||
@@ -529,7 +529,7 @@ class NODE_PT_active_node_color(Panel):
|
||||
class NODE_PT_active_node_properties(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_category = "Item"
|
||||
bl_label = "Properties"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@@ -570,7 +570,7 @@ class NODE_PT_active_node_properties(Panel):
|
||||
class NODE_PT_texture_mapping(Panel):
|
||||
bl_space_type = 'NODE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_category = "Node"
|
||||
bl_category = "Item"
|
||||
bl_label = "Texture Mapping"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
@@ -2244,7 +2244,6 @@ class USERPREF_PT_experimental_new_features(ExperimentalPanel, Panel):
|
||||
({"property": "use_switch_object_operator"}, "T80402"),
|
||||
({"property": "use_sculpt_tools_tilt"}, "T82877"),
|
||||
({"property": "use_asset_browser"}, ("project/profile/124/", "Milestone 1")),
|
||||
({"property": "use_override_templates"}, ("T73318", "Milestone 4")),
|
||||
),
|
||||
)
|
||||
|
||||
|
@@ -622,15 +622,9 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if (
|
||||
(settings := cls.paint_settings(context)) and
|
||||
(brush := settings.brush)
|
||||
):
|
||||
if context.sculpt_object or context.vertex_paint_object:
|
||||
return True
|
||||
elif context.image_paint_object:
|
||||
return (brush.image_tool == 'DRAW')
|
||||
return False
|
||||
settings = cls.paint_settings(context)
|
||||
return (settings and settings.brush and
|
||||
(context.sculpt_object or context.image_paint_object or context.vertex_paint_object))
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@@ -368,7 +368,6 @@ compositor_node_categories = [
|
||||
NodeItem("CompositorNodePixelate"),
|
||||
NodeItem("CompositorNodeSunBeams"),
|
||||
NodeItem("CompositorNodeDenoise"),
|
||||
NodeItem("CompositorNodeAntiAliasing"),
|
||||
]),
|
||||
CompositorNodeCategory("CMP_OP_VECTOR", "Vector", items=[
|
||||
NodeItem("CompositorNodeNormal"),
|
||||
@@ -485,7 +484,6 @@ geometry_node_categories = [
|
||||
GeometryNodeCategory("GEO_ATTRIBUTE", "Attribute", items=[
|
||||
NodeItem("GeometryNodeAttributeRandomize"),
|
||||
NodeItem("GeometryNodeAttributeMath"),
|
||||
NodeItem("GeometryNodeAttributeClamp"),
|
||||
NodeItem("GeometryNodeAttributeCompare"),
|
||||
NodeItem("GeometryNodeAttributeConvert"),
|
||||
NodeItem("GeometryNodeAttributeFill"),
|
||||
@@ -497,7 +495,7 @@ geometry_node_categories = [
|
||||
NodeItem("GeometryNodeAttributeCombineXYZ"),
|
||||
NodeItem("GeometryNodeAttributeSeparateXYZ"),
|
||||
NodeItem("GeometryNodeAttributeRemove"),
|
||||
NodeItem("GeometryNodeAttributeMapRange"),
|
||||
NodeItem("FunctionNodeGroup"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_COLOR", "Color", items=[
|
||||
NodeItem("ShaderNodeValToRGB"),
|
||||
@@ -523,16 +521,7 @@ geometry_node_categories = [
|
||||
NodeItem("GeometryNodeEdgeSplit"),
|
||||
NodeItem("GeometryNodeSubdivisionSurface"),
|
||||
NodeItem("GeometryNodeSubdivide"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
|
||||
NodeItem("GeometryNodeMeshCircle"),
|
||||
NodeItem("GeometryNodeMeshCone"),
|
||||
NodeItem("GeometryNodeMeshCube"),
|
||||
NodeItem("GeometryNodeMeshCylinder"),
|
||||
NodeItem("GeometryNodeMeshGrid"),
|
||||
NodeItem("GeometryNodeMeshIcoSphere"),
|
||||
NodeItem("GeometryNodeMeshLine"),
|
||||
NodeItem("GeometryNodeMeshUVSphere"),
|
||||
|
||||
]),
|
||||
GeometryNodeCategory("GEO_POINT", "Point", items=[
|
||||
NodeItem("GeometryNodePointDistribute"),
|
||||
@@ -543,6 +532,20 @@ geometry_node_categories = [
|
||||
NodeItem("GeometryNodeRotatePoints"),
|
||||
NodeItem("GeometryNodeAlignRotationToVector"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
|
||||
NodeItem("GeometryNodePointsToVolume"),
|
||||
NodeItem("GeometryNodeVolumeToMesh"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_PRIMITIVES", "Mesh Primitives", items=[
|
||||
NodeItem("GeometryNodeMeshCube"),
|
||||
NodeItem("GeometryNodeMeshCircle"),
|
||||
NodeItem("GeometryNodeMeshUVSphere"),
|
||||
NodeItem("GeometryNodeMeshIcoSphere"),
|
||||
NodeItem("GeometryNodeMeshCylinder"),
|
||||
NodeItem("GeometryNodeMeshCone"),
|
||||
NodeItem("GeometryNodeMeshLine"),
|
||||
NodeItem("GeometryNodeMeshPlane"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_UTILITIES", "Utilities", items=[
|
||||
NodeItem("ShaderNodeMapRange"),
|
||||
NodeItem("ShaderNodeClamp"),
|
||||
@@ -556,10 +559,6 @@ geometry_node_categories = [
|
||||
NodeItem("ShaderNodeVectorMath"),
|
||||
NodeItem("ShaderNodeVectorRotate"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_VOLUME", "Volume", items=[
|
||||
NodeItem("GeometryNodePointsToVolume"),
|
||||
NodeItem("GeometryNodeVolumeToMesh"),
|
||||
]),
|
||||
GeometryNodeCategory("GEO_GROUP", "Group", items=node_group_items),
|
||||
GeometryNodeCategory("GEO_LAYOUT", "Layout", items=[
|
||||
NodeItem("NodeFrame"),
|
||||
|
@@ -1,10 +0,0 @@
|
||||
shader basic_shader(
|
||||
float in_float = 1.0,
|
||||
color in_color = color(1.0, 1.0, 1.0),
|
||||
output float out_float = 0.0,
|
||||
output color out_color = color(0.0, 0.0, 0.0)
|
||||
)
|
||||
{
|
||||
out_float = in_float * 2.0;
|
||||
out_color = in_color * 2.0;
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
# This sample shows the an efficient way of doing image processing
|
||||
# over Blender's images using Python.
|
||||
|
||||
import bpy
|
||||
import numpy as np
|
||||
|
||||
|
||||
input_image_name = "Image"
|
||||
output_image_name = "NewImage"
|
||||
|
||||
# Retrieve input image.
|
||||
input_image = bpy.data.images[input_image_name]
|
||||
w, h = input_image.size
|
||||
|
||||
# Allocate a numpy array to manipulate pixel data.
|
||||
pixel_data = np.zeros((w, h, 4), 'f')
|
||||
|
||||
# Fast copy of pixel data from bpy.data to numpy array.
|
||||
input_image.pixels.foreach_get(pixel_data.ravel())
|
||||
|
||||
# Do whatever image processing you want using numpy here:
|
||||
# Example 1: Inverse red green and blue channels.
|
||||
pixel_data[:,:,:3] = 1.0 - pixel_data[:,:,:3]
|
||||
# Example 2: Change gamma on the red channel.
|
||||
pixel_data[:,:,0] = np.power(pixel_data[:,:,0], 1.5)
|
||||
|
||||
# Create output image.
|
||||
if output_image_name in bpy.data.images:
|
||||
output_image = bpy.data.images[output_image_name]
|
||||
else:
|
||||
output_image = bpy.data.images.new(output_image_name, width=w, height=h)
|
||||
|
||||
# Copy of pixel data from numpy array back to the output image.
|
||||
output_image.pixels.foreach_set(pixel_data.ravel())
|
||||
output_image.update()
|
@@ -31,7 +31,6 @@ set(SRC
|
||||
string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /nodefaultlib:MSVCRT.lib")
|
||||
|
||||
add_library(BlendThumb SHARED ${SRC})
|
||||
setup_platform_linker_flags(BlendThumb)
|
||||
target_link_libraries(BlendThumb ${ZLIB_LIBRARIES})
|
||||
|
||||
install(
|
||||
|
@@ -188,6 +188,10 @@ void BKE_pose_itasc_init(struct bItasc *itasc);
|
||||
/* Checks if a bone is part of an IK chain or not */
|
||||
bool BKE_pose_channel_in_IK_chain(struct Object *ob, struct bPoseChannel *pchan);
|
||||
|
||||
/* clears BONE_UNKEYED flags for frame changing */
|
||||
// XXX to be deprecated for a more general solution in animsys...
|
||||
void framechange_poses_clear_unkeyed(struct Main *bmain);
|
||||
|
||||
/* Bone Groups API --------------------- */
|
||||
|
||||
/* Adds a new bone-group */
|
||||
@@ -223,9 +227,6 @@ void BKE_pose_blend_read_data(struct BlendDataReader *reader, struct bPose *pose
|
||||
void BKE_pose_blend_read_lib(struct BlendLibReader *reader, struct Object *ob, struct bPose *pose);
|
||||
void BKE_pose_blend_read_expand(struct BlendExpander *expander, struct bPose *pose);
|
||||
|
||||
/* action_mirror.c */
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
@@ -342,8 +342,6 @@ void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan,
|
||||
#define PBONE_SELECTABLE(arm, bone) \
|
||||
(PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE))
|
||||
|
||||
#define PBONE_SELECTED(arm, bone) (((bone)->flag & BONE_SELECTED) & PBONE_VISIBLE(arm, bone))
|
||||
|
||||
/* context.selected_pose_bones */
|
||||
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \
|
||||
for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \
|
||||
|
@@ -39,12 +39,12 @@ struct ReportList;
|
||||
|
||||
/* Attribute.domain */
|
||||
typedef enum AttributeDomain {
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
|
||||
ATTR_DOMAIN_FACE = 3, /* Mesh Face */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_CORNER = 2, /* Mesh Corner */
|
||||
ATTR_DOMAIN_POLYGON = 3, /* Mesh Polygon */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
|
||||
ATTR_DOMAIN_NUM
|
||||
} AttributeDomain;
|
||||
|
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 15
|
||||
#define BLENDER_FILE_SUBVERSION 14
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
@@ -108,7 +108,7 @@ void BKE_curve_transform(struct Curve *cu,
|
||||
const bool do_props);
|
||||
void BKE_curve_translate(struct Curve *cu, const float offset[3], const bool do_keys);
|
||||
void BKE_curve_material_index_remove(struct Curve *cu, int index);
|
||||
bool BKE_curve_material_index_used(const struct Curve *cu, int index);
|
||||
bool BKE_curve_material_index_used(struct Curve *cu, int index);
|
||||
void BKE_curve_material_index_clear(struct Curve *cu);
|
||||
bool BKE_curve_material_index_validate(struct Curve *cu);
|
||||
void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len);
|
||||
@@ -125,10 +125,8 @@ void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, con
|
||||
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
|
||||
void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
|
||||
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(const struct ListBase *lb, int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_vert_coords_get(const struct ListBase *lb,
|
||||
float (*vert_coords)[3],
|
||||
int vert_len);
|
||||
float (*BKE_curve_nurbs_vert_coords_alloc(struct ListBase *lb, int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_vert_coords_get(struct ListBase *lb, float (*vert_coords)[3], int vert_len);
|
||||
|
||||
void BKE_curve_nurbs_vert_coords_apply_with_mat4(struct ListBase *lb,
|
||||
const float (*vert_coords)[3],
|
||||
@@ -139,7 +137,7 @@ void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb,
|
||||
const float (*vert_coords)[3],
|
||||
const bool constrain_2d);
|
||||
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(const struct ListBase *lb,
|
||||
float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb,
|
||||
float *key,
|
||||
int *r_vert_len))[3];
|
||||
void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, const float *key);
|
||||
@@ -168,8 +166,8 @@ void BKE_curve_correct_bezpart(const float v1[2], float v2[2], float v3[2], cons
|
||||
|
||||
bool BKE_nurbList_index_get_co(struct ListBase *editnurb, const int index, float r_co[3]);
|
||||
|
||||
int BKE_nurbList_verts_count(const struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count_without_handles(const struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count(struct ListBase *nurb);
|
||||
int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
|
||||
|
||||
void BKE_nurbList_free(struct ListBase *lb);
|
||||
void BKE_nurbList_duplicate(struct ListBase *lb1, const struct ListBase *lb2);
|
||||
@@ -187,7 +185,7 @@ struct Nurb *BKE_nurb_duplicate(const struct Nurb *nu);
|
||||
struct Nurb *BKE_nurb_copy(struct Nurb *src, int pntsu, int pntsv);
|
||||
|
||||
void BKE_nurb_test_2d(struct Nurb *nu);
|
||||
void BKE_nurb_minmax(const struct Nurb *nu, bool use_radius, float min[3], float max[3]);
|
||||
void BKE_nurb_minmax(struct Nurb *nu, bool use_radius, float min[3], float max[3]);
|
||||
float BKE_nurb_calc_length(const struct Nurb *nu, int resolution);
|
||||
|
||||
void BKE_nurb_makeFaces(
|
||||
|
@@ -75,31 +75,33 @@ typedef struct DispList {
|
||||
int *index;
|
||||
int charidx;
|
||||
int totindex; /* indexed array drawing surfaces */
|
||||
|
||||
unsigned int *bevel_split; /* BLI_bitmap */
|
||||
} DispList;
|
||||
|
||||
void BKE_displist_copy(struct ListBase *lbn, const struct ListBase *lb);
|
||||
void BKE_displist_copy(struct ListBase *lbn, struct ListBase *lb);
|
||||
void BKE_displist_elem_free(DispList *dl);
|
||||
DispList *BKE_displist_find_or_create(struct ListBase *lb, int type);
|
||||
DispList *BKE_displist_find(struct ListBase *lb, int type);
|
||||
void BKE_displist_normals_add(struct ListBase *lb);
|
||||
void BKE_displist_count(const struct ListBase *lb, int *totvert, int *totface, int *tottri);
|
||||
void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *tottri);
|
||||
void BKE_displist_free(struct ListBase *lb);
|
||||
bool BKE_displist_has_faces(const struct ListBase *lb);
|
||||
bool BKE_displist_has_faces(struct ListBase *lb);
|
||||
|
||||
void BKE_displist_make_surf(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *dispbase,
|
||||
struct Mesh **r_final,
|
||||
const bool for_render,
|
||||
const bool for_orco);
|
||||
void BKE_displist_make_curveTypes(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
const bool for_render,
|
||||
const bool for_orco);
|
||||
void BKE_displist_make_curveTypes_forRender(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *dispbase,
|
||||
struct Mesh **r_final,
|
||||
@@ -111,26 +113,22 @@ void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,
|
||||
struct ListBase *dispbase);
|
||||
|
||||
bool BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct ListBase *source_nurb,
|
||||
struct ListBase *target_nurb,
|
||||
const bool for_render);
|
||||
bool BKE_displist_surfindex_get(
|
||||
const struct DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
|
||||
|
||||
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
|
||||
void BKE_displist_fill(const struct ListBase *dispbase,
|
||||
struct ListBase *to,
|
||||
const float normal_proj[3],
|
||||
const bool flip_normal);
|
||||
|
||||
float BKE_displist_calc_taper(struct Depsgraph *depsgraph,
|
||||
const struct Scene *scene,
|
||||
struct Object *taperobj,
|
||||
int cur,
|
||||
int tot);
|
||||
float BKE_displist_calc_taper(
|
||||
struct Depsgraph *depsgraph, struct Scene *scene, struct Object *taperobj, int cur, int tot);
|
||||
|
||||
void BKE_displist_minmax(const struct ListBase *dispbase, float min[3], float max[3]);
|
||||
void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -232,19 +232,6 @@ int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[],
|
||||
int arraylen,
|
||||
bool *r_replace);
|
||||
|
||||
/* fcurve_cache.c */
|
||||
/* Cached f-curve look-ups, use when this needs to be done many times. */
|
||||
struct FCurvePathCache;
|
||||
struct FCurvePathCache *BKE_fcurve_pathcache_create(ListBase *list);
|
||||
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache);
|
||||
struct FCurve *BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache,
|
||||
const char rna_path[],
|
||||
const int array_index);
|
||||
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
|
||||
const char *rna_path,
|
||||
struct FCurve **fcurve_result,
|
||||
int fcurve_result_len);
|
||||
|
||||
/* get the time extents for F-Curve */
|
||||
bool BKE_fcurve_calc_range(
|
||||
struct FCurve *fcu, float *min, float *max, const bool do_sel_only, const bool do_min_length);
|
||||
@@ -258,14 +245,6 @@ bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
|
||||
const bool do_sel_only,
|
||||
const bool include_handles);
|
||||
|
||||
float *BKE_fcurves_calc_keyed_frames_ex(struct FCurve **fcurve_array,
|
||||
const int fcurve_array_len,
|
||||
const float interval,
|
||||
int *r_frames_len);
|
||||
float *BKE_fcurves_calc_keyed_frames(struct FCurve **fcurve_array,
|
||||
const int fcurve_array_len,
|
||||
int *r_frames_len);
|
||||
|
||||
void BKE_fcurve_active_keyframe_set(struct FCurve *fcu, const struct BezTriple *active_bezt);
|
||||
int BKE_fcurve_active_keyframe_index(const struct FCurve *fcu);
|
||||
|
||||
|
@@ -141,12 +141,6 @@ class GeometryComponent {
|
||||
/* The returned component should be of the same type as the type this is called on. */
|
||||
virtual GeometryComponent *copy() const = 0;
|
||||
|
||||
/* Direct data is everything except for instances of objects/collections.
|
||||
* If this returns true, the geometry set can be cached and is still valid after e.g. modifier
|
||||
* evaluation ends. Instances can only be valid as long as the data they instance is valid. */
|
||||
virtual bool owns_direct_data() const = 0;
|
||||
virtual void ensure_owns_direct_data() = 0;
|
||||
|
||||
void user_add() const;
|
||||
void user_remove() const;
|
||||
bool is_mutable() const;
|
||||
@@ -319,10 +313,6 @@ struct GeometrySet {
|
||||
friend bool operator==(const GeometrySet &a, const GeometrySet &b);
|
||||
uint64_t hash() const;
|
||||
|
||||
void clear();
|
||||
|
||||
void ensure_owns_direct_data();
|
||||
|
||||
/* Utility methods for creation. */
|
||||
static GeometrySet create_with_mesh(
|
||||
Mesh *mesh, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
|
||||
@@ -382,9 +372,6 @@ class MeshComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_MESH;
|
||||
|
||||
private:
|
||||
@@ -415,9 +402,6 @@ class PointCloudComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_POINT_CLOUD;
|
||||
|
||||
private:
|
||||
@@ -458,9 +442,6 @@ class InstancesComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_INSTANCES;
|
||||
};
|
||||
|
||||
@@ -483,8 +464,5 @@ class VolumeComponent : public GeometryComponent {
|
||||
const Volume *get_for_read() const;
|
||||
Volume *get_for_write();
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_VOLUME;
|
||||
};
|
||||
|
@@ -39,8 +39,7 @@ struct GeometryInstanceGroup {
|
||||
Vector<float4x4> transforms;
|
||||
};
|
||||
|
||||
void geometry_set_gather_instances(const GeometrySet &geometry_set,
|
||||
Vector<GeometryInstanceGroup> &r_instance_groups);
|
||||
Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set);
|
||||
|
||||
GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set);
|
||||
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
|
||||
|
@@ -74,7 +74,6 @@ bool BKE_lib_override_library_create(struct Main *bmain,
|
||||
struct ViewLayer *view_layer,
|
||||
struct ID *id_root,
|
||||
struct ID *id_reference);
|
||||
bool BKE_lib_override_library_template_create(struct ID *id);
|
||||
bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
|
@@ -483,14 +483,14 @@ void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntre
|
||||
/** \name Node Tree Interface
|
||||
* \{ */
|
||||
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
const char *identifier);
|
||||
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
const char *idname,
|
||||
const char *name);
|
||||
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
const char *idname,
|
||||
struct bNodeSocket *next_sock,
|
||||
const char *name);
|
||||
@@ -556,32 +556,30 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype);
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
struct bNodeSocket *nodeFindSocket(const struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
const char *identifier);
|
||||
struct bNodeSocket *nodeFindSocket(const struct bNode *node, int in_out, const char *identifier);
|
||||
struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
const char *idname,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeInsertSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
const char *idname,
|
||||
struct bNodeSocket *next_sock,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
const char *identifier,
|
||||
const char *name);
|
||||
struct bNodeSocket *nodeInsertStaticSocket(struct bNodeTree *ntree,
|
||||
struct bNode *node,
|
||||
eNodeSocketInOut in_out,
|
||||
int in_out,
|
||||
int type,
|
||||
int subtype,
|
||||
struct bNodeSocket *next_sock,
|
||||
@@ -1190,7 +1188,6 @@ void ntreeGPUMaterialNodes(struct bNodeTree *localtree,
|
||||
#define CMP_NODE_TRACKPOS 271
|
||||
#define CMP_NODE_INPAINT 272
|
||||
#define CMP_NODE_DESPECKLE 273
|
||||
#define CMP_NODE_ANTIALIASING 274
|
||||
|
||||
#define CMP_NODE_GLARE 301
|
||||
#define CMP_NODE_TONEMAP 302
|
||||
@@ -1396,9 +1393,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
||||
#define GEO_NODE_MESH_PRIMITIVE_ICO_SPHERE 1036
|
||||
#define GEO_NODE_MESH_PRIMITIVE_CONE 1037
|
||||
#define GEO_NODE_MESH_PRIMITIVE_LINE 1038
|
||||
#define GEO_NODE_MESH_PRIMITIVE_GRID 1039
|
||||
#define GEO_NODE_ATTRIBUTE_MAP_RANGE 1040
|
||||
#define GEO_NODE_ATTRIBUTE_CLAMP 1041
|
||||
#define GEO_NODE_MESH_PRIMITIVE_PLANE 1039
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@@ -58,7 +58,9 @@ class NodeTreeEvaluationContext {
|
||||
|
||||
uint64_t hash() const
|
||||
{
|
||||
return blender::get_default_hash_2(object_name_, modifier_session_uuid_);
|
||||
const uint64_t hash1 = blender::DefaultHash<std::string>{}(object_name_);
|
||||
const uint64_t hash2 = BLI_session_uuid_hash_uint64(&modifier_session_uuid_);
|
||||
return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
|
||||
}
|
||||
|
||||
friend bool operator==(const NodeTreeEvaluationContext &a, const NodeTreeEvaluationContext &b)
|
||||
|
@@ -34,7 +34,6 @@ struct Base;
|
||||
struct BoundBox;
|
||||
struct Curve;
|
||||
struct Depsgraph;
|
||||
struct GeometrySet;
|
||||
struct GpencilModifierData;
|
||||
struct HookGpencilModifierData;
|
||||
struct HookModifierData;
|
||||
@@ -70,8 +69,6 @@ void BKE_object_free_curve_cache(struct Object *ob);
|
||||
void BKE_object_free_derived_caches(struct Object *ob);
|
||||
void BKE_object_free_caches(struct Object *object);
|
||||
|
||||
void BKE_object_preview_geometry_set(struct Object *ob, struct GeometrySet *geometry_set);
|
||||
|
||||
void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
|
||||
void BKE_object_modifier_gpencil_hook_reset(struct Object *ob,
|
||||
struct HookGpencilModifierData *hmd);
|
||||
@@ -339,12 +336,6 @@ struct Mesh *BKE_object_get_evaluated_mesh(struct Object *object);
|
||||
struct Mesh *BKE_object_get_pre_modified_mesh(struct Object *object);
|
||||
struct Mesh *BKE_object_get_original_mesh(struct Object *object);
|
||||
|
||||
/* Lattice accessors.
|
||||
* These functions return either the regular lattice, or the edit-mode lattice,
|
||||
* whichever is currently in use. */
|
||||
struct Lattice *BKE_object_get_lattice(const struct Object *object);
|
||||
struct Lattice *BKE_object_get_evaluated_lattice(const struct Object *object);
|
||||
|
||||
int BKE_object_insert_ptcache(struct Object *ob);
|
||||
void BKE_object_delete_ptcache(struct Object *ob, int index);
|
||||
struct KeyBlock *BKE_object_shapekey_insert(struct Main *bmain,
|
||||
|
@@ -69,7 +69,6 @@ set(SRC
|
||||
intern/CCGSubSurf_util.c
|
||||
intern/DerivedMesh.cc
|
||||
intern/action.c
|
||||
intern/action_mirror.c
|
||||
intern/addon.c
|
||||
intern/anim_data.c
|
||||
intern/anim_path.c
|
||||
@@ -127,7 +126,6 @@ set(SRC
|
||||
intern/editmesh_tangent.c
|
||||
intern/effect.c
|
||||
intern/fcurve.c
|
||||
intern/fcurve_cache.c
|
||||
intern/fcurve_driver.c
|
||||
intern/fluid.c
|
||||
intern/fmodifier.c
|
||||
@@ -387,7 +385,6 @@ set(SRC
|
||||
BKE_multires.h
|
||||
BKE_nla.h
|
||||
BKE_node.h
|
||||
BKE_node_ui_storage.hh
|
||||
BKE_object.h
|
||||
BKE_object_deform.h
|
||||
BKE_object_facemap.h
|
||||
@@ -437,10 +434,10 @@ set(SRC
|
||||
nla_private.h
|
||||
particle_private.h
|
||||
tracking_private.h
|
||||
intern/attribute_access_intern.hh
|
||||
intern/CCGSubSurf.h
|
||||
intern/CCGSubSurf_inline.h
|
||||
intern/CCGSubSurf_intern.h
|
||||
intern/attribute_access_intern.hh
|
||||
intern/data_transfer_intern.h
|
||||
intern/lib_intern.h
|
||||
intern/multires_inline.h
|
||||
@@ -745,7 +742,7 @@ if(WITH_GMP)
|
||||
list(APPEND INC_SYS
|
||||
${GMP_INCLUDE_DIRS}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# # Warnings as errors, this is too strict!
|
||||
# if(MSVC)
|
||||
|
@@ -1316,6 +1316,30 @@ void BKE_pose_tag_update_constraint_flags(bPose *pose)
|
||||
pose->flag |= POSE_CONSTRAINTS_NEED_UPDATE_FLAGS;
|
||||
}
|
||||
|
||||
/* Clears all BONE_UNKEYED flags for every pose channel in every pose
|
||||
* This should only be called on frame changing, when it is acceptable to
|
||||
* do this. Otherwise, these flags should not get cleared as poses may get lost.
|
||||
*/
|
||||
void framechange_poses_clear_unkeyed(Main *bmain)
|
||||
{
|
||||
Object *ob;
|
||||
bPose *pose;
|
||||
bPoseChannel *pchan;
|
||||
|
||||
/* This needs to be done for each object that has a pose */
|
||||
/* TODO: proxies may/may not be correctly handled here... (this needs checking) */
|
||||
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||
/* we only need to do this on objects with a pose */
|
||||
if ((pose = ob->pose)) {
|
||||
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
if (pchan->bone) {
|
||||
pchan->bone->flag &= ~BONE_UNKEYED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************** Bone Groups ************************** */
|
||||
|
||||
/* Adds a new bone-group (name may be NULL) */
|
||||
|
@@ -1,457 +0,0 @@
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* Mirror/Symmetry functions applying to actions.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_string_utils.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_fcurve.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Flip the Action (Armature/Pose Objects)
|
||||
*
|
||||
* This flips the action using the rest pose (not the evaluated pose).
|
||||
*
|
||||
* Details:
|
||||
*
|
||||
* - Key-frames are modified in-place, creating new key-frames is not yet supported.
|
||||
* That could be useful if a user for example only has 2x rotation channels set.
|
||||
* In practice users typically keyframe all rotation channels or none.
|
||||
*
|
||||
* - F-curve modifiers are disabled for evaluation,
|
||||
* so the values written back to the keyframes don't include modifier offsets.
|
||||
*
|
||||
* - Sub-frame key-frames aren't supported,
|
||||
* this could be added if needed without much trouble.
|
||||
*
|
||||
* - F-curves must have a #FCurve.bezt array (sampled curves aren't supported).
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* This structure is created for each pose channels F-curve,
|
||||
* an action be evaluated and stored in `fcurve_eval`,
|
||||
* with the mirrored values written into `bezt_array`.
|
||||
*
|
||||
* Store F-curve evaluated values, constructed with a sorted array of rounded keyed-frames,
|
||||
* passed to #action_flip_pchan_cache_init.
|
||||
*/
|
||||
struct FCurve_KeyCache {
|
||||
/**
|
||||
* When NULL, ignore this channel.
|
||||
*/
|
||||
FCurve *fcurve;
|
||||
/**
|
||||
* Cached evaluated F-curve values (without modifiers).
|
||||
*/
|
||||
float *fcurve_eval;
|
||||
/**
|
||||
* Cached #FCurve.bezt values, NULL when no key-frame exists on this frame.
|
||||
*
|
||||
* \note The case where two keyframes round to the same frame isn't supported.
|
||||
* In this case only the first will be used.
|
||||
*/
|
||||
BezTriple **bezt_array;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign `fkc` path, using a `path` lookup for a single value.
|
||||
*/
|
||||
static void action_flip_pchan_cache_fcurve_assign_value(struct FCurve_KeyCache *fkc,
|
||||
int index,
|
||||
const char *path,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
FCurve *fcu = BKE_fcurve_pathcache_find(fcache, path, index);
|
||||
if (fcu && fcu->bezt) {
|
||||
fkc->fcurve = fcu;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign #FCurve_KeyCache.fcurve path, using a `path` lookup for an array.
|
||||
*/
|
||||
static void action_flip_pchan_cache_fcurve_assign_array(struct FCurve_KeyCache *fkc,
|
||||
int fkc_len,
|
||||
const char *path,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
FCurve **fcurves = alloca(sizeof(*fcurves) * fkc_len);
|
||||
if (BKE_fcurve_pathcache_find_array(fcache, path, fcurves, fkc_len)) {
|
||||
for (int i = 0; i < fkc_len; i++) {
|
||||
if (fcurves[i] && fcurves[i]->bezt) {
|
||||
fkc[i].fcurve = fcurves[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill in pose channel cache for each frame in `keyed_frames`.
|
||||
*
|
||||
* \param keyed_frames: An array of keyed_frames to evaluate,
|
||||
* note that each frame is rounded to the nearest int.
|
||||
* \param keyed_frames_len: The length of the `keyed_frames` array.
|
||||
*/
|
||||
static void action_flip_pchan_cache_init(struct FCurve_KeyCache *fkc,
|
||||
const float *keyed_frames,
|
||||
int keyed_frames_len)
|
||||
{
|
||||
BLI_assert(fkc->fcurve != NULL);
|
||||
|
||||
/* Cache the F-curve values for `keyed_frames`. */
|
||||
const int fcurve_flag = fkc->fcurve->flag;
|
||||
fkc->fcurve->flag |= FCURVE_MOD_OFF;
|
||||
fkc->fcurve_eval = MEM_mallocN(sizeof(float) * keyed_frames_len, __func__);
|
||||
for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
|
||||
const float evaltime = keyed_frames[frame_index];
|
||||
fkc->fcurve_eval[frame_index] = evaluate_fcurve_only_curve(fkc->fcurve, evaltime);
|
||||
}
|
||||
fkc->fcurve->flag = fcurve_flag;
|
||||
|
||||
/* Cache the #BezTriple for `keyed_frames`, or leave as NULL. */
|
||||
fkc->bezt_array = MEM_mallocN(sizeof(*fkc->bezt_array) * keyed_frames_len, __func__);
|
||||
BezTriple *bezt = fkc->fcurve->bezt;
|
||||
BezTriple *bezt_end = fkc->fcurve->bezt + fkc->fcurve->totvert;
|
||||
|
||||
int frame_index = 0;
|
||||
while (frame_index < keyed_frames_len) {
|
||||
const float evaltime = keyed_frames[frame_index];
|
||||
const float bezt_time = roundf(bezt->vec[1][0]);
|
||||
if (bezt_time > evaltime) {
|
||||
fkc->bezt_array[frame_index++] = NULL;
|
||||
}
|
||||
else {
|
||||
if (bezt_time == evaltime) {
|
||||
fkc->bezt_array[frame_index++] = bezt;
|
||||
}
|
||||
bezt++;
|
||||
if (bezt == bezt_end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Clear remaining unset keyed_frames (if-any). */
|
||||
while (frame_index < keyed_frames_len) {
|
||||
fkc->bezt_array[frame_index++] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
static void action_flip_pchan(Object *ob_arm,
|
||||
const bPoseChannel *pchan,
|
||||
struct FCurvePathCache *fcache)
|
||||
{
|
||||
/* Begin F-Curve pose channel value extraction. */
|
||||
/* Use a fixed buffer size as it's known this can only be at most:
|
||||
* `pose.bones["{MAXBONENAME}"].rotation_quaternion`. */
|
||||
char path_xform[256];
|
||||
char pchan_name_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
|
||||
BLI_str_escape(pchan_name_esc, pchan->name, sizeof(pchan_name_esc));
|
||||
const int path_xform_prefix_len = SNPRINTF(path_xform, "pose.bones[\"%s\"]", pchan_name_esc);
|
||||
char *path_xform_suffix = path_xform + path_xform_prefix_len;
|
||||
const int path_xform_suffix_len = sizeof(path_xform) - path_xform_prefix_len;
|
||||
|
||||
/* Lookup and assign all available #FCurve channels,
|
||||
* unavailable channels are left NULL. */
|
||||
|
||||
/**
|
||||
* Structure to store transformation F-curves corresponding to a pose bones transformation.
|
||||
* Match struct member names from #bPoseChannel so macros avoid repetition.
|
||||
*
|
||||
* \note There is no need to read values unless they influence the 4x4 transform matrix,
|
||||
* and no need to write values back unless they would be changed by a modified matrix.
|
||||
* So `rotmode` needs to be read, but doesn't need to be written back to.
|
||||
*
|
||||
* Most bendy-bone settings don't need to be included either, flipping their RNA paths is enough.
|
||||
* Although the X/Y settings could make sense to transform, in practice it would only
|
||||
* work well if the rotation happened to swap X/Y alignment, leave this for now.
|
||||
*/
|
||||
struct {
|
||||
struct FCurve_KeyCache loc[3], eul[3], quat[4], rotAxis[3], rotAngle, size[3], rotmode;
|
||||
} fkc_pchan = {{{NULL}}};
|
||||
|
||||
#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
|
||||
|
||||
#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
|
||||
BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
|
||||
action_flip_pchan_cache_fcurve_assign_array( \
|
||||
fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
|
||||
|
||||
FCURVE_ASSIGN_ARRAY(loc, ".location");
|
||||
FCURVE_ASSIGN_ARRAY(eul, ".rotation_euler");
|
||||
FCURVE_ASSIGN_ARRAY(quat, ".rotation_quaternion");
|
||||
FCURVE_ASSIGN_ARRAY(rotAxis, ".rotation_axis_angle");
|
||||
FCURVE_ASSIGN_VALUE(rotAngle, ".rotation_axis_angle", 3);
|
||||
FCURVE_ASSIGN_ARRAY(size, ".scale");
|
||||
FCURVE_ASSIGN_VALUE(rotmode, ".rotation_mode", 0);
|
||||
|
||||
#undef FCURVE_ASSIGN_VALUE
|
||||
#undef FCURVE_ASSIGN_ARRAY
|
||||
|
||||
/* Array of F-curves, for convenient access. */
|
||||
#define FCURVE_CHANNEL_LEN (sizeof(fkc_pchan) / sizeof(struct FCurve_KeyCache))
|
||||
FCurve *fcurve_array[FCURVE_CHANNEL_LEN];
|
||||
int fcurve_array_len = 0;
|
||||
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve != NULL) {
|
||||
fcurve_array[fcurve_array_len++] = fkc->fcurve;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this pose has no transform channels, there is nothing to do. */
|
||||
if (fcurve_array_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate an array of frames used by any of the key-frames in `fcurve_array`. */
|
||||
int keyed_frames_len;
|
||||
const float *keyed_frames = BKE_fcurves_calc_keyed_frames(
|
||||
fcurve_array, fcurve_array_len, &keyed_frames_len);
|
||||
|
||||
/* Initialize the pose channel curve cache from the F-curve. */
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve == NULL) {
|
||||
continue;
|
||||
}
|
||||
action_flip_pchan_cache_init(fkc, keyed_frames, keyed_frames_len);
|
||||
}
|
||||
|
||||
/* X-axis flipping matrix. */
|
||||
float flip_mtx[4][4];
|
||||
unit_m4(flip_mtx);
|
||||
flip_mtx[0][0] = -1;
|
||||
|
||||
bPoseChannel *pchan_flip = NULL;
|
||||
char pchan_name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(pchan_name_flip, pchan->name, false, sizeof(pchan_name_flip));
|
||||
if (!STREQ(pchan_name_flip, pchan->name)) {
|
||||
pchan_flip = BKE_pose_channel_find_name(ob_arm->pose, pchan_name_flip);
|
||||
}
|
||||
|
||||
float arm_mat_inv[4][4];
|
||||
invert_m4_m4(arm_mat_inv, pchan_flip ? pchan_flip->bone->arm_mat : pchan->bone->arm_mat);
|
||||
|
||||
/* Now flip the transformation & write it back to the F-curves in `fkc_pchan`. */
|
||||
|
||||
for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
|
||||
|
||||
/* Temporary pose channel to write values into,
|
||||
* using the `fkc_pchan` values, falling back to the values in the pose channel. */
|
||||
bPoseChannel pchan_temp = *pchan;
|
||||
|
||||
/* Load the values into the channel. */
|
||||
#define READ_VALUE_FLT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
pchan_temp.id = fkc_pchan.id.fcurve_eval[frame_index]; \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define READ_VALUE_INT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
pchan_temp.id = floorf(fkc_pchan.id.fcurve_eval[frame_index] + 0.5f); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define READ_ARRAY_FLT(id) \
|
||||
for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
|
||||
READ_VALUE_FLT(id[i]); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
READ_ARRAY_FLT(loc);
|
||||
READ_ARRAY_FLT(eul);
|
||||
READ_ARRAY_FLT(quat);
|
||||
READ_ARRAY_FLT(rotAxis);
|
||||
READ_VALUE_FLT(rotAngle);
|
||||
READ_ARRAY_FLT(size);
|
||||
READ_VALUE_INT(rotmode);
|
||||
|
||||
#undef READ_ARRAY_FLT
|
||||
#undef READ_VALUE_FLT
|
||||
#undef READ_VALUE_INT
|
||||
|
||||
float chan_mat[4][4];
|
||||
BKE_pchan_to_mat4(&pchan_temp, chan_mat);
|
||||
|
||||
/* Move to the pose-space. */
|
||||
mul_m4_m4m4(chan_mat, pchan->bone->arm_mat, chan_mat);
|
||||
|
||||
/* Flip the matrix. */
|
||||
mul_m4_m4m4(chan_mat, chan_mat, flip_mtx);
|
||||
mul_m4_m4m4(chan_mat, flip_mtx, chan_mat);
|
||||
|
||||
/* Move back to bone-space space, using the flipped bone if it exists. */
|
||||
mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat);
|
||||
|
||||
BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false);
|
||||
|
||||
/* Write the values back to the F-curves. */
|
||||
#define WRITE_VALUE_FLT(id) \
|
||||
if (fkc_pchan.id.fcurve_eval != NULL) { \
|
||||
BezTriple *bezt = fkc_pchan.id.bezt_array[frame_index]; \
|
||||
if (bezt != NULL) { \
|
||||
const float delta = pchan_temp.id - bezt->vec[1][1]; \
|
||||
bezt->vec[0][1] += delta; \
|
||||
bezt->vec[1][1] += delta; \
|
||||
bezt->vec[2][1] += delta; \
|
||||
} \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
#define WRITE_ARRAY_FLT(id) \
|
||||
for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
|
||||
WRITE_VALUE_FLT(id[i]); \
|
||||
} \
|
||||
((void)0)
|
||||
|
||||
/* Write the values back the the F-curves. */
|
||||
WRITE_ARRAY_FLT(loc);
|
||||
WRITE_ARRAY_FLT(eul);
|
||||
WRITE_ARRAY_FLT(quat);
|
||||
WRITE_ARRAY_FLT(rotAxis);
|
||||
WRITE_VALUE_FLT(rotAngle);
|
||||
WRITE_ARRAY_FLT(size);
|
||||
/* No need to write back 'rotmode' as it can't be transformed. */
|
||||
|
||||
#undef WRITE_ARRAY_FLT
|
||||
#undef WRITE_VALUE_FLT
|
||||
}
|
||||
|
||||
/* Recalculate handles. */
|
||||
for (int i = 0; i < fcurve_array_len; i++) {
|
||||
calchandles_fcurve_ex(fcurve_array[i], 0);
|
||||
}
|
||||
|
||||
MEM_freeN((void *)keyed_frames);
|
||||
|
||||
for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
|
||||
struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
|
||||
if (fkc->fcurve_eval) {
|
||||
MEM_freeN(fkc->fcurve_eval);
|
||||
}
|
||||
if (fkc->bezt_array) {
|
||||
MEM_freeN(fkc->bezt_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap all RNA paths left/right.
|
||||
*/
|
||||
static void action_flip_pchan_rna_paths(struct bAction *act)
|
||||
{
|
||||
const char *path_pose_prefix = "pose.bones[\"";
|
||||
const int path_pose_prefix_len = strlen(path_pose_prefix);
|
||||
|
||||
/* Tag curves that have renamed f-curves. */
|
||||
LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
|
||||
agrp->flag &= ~AGRP_TEMP;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
|
||||
if (!STRPREFIX(fcu->rna_path, path_pose_prefix)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *name_esc = fcu->rna_path + path_pose_prefix_len;
|
||||
const char *name_esc_end = BLI_str_escape_find_quote(name_esc);
|
||||
|
||||
/* While unlikely, an RNA path could be malformed. */
|
||||
if (UNLIKELY(name_esc_end == NULL)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char name[MAXBONENAME];
|
||||
const size_t name_esc_len = (size_t)(name_esc_end - name_esc);
|
||||
const size_t name_len = BLI_str_unescape(name, name_esc, name_esc_len);
|
||||
|
||||
/* While unlikely, data paths could be constructed that have longer names than
|
||||
* are currently supported. */
|
||||
if (UNLIKELY(name_len >= sizeof(name))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* When the flipped name differs, perform the rename. */
|
||||
char name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
|
||||
if (!STREQ(name_flip, name)) {
|
||||
char name_flip_esc[MAXBONENAME * 2];
|
||||
BLI_str_escape(name_flip_esc, name_flip, sizeof(name_flip_esc));
|
||||
char *path_flip = BLI_sprintfN("pose.bones[\"%s%s", name_flip_esc, name_esc_end);
|
||||
MEM_freeN(fcu->rna_path);
|
||||
fcu->rna_path = path_flip;
|
||||
|
||||
if (fcu->grp != NULL) {
|
||||
fcu->grp->flag |= AGRP_TEMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rename tagged groups. */
|
||||
LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
|
||||
if ((agrp->flag & AGRP_TEMP) == 0) {
|
||||
continue;
|
||||
}
|
||||
agrp->flag &= ~AGRP_TEMP;
|
||||
char name_flip[MAXBONENAME];
|
||||
BLI_string_flip_side_name(name_flip, agrp->name, false, sizeof(name_flip));
|
||||
if (!STREQ(name_flip, agrp->name)) {
|
||||
STRNCPY(agrp->name, name_flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm)
|
||||
{
|
||||
struct FCurvePathCache *fcache = BKE_fcurve_pathcache_create(&act->curves);
|
||||
int i;
|
||||
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob_arm->pose->chanbase, i) {
|
||||
action_flip_pchan(ob_arm, pchan, fcache);
|
||||
}
|
||||
BKE_fcurve_pathcache_destroy(fcache);
|
||||
|
||||
action_flip_pchan_rna_paths(act);
|
||||
|
||||
DEG_id_tag_update(&act->id, ID_RECALC_COPY_ON_WRITE);
|
||||
}
|
||||
|
||||
/** \} */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user