diff options
author | Fabian Schempp <fabianschempp@googlemail.com> | 2021-08-06 00:50:08 +0300 |
---|---|---|
committer | Fabian Schempp <fabianschempp@googlemail.com> | 2021-08-06 08:48:40 +0300 |
commit | 6fd836f53b0b6914933ce60b6649f5981519fe98 (patch) | |
tree | b70eb16ab218d03d82f9caac87e7a294d6ecc313 | |
parent | aef45a4ef2593365eeb40f11f4b8ea3d399c9717 (diff) | |
parent | 92edf37997c25444fc2628c8057a87b7e87c5eff (diff) |
Merged Master
278 files changed, 5492 insertions, 1613 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index b7dfb56ff02..2868324bf46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -428,6 +428,10 @@ mark_as_advanced(WITH_CYCLES_NETWORK) option(WITH_CUDA_DYNLOAD "Dynamically load CUDA libraries at runtime" ON) mark_as_advanced(WITH_CUDA_DYNLOAD) +# Draw Manager +option(WITH_DRAW_DEBUG "Add extra debug capabilities to Draw Manager" OFF) +mark_as_advanced(WITH_DRAW_DEBUG) + # LLVM option(WITH_LLVM "Use LLVM" OFF) if(APPLE) @@ -608,12 +612,6 @@ if(WIN32) option(WITH_WINDOWS_FIND_MODULES "Use find_package to locate libraries" OFF) mark_as_advanced(WITH_WINDOWS_FIND_MODULES) - option(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS "Organize the visual studio projects according to source folder structure." ON) - mark_as_advanced(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS) - - option(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS "Organize the source files in filters matching the source folders." ON) - mark_as_advanced(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS) - option(WINDOWS_PYTHON_DEBUG "Include the files needed for debugging python scripts with visual studio 2017+." OFF) mark_as_advanced(WINDOWS_PYTHON_DEBUG) @@ -631,6 +629,18 @@ if(WIN32) endif() +if(WIN32 OR XCODE) + option(IDE_GROUP_SOURCES_IN_FOLDERS "Organize the source files in filters matching the source folders." ON) + mark_as_advanced(IDE_GROUP_SOURCES_IN_FOLDERS) + + option(IDE_GROUP_PROJECTS_IN_FOLDERS "Organize the projects according to source folder structure." ON) + mark_as_advanced(IDE_GROUP_PROJECTS_IN_FOLDERS) + + if (IDE_GROUP_PROJECTS_IN_FOLDERS) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + endif() +endif() + if(UNIX) # See WITH_WINDOWS_SCCACHE for Windows. option(WITH_COMPILER_CCACHE "Use ccache to improve rebuild times (Works with Ninja, Makefiles and Xcode)" OFF) diff --git a/GNUmakefile b/GNUmakefile index 7df561ed34f..d620e5c4363 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -63,7 +63,7 @@ Package Targets * package_debian: Build a debian package. * package_pacman: Build an arch linux pacman package. - * package_archive: Build an archive package. + * package_archive: Build an archive package. Testing Targets Not associated with building Blender. @@ -167,7 +167,7 @@ endef # This makefile is not meant for Windows ifeq ($(OS),Windows_NT) - $(error On Windows, use "cmd //c make.bat" instead of "make") + $(error On Windows, use "cmd //c make.bat" instead of "make") endif # System Vars @@ -379,7 +379,7 @@ deps: .FORCE @cmake -H"$(DEPS_SOURCE_DIR)" \ -B"$(DEPS_BUILD_DIR)" \ - -DHARVEST_TARGET=$(DEPS_INSTALL_DIR) + -DHARVEST_TARGET=$(DEPS_INSTALL_DIR) @echo @echo Building dependencies ... @@ -456,7 +456,8 @@ project_eclipse: .FORCE check_cppcheck: .FORCE $(CMAKE_CONFIG) cd "$(BUILD_DIR)" ; \ - $(PYTHON) "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \ + $(PYTHON) \ + "$(BLENDER_DIR)/build_files/cmake/cmake_static_check_cppcheck.py" 2> \ "$(BLENDER_DIR)/check_cppcheck.txt" @echo "written: check_cppcheck.txt" @@ -518,8 +519,9 @@ source_archive: .FORCE python3 ./build_files/utils/make_source_archive.py source_archive_complete: .FORCE - cmake -S "$(BLENDER_DIR)/build_files/build_environment" -B"$(BUILD_DIR)/source_archive" \ - -DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE) -DPACKAGE_USE_UPSTREAM_SOURCES=OFF + cmake \ + -S "$(BLENDER_DIR)/build_files/build_environment" -B"$(BUILD_DIR)/source_archive" \ + -DCMAKE_BUILD_TYPE_INIT:STRING=$(BUILD_TYPE) -DPACKAGE_USE_UPSTREAM_SOURCES=OFF # This assumes CMake is still using a default `PACKAGE_DIR` variable: python3 ./build_files/utils/make_source_archive.py --include-packages "$(BUILD_DIR)/source_archive/packages" @@ -527,9 +529,11 @@ source_archive_complete: .FORCE INKSCAPE_BIN?="inkscape" icons: .FORCE BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ - "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py" - BLENDER_BIN=$(BLENDER_BIN) INKSCAPE_BIN=$(INKSCAPE_BIN) \ - "$(BLENDER_DIR)/release/datafiles/prvicons_update.py" + "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py" + INKSCAPE_BIN=$(INKSCAPE_BIN) \ + "$(BLENDER_DIR)/release/datafiles/prvicons_update.py" + INKSCAPE_BIN=$(INKSCAPE_BIN) \ + "$(BLENDER_DIR)/release/datafiles/alert_icons_update.py" icons_geom: .FORCE BLENDER_BIN=$(BLENDER_BIN) \ @@ -543,7 +547,7 @@ update_code: .FORCE 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) + $(PYTHON) source/tools/utils_maintenance/clang_format_paths.py $(PATHS) # ----------------------------------------------------------------------------- @@ -553,8 +557,9 @@ format: .FORCE # Simple version of ./doc/python_api/sphinx_doc_gen.sh with no PDF generation. doc_py: .FORCE ASAN_OPTIONS=halt_on_error=0:${ASAN_OPTIONS} \ - $(BLENDER_BIN) --background -noaudio --factory-startup \ - --python doc/python_api/sphinx_doc_gen.py + $(BLENDER_BIN) \ + --background -noaudio --factory-startup \ + --python doc/python_api/sphinx_doc_gen.py sphinx-build -b html -j $(NPROCS) doc/python_api/sphinx-in doc/python_api/sphinx-out @echo "docs written into: '$(BLENDER_DIR)/doc/python_api/sphinx-out/index.html'" @@ -563,8 +568,9 @@ doc_doxy: .FORCE @echo "docs written into: '$(BLENDER_DIR)/doc/doxygen/html/index.html'" doc_dna: .FORCE - $(BLENDER_BIN) --background -noaudio --factory-startup \ - --python doc/blender_file_format/BlendFileDnaExporter_25.py + $(BLENDER_BIN) \ + --background -noaudio --factory-startup \ + --python doc/blender_file_format/BlendFileDnaExporter_25.py @echo "docs written into: '$(BLENDER_DIR)/doc/blender_file_format/dna.html'" doc_man: .FORCE diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 8ad3f77c7d3..1471aa21505 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -208,7 +208,7 @@ function(blender_source_group ) # if enabled, use the sources directories as filters. - if(WINDOWS_USE_VISUAL_STUDIO_SOURCE_FOLDERS) + if(IDE_GROUP_SOURCES_IN_FOLDERS) foreach(_SRC ${sources}) # remove ../'s get_filename_component(_SRC_DIR ${_SRC} REALPATH) @@ -240,8 +240,8 @@ function(blender_source_group endforeach() endif() - # if enabled, set the FOLDER property for visual studio projects - if(WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS) + # if enabled, set the FOLDER property for the projects + if(IDE_GROUP_PROJECTS_IN_FOLDERS) get_filename_component(FolderDir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) string(REPLACE ${CMAKE_SOURCE_DIR} "" FolderDir ${FolderDir}) set_target_properties(${name} PROPERTIES FOLDER ${FolderDir}) diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake index 529c01db009..a130d265dff 100644 --- a/build_files/cmake/platform/platform_apple.cmake +++ b/build_files/cmake/platform/platform_apple.cmake @@ -500,14 +500,17 @@ endif() # makesdna, tests, etc.), we add an rpath to the OpenMP library dir through # CMAKE_BUILD_RPATH. This avoids having to make many copies of the dylib next to each binary. # -# For the installed Blender executable, CMAKE_INSTALL_RPATH will be used, but -# needs no changes since it already looks for dylibs next to the executable by -# default (@executable_path). +# For the installed Blender executable, CMAKE_INSTALL_RPATH will be used +# to locate the dylibs at @executable_path, next to the Blender executable. # # For the installed Python module, CMAKE_INSTALL_RPATH is modified to find the # dylib in an adjacent folder. set(CMAKE_SKIP_BUILD_RPATH FALSE) list(APPEND CMAKE_BUILD_RPATH "${OpenMP_LIBRARY_DIR}") + +set(CMAKE_SKIP_INSTALL_RPATH FALSE) +list(APPEND CMAKE_INSTALL_RPATH "@executable_path") + if(WITH_PYTHON_MODULE) list(APPEND CMAKE_INSTALL_RPATH "@loader_path/../Resources/${BLENDER_VERSION}/lib") endif() diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake index a0e91199c72..3773aaaffed 100644 --- a/build_files/cmake/platform/platform_win32.cmake +++ b/build_files/cmake/platform/platform_win32.cmake @@ -57,8 +57,6 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang") endif() endif() -set_property(GLOBAL PROPERTY USE_FOLDERS ${WINDOWS_USE_VISUAL_STUDIO_PROJECT_FOLDERS}) - if(NOT WITH_PYTHON_MODULE) set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT blender) endif() @@ -217,8 +215,8 @@ else() 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(PDB_INFO_OVERRIDE_FLAGS "${SYMBOL_FORMAT_RELEASE}") + set(PDB_INFO_OVERRIDE_LINKER_FLAGS "/DEBUG /OPT:REF /OPT:ICF /INCREMENTAL:NO") endif() string(APPEND CMAKE_CXX_FLAGS_DEBUG " /MDd ${SYMBOL_FORMAT}") diff --git a/build_files/windows/find_blender.cmd b/build_files/windows/find_blender.cmd new file mode 100644 index 00000000000..9adbfd35ae9 --- /dev/null +++ b/build_files/windows/find_blender.cmd @@ -0,0 +1,28 @@ +REM First see if there is an environment variable set +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the build folder next, if ninja was used there will be no +REM debug/release folder +set BLENDER_BIN=%BUILD_DIR%\bin\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the release folder next +set BLENDER_BIN=%BUILD_DIR%\bin\release\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM Check the debug folder next +set BLENDER_BIN=%BUILD_DIR%\bin\debug\blender.exe +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +REM at this point, we don't know where blender is, clear the variable +set BLENDER_BIN= + +:detect_blender_done diff --git a/build_files/windows/find_inkscape.cmd b/build_files/windows/find_inkscape.cmd new file mode 100644 index 00000000000..2fa27f70d47 --- /dev/null +++ b/build_files/windows/find_inkscape.cmd @@ -0,0 +1,21 @@ +REM First see if there is an environment variable set +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM Then see if inkscape is available in the path +for %%X in (inkscape.exe) do (set INKSCAPE_BIN=%%~$PATH:X) +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM Finally see if it is perhaps installed at the default location +set INKSCAPE_BIN=%ProgramFiles%\Inkscape\bin\inkscape.exe +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +REM If still not found clear the variable +set INKSCAPE_BIN= + +:detect_inkscape_done diff --git a/build_files/windows/icons.cmd b/build_files/windows/icons.cmd new file mode 100644 index 00000000000..473a40885a8 --- /dev/null +++ b/build_files/windows/icons.cmd @@ -0,0 +1,42 @@ +if EXIST %PYTHON% ( + goto detect_python_done +) + +set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe +if EXIST %PYTHON% ( + goto detect_python_done +) + +echo python not found at %PYTHON% +exit /b 1 + +:detect_python_done +echo found python (%PYTHON%) + +call "%~dp0\find_inkscape.cmd" + +if EXIST "%INKSCAPE_BIN%" ( + goto detect_inkscape_done +) + +echo unable to locate inkscape, run "set inkscape_BIN=full_path_to_inkscape.exe" +exit /b 1 + +:detect_inkscape_done + +call "%~dp0\find_blender.cmd" + +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe" +exit /b 1 + +:detect_blender_done + +%PYTHON% -B %BLENDER_DIR%\release\datafiles\blender_icons_update.py +%PYTHON% -B %BLENDER_DIR%\release\datafiles\prvicons_update.py +%PYTHON% -B %BLENDER_DIR%\release\datafiles\alert_icons_update.py + +:EOF diff --git a/build_files/windows/icons_geom.cmd b/build_files/windows/icons_geom.cmd new file mode 100644 index 00000000000..18312daf35b --- /dev/null +++ b/build_files/windows/icons_geom.cmd @@ -0,0 +1,29 @@ +if EXIST %PYTHON% ( + goto detect_python_done +) + +set PYTHON=%BLENDER_DIR%\..\lib\win64_vc15\python\39\bin\python.exe +if EXIST %PYTHON% ( + goto detect_python_done +) + +echo python not found at %PYTHON% +exit /b 1 + +:detect_python_done +echo found python (%PYTHON%) + +call "%~dp0\find_blender.cmd" + +if EXIST "%BLENDER_BIN%" ( + goto detect_blender_done +) + +echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe" +exit /b 1 + +:detect_blender_done + +%PYTHON% -B %BLENDER_DIR%\release\datafiles\blender_icons_geom_update.py + +:EOF diff --git a/build_files/windows/parse_arguments.cmd b/build_files/windows/parse_arguments.cmd index 000b98c992e..c71093f2394 100644 --- a/build_files/windows/parse_arguments.cmd +++ b/build_files/windows/parse_arguments.cmd @@ -107,6 +107,12 @@ if NOT "%1" == "" ( set FORMAT=1 set FORMAT_ARGS=%2 %3 %4 %5 %6 %7 %8 %9 goto EOF + ) else if "%1" == "icons" ( + set ICONS=1 + goto EOF + ) else if "%1" == "icons_geom" ( + set ICONS_GEOM=1 + goto EOF ) else ( echo Command "%1" unknown, aborting! goto ERR diff --git a/build_files/windows/reset_variables.cmd b/build_files/windows/reset_variables.cmd index 262874713eb..590d4ca246a 100644 --- a/build_files/windows/reset_variables.cmd +++ b/build_files/windows/reset_variables.cmd @@ -31,3 +31,5 @@ set PYDEBUG_CMAKE_ARGS= set FORMAT= set TEST= set BUILD_WITH_SCCACHE= +set ICONS= +set ICONS_GEOM=
\ No newline at end of file diff --git a/doc/python_api/examples/gpu.9.py b/doc/python_api/examples/gpu.9.py index e358cb517bd..b0400ce7809 100644 --- a/doc/python_api/examples/gpu.9.py +++ b/doc/python_api/examples/gpu.9.py @@ -31,7 +31,8 @@ def draw(): context.space_data, context.region, view_matrix, - projection_matrix) + projection_matrix, + True) gpu.state.depth_mask_set(False) draw_texture_2d(offscreen.texture_color, (10, 10), WIDTH, HEIGHT) diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index 824b2fb0e9c..7f7d91f0765 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -111,5 +111,5 @@ if(WITH_MOD_FLUID) endif() if (WITH_COMPOSITOR) - add_subdirectory(smaa_areatex) + add_subdirectory(smaa_areatex) endif() diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 4cd75edee5f..124223635d1 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1164,12 +1164,6 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): @classmethod def register(cls): - bpy.types.Object.cycles_visibility = PointerProperty( - name="Cycles Visibility Settings", - description="Cycles visibility settings", - type=cls, - ) - bpy.types.World.cycles_visibility = PointerProperty( name="Cycles Visibility Settings", description="Cycles visibility settings", @@ -1178,7 +1172,6 @@ class CyclesVisibilitySettings(bpy.types.PropertyGroup): @classmethod def unregister(cls): - del bpy.types.Object.cycles_visibility del bpy.types.World.cycles_visibility @@ -1268,18 +1261,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): default=0.1, ) - is_shadow_catcher: BoolProperty( - name="Shadow Catcher", - description="Only render shadows on this object, for compositing renders into real footage", - default=False, - ) - - is_holdout: BoolProperty( - name="Holdout", - description="Render objects as a holdout or matte, creating a " - "hole in the image with zero alpha, to fill out in " - "compositing with real footage or another render", - default=False, + ao_distance: FloatProperty( + name="AO Distance", + description="AO distance used for approximate global illumination (0 means use world setting)", + min=0.0, + default=0.0, + subtype='DISTANCE', ) @classmethod diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e9a4ce77080..47f7b4c6d73 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1102,7 +1102,7 @@ class CYCLES_PT_context_material(CyclesButtonsPanel, Panel): if ob: is_sortable = len(ob.material_slots) > 1 - rows = 1 + rows = 3 if (is_sortable): rows = 4 @@ -1228,6 +1228,26 @@ class CYCLES_OBJECT_PT_shading_shadow_terminator(CyclesButtonsPanel, Panel): flow.prop(cob, "shadow_terminator_offset", text="Shading Offset") +class CYCLES_OBJECT_PT_shading_gi_approximation(CyclesButtonsPanel, Panel): + bl_label = "Fast GI Approximation" + bl_parent_id = "CYCLES_OBJECT_PT_shading" + bl_context = "object" + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + scene = context.scene + ob = context.object + + cob = ob.cycles + cscene = scene.cycles + + col = layout.column() + col.active = cscene.use_fast_gi + col.prop(cob, "ao_distance") + + class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): bl_label = "Visibility" bl_context = "object" @@ -1250,10 +1270,9 @@ class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel): col.prop(ob, "hide_render", text="Renders", invert_checkbox=True, toggle=False) if has_geometry_visibility(ob): - cob = ob.cycles col = layout.column(heading="Mask") - col.prop(cob, "is_shadow_catcher") - col.prop(cob, "is_holdout") + col.prop(ob, "is_shadow_catcher") + col.prop(ob, "is_holdout") class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): @@ -1273,19 +1292,17 @@ class CYCLES_OBJECT_PT_visibility_ray_visibility(CyclesButtonsPanel, Panel): scene = context.scene ob = context.object - cob = ob.cycles - visibility = ob.cycles_visibility col = layout.column() - col.prop(visibility, "camera") - col.prop(visibility, "diffuse") - col.prop(visibility, "glossy") - col.prop(visibility, "transmission") - col.prop(visibility, "scatter") + col.prop(ob, "visible_camera", text="Camera") + col.prop(ob, "visible_diffuse", text="Diffuse") + col.prop(ob, "visible_glossy", text="Glossy") + col.prop(ob, "visible_transmission", text="Transmission") + col.prop(ob, "visible_volume_scatter", text="Volume Scatter") if ob.type != 'LIGHT': sub = col.column() - sub.prop(visibility, "shadow") + sub.prop(ob, "visible_shadow", text="Shadow") class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): @@ -2305,6 +2322,7 @@ classes = ( CYCLES_OBJECT_PT_motion_blur, CYCLES_OBJECT_PT_shading, CYCLES_OBJECT_PT_shading_shadow_terminator, + CYCLES_OBJECT_PT_shading_gi_approximation, CYCLES_OBJECT_PT_visibility, CYCLES_OBJECT_PT_visibility_ray_visibility, CYCLES_OBJECT_PT_visibility_culling, diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index f5e8db2aee1..4711e0cbe76 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -199,8 +199,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* Visibility flags for both parent and child. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); - bool use_holdout = get_boolean(cobject, "is_holdout") || - b_parent.holdout_get(PointerRNA_NULL, b_view_layer); + bool use_holdout = b_parent.holdout_get(PointerRNA_NULL, b_view_layer); uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY; if (b_parent.ptr.data != b_ob.ptr.data) { @@ -287,8 +286,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, object->set_visibility(visibility); - bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher"); - object->set_is_shadow_catcher(is_shadow_catcher); + object->set_is_shadow_catcher(b_ob.is_shadow_catcher()); float shadow_terminator_shading_offset = get_float(cobject, "shadow_terminator_offset"); object->set_shadow_terminator_shading_offset(shadow_terminator_shading_offset); @@ -297,6 +295,13 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, "shadow_terminator_geometry_offset"); object->set_shadow_terminator_geometry_offset(shadow_terminator_geometry_offset); + float ao_distance = get_float(cobject, "ao_distance"); + if (ao_distance == 0.0f && b_parent.ptr.data != b_ob.ptr.data) { + PointerRNA cparent = RNA_pointer_get(&b_parent.ptr, "cycles"); + ao_distance = get_float(cparent, "ao_distance"); + } + object->set_ao_distance(ao_distance); + /* sync the asset name for Cryptomatte */ BL::Object parent = b_ob.parent(); ustring parent_name; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 43dbb4105df..2b2188b023d 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -596,15 +596,14 @@ static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, static inline uint object_ray_visibility(BL::Object &b_ob) { - PointerRNA cvisibility = RNA_pointer_get(&b_ob.ptr, "cycles_visibility"); uint flag = 0; - flag |= get_boolean(cvisibility, "camera") ? PATH_RAY_CAMERA : 0; - flag |= get_boolean(cvisibility, "diffuse") ? PATH_RAY_DIFFUSE : 0; - flag |= get_boolean(cvisibility, "glossy") ? PATH_RAY_GLOSSY : 0; - flag |= get_boolean(cvisibility, "transmission") ? PATH_RAY_TRANSMIT : 0; - flag |= get_boolean(cvisibility, "shadow") ? PATH_RAY_SHADOW : 0; - flag |= get_boolean(cvisibility, "scatter") ? PATH_RAY_VOLUME_SCATTER : 0; + flag |= b_ob.visible_camera() ? PATH_RAY_CAMERA : 0; + flag |= b_ob.visible_diffuse() ? PATH_RAY_DIFFUSE : 0; + flag |= b_ob.visible_glossy() ? PATH_RAY_GLOSSY : 0; + flag |= b_ob.visible_transmission() ? PATH_RAY_TRANSMIT : 0; + flag |= b_ob.visible_shadow() ? PATH_RAY_SHADOW : 0; + flag |= b_ob.visible_volume_scatter() ? PATH_RAY_VOLUME_SCATTER : 0; return flag; } diff --git a/intern/cycles/cmake/macros.cmake b/intern/cycles/cmake/macros.cmake index ff62b816e6c..47196dfd1ce 100644 --- a/intern/cycles/cmake/macros.cmake +++ b/intern/cycles/cmake/macros.cmake @@ -13,7 +13,7 @@ # limitations under the License. function(cycles_set_solution_folder target) - if(WINDOWS_USE_VISUAL_STUDIO_FOLDERS) + if(IDE_GROUP_PROJECTS_IN_FOLDERS) get_filename_component(folderdir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) string(REPLACE ${CMAKE_SOURCE_DIR} "" folderdir ${folderdir}) set_target_properties(${target} PROPERTIES FOLDER ${folderdir}) diff --git a/intern/cycles/kernel/bvh/bvh_util.h b/intern/cycles/kernel/bvh/bvh_util.h index 867ea3af8d1..b1faebce957 100644 --- a/intern/cycles/kernel/bvh/bvh_util.h +++ b/intern/cycles/kernel/bvh/bvh_util.h @@ -239,4 +239,14 @@ ccl_device_forceinline int intersection_get_shader(KernelGlobals *ccl_restrict k return shader & SHADER_MASK; } +ccl_device_forceinline int intersection_get_object(KernelGlobals *ccl_restrict kg, + const Intersection *ccl_restrict isect) +{ + if (isect->object != OBJECT_NONE) { + return isect->object; + } + + return kernel_tex_fetch(__prim_object, isect->prim); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index d1f33a4d0f0..7da890b908d 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -81,7 +81,8 @@ ccl_device_noinline void compute_light_pass( kg, sd, emission_sd, L, &state, &ray, &throughput, &ss_indirect)) { while (ss_indirect.num_rays) { kernel_path_subsurface_setup_indirect(kg, &ss_indirect, &state, &ray, L, &throughput); - kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L); + kernel_path_indirect( + kg, &indirect_sd, emission_sd, &ray, throughput, &state, L, sd->object); } is_sss_sample = true; } @@ -97,7 +98,8 @@ ccl_device_noinline void compute_light_pass( state.ray_t = 0.0f; # endif /* compute indirect light */ - kernel_path_indirect(kg, &indirect_sd, emission_sd, &ray, throughput, &state, L); + kernel_path_indirect( + kg, &indirect_sd, emission_sd, &ray, throughput, &state, L, sd->object); /* sum and reset indirect light pass variables for the next samples */ path_radiance_sum_indirect(L); diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 3430543bc8e..92a097de9e1 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -58,7 +58,8 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg, ccl_addr_space PathState *state, Ray *ray, Intersection *isect, - PathRadiance *L) + PathRadiance *L, + const int last_object) { PROFILING_INIT(kg, PROFILING_SCENE_INTERSECT); @@ -66,6 +67,12 @@ ccl_device_forceinline bool kernel_path_scene_intersect(KernelGlobals *kg, if (path_state_ao_bounce(kg, state)) { ray->t = kernel_data.background.ao_distance; + if (last_object != OBJECT_NONE) { + const float object_ao_distance = kernel_tex_fetch(__objects, last_object).ao_distance; + if (object_ao_distance != 0.0f) { + ray->t = object_ao_distance; + } + } } bool hit = scene_intersect(kg, ray, visibility, isect); @@ -253,7 +260,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(KernelGlobals *kg, PROFILING_INIT(kg, PROFILING_SHADER_APPLY); #ifdef __SHADOW_TRICKS__ - if ((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) { + if (sd->object_flag & SD_OBJECT_SHADOW_CATCHER) { if (state->flag & PATH_RAY_TRANSPARENT_BACKGROUND) { state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_STORE_SHADOW_INFO); @@ -369,7 +376,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, Ray *ray, float3 throughput, PathState *state, - PathRadiance *L) + PathRadiance *L, + const int last_object) { # ifdef __SUBSURFACE__ SubsurfaceIndirectRays ss_indirect; @@ -382,7 +390,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L, last_object); /* Find intersection with lamps and compute emission for MIS. */ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, sd, L); @@ -526,7 +534,7 @@ ccl_device_forceinline void kernel_path_integrate(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L, sd.object); /* Find intersection with lamps and compute emission for MIS. */ kernel_path_lamp_emission(kg, state, ray, throughput, &isect, &sd, L); diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h index 5ea7687ec3b..a1ee1bc107e 100644 --- a/intern/cycles/kernel/kernel_path_branched.h +++ b/intern/cycles/kernel/kernel_path_branched.h @@ -92,6 +92,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, volume_ray.t = (hit) ? isect->t : FLT_MAX; float step_size = volume_stack_step_size(kg, state->volume_stack); + const int object = sd->object; # ifdef __VOLUME_DECOUPLED__ /* decoupled ray marching only supported on CPU */ @@ -134,7 +135,8 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, if (result == VOLUME_PATH_SCATTERED && kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) { - kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp * num_samples_inv, &ps, L); + kernel_path_indirect( + kg, indirect_sd, emission_sd, &pray, tp * num_samples_inv, &ps, L, object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -180,7 +182,7 @@ ccl_device_forceinline void kernel_branched_path_volume(KernelGlobals *kg, kernel_path_volume_connect_light(kg, sd, emission_sd, tp, state, L); if (kernel_path_volume_bounce(kg, sd, &tp, &ps, &L->state, &pray)) { - kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp, &ps, L); + kernel_path_indirect(kg, indirect_sd, emission_sd, &pray, tp, &ps, L, object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -266,7 +268,8 @@ ccl_device_noinline_cpu void kernel_branched_path_surface_indirect_light(KernelG ps.rng_hash = state->rng_hash; - kernel_path_indirect(kg, indirect_sd, emission_sd, &bsdf_ray, tp * num_samples_inv, &ps, L); + kernel_path_indirect( + kg, indirect_sd, emission_sd, &bsdf_ray, tp * num_samples_inv, &ps, L, sd->object); /* for render passes, sum and reset indirect light pass variables * for the next samples */ @@ -395,7 +398,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg, for (;;) { /* Find intersection with objects in scene. */ Intersection isect; - bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L); + bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L, sd.object); # ifdef __VOLUME__ /* Volume integration. */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f9ea3a2d0a8..7cbe18acf28 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1447,7 +1447,10 @@ typedef struct KernelObject { float shadow_terminator_shading_offset; float shadow_terminator_geometry_offset; - float pad1, pad2, pad3; + + float ao_distance; + + float pad1, pad2; } KernelObject; static_assert_align(KernelObject, 16); diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h index 5fef3e045f8..9ac95aafd2f 100644 --- a/intern/cycles/kernel/split/kernel_scene_intersect.h +++ b/intern/cycles/kernel/split/kernel_scene_intersect.h @@ -65,7 +65,10 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg) PathRadiance *L = &kernel_split_state.path_radiance[ray_index]; Intersection isect; - bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L); + const int last_object = state->bounce > 0 ? + intersection_get_object(kg, &kernel_split_state.isect[ray_index]) : + OBJECT_NONE; + bool hit = kernel_path_scene_intersect(kg, state, &ray, &isect, L, last_object); kernel_split_state.isect[ray_index] = isect; if (!hit) { diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 5fe4e9ed57f..c88d94fe4c2 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -102,6 +102,8 @@ NODE_DEFINE(Object) SOCKET_NODE(particle_system, "Particle System", ParticleSystem::get_node_type()); SOCKET_INT(particle_index, "Particle Index", 0); + SOCKET_FLOAT(ao_distance, "AO Distance", 0.0f); + return type; } @@ -428,6 +430,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s kobject.random_number = random_number; kobject.particle_index = particle_index; kobject.motion_offset = 0; + kobject.ao_distance = ob->ao_distance; if (geom->get_use_motion_blur()) { state->have_motion = true; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index ebb7733c2aa..c52ddce48da 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -73,6 +73,8 @@ class Object : public Node { NODE_SOCKET_API(ParticleSystem *, particle_system); NODE_SOCKET_API(int, particle_index); + NODE_SOCKET_API(float, ao_distance) + Object(); ~Object(); diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 46e3888a367..83c67f83908 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -1067,22 +1067,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_context, const char *const *action_names); /** - * Create spaces for pose-based OpenXR actions. - */ -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - -/** - * Destroy previously created spaces for OpenXR actions. - */ -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_context, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - -/** * Create input/output path bindings for OpenXR actions. */ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, @@ -1096,7 +1080,8 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_context, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_context, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); /** * Attach all created action sets to the current OpenXR session. @@ -1117,6 +1102,7 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_context, const char *action_set int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude); @@ -1126,7 +1112,8 @@ int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_context, */ void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_context, const char *action_set_name, - const char *action_name); + const char *action_name, + const char **subaction_path); /** * Get action set custom data (owned by Blender, not GHOST). @@ -1141,6 +1128,18 @@ void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_context, const char *action_set_name, const char *action_name); +/** + * Get the number of actions in an action set. + */ +unsigned int GHOST_XrGetActionCount(GHOST_XrContextHandle xr_context, const char *action_set_name); + +/** + * Get custom data for all actions in an action set. + */ +void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_context, + const char *action_set_name, + void **r_customdata_array); + #endif /* WITH_XR_OPENXR */ #ifdef __cplusplus diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 94a3fd86b73..fb19b9535ad 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -719,29 +719,27 @@ typedef struct GHOST_XrActionInfo { const char **subaction_paths; /** States for each subaction path. */ void *states; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + int16_t *axis_flags; GHOST_XrCustomdataFreeFn customdata_free_fn; void *customdata; /* wmXrAction */ } GHOST_XrActionInfo; -typedef struct GHOST_XrActionSpaceInfo { - const char *action_name; - uint32_t count_subaction_paths; - const char **subaction_paths; - /** Poses for each subaction path. */ - const GHOST_XrPose *poses; -} GHOST_XrActionSpaceInfo; - typedef struct GHOST_XrActionBindingInfo { - const char *action_name; - uint32_t count_interaction_paths; - /** Interaction path: User (sub-action) path + component path. */ - const char **interaction_paths; + const char *component_path; + float float_threshold; + int16_t axis_flag; + GHOST_XrPose pose; } GHOST_XrActionBindingInfo; typedef struct GHOST_XrActionProfileInfo { + const char *action_name; const char *profile_path; - uint32_t count_bindings; + uint32_t count_subaction_paths; + const char **subaction_paths; + /* Bindings for each subaction path. */ const GHOST_XrActionBindingInfo *bindings; } GHOST_XrActionProfileInfo; diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index cb409595e50..b1af5c131ab 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -961,28 +961,6 @@ void GHOST_XrDestroyActions(GHOST_XrContextHandle xr_contexthandle, GHOST_XR_CAPI_CALL(xr_session->destroyActions(action_set_name, count, action_names), xr_context); } -int GHOST_XrCreateActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL_RET(xr_session->createActionSpaces(action_set_name, count, infos), - xr_context); - return 0; -} - -void GHOST_XrDestroyActionSpaces(GHOST_XrContextHandle xr_contexthandle, - const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) -{ - GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; - GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionSpaces(action_set_name, count, infos), xr_context); -} - int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, @@ -998,11 +976,14 @@ int GHOST_XrCreateActionBindings(GHOST_XrContextHandle xr_contexthandle, void GHOST_XrDestroyActionBindings(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos) + const char *const *action_names, + const char *const *profile_paths) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->destroyActionBindings(action_set_name, count, infos), xr_context); + GHOST_XR_CAPI_CALL( + xr_session->destroyActionBindings(action_set_name, count, action_names, profile_paths), + xr_context); } int GHOST_XrAttachActionSets(GHOST_XrContextHandle xr_contexthandle) @@ -1024,25 +1005,29 @@ int GHOST_XrSyncActions(GHOST_XrContextHandle xr_contexthandle, const char *acti int GHOST_XrApplyHapticAction(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL_RET(xr_session->applyHapticAction( - action_set_name, action_name, *duration, *frequency, *amplitude), - xr_context); + GHOST_XR_CAPI_CALL_RET( + xr_session->applyHapticAction( + action_set_name, action_name, subaction_path, *duration, *frequency, *amplitude), + xr_context); return 0; } void GHOST_XrStopHapticAction(GHOST_XrContextHandle xr_contexthandle, const char *action_set_name, - const char *action_name) + const char *action_name, + const char **subaction_path) { GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; GHOST_XrSession *xr_session = xr_context->getSession(); - GHOST_XR_CAPI_CALL(xr_session->stopHapticAction(action_set_name, action_name), xr_context); + GHOST_XR_CAPI_CALL(xr_session->stopHapticAction(action_set_name, action_name, subaction_path), + xr_context); } void *GHOST_XrGetActionSetCustomdata(GHOST_XrContextHandle xr_contexthandle, @@ -1065,4 +1050,23 @@ void *GHOST_XrGetActionCustomdata(GHOST_XrContextHandle xr_contexthandle, return 0; } +unsigned int GHOST_XrGetActionCount(GHOST_XrContextHandle xr_contexthandle, + const char *action_set_name) +{ + GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; + GHOST_XrSession *xr_session = xr_context->getSession(); + GHOST_XR_CAPI_CALL_RET(xr_session->getActionCount(action_set_name), xr_context); + return 0; +} + +void GHOST_XrGetActionCustomdataArray(GHOST_XrContextHandle xr_contexthandle, + const char *action_set_name, + void **r_customdata_array) +{ + GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle; + GHOST_XrSession *xr_session = xr_context->getSession(); + GHOST_XR_CAPI_CALL(xr_session->getActionCustomdataArray(action_set_name, r_customdata_array), + xr_context); +} + #endif /* WITH_XR_OPENXR */ diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp index eb49dc4f98b..78c7201ff5f 100644 --- a/intern/ghost/intern/GHOST_ContextGLX.cpp +++ b/intern/ghost/intern/GHOST_ContextGLX.cpp @@ -295,8 +295,8 @@ GHOST_TSuccess GHOST_ContextGLX::initializeDrawingContext() glXMakeCurrent(m_display, m_window, m_context); - // Seems that this has to be called after MakeCurrent, - // which means we cannot use glX extensions until after we create a context + /* Seems that this has to be called after #glXMakeCurrent, + * which means we cannot use `glX` extensions until after we create a context. */ initContextGLXEW(); if (m_window) { diff --git a/intern/ghost/intern/GHOST_ImeWin32.cpp b/intern/ghost/intern/GHOST_ImeWin32.cpp index 8daa07b5003..343f4d68078 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.cpp +++ b/intern/ghost/intern/GHOST_ImeWin32.cpp @@ -32,7 +32,6 @@ GHOST_ImeWin32::GHOST_ImeWin32() : is_composing_(false), - ime_status_(false), input_language_id_(LANG_USER_DEFAULT), conversion_modes_(IME_CMODE_ALPHANUMERIC), sentence_mode_(IME_SMODE_NONE), @@ -47,18 +46,13 @@ GHOST_ImeWin32::~GHOST_ImeWin32() { } -bool GHOST_ImeWin32::SetInputLanguage() +void GHOST_ImeWin32::UpdateInputLanguage() { /** - * Retrieve the current keyboard layout from Windows and determine whether - * or not the current input context has IMEs. - * Also save its input language for language-specific operations required - * while composing a text. + * Store the current input language. */ - HKL keyboard_layout = ::GetKeyboardLayout(0); - input_language_id_ = LOWORD(keyboard_layout); - ime_status_ = ::ImmIsIME(keyboard_layout); - return ime_status_; + HKL input_locale = ::GetKeyboardLayout(0); + input_language_id_ = LOWORD(input_locale); } WORD GHOST_ImeWin32::GetInputLanguage() diff --git a/intern/ghost/intern/GHOST_ImeWin32.h b/intern/ghost/intern/GHOST_ImeWin32.h index bcc4b6eef7c..d430a7d745d 100644 --- a/intern/ghost/intern/GHOST_ImeWin32.h +++ b/intern/ghost/intern/GHOST_ImeWin32.h @@ -88,7 +88,7 @@ class GHOST_EventIME : public GHOST_Event { * An application CAN call ::DefWindowProc(). * 2.5. WM_INPUTLANGCHANGE (0x0051) * Call the functions listed below: - * - GHOST_ImeWin32::SetInputLanguage(). + * - GHOST_ImeWin32::UpdateInputLanguage(). * An application CAN call ::DefWindowProc(). */ @@ -148,13 +148,8 @@ class GHOST_ImeWin32 { /** * Retrieves the input language from Windows and update it. - * Return values - * * true - * The given input language has IMEs. - * * false - * The given input language does not have IMEs. */ - bool SetInputLanguage(); + void UpdateInputLanguage(); /* Returns the current input language id. */ WORD GetInputLanguage(); @@ -351,15 +346,6 @@ class GHOST_ImeWin32 { bool is_composing_; /** - * This value represents whether or not the current input context has IMEs. - * The following table shows the list of IME status: - * Value Description - * false The current input language does not have IMEs. - * true The current input language has IMEs. - */ - bool ime_status_; - - /** * The current input Language ID retrieved from Windows, which consists of: * * Primary Language ID (bit 0 to bit 9), which shows a natural language * (English, Korean, Chinese, Japanese, etc.) and; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 60fd175dbf7..347067eae50 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1424,7 +1424,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_INPUTLANGCHANGE: { system->handleKeyboardChange(); #ifdef WITH_INPUT_IME - window->getImeInput()->SetInputLanguage(); + window->getImeInput()->UpdateInputLanguage(); window->getImeInput()->UpdateConversionStatus(hwnd); #endif break; @@ -1471,7 +1471,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } case WM_IME_SETCONTEXT: { GHOST_ImeWin32 *ime = window->getImeInput(); - ime->SetInputLanguage(); + ime->UpdateInputLanguage(); ime->CreateImeWindow(hwnd); ime->CleanupComposition(hwnd); ime->CheckFirst(hwnd); diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 9fcad8aabf7..9422d15692d 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -802,8 +802,7 @@ static bool checkTabletProximity(Display *display, XDevice *device) if (state) { XInputClass *cls = state->data; - // printf("%d class%s :\n", state->num_classes, - // (state->num_classes > 1) ? "es" : ""); + // printf("%d class%s :\n", state->num_classes, (state->num_classes > 1) ? "es" : ""); for (int loop = 0; loop < state->num_classes; loop++) { switch (cls->c_class) { case ValuatorClass: diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 185d12717e7..de389951613 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1275,15 +1275,15 @@ GHOST_Context *GHOST_WindowX11::newDrawingContext(GHOST_TDrawingContextType type { if (type == GHOST_kDrawingContextTypeOpenGL) { - // During development: - // try 4.x compatibility profile - // try 3.3 compatibility profile - // fall back to 3.0 if needed - // - // Final Blender 2.8: - // try 4.x core profile - // try 3.3 core profile - // no fallbacks + /* During development: + * - Try 4.x compatibility profile. + * - Try 3.3 compatibility profile. + * - Fall back to 3.0 if needed. + * + * Final Blender 2.8: + * - Try 4.x core profile + * - Try 3.3 core profile + * - No fall-backs. */ #if defined(WITH_GL_PROFILE_CORE) { diff --git a/intern/ghost/intern/GHOST_XrAction.cpp b/intern/ghost/intern/GHOST_XrAction.cpp index 9c4f7fbc7d8..07eb42c14e6 100644 --- a/intern/ghost/intern/GHOST_XrAction.cpp +++ b/intern/ghost/intern/GHOST_XrAction.cpp @@ -33,24 +33,22 @@ * * \{ */ -GHOST_XrActionSpace::GHOST_XrActionSpace(XrInstance instance, - XrSession session, +GHOST_XrActionSpace::GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx) + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose) { - const char *subaction_path = info.subaction_paths[subaction_idx]; - CHECK_XR(xrStringToPath(instance, subaction_path, &m_subaction_path), - (std::string("Failed to get user path \"") + subaction_path + "\".").data()); - XrActionSpaceCreateInfo action_space_info{XR_TYPE_ACTION_SPACE_CREATE_INFO}; action_space_info.action = action; - action_space_info.subactionPath = m_subaction_path; - copy_ghost_pose_to_openxr_pose(info.poses[subaction_idx], action_space_info.poseInActionSpace); + action_space_info.subactionPath = subaction_path; + copy_ghost_pose_to_openxr_pose(pose, action_space_info.poseInActionSpace); CHECK_XR(xrCreateActionSpace(session, &action_space_info, &m_space), - (std::string("Failed to create space \"") + subaction_path + "\" for action \"" + - info.action_name + "\".") + (std::string("Failed to create space \"") + subaction_path_str + "\" for action \"" + + action_name + "\" and profile \"" + profile_path + "\".") .data()); } @@ -66,11 +64,6 @@ XrSpace GHOST_XrActionSpace::getSpace() const return m_space; } -const XrPath &GHOST_XrActionSpace::getSubactionPath() const -{ - return m_subaction_path; -} - /** \} */ /* -------------------------------------------------------------------- */ @@ -79,13 +72,19 @@ const XrPath &GHOST_XrActionSpace::getSubactionPath() const * \{ */ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info) { - CHECK_XR( - xrStringToPath(instance, profile_path, &m_profile), - (std::string("Failed to get interaction profile path \"") + profile_path + "\".").data()); + CHECK_XR(xrStringToPath(instance, info.profile_path, &m_profile), + (std::string("Failed to get interaction profile path \"") + info.profile_path + "\".") + .data()); + + const bool is_float_action = (type == GHOST_kXrActionTypeFloatInput || + type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || type == GHOST_kXrActionTypeBooleanInput); + const bool is_pose_action = (type == GHOST_kXrActionTypePoseInput); /* Create bindings. */ XrInteractionProfileSuggestedBinding bindings_info{ @@ -93,31 +92,80 @@ GHOST_XrActionProfile::GHOST_XrActionProfile(XrInstance instance, bindings_info.interactionProfile = m_profile; bindings_info.countSuggestedBindings = 1; - for (uint32_t interaction_idx = 0; interaction_idx < info.count_interaction_paths; - ++interaction_idx) { - const char *interaction_path = info.interaction_paths[interaction_idx]; + for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { + const char *subaction_path_str = info.subaction_paths[subaction_idx]; + const GHOST_XrActionBindingInfo &binding_info = info.bindings[subaction_idx]; + + const std::string interaction_path = std::string(subaction_path_str) + + binding_info.component_path; if (m_bindings.find(interaction_path) != m_bindings.end()) { continue; } XrActionSuggestedBinding sbinding; sbinding.action = action; - CHECK_XR(xrStringToPath(instance, interaction_path, &sbinding.binding), + CHECK_XR(xrStringToPath(instance, interaction_path.data(), &sbinding.binding), (std::string("Failed to get interaction path \"") + interaction_path + "\".").data()); bindings_info.suggestedBindings = &sbinding; /* Although the bindings will be re-suggested in GHOST_XrSession::attachActionSets(), it * greatly improves error checking to suggest them here first. */ CHECK_XR(xrSuggestInteractionProfileBindings(instance, &bindings_info), - (std::string("Failed to create binding for profile \"") + profile_path + - "\" and action \"" + info.action_name + - "\". Are the profile and action paths correct?") + (std::string("Failed to create binding for action \"") + info.action_name + + "\" and profile \"" + info.profile_path + + "\". Are the action and profile paths correct?") .data()); m_bindings.insert({interaction_path, sbinding.binding}); + + if (m_subaction_data.find(subaction_path_str) == m_subaction_data.end()) { + std::map<std::string, GHOST_XrSubactionData>::iterator it = + m_subaction_data + .emplace( + std::piecewise_construct, std::make_tuple(subaction_path_str), std::make_tuple()) + .first; + GHOST_XrSubactionData &subaction = it->second; + + CHECK_XR(xrStringToPath(instance, subaction_path_str, &subaction.subaction_path), + (std::string("Failed to get user path \"") + subaction_path_str + "\".").data()); + + if (is_float_action || is_button_action) { + if (is_float_action) { + subaction.float_threshold = binding_info.float_threshold; + } + if (is_button_action) { + subaction.axis_flag = binding_info.axis_flag; + } + } + else if (is_pose_action) { + /* Create action space for pose bindings. */ + subaction.space = std::make_unique<GHOST_XrActionSpace>(session, + action, + info.action_name, + info.profile_path, + subaction.subaction_path, + subaction_path_str, + binding_info.pose); + } + } } } +XrPath GHOST_XrActionProfile::getProfile() const +{ + return m_profile; +} + +const GHOST_XrSubactionData *GHOST_XrActionProfile::getSubaction(XrPath subaction_path) const +{ + for (auto &[subaction_path_str, subaction] : m_subaction_data) { + if (subaction.subaction_path == subaction_path) { + return &subaction; + } + } + return nullptr; +} + void GHOST_XrActionProfile::getBindings( XrAction action, std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const { @@ -152,14 +200,18 @@ GHOST_XrAction::GHOST_XrAction(XrInstance instance, const GHOST_XrActionInfo &info) : m_type(info.type), m_states(info.states), + m_float_thresholds(info.float_thresholds), + m_axis_flags(info.axis_flags), m_custom_data_( std::make_unique<GHOST_C_CustomDataWrapper>(info.customdata, info.customdata_free_fn)) { m_subaction_paths.resize(info.count_subaction_paths); for (uint32_t i = 0; i < info.count_subaction_paths; ++i) { - CHECK_XR(xrStringToPath(instance, info.subaction_paths[i], &m_subaction_paths[i]), - (std::string("Failed to get user path \"") + info.subaction_paths[i] + "\".").data()); + const char *subaction_path_str = info.subaction_paths[i]; + CHECK_XR(xrStringToPath(instance, subaction_path_str, &m_subaction_paths[i]), + (std::string("Failed to get user path \"") + subaction_path_str + "\".").data()); + m_subaction_indices.insert({subaction_path_str, i}); } XrActionCreateInfo action_info{XR_TYPE_ACTION_CREATE_INFO}; @@ -201,52 +253,25 @@ GHOST_XrAction::~GHOST_XrAction() } } -bool GHOST_XrAction::createSpace(XrInstance instance, - XrSession session, - const GHOST_XrActionSpaceInfo &info) -{ - uint32_t subaction_idx = 0; - for (; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - if (m_spaces.find(info.subaction_paths[subaction_idx]) != m_spaces.end()) { - return false; - } - } - - for (subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - m_spaces.emplace(std::piecewise_construct, - std::make_tuple(info.subaction_paths[subaction_idx]), - std::make_tuple(instance, session, m_action, info, subaction_idx)); - } - - return true; -} - -void GHOST_XrAction::destroySpace(const char *subaction_path) -{ - if (m_spaces.find(subaction_path) != m_spaces.end()) { - m_spaces.erase(subaction_path); - } -} - bool GHOST_XrAction::createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info) + XrSession session, + const GHOST_XrActionProfileInfo &info) { - if (m_profiles.find(profile_path) != m_profiles.end()) { + if (m_profiles.find(info.profile_path) != m_profiles.end()) { return false; } m_profiles.emplace(std::piecewise_construct, - std::make_tuple(profile_path), - std::make_tuple(instance, m_action, profile_path, info)); + std::make_tuple(info.profile_path), + std::make_tuple(instance, session, m_action, m_type, info)); return true; } -void GHOST_XrAction::destroyBinding(const char *interaction_profile_path) +void GHOST_XrAction::destroyBinding(const char *profile_path) { - if (m_profiles.find(interaction_profile_path) != m_profiles.end()) { - m_profiles.erase(interaction_profile_path); + if (m_profiles.find(profile_path) != m_profiles.end()) { + m_profiles.erase(profile_path); } } @@ -255,6 +280,10 @@ void GHOST_XrAction::updateState(XrSession session, XrSpace reference_space, const XrTime &predicted_display_time) { + const bool is_float_action = (m_type == GHOST_kXrActionTypeFloatInput || + m_type == GHOST_kXrActionTypeVector2fInput); + const bool is_button_action = (is_float_action || m_type == GHOST_kXrActionTypeBooleanInput); + XrActionStateGetInfo state_info{XR_TYPE_ACTION_STATE_GET_INFO}; state_info.action = m_action; @@ -262,6 +291,28 @@ void GHOST_XrAction::updateState(XrSession session, for (size_t subaction_idx = 0; subaction_idx < count_subaction_paths; ++subaction_idx) { state_info.subactionPath = m_subaction_paths[subaction_idx]; + /* Set subaction data based on current interaction profile. */ + XrInteractionProfileState profile_state{XR_TYPE_INTERACTION_PROFILE_STATE}; + CHECK_XR(xrGetCurrentInteractionProfile(session, state_info.subactionPath, &profile_state), + "Failed to get current interaction profile."); + + const GHOST_XrSubactionData *subaction = nullptr; + for (auto &[profile_path, profile] : m_profiles) { + if (profile.getProfile() == profile_state.interactionProfile) { + subaction = profile.getSubaction(state_info.subactionPath); + break; + } + } + + if (subaction != nullptr) { + if (is_float_action) { + m_float_thresholds[subaction_idx] = subaction->float_threshold; + } + if (is_button_action) { + m_axis_flags[subaction_idx] = subaction->axis_flag; + } + } + switch (m_type) { case GHOST_kXrActionTypeBooleanInput: { XrActionStateBoolean state{XR_TYPE_ACTION_STATE_BOOLEAN}; @@ -299,14 +350,9 @@ void GHOST_XrAction::updateState(XrSession session, xrGetActionStatePose(session, &state_info, &state), (std::string("Failed to get state for pose action \"") + action_name + "\".").data()); if (state.isActive) { - XrSpace pose_space = XR_NULL_HANDLE; - for (auto &[path, space] : m_spaces) { - if (space.getSubactionPath() == state_info.subactionPath) { - pose_space = space.getSpace(); - break; - } - } - + XrSpace pose_space = ((subaction != nullptr) && (subaction->space != nullptr)) ? + subaction->space->getSpace() : + XR_NULL_HANDLE; if (pose_space != XR_NULL_HANDLE) { XrSpaceLocation space_location{XR_TYPE_SPACE_LOCATION}; CHECK_XR( @@ -329,6 +375,7 @@ void GHOST_XrAction::updateState(XrSession session, void GHOST_XrAction::applyHapticFeedback(XrSession session, const char *action_name, + const char **subaction_path_str, const int64_t &duration, const float &frequency, const float &litude) @@ -342,24 +389,46 @@ void GHOST_XrAction::applyHapticFeedback(XrSession session, XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO}; haptic_info.action = m_action; - for (std::vector<XrPath>::iterator it = m_subaction_paths.begin(); it != m_subaction_paths.end(); - ++it) { - haptic_info.subactionPath = *it; - CHECK_XR(xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), - (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + if (subaction_path_str != nullptr) { + SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str); + if (it != m_subaction_indices.end()) { + haptic_info.subactionPath = m_subaction_paths[it->second]; + CHECK_XR( + xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), + (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + } + } + else { + for (const XrPath &subaction_path : m_subaction_paths) { + haptic_info.subactionPath = subaction_path; + CHECK_XR( + xrApplyHapticFeedback(session, &haptic_info, (const XrHapticBaseHeader *)&vibration), + (std::string("Failed to apply haptic action \"") + action_name + "\".").data()); + } } } -void GHOST_XrAction::stopHapticFeedback(XrSession session, const char *action_name) +void GHOST_XrAction::stopHapticFeedback(XrSession session, + const char *action_name, + const char **subaction_path_str) { XrHapticActionInfo haptic_info{XR_TYPE_HAPTIC_ACTION_INFO}; haptic_info.action = m_action; - for (std::vector<XrPath>::iterator it = m_subaction_paths.begin(); it != m_subaction_paths.end(); - ++it) { - haptic_info.subactionPath = *it; - CHECK_XR(xrStopHapticFeedback(session, &haptic_info), - (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + if (subaction_path_str != nullptr) { + SubactionIndexMap::iterator it = m_subaction_indices.find(*subaction_path_str); + if (it != m_subaction_indices.end()) { + haptic_info.subactionPath = m_subaction_paths[it->second]; + CHECK_XR(xrStopHapticFeedback(session, &haptic_info), + (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + } + } + else { + for (const XrPath &subaction_path : m_subaction_paths) { + haptic_info.subactionPath = subaction_path; + CHECK_XR(xrStopHapticFeedback(session, &haptic_info), + (std::string("Failed to stop haptic action \"") + action_name + "\".").data()); + } } } @@ -467,6 +536,19 @@ void *GHOST_XrActionSet::getCustomdata() return m_custom_data_->custom_data_; } +uint32_t GHOST_XrActionSet::getActionCount() const +{ + return (uint32_t)m_actions.size(); +} + +void GHOST_XrActionSet::getActionCustomdataArray(void **r_customdata_array) +{ + uint32_t i = 0; + for (auto &[name, action] : m_actions) { + r_customdata_array[i++] = action.getCustomdata(); + } +} + void GHOST_XrActionSet::getBindings( std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const { diff --git a/intern/ghost/intern/GHOST_XrAction.h b/intern/ghost/intern/GHOST_XrAction.h index 32445c616bd..70eaa694ae9 100644 --- a/intern/ghost/intern/GHOST_XrAction.h +++ b/intern/ghost/intern/GHOST_XrAction.h @@ -18,8 +18,8 @@ * \ingroup GHOST */ -/* Note: Requires OpenXR headers to be included before this one for OpenXR types (XrSpace, XrPath, - * etc.). */ +/* NOTE: Requires OpenXR headers to be included before this one for OpenXR types + * (XrSpace, XrPath, etc.). */ #pragma once @@ -34,38 +34,53 @@ class GHOST_XrActionSpace { public: GHOST_XrActionSpace() = delete; /* Default constructor for map storage. */ - GHOST_XrActionSpace(XrInstance instance, - XrSession session, + GHOST_XrActionSpace(XrSession session, XrAction action, - const GHOST_XrActionSpaceInfo &info, - uint32_t subaction_idx); + const char *action_name, + const char *profile_path, + XrPath subaction_path, + const char *subaction_path_str, + const GHOST_XrPose &pose); ~GHOST_XrActionSpace(); XrSpace getSpace() const; - const XrPath &getSubactionPath() const; private: XrSpace m_space = XR_NULL_HANDLE; - XrPath m_subaction_path = XR_NULL_PATH; }; /* -------------------------------------------------------------------- */ +typedef struct GHOST_XrSubactionData { + XrPath subaction_path = XR_NULL_PATH; + float float_threshold; + int16_t axis_flag; + std::unique_ptr<GHOST_XrActionSpace> space = nullptr; +} GHOST_XrSubactionData; + +/* -------------------------------------------------------------------- */ + class GHOST_XrActionProfile { public: GHOST_XrActionProfile() = delete; /* Default constructor for map storage. */ GHOST_XrActionProfile(XrInstance instance, + XrSession session, XrAction action, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + GHOST_XrActionType type, + const GHOST_XrActionProfileInfo &info); ~GHOST_XrActionProfile() = default; + XrPath getProfile() const; + const GHOST_XrSubactionData *getSubaction(XrPath subaction_path) const; void getBindings(XrAction action, std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const; private: XrPath m_profile = XR_NULL_PATH; - /* Bindings identified by interaction (user (subaction) + component) path. */ + + /** Sub-action data identified by user `subaction` path. */ + std::map<std::string, GHOST_XrSubactionData> m_subaction_data; + /** Bindings identified by interaction (user `subaction` + component) path. */ std::map<std::string, XrPath> m_bindings; }; @@ -77,12 +92,9 @@ class GHOST_XrAction { GHOST_XrAction(XrInstance instance, XrActionSet action_set, const GHOST_XrActionInfo &info); ~GHOST_XrAction(); - bool createSpace(XrInstance instance, XrSession session, const GHOST_XrActionSpaceInfo &info); - void destroySpace(const char *subaction_path); - bool createBinding(XrInstance instance, - const char *profile_path, - const GHOST_XrActionBindingInfo &info); + XrSession session, + const GHOST_XrActionProfileInfo &info); void destroyBinding(const char *profile_path); void updateState(XrSession session, @@ -91,26 +103,31 @@ class GHOST_XrAction { const XrTime &predicted_display_time); void applyHapticFeedback(XrSession session, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude); - void stopHapticFeedback(XrSession session, const char *action_name); + void stopHapticFeedback(XrSession session, const char *action_name, const char **subaction_path); void *getCustomdata(); void getBindings(std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const; private: + using SubactionIndexMap = std::map<std::string, uint32_t>; + XrAction m_action = XR_NULL_HANDLE; GHOST_XrActionType m_type; + SubactionIndexMap m_subaction_indices; std::vector<XrPath> m_subaction_paths; /** States for each subaction path. */ void *m_states; + /** Input thresholds/regions for each subaction path. */ + float *m_float_thresholds; + int16_t *m_axis_flags; std::unique_ptr<GHOST_C_CustomDataWrapper> m_custom_data_ = nullptr; /* wmXrAction */ - /* Spaces identified by user (subaction) path. */ - std::map<std::string, GHOST_XrActionSpace> m_spaces; - /* Profiles identified by interaction profile path. */ + /** Profiles identified by interaction profile path. */ std::map<std::string, GHOST_XrActionProfile> m_profiles; }; @@ -132,6 +149,8 @@ class GHOST_XrActionSet { XrActionSet getActionSet() const; void *getCustomdata(); + uint32_t getActionCount() const; + void getActionCustomdataArray(void **r_customdata_array); void getBindings(std::map<XrPath, std::vector<XrActionSuggestedBinding>> &r_bindings) const; private: diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 919d11d22a9..a63ce5c9344 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -610,9 +610,9 @@ void GHOST_XrSession::destroyActions(const char *action_set_name, } } -bool GHOST_XrSession::createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +bool GHOST_XrSession::createActionBindings(const char *action_set_name, + uint32_t count, + const GHOST_XrActionProfileInfo *infos) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { @@ -622,98 +622,37 @@ bool GHOST_XrSession::createActionSpaces(const char *action_set_name, XrInstance instance = m_context->getInstance(); XrSession session = m_oxr->session; - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; + for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { + const GHOST_XrActionProfileInfo &info = infos[profile_idx]; GHOST_XrAction *action = action_set->findAction(info.action_name); if (action == nullptr) { continue; } - if (!action->createSpace(instance, session, info)) { - return false; - } + action->createBinding(instance, session, info); } return true; } -void GHOST_XrSession::destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos) +void GHOST_XrSession::destroyActionBindings(const char *action_set_name, + uint32_t count, + const char *const *action_names, + const char *const *profile_paths) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { return; } - for (uint32_t action_idx = 0; action_idx < count; ++action_idx) { - const GHOST_XrActionSpaceInfo &info = infos[action_idx]; - - GHOST_XrAction *action = action_set->findAction(info.action_name); + for (uint32_t i = 0; i < count; ++i) { + GHOST_XrAction *action = action_set->findAction(action_names[i]); if (action == nullptr) { continue; } - for (uint32_t subaction_idx = 0; subaction_idx < info.count_subaction_paths; ++subaction_idx) { - action->destroySpace(info.subaction_paths[subaction_idx]); - } - } -} - -bool GHOST_XrSession::createActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return false; - } - - XrInstance instance = m_context->getInstance(); - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->createBinding(instance, profile_path, binding); - } - } - - return true; -} - -void GHOST_XrSession::destroyActionBindings(const char *action_set_name, - uint32_t count, - const GHOST_XrActionProfileInfo *infos) -{ - GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); - if (action_set == nullptr) { - return; - } - - for (uint32_t profile_idx = 0; profile_idx < count; ++profile_idx) { - const GHOST_XrActionProfileInfo &info = infos[profile_idx]; - const char *profile_path = info.profile_path; - - for (uint32_t binding_idx = 0; binding_idx < info.count_bindings; ++binding_idx) { - const GHOST_XrActionBindingInfo &binding = info.bindings[binding_idx]; - - GHOST_XrAction *action = action_set->findAction(binding.action_name); - if (action == nullptr) { - continue; - } - - action->destroyBinding(profile_path); - } + action->destroyBinding(profile_paths[i]); } } @@ -815,6 +754,7 @@ bool GHOST_XrSession::syncActions(const char *action_set_name) bool GHOST_XrSession::applyHapticAction(const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude) @@ -829,12 +769,15 @@ bool GHOST_XrSession::applyHapticAction(const char *action_set_name, return false; } - action->applyHapticFeedback(m_oxr->session, action_name, duration, frequency, amplitude); + action->applyHapticFeedback( + m_oxr->session, action_name, subaction_path, duration, frequency, amplitude); return true; } -void GHOST_XrSession::stopHapticAction(const char *action_set_name, const char *action_name) +void GHOST_XrSession::stopHapticAction(const char *action_set_name, + const char *action_name, + const char **subaction_path) { GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); if (action_set == nullptr) { @@ -846,7 +789,7 @@ void GHOST_XrSession::stopHapticAction(const char *action_set_name, const char * return; } - action->stopHapticFeedback(m_oxr->session, action_name); + action->stopHapticFeedback(m_oxr->session, action_name, subaction_path); } void *GHOST_XrSession::getActionSetCustomdata(const char *action_set_name) @@ -874,4 +817,25 @@ void *GHOST_XrSession::getActionCustomdata(const char *action_set_name, const ch return action->getCustomdata(); } +uint32_t GHOST_XrSession::getActionCount(const char *action_set_name) +{ + GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); + if (action_set == nullptr) { + return 0; + } + + return action_set->getActionCount(); +} + +void GHOST_XrSession::getActionCustomdataArray(const char *action_set_name, + void **r_customdata_array) +{ + GHOST_XrActionSet *action_set = find_action_set(m_oxr.get(), action_set_name); + if (action_set == nullptr) { + return; + } + + action_set->getActionCustomdataArray(r_customdata_array); +} + /** \} */ /* Actions */ diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h index d448585d14c..ec15897058f 100644 --- a/intern/ghost/intern/GHOST_XrSession.h +++ b/intern/ghost/intern/GHOST_XrSession.h @@ -60,18 +60,13 @@ class GHOST_XrSession { void destroyActions(const char *action_set_name, uint32_t count, const char *const *action_names); - bool createActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); - void destroyActionSpaces(const char *action_set_name, - uint32_t count, - const GHOST_XrActionSpaceInfo *infos); bool createActionBindings(const char *action_set_name, uint32_t count, const GHOST_XrActionProfileInfo *infos); void destroyActionBindings(const char *action_set_name, uint32_t count, - const GHOST_XrActionProfileInfo *infos); + const char *const *action_names, + const char *const *profile_paths); bool attachActionSets(); /** @@ -81,14 +76,19 @@ class GHOST_XrSession { bool syncActions(const char *action_set_name = nullptr); bool applyHapticAction(const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t &duration, const float &frequency, const float &litude); - void stopHapticAction(const char *action_set_name, const char *action_name); + void stopHapticAction(const char *action_set_name, + const char *action_name, + const char **subaction_path); /* Custom data (owned by Blender, not GHOST) accessors. */ void *getActionSetCustomdata(const char *action_set_name); void *getActionCustomdata(const char *action_set_name, const char *action_name); + uint32_t getActionCount(const char *action_set_name); + void getActionCustomdataArray(const char *action_set_name, void **r_customdata_array); private: /** Pointer back to context managing this session. Would be nice to avoid, but needed to access @@ -58,6 +58,16 @@ if "%BUILD_UPDATE%" == "1" ( call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd" +if "%ICONS%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\icons.cmd" + goto EOF +) + +if "%ICONS_GEOM%" == "1" ( + call "%BLENDER_DIR%\build_files\windows\icons_geom.cmd" + goto EOF +) + echo Building blender with VS%BUILD_VS_YEAR% for %BUILD_ARCH% in %BUILD_DIR% call "%BLENDER_DIR%\build_files\windows\check_libraries.cmd" diff --git a/release/datafiles/alert_icons.png b/release/datafiles/alert_icons.png Binary files differindex e1cb671713f..0add7a3ccf8 100644 --- a/release/datafiles/alert_icons.png +++ b/release/datafiles/alert_icons.png diff --git a/release/datafiles/alert_icons_update.py b/release/datafiles/alert_icons_update.py index dba96c2126a..34a2798a18c 100644..100755 --- a/release/datafiles/alert_icons_update.py +++ b/release/datafiles/alert_icons_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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> + # This script updates icons from the SVG file import os import subprocess @@ -7,19 +27,19 @@ import sys BASEDIR = os.path.abspath(os.path.dirname(__file__)) -inkscape_path = 'inkscape' +inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") if sys.platform == 'darwin': - inkscape_app_path = '/Applications/Inkscape.app/Contents/Resources/script' + inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape' if os.path.exists(inkscape_app_path): - inkscape_path = inkscape_app_path + inkscape_bin = inkscape_app_path cmd = ( - inkscape_path, + inkscape_bin, os.path.join(BASEDIR, "alert_icons.svg"), "--export-width=1280", "--export-height=256", - "--without-gui", - "--export-png=" + os.path.join(BASEDIR, "alert_icons.png"), + "--export-type=png", + "--export-filename=" + os.path.join(BASEDIR, "alert_icons.png"), ) subprocess.check_call(cmd) diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index f894ca3f298..c3461fd1bea 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -17301,6 +17301,26 @@ d="m 1800,348 h 3 v 14 h -3 z m -4,7 h 16 v 3 h -16 z" inkscape:connector-curvature="0" /> </g> + <path + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.98999999;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" + d="m 418.85321,140.04954 -2.82,-2.82 a 0.62,0.62 0 0 0 -0.4,-0.18 0.6,0.6 0 0 0 -0.6,0.6 0.62,0.62 0 0 0 0.18,0.43 l 1,1 -9.18,9.12 -1,-1 a 0.62,0.62 0 0 0 -0.4,-0.15 0.6,0.6 0 0 0 -0.6,0.6 0.62,0.62 0 0 0 0.18,0.4 l 2.82,2.82 a 0.6,0.6 0 0 0 0.82,-0.82 l -1,-1 9.18,-9.15 1,1 a 0.6,0.6 0 0 0 0.82,-0.85 z" + id="path3261" + inkscape:connector-curvature="0" /> + <g + style="display:inline;enable-background:new" + transform="translate(-0.35812,42.294299)" + id="g4073"> + <path + sodipodi:nodetypes="cccccccccccccssssccs" + d="m 388.17266,99.291166 c -0.27613,4e-5 -0.49997,0.22388 -0.5,0.5 v 1.261304 h -3.16865 v 1.46027 h 3.16865 v 1.27843 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 4 c 0.27613,-3e-5 0.49997,-0.22387 0.5,-0.5 v -4.000004 c -3e-5,-0.27612 -0.22387,-0.49996 -0.5,-0.5 z m 2.59221,-4.74807 c 2.50006,0 4.81247,1.33488 6.0625,3.5 1.25002,2.165124 1.25002,4.834884 0,7.000004 -1.25003,2.16512 -3.56244,3.5 -6.0625,3.5 h -6.5 c 0,-4.66667 0,-9.333336 0,-14.000004 z" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" + id="rect10339-4-1-6" /> + </g> + <path + id="rect10339-4-1-7-3" + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" + d="m 368.30892,141.58547 c -0.27613,4e-5 -0.49997,0.22388 -0.5,0.5 v 1.26473 h -4.76715 v 1.4911 h 4.76715 v 1.24417 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 0.63583,0.004 3.43318,-0.006 3.9995,-0.006 0.24106,0 0.46127,-0.0485 0.46127,-0.50967 4e-5,-0.85242 -8.9e-4,-2.98571 -8.9e-4,-3.95935 0,-0.30244 -0.19636,-0.51552 -0.46153,-0.51552 -0.82724,0 -3.36276,-0.009 -3.99823,-0.009 v 2e-5 z m 2.30359,-4.68113 -0.005,4.25868 c 0.48989,0.002 1.39549,0.005 1.88538,0.007 0.44541,0.0357 0.71675,0.47423 0.71675,0.85988 -6.6e-4,1.00616 -0.009,2.97018 -0.009,4.15122 0,0.46073 -0.24756,0.84994 -0.6533,0.84994 -0.48399,0.0143 -1.44986,-1.1e-4 -1.93405,-1.6e-4 v 3.87356 l -7.75691,-0.0669 v -14.00001 z" + sodipodi:nodetypes="cccccccccccccccccccccccccc" /> </g> <g inkscape:groupmode="layer" diff --git a/release/datafiles/blender_icons16/icon16_fixed_size.dat b/release/datafiles/blender_icons16/icon16_fixed_size.dat Binary files differnew file mode 100644 index 00000000000..95a777e733f --- /dev/null +++ b/release/datafiles/blender_icons16/icon16_fixed_size.dat diff --git a/release/datafiles/blender_icons16/icon16_force_boid.dat b/release/datafiles/blender_icons16/icon16_force_boid.dat Binary files differindex 71f89bd7c04..f719054d84a 100644 --- a/release/datafiles/blender_icons16/icon16_force_boid.dat +++ b/release/datafiles/blender_icons16/icon16_force_boid.dat diff --git a/release/datafiles/blender_icons16/icon16_gp_caps_flat.dat b/release/datafiles/blender_icons16/icon16_gp_caps_flat.dat Binary files differnew file mode 100644 index 00000000000..cdd76d850a3 --- /dev/null +++ b/release/datafiles/blender_icons16/icon16_gp_caps_flat.dat diff --git a/release/datafiles/blender_icons16/icon16_gp_caps_round.dat b/release/datafiles/blender_icons16/icon16_gp_caps_round.dat Binary files differnew file mode 100644 index 00000000000..7c5f4c56497 --- /dev/null +++ b/release/datafiles/blender_icons16/icon16_gp_caps_round.dat diff --git a/release/datafiles/blender_icons32/icon32_fixed_size.dat b/release/datafiles/blender_icons32/icon32_fixed_size.dat Binary files differnew file mode 100644 index 00000000000..a83e3755229 --- /dev/null +++ b/release/datafiles/blender_icons32/icon32_fixed_size.dat diff --git a/release/datafiles/blender_icons32/icon32_force_boid.dat b/release/datafiles/blender_icons32/icon32_force_boid.dat Binary files differindex 7fc7cb5ee8c..9043989024b 100644 --- a/release/datafiles/blender_icons32/icon32_force_boid.dat +++ b/release/datafiles/blender_icons32/icon32_force_boid.dat diff --git a/release/datafiles/blender_icons32/icon32_gp_caps_flat.dat b/release/datafiles/blender_icons32/icon32_gp_caps_flat.dat Binary files differnew file mode 100644 index 00000000000..fcd3c466c83 --- /dev/null +++ b/release/datafiles/blender_icons32/icon32_gp_caps_flat.dat diff --git a/release/datafiles/blender_icons32/icon32_gp_caps_round.dat b/release/datafiles/blender_icons32/icon32_gp_caps_round.dat Binary files differnew file mode 100644 index 00000000000..e7f5b80aecb --- /dev/null +++ b/release/datafiles/blender_icons32/icon32_gp_caps_round.dat diff --git a/release/datafiles/blender_icons_geom_update.py b/release/datafiles/blender_icons_geom_update.py index 5b95961ae6b..257b7a49285 100755 --- a/release/datafiles/blender_icons_geom_update.py +++ b/release/datafiles/blender_icons_geom_update.py @@ -1,15 +1,34 @@ #!/usr/bin/env python3 +# ##### 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> + # This script updates icons from the BLEND file import os import subprocess import sys -def run(cmd): +def run(cmd, *, env=None): print(" ", " ".join(cmd)) - # Don't use check_call because asan causes nonzero exitcode :S - subprocess.call(cmd) + subprocess.check_call(cmd, env=env) def edit_text_file(filename, marker_begin, marker_end, content): @@ -73,7 +92,17 @@ for blend in icons_blend: "--group", "Export", "--output-dir", output_dir, ) - run(cmd) + + env = {} + # Developers may have ASAN enabled, avoid non-zero exit codes. + env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") + # These NEED to be set on windows for python to initialize properly. + if sys.platform[:3] == "win": + env["PATHEXT"] = os.environ.get("PATHEXT", "") + env["SystemDrive"] = os.environ.get("SystemDrive", "") + env["SystemRoot"] = os.environ.get("SystemRoot", "") + + run(cmd, env=env) files_new = set(names_and_time_from_path(output_dir)) icon_files.extend([ diff --git a/release/datafiles/blender_icons_update.py b/release/datafiles/blender_icons_update.py index 8167b8b25e6..524cc512f29 100755 --- a/release/datafiles/blender_icons_update.py +++ b/release/datafiles/blender_icons_update.py @@ -1,18 +1,48 @@ #!/usr/bin/env python3 +# ##### 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> + # This script updates icons from the SVG file import os import subprocess import sys -def run(cmd): +def run(cmd, *, env=None): print(" ", " ".join(cmd)) - subprocess.check_call(cmd) + subprocess.check_call(cmd, env=env) BASEDIR = os.path.abspath(os.path.dirname(__file__)) +env = {} +# Developers may have ASAN enabled, avoid non-zero exit codes. +env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "") + +# These NEED to be set on windows for python to initialize properly. +if sys.platform[:3] == "win": + env["PATHEXT"] = os.environ.get("PATHEXT", "") + env["SystemDrive"] = os.environ.get("SystemDrive", "") + env["SystemRoot"] = os.environ.get("SystemRoot", "") + inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") blender_bin = os.environ.get("BLENDER_BIN", "blender") @@ -32,7 +62,7 @@ cmd = ( "--export-type=png", "--export-filename=" + os.path.join(BASEDIR, "blender_icons16.png"), ) -run(cmd) +run(cmd, env=env) cmd = ( inkscape_bin, @@ -42,7 +72,7 @@ cmd = ( "--export-type=png", "--export-filename=" + os.path.join(BASEDIR, "blender_icons32.png"), ) -run(cmd) +run(cmd, env=env) # For testing it can be good to clear all old @@ -64,7 +94,7 @@ cmd = ( "--minx_icon", "2", "--maxx_icon", "2", "--miny_icon", "2", "--maxy_icon", "2", "--spacex_icon", "1", "--spacey_icon", "1", ) -run(cmd) +run(cmd, env=env) cmd = ( blender_bin, "--background", "--factory-startup", "-noaudio", @@ -78,7 +108,7 @@ cmd = ( "--minx_icon", "4", "--maxx_icon", "4", "--miny_icon", "4", "--maxy_icon", "4", "--spacex_icon", "2", "--spacey_icon", "2", ) -run(cmd) +run(cmd, env=env) os.remove(os.path.join(BASEDIR, "blender_icons16.png")) os.remove(os.path.join(BASEDIR, "blender_icons32.png")) diff --git a/release/datafiles/ctodata.py b/release/datafiles/ctodata.py index 0471faad565..20f119c4264 100755 --- a/release/datafiles/ctodata.py +++ b/release/datafiles/ctodata.py @@ -1,27 +1,25 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# ***** BEGIN GPL LICENSE BLOCK ***** +# ##### 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 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. +# 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. +# 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) 2009 Blender Foundation. # All rights reserved. # -# ***** END GPL LICENCE BLOCK ***** - +# ##### END GPL LICENSE BLOCK ##### # <pep8 compliant> diff --git a/release/datafiles/prvicons_update.py b/release/datafiles/prvicons_update.py index fa526f88e96..ad42ede9772 100755 --- a/release/datafiles/prvicons_update.py +++ b/release/datafiles/prvicons_update.py @@ -1,5 +1,25 @@ #!/usr/bin/env python3 +# ##### 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> + # This script updates icons from the SVG file import os import subprocess @@ -7,15 +27,15 @@ import sys BASEDIR = os.path.abspath(os.path.dirname(__file__)) -inkscape_path = 'inkscape' +inkscape_bin = os.environ.get("INKSCAPE_BIN", "inkscape") if sys.platform == 'darwin': inkscape_app_path = '/Applications/Inkscape.app/Contents/MacOS/inkscape' if os.path.exists(inkscape_app_path): - inkscape_path = inkscape_app_path + inkscape_bin = inkscape_app_path cmd = ( - inkscape_path, + inkscape_bin, os.path.join(BASEDIR, "prvicons.svg"), "--export-width=1792", "--export-height=256", diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index a37577e898b..a67c5244611 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -3329,6 +3329,8 @@ def km_grease_pencil_stroke_edit_mode(params): ("gpencil.layer_isolate", {"type": 'NUMPAD_ASTERIX', "value": 'PRESS'}, None), # Move to layer op_menu("GPENCIL_MT_move_to_layer", {"type": 'M', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Transform tools ("transform.translate", {"type": 'G', "value": 'PRESS'}, None), ("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, None), @@ -3427,6 +3429,8 @@ def km_grease_pencil_stroke_paint_mode(params): {"properties": [("unselected", True)]}), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Active material op_menu("GPENCIL_MT_material_active", {"type": 'U', "value": 'PRESS'}), # Keyframe menu @@ -3592,6 +3596,8 @@ def km_grease_pencil_stroke_sculpt_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Context menu @@ -3809,6 +3815,8 @@ def km_grease_pencil_stroke_weight_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Context menu @@ -3873,6 +3881,8 @@ def km_grease_pencil_stroke_vertex_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Merge Layer + ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu op_menu("VIEW3D_MT_gpencil_animation", {"type": 'I', "value": 'PRESS'}), # Vertex Paint context menu diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 4ea1ec26738..46a16a70dca 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -399,6 +399,10 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel): col = layout.column(heading="Grease Pencil") col.prop(ob, "use_grease_pencil_lights", toggle=False) + layout.separator() + col = layout.column(heading="Mask") + col.prop(ob, "is_holdout") + class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 4bfd2fd32b0..97a0c5abf24 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -1252,6 +1252,12 @@ def brush_basic_gpencil_paint_settings(layout, context, brush, *, compact=False) if brush.gpencil_tool == 'TINT': row = layout.row(align=True) row.prop(gp_settings, "vertex_mode", text="Mode") + else: + row = layout.row(align=True) + if context.region.type == 'TOOL_HEADER': + row.prop(gp_settings, "caps_type", text="", expand=True) + else: + row.prop(gp_settings, "caps_type", text="Caps Type") # FIXME: tools must use their own UI drawing! if tool.idname in { diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index df41445ee6f..20b706f5004 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -6386,7 +6386,13 @@ class VIEW3D_PT_overlay_edit_mesh_normals(Panel): sub = row.row(align=True) sub.active = overlay.show_vertex_normals or overlay.show_face_normals or overlay.show_split_normals - sub.prop(overlay, "normals_length", text="Size") + if overlay.use_normals_constant_screen_size: + sub.prop(overlay, "normals_constant_screen_size", text="Size") + else: + sub.prop(overlay, "normals_length", text="Size") + + row.prop(overlay, "use_normals_constant_screen_size", text="", icon='FIXED_SIZE') + class VIEW3D_PT_overlay_edit_mesh_freestyle(Panel): diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 1d3daf01e86..c66d8d3feac 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -510,6 +510,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeCurveTrim"), NodeItem("GeometryNodeCurveLength"), NodeItem("GeometryNodeCurveReverse"), + NodeItem("GeometryNodeCurveSplineType"), NodeItem("GeometryNodeCurveSetHandles"), ]), GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[ diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 53c4135254a..6e2be4a8353 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -1359,9 +1359,15 @@ FontBLF *blf_font_new(const char *name, const char *filename) return NULL; } - err = FT_Select_Charmap(font->face, ft_encoding_unicode); + err = FT_Select_Charmap(font->face, FT_ENCODING_UNICODE); if (err) { - printf("Can't set the unicode character map!\n"); + err = FT_Select_Charmap(font->face, FT_ENCODING_APPLE_ROMAN); + } + if (err && font->face->num_charmaps > 0) { + err = FT_Select_Charmap(font->face, font->face->charmaps[0]->encoding); + } + if (err) { + printf("Can't set a character map!\n"); FT_Done_Face(font->face); MEM_freeN(font); return NULL; diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index e76e3ed8fe0..5ef56fab9cb 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -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 17 /* 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 diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 0326386e5c1..8b8d0f7b107 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -197,13 +197,14 @@ typedef void (*BKE_scene_collections_Cb)(struct Collection *ob, void *data); #define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(_collection, _object, _mode) \ { \ int _base_flag = (_mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER; \ - int _object_restrict_flag = (_mode == DAG_EVAL_VIEWPORT) ? OB_RESTRICT_VIEWPORT : \ - OB_RESTRICT_RENDER; \ + int _object_visibility_flag = (_mode == DAG_EVAL_VIEWPORT) ? OB_HIDE_VIEWPORT : \ + OB_HIDE_RENDER; \ int _base_id = 0; \ for (Base *_base = (Base *)BKE_collection_object_cache_get(_collection).first; _base; \ _base = _base->next, _base_id++) { \ Object *_object = _base->object; \ - if ((_base->flag & _base_flag) && (_object->restrictflag & _object_restrict_flag) == 0) { + if ((_base->flag & _base_flag) && \ + (_object->visibility_flag & _object_visibility_flag) == 0) { #define FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END \ } \ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 69c950a86dc..31928b5e80a 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -70,6 +70,7 @@ typedef struct Global { * * -16384 and below: Reserved for python (add-ons) usage. * * -1: Disable faster motion paths computation (since 08/2018). * * 1 - 30: EEVEE debug/stats values (01/2018). + * * 31: Enable the Select Debug Engine. Only available with #WITH_DRAW_DEBUG (08/2021). * * 101: Enable UI debug drawing of fullscreen area's corner widget (10/2014). * * 666: Use quicker batch delete for outliners' delete hierarchy (01/2019). * * 777: Enable UI node panel's sockets polling (11/2011). diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 73921f3e61d..bfa3c58cbe2 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1475,7 +1475,8 @@ int ntreeTexExecTree(struct bNodeTree *ntree, #define GEO_NODE_CURVE_PRIMITIVE_QUADRILATERAL 1070 #define GEO_NODE_CURVE_TRIM 1071 #define GEO_NODE_CURVE_SET_HANDLES 1072 -#define GEO_NODE_EXTRUDE 1073 +#define GEO_NODE_CURVE_SPLINE_TYPE 1073 +#define GEO_NODE_EXTRUDE 1074 /** \} */ diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h index 2c0c6989acf..380f9045520 100644 --- a/source/blender/blenkernel/BKE_ocean.h +++ b/source/blender/blenkernel/BKE_ocean.h @@ -74,11 +74,13 @@ struct Ocean *BKE_ocean_add(void); void BKE_ocean_free_data(struct Ocean *oc); void BKE_ocean_free(struct Ocean *oc); bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution); -void BKE_ocean_init_from_modifier(struct Ocean *ocean, +bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, const int resolution); -void BKE_ocean_init(struct Ocean *o, +bool BKE_ocean_is_valid(const struct Ocean *o); + +bool BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index fae75762cde..10a865880f2 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -426,7 +426,7 @@ bool BKE_animsys_rna_path_resolve(PointerRNA *ptr, } /* less than 1.0 evaluates to false, use epsilon to avoid float error */ -#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) +#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > (1.0f - FLT_EPSILON)) bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value) { @@ -2625,7 +2625,7 @@ static void animsys_create_action_track_strip(const AnimData *adt, bAction *action = adt->action; - if ((adt->flag & ADT_NLA_EDIT_ON)) { + if (adt->flag & ADT_NLA_EDIT_ON) { action = adt->tmpact; } diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc index 47853deec3e..99eb064d061 100644 --- a/source/blender/blenkernel/intern/armature_test.cc +++ b/source/blender/blenkernel/intern/armature_test.cc @@ -180,7 +180,7 @@ class BKE_armature_find_selected_bones_test : public testing::Test { BLI_addtail(&arm.bonebase, &bone2); // bone2 is root bone BLI_addtail(&bone2.childbase, &bone3); // bone3 has bone2 as parent - // Make sure the armature & its bones are visible, to make them selectable. + /* Make sure the armature & its bones are visible, to make them selectable. */ arm.layer = bone1.layer = bone2.layer = bone3.layer = 1; } }; @@ -200,8 +200,8 @@ TEST_F(BKE_armature_find_selected_bones_test, some_bones_selected) EXPECT_EQ(seen_bones[0], &bone1); EXPECT_EQ(seen_bones[1], &bone3); - EXPECT_FALSE(result.all_bones_selected); // Bone 2 was not selected. - EXPECT_FALSE(result.no_bones_selected); // Bones 1 and 3 were selected. + EXPECT_FALSE(result.all_bones_selected); /* Bone 2 was not selected. */ + EXPECT_FALSE(result.no_bones_selected); /* Bones 1 and 3 were selected. */ } TEST_F(BKE_armature_find_selected_bones_test, no_bones_selected) diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c index 07b096af941..3aec646b024 100644 --- a/source/blender/blenkernel/intern/autoexec.c +++ b/source/blender/blenkernel/intern/autoexec.c @@ -56,7 +56,7 @@ bool BKE_autoexec_match(const char *path) if (path_cmp->path[0] == '\0') { /* pass */ } - else if ((path_cmp->flag & USER_PATHCMP_GLOB)) { + else if (path_cmp->flag & USER_PATHCMP_GLOB) { if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) { return true; } diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index b90214f1814..dbcd80fe065 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -806,10 +806,10 @@ static void collection_object_cache_fill(ListBase *lb, /* Only collection flags are checked here currently, object restrict flag is checked * in FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN since it can be animated * without updating the cache. */ - if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0)) { + if (((child_restrict & COLLECTION_HIDE_VIEWPORT) == 0)) { base->flag |= BASE_ENABLED_VIEWPORT; } - if (((child_restrict & COLLECTION_RESTRICT_RENDER) == 0)) { + if (((child_restrict & COLLECTION_HIDE_RENDER) == 0)) { base->flag |= BASE_ENABLED_RENDER; } } @@ -1755,7 +1755,7 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect { bool changed = false; - if (collection->flag & COLLECTION_RESTRICT_SELECT) { + if (collection->flag & COLLECTION_HIDE_SELECT) { return false; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 022073b0f12..0da29ded13d 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2982,6 +2982,16 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) { switch (data->mix_mode) { + /* Simple matrix multiplication. */ + case ACTCON_MIX_BEFORE_FULL: + mul_m4_m4m4(cob->matrix, ct->matrix, cob->matrix); + break; + + case ACTCON_MIX_AFTER_FULL: + mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix); + break; + + /* Aligned Inherit Scale emulation. */ case ACTCON_MIX_BEFORE: mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix); break; @@ -2990,8 +3000,13 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix); break; - case ACTCON_MIX_AFTER_FULL: - mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix); + /* Fully separate handling of channels. */ + case ACTCON_MIX_BEFORE_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, ct->matrix, cob->matrix); + break; + + case ACTCON_MIX_AFTER_SPLIT: + mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, ct->matrix); break; default: @@ -4616,9 +4631,7 @@ static void splineik_free(bConstraint *con) bSplineIKConstraint *data = con->data; /* binding array */ - if (data->points) { - MEM_freeN(data->points); - } + MEM_SAFE_FREE(data->points); } static void splineik_copy(bConstraint *con, bConstraint *srccon) @@ -5769,6 +5782,17 @@ static bConstraint *add_new_constraint(Object *ob, } break; } + case CONSTRAINT_TYPE_ACTION: { + /* The Before or Split modes require computing in local space, but + * for objects the Local space doesn't make sense (T78462, D6095 etc). + * So only default to Before (Split) if the constraint is on a bone. */ + if (pchan) { + bActionConstraint *data = con->data; + data->mix_mode = ACTCON_MIX_BEFORE_SPLIT; + con->ownspace = CONSTRAINT_SPACE_LOCAL; + } + break; + } } return con; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 92fd220549a..d33697d551e 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -4153,7 +4153,7 @@ static void BKE_fluid_modifier_process( { const int scene_framenr = (int)DEG_get_ctime(depsgraph); - if ((fmd->type & MOD_FLUID_TYPE_FLOW)) { + if (fmd->type & MOD_FLUID_TYPE_FLOW) { BKE_fluid_modifier_processFlow(fmd, depsgraph, scene, ob, me, scene_framenr); } else if (fmd->type & MOD_FLUID_TYPE_EFFEC) { diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index d0b9aeefa55..37fc14911fe 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -337,13 +337,9 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath) vfd = BLI_vfontdata_from_freetypefont(pf); if (vfd) { - vfont = BKE_libblock_alloc(bmain, ID_VF, filename, 0); + /* If there's a font name, use it for the ID name. */ + vfont = BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0); vfont->data = vfd; - - /* if there's a font name, use it for the ID name */ - if (vfd->name[0] != '\0') { - BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2); - } BLI_strncpy(vfont->filepath, filepath, sizeof(vfont->filepath)); /* if autopack is on store the packedfile in de font structure */ diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index ae1863f0a47..e7d83c668c8 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -602,7 +602,7 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc) } /* Check visiblilty restriction flags */ - if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_HIDE_VIEWPORT) { return true; } @@ -1005,22 +1005,22 @@ static void layer_collection_objects_sync(ViewLayer *view_layer, BLI_addtail(r_lb_new_object_bases, base); } - if ((collection_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) { + if ((collection_restrict & COLLECTION_HIDE_VIEWPORT) == 0) { base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH); if ((layer_restrict & LAYER_COLLECTION_HIDE) == 0) { base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER; } - if (((collection_restrict & COLLECTION_RESTRICT_SELECT) == 0)) { + if (((collection_restrict & COLLECTION_HIDE_SELECT) == 0)) { base->flag_from_collection |= BASE_SELECTABLE; } } - if ((collection_restrict & COLLECTION_RESTRICT_RENDER) == 0) { + if ((collection_restrict & COLLECTION_HIDE_RENDER) == 0) { base->flag_from_collection |= BASE_ENABLED_RENDER; } /* Holdout and indirect only */ - if (layer->flag & LAYER_COLLECTION_HOLDOUT) { + if ((layer->flag & LAYER_COLLECTION_HOLDOUT) || (base->object->visibility_flag & OB_HOLDOUT)) { base->flag_from_collection |= BASE_HOLDOUT; } if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) { @@ -1150,11 +1150,11 @@ static void layer_collection_sync(ViewLayer *view_layer, /* We separate restrict viewport and visible view layer because a layer collection can be * hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */ - if (child_collection_restrict & COLLECTION_RESTRICT_VIEWPORT) { - child_layer->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT; + if (child_collection_restrict & COLLECTION_HIDE_VIEWPORT) { + child_layer->runtime_flag |= LAYER_COLLECTION_HIDE_VIEWPORT; } - if (((child_layer->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) && + if (((child_layer->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) == 0) && ((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) { child_layer->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER; } @@ -1333,7 +1333,7 @@ void BKE_main_collection_sync_remap(const Main *bmain) */ bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect) { - if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) { + if (lc->collection->flag & COLLECTION_HIDE_SELECT) { return false; } @@ -1369,7 +1369,7 @@ bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection bool BKE_layer_collection_has_selected_objects(ViewLayer *view_layer, LayerCollection *lc) { - if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) { + if (lc->collection->flag & COLLECTION_HIDE_SELECT) { return false; } @@ -1457,7 +1457,7 @@ bool BKE_object_is_visible_in_viewport(const View3D *v3d, const struct Object *o { BLI_assert(v3d != NULL); - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { return false; } @@ -2146,14 +2146,14 @@ void BKE_base_eval_flags(Base *base) base->flag |= (base->flag_from_collection & g_base_collection_flags); /* Apply object restrictions. */ - const int object_restrict = base->object->restrictflag; - if (object_restrict & OB_RESTRICT_VIEWPORT) { + const int object_restrict = base->object->visibility_flag; + if (object_restrict & OB_HIDE_VIEWPORT) { base->flag &= ~BASE_ENABLED_VIEWPORT; } - if (object_restrict & OB_RESTRICT_RENDER) { + if (object_restrict & OB_HIDE_RENDER) { base->flag &= ~BASE_ENABLED_RENDER; } - if (object_restrict & OB_RESTRICT_SELECT) { + if (object_restrict & OB_HIDE_SELECT) { base->flag &= ~BASE_SELECTABLE; } diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 62d29188c5a..5e1027c62af 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -73,6 +73,7 @@ #include "BKE_rigidbody.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "RNA_access.h" @@ -141,7 +142,8 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData * { ID *id = cb_data->user_data; if (*cb_data->id_pointer == id) { - DEG_id_tag_update_ex(cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO); + DEG_id_tag_update_ex( + cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO | ID_RECALC_COPY_ON_WRITE); return IDWALK_RET_STOP_ITER; } return IDWALK_RET_NOP; @@ -193,6 +195,8 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id) if (key != NULL) { lib_id_clear_library_data_ex(bmain, &key->id); } + + DEG_relations_tag_update(bmain); } void BKE_lib_id_clear_library_data(Main *bmain, ID *id) diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 8e67547b719..67ed7d1b394 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -571,7 +571,7 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat * would use one of those. * NOTE: missing IDs (aka placeholders) are never overridden. */ if (ELEM(GS(to_id->name), ID_OB, ID_GR)) { - if ((to_id->tag & LIB_TAG_MISSING)) { + if (to_id->tag & LIB_TAG_MISSING) { to_id->tag |= missing_tag; } else { @@ -604,7 +604,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) const bool is_resync = data->is_resync; BLI_assert(!data->is_override); - if ((id_root->tag & LIB_TAG_MISSING)) { + if (id_root->tag & LIB_TAG_MISSING) { id_root->tag |= data->missing_tag; } else { @@ -654,7 +654,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data) if (instantiating_collection == NULL && instantiating_collection_override_candidate != NULL) { - if ((instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING)) { + if (instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING) { instantiating_collection_override_candidate->id.tag |= data->missing_tag; } else { @@ -730,7 +730,7 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data) BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root)); BLI_assert(data->is_override); - if ((id_root->override_library->reference->tag & LIB_TAG_MISSING)) { + if (id_root->override_library->reference->tag & LIB_TAG_MISSING) { id_root->tag |= data->missing_tag; } else { @@ -855,8 +855,8 @@ static void lib_override_library_create_post_process(Main *bmain, default_instantiating_collection = BKE_collection_add( bmain, (Collection *)id_root, "OVERRIDE_HIDDEN"); /* Hide the collection from viewport and render. */ - default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + default_instantiating_collection->flag |= COLLECTION_HIDE_VIEWPORT | + COLLECTION_HIDE_RENDER; break; } case ID_OB: { @@ -1599,6 +1599,17 @@ static void lib_override_library_main_resync_on_library_indirect_level( (!ID_IS_LINKED(id) && library_indirect_level != 0)) { continue; } + + /* We cannot resync a scene that is currently active. */ + if (id == &scene->id) { + id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + BKE_reportf(reports->reports, + RPT_WARNING, + "Scene '%s' was not resynced as it is the currently active one", + scene->id.name + 2); + continue; + } + Library *library = id->lib; int level = 0; @@ -1731,8 +1742,7 @@ void BKE_lib_override_library_main_resync(Main *bmain, override_resync_residual_storage = BKE_collection_add( bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME); /* Hide the collection from viewport and render. */ - override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } /* Necessary to improve performances, and prevent layers matching override sub-collections to be diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 34dd38164c2..f40d1db60ff 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -429,7 +429,7 @@ MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay) masklay_new->blend_flag = masklay->blend_flag; masklay_new->flag = masklay->flag; masklay_new->falloff = masklay->falloff; - masklay_new->restrictflag = masklay->restrictflag; + masklay_new->visibility_flag = masklay->visibility_flag; for (spline = masklay->splines.first; spline; spline = spline->next) { MaskSpline *spline_new = BKE_mask_spline_copy(spline); @@ -2092,7 +2092,7 @@ void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer) MaskSpline *spline; /* Nothing to do if selection if disabled for the given layer. */ - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { return; } diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 00ed7d86975..8acc929a089 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -619,7 +619,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, unsigned int tot_boundary_found = 0; #endif - if (masklay->restrictflag & MASK_RESTRICT_RENDER) { + if (masklay->visibility_flag & MASK_HIDE_RENDER) { /* skip the layer */ mr_handle->layers_tot--; masklay_index--; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 8d74002ad79..b00670aad4c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -389,6 +389,7 @@ enum { MESHCMP_EDGEUNKNOWN, MESHCMP_VERTCOMISMATCH, MESHCMP_CDLAYERS_MISMATCH, + MESHCMP_ATTRIBUTE_VALUE_MISMATCH, }; static const char *cmpcode_to_str(int code) @@ -416,6 +417,8 @@ static const char *cmpcode_to_str(int code) return "Vertex Coordinate Mismatch"; case MESHCMP_CDLAYERS_MISMATCH: return "CustomData Layer Count Mismatch"; + case MESHCMP_ATTRIBUTE_VALUE_MISMATCH: + return "Attribute Value Mismatch"; default: return "Mesh Comparison Code Unknown"; } @@ -423,13 +426,13 @@ static const char *cmpcode_to_str(int code) /** Thresh is threshold for comparing vertices, UV's, vertex colors, weights, etc. */ static int customdata_compare( - CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh) + CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh) { const float thresh_sq = thresh * thresh; CustomDataLayer *l1, *l2; - int i, i1 = 0, i2 = 0, tot, j; + int i1 = 0, i2 = 0, tot, j; - for (i = 0; i < c1->totlayer; i++) { + for (int i = 0; i < c1->totlayer; i++) { if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, @@ -441,7 +444,7 @@ static int customdata_compare( } } - for (i = 0; i < c2->totlayer; i++) { + for (int i = 0; i < c2->totlayer; i++) { if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, @@ -459,10 +462,84 @@ static int customdata_compare( l1 = c1->layers; l2 = c2->layers; + + for (i1 = 0; i1 < c1->totlayer; i1++) { + l1 = c1->layers + i1; + if ((CD_TYPE_AS_MASK(l1->type) & CD_MASK_PROP_ALL) == 0) { + /* Skip non generic attribute layers. */ + continue; + } + + bool found_corresponding_layer = false; + for (i2 = 0; i2 < c2->totlayer; i2++) { + l2 = c2->layers + i2; + if (l1->type != l2->type || !STREQ(l1->name, l2->name)) { + continue; + } + found_corresponding_layer = true; + /* At this point `l1` and `l2` have the same name and type, so they should be compared. */ + + switch (l1->type) { + + case CD_PROP_FLOAT: { + const float *l1_data = l1->data; + const float *l2_data = l2->data; + + for (int i = 0; i < total_length; i++) { + if (fabsf(l1_data[i] - l2_data[i]) > thresh) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + case CD_PROP_FLOAT2: { + const float(*l1_data)[2] = l1->data; + const float(*l2_data)[2] = l2->data; + + for (int i = 0; i < total_length; i++) { + if (len_squared_v2v2(l1_data[i], l2_data[i]) > thresh_sq) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + case CD_PROP_FLOAT3: { + const float(*l1_data)[3] = l1->data; + const float(*l2_data)[3] = l2->data; + + for (int i = 0; i < total_length; i++) { + if (len_squared_v3v3(l1_data[i], l2_data[i]) > thresh_sq) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + default: { + int element_size = CustomData_sizeof(l1->type); + for (int i = 0; i < total_length; i++) { + int offset = element_size * i; + if (!CustomData_data_equals(l1->type, + POINTER_OFFSET(l1->data, offset), + POINTER_OFFSET(l2->data, offset))) { + return MESHCMP_ATTRIBUTE_VALUE_MISMATCH; + } + } + break; + } + } + } + + if (!found_corresponding_layer) { + return MESHCMP_CDLAYERS_MISMATCH; + } + } + + l1 = c1->layers; + l2 = c2->layers; tot = i1; i1 = 0; i2 = 0; - for (i = 0; i < tot; i++) { + for (int i = 0; i < tot; i++) { while ( i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { @@ -626,19 +703,19 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh) return "Number of loops don't match"; } - if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) { return cmpcode_to_str(c); } - if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) { + if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) { return cmpcode_to_str(c); } diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index 63b0403dcea..9f5703a015d 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -292,7 +292,7 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh, void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); @@ -330,7 +330,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source) void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT); @@ -377,7 +377,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source) void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) { - BVHTreeFromMesh bvhtree = {{nullptr}}; + BVHTreeFromMesh bvhtree = {nullptr}; BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2); int tot_color_layer = CustomData_number_of_layers(&source->vdata, CD_PROP_COLOR); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index aa92fede3a5..d30d0509867 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -5149,6 +5149,7 @@ static void registerGeometryNodes() register_node_type_geo_curve_resample(); register_node_type_geo_curve_reverse(); register_node_type_geo_curve_set_handles(); + register_node_type_geo_curve_spline_type(); register_node_type_geo_curve_subdivide(); register_node_type_geo_curve_to_mesh(); register_node_type_geo_curve_to_points(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6a309e040c0..f969ca0ff1c 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2081,6 +2081,12 @@ static void object_init(Object *ob, const short ob_type) if (ob->type == OB_GPENCIL) { ob->dtx |= OB_USE_GPENCIL_LIGHTS; } + + if (ob->type == OB_LAMP) { + /* Lights are invisible to camera rays and are assumed to be a + * shadow catcher by default. */ + ob->visibility_flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER; + } } void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 77969328365..141a9a25eca 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1554,15 +1554,15 @@ static const DupliGenerator gen_dupli_particles = { static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) { int transflag = ctx->object->transflag; - int restrictflag = ctx->object->restrictflag; + int visibility_flag = ctx->object->visibility_flag; if ((transflag & OB_DUPLI) == 0 && ctx->object->runtime.geometry_set_eval == nullptr) { return nullptr; } /* Should the dupli's be generated for this object? - Respect restrict flags. */ - if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : - (restrictflag & OB_RESTRICT_VIEWPORT)) { + if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (visibility_flag & OB_HIDE_RENDER) : + (visibility_flag & OB_HIDE_VIEWPORT)) { return nullptr; } diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 3aee5cd639d..4d003ddc900 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -650,6 +650,14 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskd fftw_execute(o->_N_z_plan); } +/** + * Return true if the ocean is valid and can be used. + */ +bool BKE_ocean_is_valid(const struct Ocean *o) +{ + return o->_k != NULL; +} + void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount) { TaskPool *pool; @@ -769,7 +777,10 @@ bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution) return true; } -void BKE_ocean_init_from_modifier(struct Ocean *ocean, +/** + * Return true if the ocean data is valid and can be used. + */ +bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, const int resolution) { @@ -783,31 +794,34 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean, BKE_ocean_free_data(ocean); - BKE_ocean_init(ocean, - resolution * resolution, - resolution * resolution, - omd->spatial_size, - omd->spatial_size, - omd->wind_velocity, - omd->smallest_wave, - 1.0, - omd->wave_direction, - omd->damp, - omd->wave_alignment, - omd->depth, - omd->time, - omd->spectrum, - omd->fetch_jonswap, - omd->sharpen_peak_jonswap, - do_heightfield, - do_chop, - do_spray, - do_normals, - do_jacobian, - omd->seed); -} - -void BKE_ocean_init(struct Ocean *o, + return BKE_ocean_init(ocean, + resolution * resolution, + resolution * resolution, + omd->spatial_size, + omd->spatial_size, + omd->wind_velocity, + omd->smallest_wave, + 1.0, + omd->wave_direction, + omd->damp, + omd->wave_alignment, + omd->depth, + omd->time, + omd->spectrum, + omd->fetch_jonswap, + omd->sharpen_peak_jonswap, + do_heightfield, + do_chop, + do_spray, + do_normals, + do_jacobian, + omd->seed); +} + +/** + * Return true if the ocean data is valid and can be used. + */ +bool BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, @@ -830,7 +844,6 @@ void BKE_ocean_init(struct Ocean *o, short do_jacobian, int seed) { - RNG *rng; int i, j, ii; BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); @@ -858,18 +871,34 @@ void BKE_ocean_init(struct Ocean *o, o->_fetch_jonswap = fetch_jonswap; o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f; + /* NOTE: most modifiers don't account for failure to allocate. + * In this case however a large resolution can easily perform large allocations that fail, + * support early exiting in this case. */ + if ((o->_k = (float *)MEM_mallocN(sizeof(float) * (size_t)M * (1 + N / 2), "ocean_k")) && + (o->_h0 = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N, "ocean_h0")) && + (o->_h0_minus = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N, + "ocean_h0_minus")) && + (o->_kx = (float *)MEM_mallocN(sizeof(float) * o->_M, "ocean_kx")) && + (o->_kz = (float *)MEM_mallocN(sizeof(float) * o->_N, "ocean_kz"))) { + /* Success. */ + } + else { + MEM_SAFE_FREE(o->_k); + MEM_SAFE_FREE(o->_h0); + MEM_SAFE_FREE(o->_h0_minus); + MEM_SAFE_FREE(o->_kx); + MEM_SAFE_FREE(o->_kz); + + BLI_rw_mutex_unlock(&o->oceanmutex); + return false; + } + o->_do_disp_y = do_height_field; o->_do_normals = do_normals; o->_do_spray = do_spray; o->_do_chop = do_chop; o->_do_jacobian = do_jacobian; - o->_k = (float *)MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k"); - o->_h0 = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0"); - o->_h0_minus = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus"); - o->_kx = (float *)MEM_mallocN(o->_M * sizeof(float), "ocean_kx"); - o->_kz = (float *)MEM_mallocN(o->_N * sizeof(float), "ocean_kz"); - /* make this robust in the face of erroneous usage */ if (o->_Lx == 0.0f) { o->_Lx = 0.001f; @@ -902,11 +931,11 @@ void BKE_ocean_init(struct Ocean *o, /* pre-calculate the k matrix */ for (i = 0; i < o->_M; i++) { for (j = 0; j <= o->_N / 2; j++) { - o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); + o->_k[(size_t)i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]); } } - rng = BLI_rng_new(seed); + RNG *rng = BLI_rng_new(seed); for (i = 0; i < o->_M; i++) { for (j = 0; j < o->_N; j++) { @@ -1029,6 +1058,8 @@ void BKE_ocean_init(struct Ocean *o, set_height_normalize_factor(o); BLI_rng_free(rng); + + return true; } void BKE_ocean_free_data(struct Ocean *oc) @@ -1608,7 +1639,7 @@ struct Ocean *BKE_ocean_add(void) return oc; } -void BKE_ocean_init(struct Ocean *UNUSED(o), +bool BKE_ocean_init(struct Ocean *UNUSED(o), int UNUSED(M), int UNUSED(N), float UNUSED(Lx), @@ -1631,6 +1662,7 @@ void BKE_ocean_init(struct Ocean *UNUSED(o), short UNUSED(do_jacobian), int UNUSED(seed)) { + return false; } void BKE_ocean_free_data(struct Ocean *UNUSED(oc)) @@ -1700,10 +1732,11 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o), (void)update_cb; } -void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), +bool BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), struct OceanModifierData const *UNUSED(omd), int UNUSED(resolution)) { + return true; } #endif /* WITH_OCEANSIM */ diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 461ffa7765e..ca1fada8c76 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1026,7 +1026,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, PBVHNode *node = data->nodes[n]; float(*vnors)[3] = data->vnors; - if ((node->flag & PBVH_UpdateNormals)) { + if (node->flag & PBVH_UpdateNormals) { unsigned int mpoly_prev = UINT_MAX; float fn[3]; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a6adff35a7f..57225872c7e 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3369,7 +3369,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) } /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ - if ((cancel || G.is_break)) { + if (cancel || G.is_break) { break; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 3f75d0963c6..9dab276af95 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -2178,7 +2178,7 @@ int BKE_scene_base_iter_next( /* exception: empty scene layer */ while ((*scene)->set) { (*scene) = (*scene)->set; - ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { *base = view_layer_set->object_bases.first; *ob = (*base)->object; @@ -2199,7 +2199,7 @@ int BKE_scene_base_iter_next( /* (*scene) is finished, now do the set */ while ((*scene)->set) { (*scene) = (*scene)->set; - ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene); if (view_layer_set->object_bases.first) { *base = view_layer_set->object_bases.first; *ob = (*base)->object; @@ -2305,7 +2305,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene) Object *first_camera = NULL; LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) { - if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) { + if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) { if ((m->frame <= ctime) && (m->frame > frame)) { camera = m->camera; frame = m->frame; @@ -2898,7 +2898,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base) next_set: /* Reached the end, get the next base in the set. */ while ((*sce_iter = (*sce_iter)->set)) { - ViewLayer *view_layer_set = BKE_view_layer_default_render((*sce_iter)); + ViewLayer *view_layer_set = BKE_view_layer_default_render(*sce_iter); base = (Base *)view_layer_set->object_bases.first; if (base) { @@ -3118,7 +3118,7 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene return false; } - if ((srv->viewflag & SCE_VIEW_DISABLE)) { + if (srv->viewflag & SCE_VIEW_DISABLE) { return false; } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 1a408aceeb2..f41251f6ea5 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3447,10 +3447,10 @@ static void softbody_step( float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */ if (sb->scratch->flag & SBF_DOFUZZY) { - ///* stay with this stepsize unless err really small */ + // /* stay with this stepsize unless err really small */ // if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { newtime = forcetime; - //} + // } } else { if (err > SoftHeunTol / 2.0f) { /* stay with this stepsize unless err really small */ diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c index dc5162f201e..95436372a65 100644 --- a/source/blender/blenkernel/intern/studiolight.c +++ b/source/blender/blenkernel/intern/studiolight.c @@ -475,7 +475,7 @@ static void studiolight_load_equirect_image(StudioLight *sl) NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4); } - if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) { + if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) { sl->matcap_diffuse.ibuf = diffuse_ibuf; sl->matcap_specular.ibuf = specular_ibuf; if (specular_ibuf != NULL) { @@ -1192,7 +1192,7 @@ static void studiolight_add_files_from_datafolder(const int folder_id, uint totfile = BLI_filelist_dir_contents(folder, &dir); int i; for (i = 0; i < totfile; i++) { - if ((dir[i].type & S_IFREG)) { + if (dir[i].type & S_IFREG) { studiolight_add_file(dir[i].path, flag); } } @@ -1473,7 +1473,7 @@ struct StudioLight *BKE_studiolight_find_default(int flag) } LISTBASE_FOREACH (StudioLight *, sl, &studiolights) { - if ((sl->flag & flag)) { + if (sl->flag & flag) { return sl; } } @@ -1484,7 +1484,7 @@ struct StudioLight *BKE_studiolight_find(const char *name, int flag) { LISTBASE_FOREACH (StudioLight *, sl, &studiolights) { if (STREQLEN(sl->name, name, FILE_MAXFILE)) { - if ((sl->flag & flag)) { + if (sl->flag & flag) { return sl; } @@ -1542,32 +1542,32 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag) return; } - if ((flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED)) { + if (flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED) { studiolight_load_equirect_image(sl); } - if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) { + if (flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED) { studiolight_calculate_radiance_cubemap_buffers(sl); } - if ((flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED)) { + if (flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED) { if (!studiolight_load_spherical_harmonics_coefficients(sl)) { studiolight_calculate_diffuse_light(sl); } } - if ((flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE) { studiolight_create_equirect_radiance_gputexture(sl); } - if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE) { studiolight_create_equirect_irradiance_gputexture(sl); } - if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED)) { + if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED) { if (!studiolight_load_irradiance_equirect_image(sl)) { studiolight_calculate_irradiance_equirect_image(sl); } } - if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE) { studiolight_create_matcap_diffuse_gputexture(sl); } - if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) { + if (flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE) { studiolight_create_matcap_specular_gputexture(sl); } } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 80ff8ce9162..6048e823abb 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2331,7 +2331,7 @@ int txt_setcurr_tab_spaces(Text *text, int space) } while (text->curl->line[i] == indent) { - // we only count those tabs/spaces that are before any text or before the curs; + /* We only count those tabs/spaces that are before any text or before the curs; */ if (i == text->curc) { return i; } diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index f107fc4d6bc..92ff0911cf3 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -322,7 +322,7 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker, static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker) { - if ((marker->flag & MARKER_DISABLED)) { + if (marker->flag & MARKER_DISABLED) { return false; } return true; @@ -797,7 +797,7 @@ void BKE_autotrack_context_finish(AutoTrackContext *context) clip, context->start_scene_frame); LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) { - if ((plane_track->flag & PLANE_TRACK_AUTOKEY)) { + if (plane_track->flag & PLANE_TRACK_AUTOKEY) { continue; } for (int track_index = 0; track_index < context->num_all_tracks; track_index++) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 9b3103a638b..32057709c38 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -741,7 +741,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context, } } - if ((of->oformat->flags & AVFMT_GLOBALHEADER)) { + if (of->oformat->flags & AVFMT_GLOBALHEADER) { PRINT("Using global header\n"); c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h index 6bf29a6168f..084f573e8c7 100644 --- a/source/blender/blenlib/BLI_array.h +++ b/source/blender/blenlib/BLI_array.h @@ -156,7 +156,7 @@ void _bli_array_grow_func(void **arr_p, * \{ */ /** - * not part of the 'API' but handy funcs, + * Not part of the 'API' but handy functions, * same purpose as #BLI_array_staticdeclare() * but use when the max size is known ahead of time */ #define BLI_array_fixedstack_declare(arr, maxstatic, realsize, allocstr) \ diff --git a/source/blender/blenlib/BLI_enumerable_thread_specific.hh b/source/blender/blenlib/BLI_enumerable_thread_specific.hh index 3051d980d45..b5981028893 100644 --- a/source/blender/blenlib/BLI_enumerable_thread_specific.hh +++ b/source/blender/blenlib/BLI_enumerable_thread_specific.hh @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 88dc20a64f2..e877503e835 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -120,6 +120,9 @@ MINLINE double interpd(double a, double b, double t); MINLINE float ratiof(float min, float max, float pos); MINLINE double ratiod(double min, double max, double pos); +MINLINE float scalenorm(float a, float b, float x); +MINLINE double scalenormd(double a, double b, double x); + /* NOTE: Compilers will upcast all types smaller than int to int when performing arithmetic * operation. */ MINLINE int square_s(short a); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 9ac14a6edfe..bcda25ca533 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -682,14 +682,14 @@ void planes_from_projmat(const float mat[4][4], float near[4], float far[4]); -void projmat_dimensions(const float projmat[4][4], +void projmat_dimensions(const float winmat[4][4], float *r_left, float *r_right, float *r_bottom, float *r_top, float *r_near, float *r_far); -void projmat_dimensions_db(const float projmat[4][4], +void projmat_dimensions_db(const float winmat[4][4], double *r_left, double *r_right, double *r_bottom, diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 0953e3f1946..bf09b56c779 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -45,7 +45,7 @@ #undef small -// These definitions are also in BLI_math for simplicity +/* These definitions are also in BLI_math for simplicity. */ #ifdef __cplusplus extern "C" { @@ -72,7 +72,7 @@ extern "C" { #if defined(_MSC_VER) # define R_OK 4 # define W_OK 2 -// not accepted by access() on windows +/* Not accepted by `access()` on windows. */ //# define X_OK 1 # define F_OK 0 #endif diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 98da85e3a8c..a8b50b66f5f 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -40,6 +40,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" +#include "BLI_string_utf8.h" #include "BLI_utildefines.h" #include "BLI_vfontdata.h" @@ -286,7 +287,6 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) const FT_ULong charcode_reserve = 256; FT_ULong charcode = 0, lcode; FT_UInt glyph_index; - const char *fontname; VFontData *vfd; /* load the freetype font */ @@ -299,36 +299,29 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile *pf) /* allocate blender font */ vfd = MEM_callocN(sizeof(*vfd), "FTVFontData"); - /* get the name */ - fontname = FT_Get_Postscript_Name(face); - BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name)); + /* Get the name. */ + if (face->family_name) { + BLI_snprintf(vfd->name, sizeof(vfd->name), "%s %s", face->family_name, face->style_name); + BLI_utf8_invalid_strip(vfd->name, strlen(vfd->name)); + } + + /* Select a character map. */ + err = FT_Select_Charmap(face, FT_ENCODING_UNICODE); + if (err) { + err = FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN); + } + if (err && face->num_charmaps > 0) { + err = FT_Select_Charmap(face, face->charmaps[0]->encoding); + } + if (err) { + FT_Done_Face(face); + MEM_freeN(vfd); + return NULL; + } /* Extract the first 256 character from TTF */ lcode = charcode = FT_Get_First_Char(face, &glyph_index); - /* No `charmap` found from the TTF so we need to figure it out. */ - if (glyph_index == 0) { - FT_CharMap found = NULL; - FT_CharMap charmap; - int n; - - for (n = 0; n < face->num_charmaps; n++) { - charmap = face->charmaps[n]; - if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) { - found = charmap; - break; - } - } - - err = FT_Set_Charmap(face, found); - - if (err) { - return NULL; - } - - lcode = charcode = FT_Get_First_Char(face, &glyph_index); - } - /* Blender default BFont is not "complete". */ const bool complete_font = (face->ascender != 0) && (face->descender != 0) && (face->ascender != face->descender); diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 6e3846e59c6..a80c495ecf3 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -199,6 +199,13 @@ MINLINE float scalenorm(float a, float b, float x) return (x * (b - a)) + a; } +/* Map a normalized value, i.e. from interval [0, 1] to interval [a, b]. */ +MINLINE double scalenormd(double a, double b, double x) +{ + BLI_assert(x <= 1 && x >= 0); + return (x * (b - a)) + a; +} + /* Used for zoom values. */ MINLINE float power_of_2(float val) { diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 803291e4a3b..8afb6b5a2be 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1787,7 +1787,7 @@ bool isect_ray_tri_v3(const float ray_origin[3], } *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -1864,7 +1864,7 @@ bool isect_ray_tri_epsilon_v3(const float ray_origin[3], } *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -2024,7 +2024,7 @@ bool isect_ray_tri_threshold_v3(const float ray_origin[3], cross_v3_v3v3(q, s, e1); *r_lambda = f * dot_v3v3(e2, q); - if ((*r_lambda < 0.0f)) { + if (*r_lambda < 0.0f) { return false; } @@ -3325,7 +3325,7 @@ bool isect_ray_aabb_v3_simple(const float orig[3], t[5] = (double)(bb_max[2] - orig[2]) * invdirz; hit_dist[0] = (float)fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); hit_dist[1] = (float)fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); - if ((hit_dist[1] < 0.0f || hit_dist[0] > hit_dist[1])) { + if ((hit_dist[1] < 0.0f) || (hit_dist[0] > hit_dist[1])) { return false; } @@ -4962,7 +4962,7 @@ void planes_from_projmat(const float mat[4][4], } } -void projmat_dimensions(const float projmat[4][4], +void projmat_dimensions(const float winmat[4][4], float *r_left, float *r_right, float *r_bottom, @@ -4970,27 +4970,27 @@ void projmat_dimensions(const float projmat[4][4], float *r_near, float *r_far) { - bool is_persp = projmat[3][3] == 0.0f; - + const bool is_persp = winmat[3][3] == 0.0f; if (is_persp) { - *r_left = (projmat[2][0] - 1.0f) / projmat[0][0]; - *r_right = (projmat[2][0] + 1.0f) / projmat[0][0]; - *r_bottom = (projmat[2][1] - 1.0f) / projmat[1][1]; - *r_top = (projmat[2][1] + 1.0f) / projmat[1][1]; - *r_near = projmat[3][2] / (projmat[2][2] - 1.0f); - *r_far = projmat[3][2] / (projmat[2][2] + 1.0f); + const float near = winmat[3][2] / (winmat[2][2] - 1.0f); + *r_left = near * ((winmat[2][0] - 1.0f) / winmat[0][0]); + *r_right = near * ((winmat[2][0] + 1.0f) / winmat[0][0]); + *r_bottom = near * ((winmat[2][1] - 1.0f) / winmat[1][1]); + *r_top = near * ((winmat[2][1] + 1.0f) / winmat[1][1]); + *r_near = near; + *r_far = winmat[3][2] / (winmat[2][2] + 1.0f); } else { - *r_left = (-projmat[3][0] - 1.0f) / projmat[0][0]; - *r_right = (-projmat[3][0] + 1.0f) / projmat[0][0]; - *r_bottom = (-projmat[3][1] - 1.0f) / projmat[1][1]; - *r_top = (-projmat[3][1] + 1.0f) / projmat[1][1]; - *r_near = (projmat[3][2] + 1.0f) / projmat[2][2]; - *r_far = (projmat[3][2] - 1.0f) / projmat[2][2]; + *r_left = (-winmat[3][0] - 1.0f) / winmat[0][0]; + *r_right = (-winmat[3][0] + 1.0f) / winmat[0][0]; + *r_bottom = (-winmat[3][1] - 1.0f) / winmat[1][1]; + *r_top = (-winmat[3][1] + 1.0f) / winmat[1][1]; + *r_near = (winmat[3][2] + 1.0f) / winmat[2][2]; + *r_far = (winmat[3][2] - 1.0f) / winmat[2][2]; } } -void projmat_dimensions_db(const float projmat_fl[4][4], +void projmat_dimensions_db(const float winmat_fl[4][4], double *r_left, double *r_right, double *r_bottom, @@ -4998,26 +4998,26 @@ void projmat_dimensions_db(const float projmat_fl[4][4], double *r_near, double *r_far) { - double projmat[4][4]; - copy_m4d_m4(projmat, projmat_fl); - - bool is_persp = projmat[3][3] == 0.0f; + double winmat[4][4]; + copy_m4d_m4(winmat, winmat_fl); + const bool is_persp = winmat[3][3] == 0.0f; if (is_persp) { - *r_left = (projmat[2][0] - 1.0) / projmat[0][0]; - *r_right = (projmat[2][0] + 1.0) / projmat[0][0]; - *r_bottom = (projmat[2][1] - 1.0) / projmat[1][1]; - *r_top = (projmat[2][1] + 1.0) / projmat[1][1]; - *r_near = projmat[3][2] / (projmat[2][2] - 1.0); - *r_far = projmat[3][2] / (projmat[2][2] + 1.0); + const double near = winmat[3][2] / (winmat[2][2] - 1.0); + *r_left = near * ((winmat[2][0] - 1.0) / winmat[0][0]); + *r_right = near * ((winmat[2][0] + 1.0) / winmat[0][0]); + *r_bottom = near * ((winmat[2][1] - 1.0) / winmat[1][1]); + *r_top = near * ((winmat[2][1] + 1.0) / winmat[1][1]); + *r_near = near; + *r_far = winmat[3][2] / (winmat[2][2] + 1.0); } else { - *r_left = (-projmat[3][0] - 1.0) / projmat[0][0]; - *r_right = (-projmat[3][0] + 1.0) / projmat[0][0]; - *r_bottom = (-projmat[3][1] - 1.0) / projmat[1][1]; - *r_top = (-projmat[3][1] + 1.0) / projmat[1][1]; - *r_near = (projmat[3][2] + 1.0) / projmat[2][2]; - *r_far = (projmat[3][2] - 1.0) / projmat[2][2]; + *r_left = (-winmat[3][0] - 1.0) / winmat[0][0]; + *r_right = (-winmat[3][0] + 1.0) / winmat[0][0]; + *r_bottom = (-winmat[3][1] - 1.0) / winmat[1][1]; + *r_top = (-winmat[3][1] + 1.0) / winmat[1][1]; + *r_near = (winmat[3][2] + 1.0) / winmat[2][2]; + *r_far = (winmat[3][2] - 1.0) / winmat[2][2]; } } diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 99fae1f1616..4d0678035ba 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1102,12 +1102,9 @@ bool BLI_path_abs(char *path, const char *basepath) } #ifdef WIN32 - /* skip first two chars, which in case of - * absolute path will be drive:/blabla and - * in case of relpath //blabla/. So relpath - * // will be retained, rest will be nice and - * shiny win32 backward slashes :) -jesterKing - */ + /* NOTE(@jesterking): Skip first two chars, which in case of absolute path will + * be `drive:/blabla` and in case of `relpath` `//blabla/`. + * So `relpath` `//` will be retained, rest will be nice and shiny WIN32 backward slashes. */ BLI_str_replace_char(path + 2, '/', '\\'); #endif diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c index 7781e3a0f6f..ed07b002e32 100644 --- a/source/blender/blenlib/intern/polyfill_2d_beautify.c +++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c @@ -25,7 +25,7 @@ * on a simple polygon representation where we _know_: * * - The polygon is primitive with no holes with a continuous boundary. - * - Tris have consistent winding. + * - Triangles have consistent winding. * - 2d (saves some hassles projecting face pairs on an axis for every edge-rotation) * also saves us having to store all previous edge-states (see #EdRotState in bmesh_beautify.c) * diff --git a/source/blender/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c index 858f5d85a90..7c644fa3b55 100644 --- a/source/blender/blenloader/intern/versioning_260.c +++ b/source/blender/blenloader/intern/versioning_260.c @@ -2390,7 +2390,7 @@ void blo_do_versions_260(FileData *fd, Library *UNUSED(lib), Main *bmain) for (md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Triangulate) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; - if ((tmd->flag & MOD_TRIANGULATE_BEAUTY)) { + if (tmd->flag & MOD_TRIANGULATE_BEAUTY) { tmd->quad_method = MOD_TRIANGULATE_QUAD_BEAUTY; tmd->ngon_method = MOD_TRIANGULATE_NGON_BEAUTY; } diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index af05c4b902f..9d65488e8d4 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -111,40 +111,13 @@ #include "BLO_readfile.h" #include "readfile.h" +#include "versioning_common.h" + #include "MEM_guardedalloc.h" /* Make preferences read-only, use versioning_userdef.c. */ #define U (*((const UserDef *)&U)) -/** - * Rename if the ID doesn't exist. - */ -static ID *rename_id_for_versioning(Main *bmain, - const short id_type, - const char *name_src, - const char *name_dst) -{ - /* We can ignore libraries */ - ListBase *lb = which_libbase(bmain, id_type); - ID *id = NULL; - LISTBASE_FOREACH (ID *, idtest, lb) { - if (idtest->lib == NULL) { - if (STREQ(idtest->name + 2, name_src)) { - id = idtest; - } - if (STREQ(idtest->name + 2, name_dst)) { - return NULL; - } - } - } - if (id != NULL) { - BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); - /* We know it's unique, this just sorts. */ - BLI_libblock_ensure_unique_name(bmain, id->name); - } - return id; -} - static bScreen *screen_parent_find(const bScreen *screen) { /* Can avoid lookup if screen state isn't maximized/full @@ -348,7 +321,7 @@ static void do_version_layer_collection_post(ViewLayer *view_layer, lc->flag |= LAYER_COLLECTION_EXCLUDE; } if (enabled && !selectable) { - lc->collection->flag |= COLLECTION_RESTRICT_SELECT; + lc->collection->flag |= COLLECTION_HIDE_SELECT; } } @@ -477,7 +450,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene) collections[layer] = collection; if (!(scene->lay & (1 << layer))) { - collection->flag |= COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER; + collection->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } } @@ -1225,7 +1198,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) /* Add fake user for all existing groups. */ id_fake_user_set(&collection->id); - if (collection->flag & (COLLECTION_RESTRICT_VIEWPORT | COLLECTION_RESTRICT_RENDER)) { + if (collection->flag & (COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER)) { continue; } @@ -1256,8 +1229,7 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) char name[MAX_ID_NAME]; BLI_snprintf(name, sizeof(name), DATA_("Hidden %d"), coll_idx + 1); *collection_hidden = BKE_collection_add(bmain, collection, name); - (*collection_hidden)->flag |= COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_RENDER; + (*collection_hidden)->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER; } BKE_collection_object_add(bmain, *collection_hidden, ob); @@ -1679,32 +1651,32 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) Brush *brush; Material *ma; /* Pen Soft brush. */ - brush = (Brush *)rename_id_for_versioning(bmain, ID_BR, "Draw Soft", "Pencil Soft"); + brush = (Brush *)do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft"); if (brush) { brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; } - rename_id_for_versioning(bmain, ID_BR, "Draw Pencil", "Pencil"); - rename_id_for_versioning(bmain, ID_BR, "Draw Pen", "Pen"); - rename_id_for_versioning(bmain, ID_BR, "Draw Ink", "Ink Pen"); - rename_id_for_versioning(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); - rename_id_for_versioning(bmain, ID_BR, "Draw Marker", "Marker Bold"); - rename_id_for_versioning(bmain, ID_BR, "Draw Block", "Marker Chisel"); + do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); + do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); + do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); + do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); ma = BLI_findstring(&bmain->materials, "Black", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); } ma = BLI_findstring(&bmain->materials, "Red", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Red", "Squares Stroke"); + do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); } ma = BLI_findstring(&bmain->materials, "Grey", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Grey", "Solid Fill"); + do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); } ma = BLI_findstring(&bmain->materials, "Black Dots", offsetof(ID, name) + 2); if (ma && ma->gp_style) { - rename_id_for_versioning(bmain, ID_MA, "Black Dots", "Dots Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); } brush = BLI_findstring(&bmain->brushes, "Pencil", offsetof(ID, name) + 2); @@ -4110,9 +4082,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) if (!MAIN_VERSION_ATLEAST(bmain, 280, 75)) { for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) { if (scene->master_collection != NULL) { - scene->master_collection->flag &= ~(COLLECTION_RESTRICT_VIEWPORT | - COLLECTION_RESTRICT_SELECT | - COLLECTION_RESTRICT_RENDER); + scene->master_collection->flag &= ~(COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_SELECT | + COLLECTION_HIDE_RENDER); } UnitSettings *unit = &scene->unit; diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index 09d43676b8f..7f7a2d97cbb 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -170,7 +170,7 @@ static void seq_convert_transform_crop(const Scene *scene, int image_size_x = scene->r.xsch; int image_size_y = scene->r.ysch; - /* Hardcoded legacy bit-flags which has been removed. */ + /* Hard-coded legacy bit-flags which has been removed. */ const uint32_t use_transform_flag = (1 << 16); const uint32_t use_crop_flag = (1 << 17); diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c index 9aec18ea279..42af8f4bda2 100644 --- a/source/blender/blenloader/intern/versioning_300.c +++ b/source/blender/blenloader/intern/versioning_300.c @@ -29,6 +29,7 @@ #include "DNA_armature_types.h" #include "DNA_brush_types.h" #include "DNA_collection_types.h" +#include "DNA_constraint_types.h" #include "DNA_curve_types.h" #include "DNA_genfile.h" #include "DNA_listBase.h" @@ -383,6 +384,19 @@ static void do_version_bones_bbone_len_scale(ListBase *lb) } } +static void do_version_constraints_spline_ik_joint_bindings(ListBase *lb) +{ + /* Binding array data could be freed without properly resetting its size data. */ + LISTBASE_FOREACH (bConstraint *, con, lb) { + if (con->type == CONSTRAINT_TYPE_SPLINEIK) { + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + if (data->points == NULL) { + data->numpoints = 0; + } + } + } +} + /* NOLINTNEXTLINE: readability-function-size */ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) { @@ -691,6 +705,39 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain) } } + /* Font names were copied directly into ID names, see: T90417. */ + if (!MAIN_VERSION_ATLEAST(bmain, 300, 16)) { + ListBase *lb = which_libbase(bmain, ID_VF); + BKE_main_id_repair_duplicate_names_listbase(lb); + } + + if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) { + if (!DNA_struct_elem_find( + fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) { + LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + v3d->overlay.normals_constant_screen_size = 7.0f; + } + } + } + } + } + + /* Fix SplineIK constraint's inconsistency between binding points array and its stored size. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + /* NOTE: Objects should never have SplineIK constraint, so no need to apply this fix on + * their constraints. */ + if (ob->pose) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { + do_version_constraints_spline_ik_joint_bindings(&pchan->constraints); + } + } + } + } + /** * Versioning code until next subversion bump goes here. * diff --git a/source/blender/blenloader/intern/versioning_common.cc b/source/blender/blenloader/intern/versioning_common.cc index f5083b8e259..208c02b60d1 100644 --- a/source/blender/blenloader/intern/versioning_common.cc +++ b/source/blender/blenloader/intern/versioning_common.cc @@ -20,9 +20,15 @@ /* allow readfile to use deprecated functionality */ #define DNA_DEPRECATED_ALLOW +#include <cstring> + #include "DNA_screen_types.h" #include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BKE_lib_id.h" +#include "BKE_main.h" #include "MEM_guardedalloc.h" @@ -48,3 +54,34 @@ ARegion *do_versions_add_region_if_not_found(ListBase *regionbase, BLI_insertlinkafter(regionbase, link_after_region, new_region); return new_region; } + +/** + * Rename if the ID doesn't exist. + * + * \return the ID (if found). + */ +ID *do_versions_rename_id(Main *bmain, + const short id_type, + const char *name_src, + const char *name_dst) +{ + /* We can ignore libraries */ + ListBase *lb = which_libbase(bmain, id_type); + ID *id = nullptr; + LISTBASE_FOREACH (ID *, idtest, lb) { + if (idtest->lib == nullptr) { + if (STREQ(idtest->name + 2, name_src)) { + id = idtest; + } + if (STREQ(idtest->name + 2, name_dst)) { + return nullptr; + } + } + } + if (id != nullptr) { + BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); + /* We know it's unique, this just sorts. */ + BLI_libblock_ensure_unique_name(bmain, id->name); + } + return id; +} diff --git a/source/blender/blenloader/intern/versioning_common.h b/source/blender/blenloader/intern/versioning_common.h index a1769d4639e..47e0b74a3e4 100644 --- a/source/blender/blenloader/intern/versioning_common.h +++ b/source/blender/blenloader/intern/versioning_common.h @@ -22,6 +22,7 @@ struct ARegion; struct ListBase; +struct Main; #ifdef __cplusplus extern "C" { @@ -32,6 +33,11 @@ struct ARegion *do_versions_add_region_if_not_found(struct ListBase *regionbase, const char *name, int link_after_region_type); +ID *do_versions_rename_id(Main *bmain, + const short id_type, + const char *name_src, + const char *name_dst); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c index 94ee89c5120..90e6b43f02e 100644 --- a/source/blender/blenloader/intern/versioning_cycles.c +++ b/source/blender/blenloader/intern/versioning_cycles.c @@ -78,6 +78,12 @@ static IDProperty *cycles_properties_from_ID(ID *id) return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles", IDP_GROUP) : NULL; } +static IDProperty *cycles_visibility_properties_from_ID(ID *id) +{ + IDProperty *idprop = IDP_GetProperties(id, false); + return (idprop) ? IDP_GetPropertyTypeFromGroup(idprop, "cycles_visibility", IDP_GROUP) : NULL; +} + static IDProperty *cycles_properties_from_view_layer(ViewLayer *view_layer) { IDProperty *idprop = view_layer->id_properties; @@ -1600,4 +1606,35 @@ void do_versions_after_linking_cycles(Main *bmain) } } } + + /* Move visibility from Cycles to Blender. */ + if (!MAIN_VERSION_ATLEAST(bmain, 300, 17)) { + LISTBASE_FOREACH (Object *, object, &bmain->objects) { + IDProperty *cvisibility = cycles_visibility_properties_from_ID(&object->id); + int flag = 0; + + if (cvisibility) { + flag |= cycles_property_boolean(cvisibility, "camera", true) ? 0 : OB_HIDE_CAMERA; + flag |= cycles_property_boolean(cvisibility, "diffuse", true) ? 0 : OB_HIDE_DIFFUSE; + flag |= cycles_property_boolean(cvisibility, "glossy", true) ? 0 : OB_HIDE_GLOSSY; + flag |= cycles_property_boolean(cvisibility, "transmission", true) ? 0 : + OB_HIDE_TRANSMISSION; + flag |= cycles_property_boolean(cvisibility, "scatter", true) ? 0 : OB_HIDE_VOLUME_SCATTER; + flag |= cycles_property_boolean(cvisibility, "shadow", true) ? 0 : OB_HIDE_SHADOW; + } + + IDProperty *cobject = cycles_properties_from_ID(&object->id); + if (cobject) { + flag |= cycles_property_boolean(cobject, "is_holdout", false) ? OB_HOLDOUT : 0; + flag |= cycles_property_boolean(cobject, "is_shadow_catcher", false) ? OB_SHADOW_CATCHER : + 0; + } + + if (object->type == OB_LAMP) { + flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER; + } + + object->visibility_flag |= flag; + } + } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 8362e001ea6..82c577d11a0 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -65,38 +65,11 @@ #include "BLO_readfile.h" +#include "versioning_common.h" + /* Make preferences read-only, use versioning_userdef.c. */ #define U (*((const UserDef *)&U)) -/** - * Rename if the ID doesn't exist. - */ -static ID *rename_id_for_versioning(Main *bmain, - const short id_type, - const char *name_src, - const char *name_dst) -{ - /* We can ignore libraries */ - ListBase *lb = which_libbase(bmain, id_type); - ID *id = NULL; - LISTBASE_FOREACH (ID *, idtest, lb) { - if (idtest->lib == NULL) { - if (STREQ(idtest->name + 2, name_src)) { - id = idtest; - } - if (STREQ(idtest->name + 2, name_dst)) { - return NULL; - } - } - } - if (id != NULL) { - BLI_strncpy(id->name + 2, name_dst, sizeof(id->name) - 2); - /* We know it's unique, this just sorts. */ - BLI_libblock_ensure_unique_name(bmain, id->name); - } - return id; -} - static bool blo_is_builtin_template(const char *app_template) { /* For all builtin templates shipped with Blender. */ @@ -217,6 +190,7 @@ static void blo_update_defaults_screen(bScreen *screen, } /* Disable Curve Normals. */ v3d->overlay.edit_flag &= ~V3D_OVERLAY_EDIT_CU_NORMALS; + v3d->overlay.normals_constant_screen_size = 7.0f; } else if (area->spacetype == SPACE_CLIP) { SpaceClip *sclip = area->spacedata.first; @@ -406,28 +380,28 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) Brush *brush; /* Pencil brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Pencil", "Pencil"); + do_versions_rename_id(bmain, ID_BR, "Draw Pencil", "Pencil"); /* Pen brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Pen", "Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Pen", "Pen"); /* Pen Soft brush. */ - brush = (Brush *)rename_id_for_versioning(bmain, ID_BR, "Draw Soft", "Pencil Soft"); + brush = (Brush *)do_versions_rename_id(bmain, ID_BR, "Draw Soft", "Pencil Soft"); if (brush) { brush->gpencil_settings->icon_id = GP_BRUSH_ICON_PEN; } /* Ink Pen brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Ink", "Ink Pen"); + do_versions_rename_id(bmain, ID_BR, "Draw Ink", "Ink Pen"); /* Ink Pen Rough brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); + do_versions_rename_id(bmain, ID_BR, "Draw Noise", "Ink Pen Rough"); /* Marker Bold brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Marker", "Marker Bold"); + do_versions_rename_id(bmain, ID_BR, "Draw Marker", "Marker Bold"); /* Marker Chisel brush. */ - rename_id_for_versioning(bmain, ID_BR, "Draw Block", "Marker Chisel"); + do_versions_rename_id(bmain, ID_BR, "Draw Block", "Marker Chisel"); /* Remove useless Fill Area.001 brush. */ brush = BLI_findstring(&bmain->brushes, "Fill Area.001", offsetof(ID, name) + 2); @@ -438,10 +412,10 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) /* Rename and fix materials and enable default object lights on. */ if (app_template && STREQ(app_template, "2D_Animation")) { Material *ma = NULL; - rename_id_for_versioning(bmain, ID_MA, "Black", "Solid Stroke"); - rename_id_for_versioning(bmain, ID_MA, "Red", "Squares Stroke"); - rename_id_for_versioning(bmain, ID_MA, "Grey", "Solid Fill"); - rename_id_for_versioning(bmain, ID_MA, "Black Dots", "Dots Stroke"); + do_versions_rename_id(bmain, ID_MA, "Black", "Solid Stroke"); + do_versions_rename_id(bmain, ID_MA, "Red", "Squares Stroke"); + do_versions_rename_id(bmain, ID_MA, "Grey", "Solid Fill"); + do_versions_rename_id(bmain, ID_MA, "Black Dots", "Dots Stroke"); /* Dots Stroke. */ ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2); @@ -553,8 +527,8 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template) } /* Objects */ - rename_id_for_versioning(bmain, ID_OB, "Lamp", "Light"); - rename_id_for_versioning(bmain, ID_LA, "Lamp", "Light"); + do_versions_rename_id(bmain, ID_OB, "Lamp", "Light"); + do_versions_rename_id(bmain, ID_LA, "Lamp", "Light"); if (app_template && STREQ(app_template, "2D_Animation")) { for (Object *object = bmain->objects.first; object; object = object->id.next) { diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 95cfc9975d7..81371e1c1ed 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1335,7 +1335,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) ME_OPT_EDGES = (1 << 8), }; - if ((me->flag & ME_SUBSURF)) { + if (me->flag & ME_SUBSURF) { SubsurfModifierData *smd = (SubsurfModifierData *)BKE_modifier_new( eModifierType_Subsurf); diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c index 746f094aed6..8eda38046a1 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.c +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c @@ -50,8 +50,6 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const float split_angle_cos); -static void bm_edge_tag_clear(BMEdge *e); - /* -------------------------------------------------------------------- */ /** \name Update Vertex & Face Normals * \{ */ @@ -866,13 +864,6 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const flo } } -static void bm_edge_tag_clear(BMEdge *e) -{ - /* No need for atomics here as this is a single byte. */ - char *hflag_p = &e->head.hflag; - *hflag_p = *hflag_p & ~BM_ELEM_TAG; -} - /** * A version of #bm_edge_tag_from_smooth that sets sharp edges * when they would be considered smooth but exceed the split angle . @@ -941,6 +932,7 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, const bool has_clnors = true; LinkNode *loops_of_vert = NULL; int loops_of_vert_count = 0; + /* When false the caller must have already tagged the edges. */ const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); /* The loop with the lowest index. */ @@ -954,13 +946,9 @@ static void bm_mesh_loops_calc_normals_for_vert_with_clnors(BMesh *bm, continue; } - /* Always set as #bm_mesh_loops_calc_normals_for_loop checks the tag. */ if (do_edge_tag) { bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); } - else { - bm_edge_tag_clear(e_curr_iter); - } do { /* Radial loops. */ if (l_curr->v != v) { @@ -1053,6 +1041,7 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( { const bool has_clnors = false; const short(*clnors_data)[2] = NULL; + /* When false the caller must have already tagged the edges. */ const bool do_edge_tag = (split_angle_cos != EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS); const int cd_loop_clnors_offset = -1; @@ -1066,13 +1055,9 @@ static void bm_mesh_loops_calc_normals_for_vert_without_clnors( continue; } - /* Always set as #bm_mesh_loops_calc_normals_for_loop checks the tag. */ if (do_edge_tag) { bm_edge_tag_from_smooth(fnos, e_curr_iter, split_angle_cos); } - else { - bm_edge_tag_clear(e_curr_iter); - } do { /* Radial loops. */ if (l_curr->v != v) { @@ -1156,10 +1141,6 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } - if (split_angle_cos != -1.0f) { - bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false); - } - /* Clear all loops' tags (means none are to be skipped for now). */ int index_face, index_loop = 0; BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { @@ -1171,10 +1152,17 @@ static void bm_mesh_loops_calc_normals__single_threaded(BMesh *bm, do { BM_elem_index_set(l_curr, index_loop++); /* set_inline */ BM_elem_flag_disable(l_curr, BM_ELEM_TAG); + /* Needed for when #bm_mesh_edges_sharp_tag doesn't run. + * Mark smooth if there is no smoothing angle. */ + BM_elem_flag_enable(l_curr->e, BM_ELEM_TAG); } while ((l_curr = l_curr->next) != l_first); } bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); + if (split_angle_cos != -1.0f) { + bm_mesh_edges_sharp_tag(bm, fnos, has_clnors ? (float)M_PI : split_angle, false); + } + /* We now know edges that can be smoothed (they are tagged), * and edges that will be hard (they aren't). * Now, time to generate the normals. diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index e66afcd88d9..7931e953295 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -203,9 +203,9 @@ static void *bmw_VertShellWalker_step(BMWalker *walker) curedge = shellWalk.curedge; do { if (!BLI_gset_haskey(walker->visit_set, curedge)) { - if (!walker->restrictflag || - (walker->restrictflag && - BMO_edge_flag_test(walker->bm, curedge, walker->restrictflag))) { + if (!walker->visibility_flag || + (walker->visibility_flag && + BMO_edge_flag_test(walker->bm, curedge, walker->visibility_flag))) { BMwShellWalker *newstate; v_old = BM_edge_other_vert(curedge, shellWalk.base); @@ -714,7 +714,7 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) iwalk->base = owalk.base; #if 0 - if (!BMO_face_flag_test(walker->bm, l->f, walker->restrictflag)) { + if (!BMO_face_flag_test(walker->bm, l->f, walker->visibility_flag)) { iwalk->curloop = l->radial_next; } else { diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index b02a3e8652f..23d63bbe5ab 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -1122,7 +1122,6 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) /* apply the offset */ if (use_attributes) { - printf("index: %i\n", v_split->head.index); madd_v3_v3fl(v_split->co, tvec, thickness_array[v_split->head.index]); } else { diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index b2b93bfd003..94856701e72 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -37,14 +37,14 @@ struct BLaplacianSystem { float *eweights; /* Length weights per Edge. */ - float (*fweights)[3]; /* Cotangent weights per face. */ + float (*fweights)[3]; /* Cotangent weights per loop. */ float *ring_areas; /* Total area per ring. */ float *vlengths; /* Total sum of lengths(edges) per vertex. */ float *vweights; /* Total sum of weights per vertex. */ int numEdges; /* Number of edges. */ - int numFaces; /* Number of faces. */ + int numLoops; /* Number of loops. */ int numVerts; /* Number of verts. */ - short *zerola; /* Is zero area or length. */ + bool *zerola; /* Is zero area or length. */ /* Pointers to data. */ BMesh *bm; @@ -57,7 +57,7 @@ struct BLaplacianSystem { typedef struct BLaplacianSystem LaplacianSystem; static bool vert_is_boundary(BMVert *v); -static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts); static void init_laplacian_matrix(LaplacianSystem *sys); static void delete_laplacian_system(LaplacianSystem *sys); static void delete_void_pointer(void *data); @@ -94,19 +94,19 @@ static void delete_laplacian_system(LaplacianSystem *sys) static void memset_laplacian_system(LaplacianSystem *sys, int val) { memset(sys->eweights, val, sizeof(float) * sys->numEdges); - memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3); + memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops); memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); memset(sys->vlengths, val, sizeof(float) * sys->numVerts); memset(sys->vweights, val, sizeof(float) * sys->numVerts); - memset(sys->zerola, val, sizeof(short) * sys->numVerts); + memset(sys->zerola, val, sizeof(bool) * sys->numVerts); } -static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts) +static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts) { LaplacianSystem *sys; sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem"); sys->numEdges = a_numEdges; - sys->numFaces = a_numFaces; + sys->numLoops = a_numLoops; sys->numVerts = a_numVerts; sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight"); @@ -115,7 +115,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in return NULL; } - sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numFaces, "ModLaplSmoothFWeight"); + sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numLoops, "ModLaplSmoothFWeight"); if (!sys->fweights) { delete_laplacian_system(sys); return NULL; @@ -139,7 +139,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in return NULL; } - sys->zerola = MEM_callocN(sizeof(short) * sys->numVerts, "ModLaplSmoothZeloa"); + sys->zerola = MEM_callocN(sizeof(bool) * sys->numVerts, "ModLaplSmoothZeloa"); if (!sys->zerola) { delete_laplacian_system(sys); return NULL; @@ -166,219 +166,160 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in static void init_laplacian_matrix(LaplacianSystem *sys) { - float areaf; - float *v1, *v2, *v3, *v4; - float w1, w2, w3, w4; - int i, j; - bool has_4_vert; - uint idv1, idv2, idv3, idv4, idv[4]; BMEdge *e; BMFace *f; BMIter eiter; BMIter fiter; - BMIter vi; - BMVert *vn; - BMVert *vf[4]; - - BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, j) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { - v1 = e->v1->co; - v2 = e->v2->co; - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); - - w1 = len_v3v3(v1, v2); - if (w1 > sys->min_area) { - w1 = 1.0f / w1; - i = BM_elem_index_get(e); - sys->eweights[i] = w1; - sys->vlengths[idv1] += w1; - sys->vlengths[idv2] += w1; - } - else { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; - } - } - } - - BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { + uint i; - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { - vf[i] = vn; - } - has_4_vert = (i == 4) ? 1 : 0; - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0; - - v1 = vf[0]->co; - v2 = vf[1]->co; - v3 = vf[2]->co; - v4 = has_4_vert ? vf[3]->co : NULL; - - if (has_4_vert) { - areaf = area_quad_v3(v1, v2, v3, v4); - } - else { - areaf = area_tri_v3(v1, v2, v3); - } + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { + continue; + } - if (fabsf(areaf) < sys->min_area) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; - sys->zerola[idv3] = 1; - if (has_4_vert) { - sys->zerola[idv4] = 1; - } - } + const float *v1 = e->v1->co; + const float *v2 = e->v2->co; + const int idv1 = BM_elem_index_get(e->v1); + const int idv2 = BM_elem_index_get(e->v2); + + float w1 = len_v3v3(v1, v2); + if (w1 > sys->min_area) { + w1 = 1.0f / w1; + sys->eweights[i] = w1; + sys->vlengths[idv1] += w1; + sys->vlengths[idv2] += w1; + } + else { + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; + } + } - sys->ring_areas[idv1] += areaf; - sys->ring_areas[idv2] += areaf; - sys->ring_areas[idv3] += areaf; - if (has_4_vert) { - sys->ring_areas[idv4] += areaf; - } + uint l_curr_index = 0; - if (has_4_vert) { + BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + l_curr_index += f->len; + continue; + } - idv[0] = idv1; - idv[1] = idv2; - idv[2] = idv3; - idv[3] = idv4; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; + l_iter = l_first; + do { + const int vi_prev = BM_elem_index_get(l_iter->prev->v); + const int vi_curr = BM_elem_index_get(l_iter->v); + const int vi_next = BM_elem_index_get(l_iter->next->v); - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; + const float *co_prev = l_iter->prev->v->co; + const float *co_curr = l_iter->v->co; + const float *co_next = l_iter->next->v->co; - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); + const float areaf = area_tri_v3(co_prev, co_curr, co_next); - sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f; - } + if (areaf < sys->min_area) { + sys->zerola[vi_curr] = true; } - else { - i = BM_elem_index_get(f); - w1 = cotangent_tri_weight_v3(v1, v2, v3); - w2 = cotangent_tri_weight_v3(v2, v3, v1); - w3 = cotangent_tri_weight_v3(v3, v1, v2); + sys->ring_areas[vi_prev] += areaf; + sys->ring_areas[vi_curr] += areaf; + sys->ring_areas[vi_next] += areaf; - sys->fweights[i][0] += w1; - sys->fweights[i][1] += w2; - sys->fweights[i][2] += w3; + const float w1 = cotangent_tri_weight_v3(co_curr, co_next, co_prev) / 2.0f; + const float w2 = cotangent_tri_weight_v3(co_next, co_prev, co_curr) / 2.0f; + const float w3 = cotangent_tri_weight_v3(co_prev, co_curr, co_next) / 2.0f; - sys->vweights[idv1] += w2 + w3; - sys->vweights[idv2] += w1 + w3; - sys->vweights[idv3] += w1 + w2; - } - } + sys->fweights[l_curr_index][0] += w1; + sys->fweights[l_curr_index][1] += w2; + sys->fweights[l_curr_index][2] += w3; + + sys->vweights[vi_prev] += w1 + w2; + sys->vweights[vi_curr] += w2 + w3; + sys->vweights[vi_next] += w1 + w3; + } while (((void)(l_curr_index += 1), (l_iter = l_iter->next) != l_first)); } } static void fill_laplacian_matrix(LaplacianSystem *sys) { - float *v1, *v2, *v3, *v4; - float w2, w3, w4; - int i, j; - bool has_4_vert; - uint idv1, idv2, idv3, idv4, idv[4]; - BMEdge *e; BMFace *f; BMIter eiter; BMIter fiter; - BMIter vi; - BMVert *vn; - BMVert *vf[4]; + int i; + + uint l_curr_index = 0; BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { - vf[i] = vn; + if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) { + l_curr_index += f->len; + continue; + } + + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + + int vi_prev = BM_elem_index_get(l_iter->prev->v); + int vi_curr = BM_elem_index_get(l_iter->v); + + bool ok_prev = (sys->zerola[vi_prev] == false) && !vert_is_boundary(l_iter->prev->v); + bool ok_curr = (sys->zerola[vi_curr] == false) && !vert_is_boundary(l_iter->v); + + do { + const int vi_next = BM_elem_index_get(l_iter->next->v); + const bool ok_next = (sys->zerola[vi_next] == false) && !vert_is_boundary(l_iter->next->v); + + if (ok_prev) { + EIG_linear_solver_matrix_add(sys->context, + vi_prev, + vi_curr, + sys->fweights[l_curr_index][1] * sys->vweights[vi_prev]); + EIG_linear_solver_matrix_add(sys->context, + vi_prev, + vi_next, + sys->fweights[l_curr_index][0] * sys->vweights[vi_prev]); } - has_4_vert = (i == 4) ? 1 : 0; - if (has_4_vert) { - idv[0] = BM_elem_index_get(vf[0]); - idv[1] = BM_elem_index_get(vf[1]); - idv[2] = BM_elem_index_get(vf[2]); - idv[3] = BM_elem_index_get(vf[3]); - for (j = 0; j < 4; j++) { - idv1 = idv[j]; - idv2 = idv[(j + 1) % 4]; - idv3 = idv[(j + 2) % 4]; - idv4 = idv[(j + 3) % 4]; - - v1 = vf[j]->co; - v2 = vf[(j + 1) % 4]->co; - v3 = vf[(j + 2) % 4]->co; - v4 = vf[(j + 3) % 4]->co; - - w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2); - w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3); - w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1); - - w2 = w2 / 4.0f; - w3 = w3 / 4.0f; - w4 = w4 / 4.0f; - - if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == 0) { - EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]); - EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]); - } - } + if (ok_curr) { + EIG_linear_solver_matrix_add(sys->context, + vi_curr, + vi_next, + sys->fweights[l_curr_index][2] * sys->vweights[vi_curr]); + EIG_linear_solver_matrix_add(sys->context, + vi_curr, + vi_prev, + sys->fweights[l_curr_index][1] * sys->vweights[vi_curr]); } - else { - idv1 = BM_elem_index_get(vf[0]); - idv2 = BM_elem_index_get(vf[1]); - idv3 = BM_elem_index_get(vf[2]); - /* Is ring if number of faces == number of edges around vertice. */ - i = BM_elem_index_get(f); - if (!vert_is_boundary(vf[0]) && sys->zerola[idv1] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv1, idv2, sys->fweights[i][2] * sys->vweights[idv1]); - EIG_linear_solver_matrix_add( - sys->context, idv1, idv3, sys->fweights[i][1] * sys->vweights[idv1]); - } - if (!vert_is_boundary(vf[1]) && sys->zerola[idv2] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv2, idv1, sys->fweights[i][2] * sys->vweights[idv2]); - EIG_linear_solver_matrix_add( - sys->context, idv2, idv3, sys->fweights[i][0] * sys->vweights[idv2]); - } - if (!vert_is_boundary(vf[2]) && sys->zerola[idv3] == 0) { - EIG_linear_solver_matrix_add( - sys->context, idv3, idv1, sys->fweights[i][1] * sys->vweights[idv3]); - EIG_linear_solver_matrix_add( - sys->context, idv3, idv2, sys->fweights[i][0] * sys->vweights[idv3]); - } + if (ok_next) { + EIG_linear_solver_matrix_add(sys->context, + vi_next, + vi_curr, + sys->fweights[l_curr_index][2] * sys->vweights[vi_next]); + EIG_linear_solver_matrix_add(sys->context, + vi_next, + vi_prev, + sys->fweights[l_curr_index][0] * sys->vweights[vi_next]); } - } + + vi_prev = vi_curr; + vi_curr = vi_next; + + ok_prev = ok_curr; + ok_curr = ok_next; + + } while (((void)(l_curr_index += 1), (l_iter = l_iter->next) != l_first)); } - BM_ITER_MESH (e, &eiter, sys->bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_boundary(e)) { - v1 = e->v1->co; - v2 = e->v2->co; - idv1 = BM_elem_index_get(e->v1); - idv2 = BM_elem_index_get(e->v2); - if (sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { - i = BM_elem_index_get(e); - EIG_linear_solver_matrix_add( - sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); - EIG_linear_solver_matrix_add( - sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); - } + BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) { + continue; + } + const uint idv1 = BM_elem_index_get(e->v1); + const uint idv2 = BM_elem_index_get(e->v2); + if (sys->zerola[idv1] == false && sys->zerola[idv2] == false) { + EIG_linear_solver_matrix_add( + sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); + EIG_linear_solver_matrix_add( + sys->context, idv2, idv1, sys->eweights[i] * sys->vlengths[idv2]); } } } @@ -453,8 +394,8 @@ static void validate_solution( lene = len_v3v3(ve1, ve2); if (lene > leni * SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE || lene < leni * SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; } } @@ -463,7 +404,7 @@ static void validate_solution( } BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); - if (sys->zerola[m_vertex_id] == 0) { + if (sys->zerola[m_vertex_id] == false) { if (usex) { v->co[0] = EIG_linear_solver_variable_get(sys->context, 0, m_vertex_id); } @@ -495,7 +436,7 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) if (bm->totface == 0) { return; } - sys = init_laplacian_system(bm->totedge, bm->totface, bm->totvert); + sys = init_laplacian_system(bm->totedge, bm->totloop, bm->totvert); if (!sys) { return; } @@ -533,7 +474,10 @@ void bmo_smooth_laplacian_vert_exec(BMesh *bm, BMOperator *op) EIG_linear_solver_right_hand_side_add(sys->context, 1, m_vertex_id, v->co[1]); EIG_linear_solver_right_hand_side_add(sys->context, 2, m_vertex_id, v->co[2]); i = m_vertex_id; - if (sys->zerola[i] == 0) { + if ((sys->zerola[i] == false) && + /* Non zero check is to account for vertices that aren't connected to a selected face. + * Without this wire edges become `nan`, see T89214. */ + (sys->ring_areas[i] != 0.0f)) { w = sys->vweights[i] * sys->ring_areas[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -lambda_factor / (4.0f * w); w = sys->vlengths[i]; diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index 20b6903b239..97fccbe01fd 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -935,9 +935,9 @@ static bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) } /** - * special, highly limited edge collapse function + * Special, highly limited edge collapse function * intended for speed over flexibility. - * can only collapse edges connected to (1, 2) tris. + * can only collapse edges connected to (1, 2) triangles. * * Important - don't add vert/edge/face data on collapsing! * diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 000ba298c2d..ee287c65fe9 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -597,16 +597,16 @@ add_definitions(-DCL_USE_DEPRECATED_OPENCL_1_1_APIS) set(GENSRC_DIR ${CMAKE_CURRENT_BINARY_DIR}/operations) set(GENSRC ${GENSRC_DIR}/COM_SMAAAreaTexture.h) add_custom_command( - OUTPUT ${GENSRC} - COMMAND ${CMAKE_COMMAND} -E make_directory ${GENSRC_DIR} - COMMAND "$<TARGET_FILE:smaa_areatex>" ${GENSRC} - DEPENDS smaa_areatex + OUTPUT ${GENSRC} + COMMAND ${CMAKE_COMMAND} -E make_directory ${GENSRC_DIR} + COMMAND "$<TARGET_FILE:smaa_areatex>" ${GENSRC} + DEPENDS smaa_areatex ) add_custom_target(smaa_areatex_header - SOURCES ${GENSRC} + SOURCES ${GENSRC} ) list(APPEND SRC - ${GENSRC} + ${GENSRC} ) unset(GENSRC) unset(GENSRC_DIR) @@ -650,4 +650,3 @@ if(WITH_GTESTS) include(GTestTesting) blender_add_test_lib(bf_compositor_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}") endif() - diff --git a/source/blender/compositor/nodes/COM_MaskNode.cc b/source/blender/compositor/nodes/COM_MaskNode.cc index ef171c01653..b5b23798160 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.cc +++ b/source/blender/compositor/nodes/COM_MaskNode.cc @@ -41,7 +41,7 @@ void MaskNode::convertToOperations(NodeConverter &converter, NodeMask *data = (NodeMask *)editorNode->storage; Mask *mask = (Mask *)editorNode->id; - // always connect the output image + /* Always connect the output image. */ MaskOperation *operation = new MaskOperation(); if (editorNode->custom1 & CMP_NODEFLAG_MASK_FIXED) { diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cc b/source/blender/compositor/nodes/COM_MovieClipNode.cc index 50bd9b4d71b..b80071d27c7 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cc +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cc @@ -62,7 +62,7 @@ void MovieClipNode::convertToOperations(NodeConverter &converter, } } - // always connect the output image + /* Always connect the output image. */ MovieClipOperation *operation = new MovieClipOperation(); operation->setMovieClip(movieClip); operation->setMovieClipUser(movieClipUser); diff --git a/source/blender/compositor/operations/COM_CryptomatteOperation.cc b/source/blender/compositor/operations/COM_CryptomatteOperation.cc index 52ae1d6d5b5..1a86fadad76 100644 --- a/source/blender/compositor/operations/COM_CryptomatteOperation.cc +++ b/source/blender/compositor/operations/COM_CryptomatteOperation.cc @@ -57,8 +57,8 @@ void CryptomatteOperation::executePixel(float output[4], int x, int y, void *dat ::memcpy(&m3hash, &input[0], sizeof(uint32_t)); /* Since the red channel is likely to be out of display range, * setting green and blue gives more meaningful images. */ - output[1] = ((float)((m3hash << 8)) / (float)UINT32_MAX); - output[2] = ((float)((m3hash << 16)) / (float)UINT32_MAX); + output[1] = ((float)(m3hash << 8) / (float)UINT32_MAX); + output[2] = ((float)(m3hash << 16) / (float)UINT32_MAX); } for (float hash : m_objectIndex) { if (input[0] == hash) { diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cc b/source/blender/compositor/operations/COM_DilateErodeOperation.cc index 2454f507664..c67a35b686c 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cc +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cc @@ -24,7 +24,7 @@ namespace blender::compositor { -// DilateErode Distance Threshold +/* DilateErode Distance Threshold */ DilateErodeThresholdOperation::DilateErodeThresholdOperation() { this->addInputSocket(DataType::Value); @@ -258,7 +258,7 @@ void DilateDistanceOperation::executeOpenCL(OpenCLDevice *device, device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this); } -// Erode Distance +/* Erode Distance */ ErodeDistanceOperation::ErodeDistanceOperation() : DilateDistanceOperation() { /* pass */ @@ -318,7 +318,7 @@ void ErodeDistanceOperation::executeOpenCL(OpenCLDevice *device, device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this); } -// Dilate step +/* Dilate step */ DilateStepOperation::DilateStepOperation() { this->addInputSocket(DataType::Value); @@ -331,7 +331,7 @@ void DilateStepOperation::initExecution() this->m_inputProgram = this->getInputSocketReader(0); } -// small helper to pass data from initializeTileData to executePixel +/* Small helper to pass data from initializeTileData to executePixel. */ struct tile_info { rcti rect; int width; @@ -370,21 +370,21 @@ void *DilateStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // NOTE: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. + /* NOTE: Cache buffer has original tile-size width, but new height. + * We have to calculate the additional rows in the first pass, + * to have valid data available for the second pass. */ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); float *rectf = result->buffer; - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. + /* temp holds maxima for every step in the algorithm, buf holds a + * single row or column of input values, padded with FLT_MAX's to + * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode + /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + * first pass, horizontal dilate/erode. */ for (y = ymin; y < ymax; y++) { for (x = 0; x < bwidth + 5 * half_window; x++) { buf[x] = -FLT_MAX; @@ -409,7 +409,7 @@ void *DilateStepOperation::initializeTileData(rcti *rect) } } - // second pass, vertical dilate/erode + /* Second pass, vertical dilate/erode. */ for (x = 0; x < bwidth; x++) { for (y = 0; y < bheight + 5 * half_window; y++) { buf[y] = -FLT_MAX; @@ -475,7 +475,7 @@ bool DilateStepOperation::determineDependingAreaOfInterest(rcti *input, return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -// Erode step +/* Erode step */ ErodeStepOperation::ErodeStepOperation() : DilateStepOperation() { /* pass */ @@ -500,21 +500,21 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) int bwidth = rect->xmax - rect->xmin; int bheight = rect->ymax - rect->ymin; - // NOTE: Cache buffer has original tilesize width, but new height. - // We have to calculate the additional rows in the first pass, - // to have valid data available for the second pass. + /* NOTE: Cache buffer has original tilesize width, but new height. + * We have to calculate the additional rows in the first pass, + * to have valid data available for the second pass. */ tile_info *result = create_cache(rect->xmin, rect->xmax, ymin, ymax); float *rectf = result->buffer; - // temp holds maxima for every step in the algorithm, buf holds a - // single row or column of input values, padded with FLT_MAX's to - // simplify the logic. + /* temp holds maxima for every step in the algorithm, buf holds a + * single row or column of input values, padded with FLT_MAX's to + * simplify the logic. */ float *temp = (float *)MEM_mallocN(sizeof(float) * (2 * window - 1), "dilate erode temp"); float *buf = (float *)MEM_mallocN(sizeof(float) * (MAX2(bwidth, bheight) + 5 * half_window), "dilate erode buf"); - // The following is based on the van Herk/Gil-Werman algorithm for morphology operations. - // first pass, horizontal dilate/erode + /* The following is based on the van Herk/Gil-Werman algorithm for morphology operations. + * first pass, horizontal dilate/erode */ for (y = ymin; y < ymax; y++) { for (x = 0; x < bwidth + 5 * half_window; x++) { buf[x] = FLT_MAX; @@ -539,7 +539,7 @@ void *ErodeStepOperation::initializeTileData(rcti *rect) } } - // second pass, vertical dilate/erode + /* Second pass, vertical dilate/erode. */ for (x = 0; x < bwidth; x++) { for (y = 0; y < bheight + 5 * half_window; y++) { buf[y] = FLT_MAX; diff --git a/source/blender/compositor/operations/COM_GlareBaseOperation.h b/source/blender/compositor/operations/COM_GlareBaseOperation.h index 50db4e02940..6dac6f5ecc7 100644 --- a/source/blender/compositor/operations/COM_GlareBaseOperation.h +++ b/source/blender/compositor/operations/COM_GlareBaseOperation.h @@ -23,8 +23,8 @@ namespace blender::compositor { -/* utility functions used by glare, tonemap and lens distortion */ -/* soms macros for color handling */ +/* Utility functions used by glare, tone-map and lens distortion. */ +/* Some macros for color handling. */ typedef float fRGB[4]; /* TODO: replace with BLI_math_vector. */ diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cc b/source/blender/compositor/operations/COM_OutputFileOperation.cc index 7e896046f01..6c5984e3414 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cc +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cc @@ -160,7 +160,7 @@ int get_datatype_size(DataType datatype) static float *init_buffer(unsigned int width, unsigned int height, DataType datatype) { - // When initializing the tree during initial load the width and height can be zero. + /* When initializing the tree during initial load the width and height can be zero. */ if (width != 0 && height != 0) { int size = get_datatype_size(datatype); return (float *)MEM_callocN(width * height * size * sizeof(float), "OutputFile buffer"); diff --git a/source/blender/compositor/operations/COM_WrapOperation.cc b/source/blender/compositor/operations/COM_WrapOperation.cc index d0d2fcac3ac..888602114cc 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cc +++ b/source/blender/compositor/operations/COM_WrapOperation.cc @@ -57,20 +57,20 @@ void WrapOperation::executePixelSampled(float output[4], float x, float y, Pixel MemoryBufferExtend extend_x = MemoryBufferExtend::Clip, extend_y = MemoryBufferExtend::Clip; switch (m_wrappingType) { case CMP_NODE_WRAP_NONE: - // Intentionally empty, originalXPos and originalYPos have been set before + /* Intentionally empty, originalXPos and originalYPos have been set before. */ break; case CMP_NODE_WRAP_X: - // wrap only on the x-axis + /* Wrap only on the x-axis. */ nx = this->getWrappedOriginalXPos(x); extend_x = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_Y: - // wrap only on the y-axis + /* Wrap only on the y-axis. */ ny = this->getWrappedOriginalYPos(y); extend_y = MemoryBufferExtend::Repeat; break; case CMP_NODE_WRAP_XY: - // wrap on both + /* Wrap on both. */ nx = this->getWrappedOriginalXPos(x); ny = this->getWrappedOriginalYPos(y); extend_x = MemoryBufferExtend::Repeat; @@ -92,7 +92,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, newInput.ymax = input->ymax; if (ELEM(m_wrappingType, CMP_NODE_WRAP_X, CMP_NODE_WRAP_XY)) { - // wrap only on the x-axis if tile is wrapping + /* Wrap only on the x-axis if tile is wrapping. */ newInput.xmin = getWrappedOriginalXPos(input->xmin); newInput.xmax = roundf(getWrappedOriginalXPos(input->xmax)); if (newInput.xmin >= newInput.xmax) { @@ -101,7 +101,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, } } if (ELEM(m_wrappingType, CMP_NODE_WRAP_Y, CMP_NODE_WRAP_XY)) { - // wrap only on the y-axis if tile is wrapping + /* Wrap only on the y-axis if tile is wrapping. */ newInput.ymin = getWrappedOriginalYPos(input->ymin); newInput.ymax = roundf(getWrappedOriginalYPos(input->ymax)); if (newInput.ymin >= newInput.ymax) { diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index 749b1bba871..47dad17b482 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -85,7 +85,7 @@ extern "C" { // Get main depsgraph instance from context! /* Create new Depsgraph instance */ -// TODO: what args are needed here? What's the building-graph entry point? +/* TODO: what args are needed here? What's the building-graph entry point? */ Depsgraph *DEG_graph_new(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 8d1074d912f..22bce10937d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -648,9 +648,9 @@ void DepsgraphNodeBuilder::build_idproperties(IDProperty *id_property) void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection, Collection *collection) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; - const bool is_collection_restricted = (collection->flag & restrict_flag); + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; + const bool is_collection_restricted = (collection->flag & visibility_flag); const bool is_collection_visible = !is_collection_restricted && is_parent_collection_visible_; IDNode *id_node; if (built_map_.checkIsBuiltAndTag(collection)) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 29aa05b83db..b6e3f4fa935 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -60,11 +60,11 @@ namespace blender::deg { void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { - if (lc->collection->flag & restrict_flag) { + if (lc->collection->flag & visibility_flag) { continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index 24876049942..c37fb1b83a4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -61,11 +61,11 @@ namespace blender::deg { void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb) { - const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEWPORT : - COLLECTION_RESTRICT_RENDER; + const int visibility_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_HIDE_VIEWPORT : + COLLECTION_HIDE_RENDER; for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) { - if ((lc->collection->flag & restrict_flag)) { + if (lc->collection->flag & visibility_flag) { continue; } if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index bdabd67cc07..40e59875832 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -400,8 +400,8 @@ RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id) bool rna_prop_affects_parameters_node(const PointerRNA *ptr, const PropertyRNA *prop) { return prop != nullptr && RNA_property_is_idprop(prop) && - /* ID properties in the geometry nodes modifier don't affect that parameters node. Instead - they affect the modifier and therefore the geometry node directly. */ + /* ID properties in the geometry nodes modifier don't affect that parameters node. + * Instead they affect the modifier and therefore the geometry node directly. */ !RNA_struct_is_a(ptr->type, &RNA_NodesModifier); } diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 930d82fa225..257eb80ae0b 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -483,6 +483,13 @@ data_to_c_simple(engines/image/shaders/engine_image_vert.glsl SRC) list(APPEND INC ) +if(WITH_DRAW_DEBUG) + list(APPEND SRC + engines/select/select_debug_engine.c + ) + add_definitions(-DWITH_DRAW_DEBUG) +endif() + if(WITH_MOD_FLUID) list(APPEND INC ../../../intern/mantaflow/extern diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index a7ed6c777e8..3a2871249a2 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -132,6 +132,11 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata) DRW_shgroup_uniform_float_copy(grp, "normalSize", v3d->overlay.normals_length); DRW_shgroup_uniform_float_copy(grp, "alpha", backwire_opacity); DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tex); + DRW_shgroup_uniform_bool_copy(grp, + "isConstantScreenSizeNormals", + (flag & V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS) != 0); + DRW_shgroup_uniform_float_copy( + grp, "normalScreenSize", v3d->overlay.normals_constant_screen_size); } { /* Mesh Analysis Pass */ diff --git a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl index 007495f84e0..d370943db03 100644 --- a/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl +++ b/source/blender/draw/engines/overlay/shaders/edit_mesh_normal_vert.glsl @@ -1,5 +1,7 @@ uniform float normalSize; +uniform float normalScreenSize; +uniform bool isConstantScreenSizeNormals; uniform sampler2D depthTex; uniform float alpha = 1.0; @@ -49,11 +51,24 @@ void main() } vec3 n = normalize(normal_object_to_world(nor)); - vec3 world_pos = point_object_to_world(pos); if (gl_VertexID == 0) { - world_pos += n * normalSize; + if (isConstantScreenSizeNormals) { + bool is_persp = (ProjectionMatrix[3][3] == 0.0); + if (is_persp) { + float dist_fac = length(cameraPos - world_pos); + float cos_fac = dot(cameraForward, cameraVec(world_pos)); + world_pos += n * normalScreenSize * dist_fac * cos_fac * pixelFac * sizePixel; + } + else { + float frustrum_fac = mul_project_m4_v3_zfac(n) * sizePixel; + world_pos += n * normalScreenSize * frustrum_fac; + } + } + else { + world_pos += n * normalSize; + } } gl_Position = point_world_to_ndc(world_pos); diff --git a/source/blender/draw/engines/select/select_debug_engine.c b/source/blender/draw/engines/select/select_debug_engine.c new file mode 100644 index 00000000000..ded96be23f3 --- /dev/null +++ b/source/blender/draw/engines/select/select_debug_engine.c @@ -0,0 +1,135 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2019, Blender Foundation. + */ + +/** \file + * \ingroup draw_engine + * + * Engine for debuging the selection map drawing. + */ + +#include "DNA_ID.h" +#include "DNA_vec_types.h" + +#include "DRW_engine.h" +#include "DRW_select_buffer.h" + +#include "draw_cache.h" +#include "draw_manager.h" + +#include "select_engine.h" + +#define SELECT_DEBUG_ENGINE "SELECT_DEBUG_ENGINE" + +/* -------------------------------------------------------------------- */ +/** \name Structs and static variables + * \{ */ + +typedef struct SELECTIDDEBUG_PassList { + struct DRWPass *debug_pass; +} SELECTIDDEBUG_PassList; + +typedef struct SELECTIDDEBUG_Data { + void *engine_type; + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + SELECTIDDEBUG_PassList *psl; + DRWViewportEmptyList *stl; +} SELECTIDDEBUG_Data; + +static struct { + struct GPUShader *select_debug_sh; +} e_data = {{NULL}}; /* Engine data */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Functions + * \{ */ + +static void select_debug_engine_init(void *vedata) +{ + SELECTIDDEBUG_PassList *psl = ((SELECTIDDEBUG_Data *)vedata)->psl; + + if (!e_data.select_debug_sh) { + e_data.select_debug_sh = DRW_shader_create_fullscreen( + "uniform usampler2D image;" + "in vec4 uvcoordsvar;" + "out vec4 fragColor;" + "void main() {" + " uint px = texture(image, uvcoordsvar.xy).r;" + " fragColor = vec4(1.0, 1.0, 1.0, 0.0);" + " if (px != 0u) {" + " fragColor.a = 1.0;" + " px &= 0x3Fu;" + " fragColor.r = ((px >> 0) & 0x3u) / float(0x3u);" + " fragColor.g = ((px >> 2) & 0x3u) / float(0x3u);" + " fragColor.b = ((px >> 4) & 0x3u) / float(0x3u);" + " }" + "}\n", + NULL); + } + + psl->debug_pass = DRW_pass_create("Debug Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA); + GPUTexture *texture_u32 = DRW_engine_select_texture_get(); + if (texture_u32) { + DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.select_debug_sh, psl->debug_pass); + DRW_shgroup_uniform_texture(shgrp, "image", texture_u32); + DRW_shgroup_call_procedural_triangles(shgrp, NULL, 1); + } +} + +static void select_debug_draw_scene(void *vedata) +{ + SELECTIDDEBUG_PassList *psl = ((SELECTIDDEBUG_Data *)vedata)->psl; + DRW_draw_pass(psl->debug_pass); +} + +static void select_debug_engine_free(void) +{ + DRW_SHADER_FREE_SAFE(e_data.select_debug_sh); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Engine Type + * \{ */ + +static const DrawEngineDataSize select_debug_data_size = DRW_VIEWPORT_DATA_SIZE( + SELECTIDDEBUG_Data); + +DrawEngineType draw_engine_debug_select_type = { + NULL, + NULL, + N_("Select ID Debug"), + &select_debug_data_size, + &select_debug_engine_init, + &select_debug_engine_free, + NULL, + NULL, + NULL, + &select_debug_draw_scene, + NULL, + NULL, + NULL, + NULL, +}; + +/** \} */ + +#undef SELECT_DEBUG_ENGINE diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h index 2b35cf6bee5..d6192103178 100644 --- a/source/blender/draw/engines/select/select_engine.h +++ b/source/blender/draw/engines/select/select_engine.h @@ -22,9 +22,15 @@ #pragma once +/* select_engine.c */ extern DrawEngineType draw_engine_select_type; extern RenderEngineType DRW_engine_viewport_select_type; +#ifdef WITH_DRAW_DEBUG +/* select_debug_engine.c */ +extern DrawEngineType draw_engine_debug_select_type; +#endif + struct SELECTID_Context *DRW_select_engine_context_get(void); struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void); diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 453ef9c7f8e..e17bd7d9956 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -399,7 +399,7 @@ typedef struct WORKBENCH_ViewLayerData { /* inline helper functions */ BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd) { - if ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) { + if (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) { if (STUDIOLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) { return (wpd->studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS) != 0; } diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 336ccd40d5c..2a476ab41bb 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -552,6 +552,9 @@ bGPDstroke *DRW_cache_gpencil_sbuffer_stroke_data_get(Object *ob) gps->caps[0] = gps->caps[1] = GP_STROKE_CAP_ROUND; gps->runtime.stroke_start = 1; /* Add one for the adjacency index. */ copy_v4_v4(gps->vert_color_fill, gpd->runtime.vert_color_fill); + /* Caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + gpd->runtime.sbuffer_gps = gps; } return gpd->runtime.sbuffer_gps; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index a8cbe7b18b5..027ab8ce32b 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -512,7 +512,7 @@ static void drw_context_state_init(void) if (DST.draw_ctx.object_mode & OB_MODE_POSE) { DST.draw_ctx.object_pose = DST.draw_ctx.obact; } - else if ((DST.draw_ctx.object_mode & OB_MODE_ALL_WEIGHT_PAINT)) { + else if (DST.draw_ctx.object_mode & OB_MODE_ALL_WEIGHT_PAINT) { DST.draw_ctx.object_pose = BKE_object_pose_armature_get(DST.draw_ctx.obact); } else { @@ -1281,6 +1281,12 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer), use_drw_engine(&draw_engine_gpencil_type); } drw_engines_enable_overlays(); + +#ifdef WITH_DRAW_DEBUG + if (G.debug_value == 31) { + use_drw_engine(&draw_engine_debug_select_type); + } +#endif } static void drw_engines_disable(void) @@ -2940,6 +2946,9 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_overlay_type); DRW_engine_register(&draw_engine_select_type); DRW_engine_register(&draw_engine_basic_type); +#ifdef WITH_DRAW_DEBUG + DRW_engine_register(&draw_engine_debug_select_type); +#endif DRW_engine_register(&draw_engine_image_type); DRW_engine_register(DRW_engine_viewport_external_type.draw_engine); diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 2126385a352..af331c86a8b 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -1533,13 +1533,6 @@ static void draw_frustum_boundbox_calc(const float (*viewinv)[4], projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far); - if (is_persp) { - left *= near; - right *= near; - bottom *= near; - top *= near; - } - r_bbox->vec[0][2] = r_bbox->vec[3][2] = r_bbox->vec[7][2] = r_bbox->vec[4][2] = -near; r_bbox->vec[0][0] = r_bbox->vec[3][0] = left; r_bbox->vec[4][0] = r_bbox->vec[7][0] = right; diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c index 7f7696d485c..22356a3c57b 100644 --- a/source/blender/draw/intern/draw_manager_exec.c +++ b/source/blender/draw/intern/draw_manager_exec.c @@ -283,11 +283,11 @@ void DRW_state_reset_ex(DRWState state) static void drw_state_validate(void) { /* Cannot write to stencil buffer without stencil test. */ - if ((DST.state & DRW_STATE_WRITE_STENCIL_ENABLED)) { + if (DST.state & DRW_STATE_WRITE_STENCIL_ENABLED) { BLI_assert(DST.state & DRW_STATE_STENCIL_TEST_ENABLED); } /* Cannot write to depth buffer without depth test. */ - if ((DST.state & DRW_STATE_WRITE_DEPTH)) { + if (DST.state & DRW_STATE_WRITE_DEPTH) { BLI_assert(DST.state & DRW_STATE_DEPTH_TEST_ENABLED); } } diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 6469c47ab11..735f3b86924 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -522,6 +522,7 @@ static bool find_prev_next_keyframes(struct bContext *C, int *r_nextfra, int *r_ mask_to_keylist(&ads, masklay, keylist); } + /* TODO(jbakker): Keylists are ordered, no need to do any searching at all. */ /* find matching keyframe in the right direction */ do { aknext = ED_keylist_find_next(keylist, cfranext); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index b2d387ea898..020518b5813 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1892,7 +1892,7 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { continue; } } @@ -3098,7 +3098,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_m } /* outliner restrict-flag */ - if (ob->restrictflag & OB_RESTRICT_VIEWPORT) { + if (ob->visibility_flag & OB_HIDE_VIEWPORT) { return false; } } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index cfcea950955..0de3f429bc7 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -445,7 +445,7 @@ static void draw_marker_name(const uchar *text_color, if (marker->camera) { Object *camera = marker->camera; name = camera->id.name + 2; - if (camera->restrictflag & OB_RESTRICT_RENDER) { + if (camera->visibility_flag & OB_HIDE_RENDER) { final_text_color[3] = 100; } } diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c index 2a3ae35aab0..d976f5f72ad 100644 --- a/source/blender/editors/animation/anim_motion_paths.c +++ b/source/blender/editors/animation/anim_motion_paths.c @@ -234,6 +234,7 @@ static void motionpath_get_global_framerange(ListBase *targets, int *r_sfra, int } } +/* TODO(jbakker): Remove complexity, keylists are ordered. */ static int motionpath_get_prev_keyframe(MPathTarget *mpt, struct AnimKeylist *keylist, int current_frame) diff --git a/source/blender/editors/animation/time_scrub_ui.c b/source/blender/editors/animation/time_scrub_ui.c index 182e61e53b6..8aeb6a57124 100644 --- a/source/blender/editors/animation/time_scrub_ui.c +++ b/source/blender/editors/animation/time_scrub_ui.c @@ -244,8 +244,8 @@ void ED_time_scrub_channel_search_draw(const bContext *C, ARegion *region, bDope UI_block_align_end(block); UI_block_layout_resolve(block, NULL, NULL); - /* Make sure the events are consumed from the search and dont reach other UI blocks since this is - * drawn on top of animchannels. */ + /* Make sure the events are consumed from the search and don't reach other UI blocks since this + * is drawn on top of animation-channels. */ UI_block_flag_enable(block, UI_BLOCK_CLIP_EVENTS); UI_block_bounds_set_normal(block, 0); UI_block_end(C, block); diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 1118e84ef4f..3798ca308ed 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -908,7 +908,7 @@ static int pose_paste_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); /* Recalculate paths if any of the bones have paths... */ - if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { ED_pose_recalculate_paths(C, scene, ob, POSE_PATH_CALC_RANGE_FULL); } @@ -1219,7 +1219,7 @@ static int pose_clear_transform_generic_exec(bContext *C, ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); /* now recalculate paths */ - if ((ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + if (ob_iter->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) { ED_pose_recalculate_paths(C, scene, ob_iter, POSE_PATH_CALC_RANGE_FULL); } diff --git a/source/blender/editors/asset/intern/asset_ops.cc b/source/blender/editors/asset/intern/asset_ops.cc index f18cf9712db..579803f7ff7 100644 --- a/source/blender/editors/asset/intern/asset_ops.cc +++ b/source/blender/editors/asset/intern/asset_ops.cc @@ -110,7 +110,7 @@ void AssetMarkHelper::reportResults(ReportList &reports) const { /* User feedback on failure. */ if (!wasSuccessful()) { - if ((stats.tot_already_asset > 0)) { + if (stats.tot_already_asset > 0) { BKE_report(&reports, RPT_ERROR, "Selected data-blocks are already assets (or do not support use as assets)"); diff --git a/source/blender/editors/curve/editcurve_add.c b/source/blender/editors/curve/editcurve_add.c index 2be55accd3a..d1fe162fc4a 100644 --- a/source/blender/editors/curve/editcurve_add.c +++ b/source/blender/editors/curve/editcurve_add.c @@ -431,7 +431,7 @@ Nurb *ED_curve_add_nurbs_primitive( if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { + else if (U.flag & USER_ADD_VIEWALIGNED) { ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); } else { @@ -466,7 +466,7 @@ Nurb *ED_curve_add_nurbs_primitive( if (newob && (U.flag & USER_ADD_VIEWALIGNED) == 0) { ed_editnurb_spin(umat, NULL, obedit, tmp_vec, tmp_cent); } - else if ((U.flag & USER_ADD_VIEWALIGNED)) { + else if (U.flag & USER_ADD_VIEWALIGNED) { ed_editnurb_spin(viewmat, NULL, obedit, zvec, mat[3]); } else { diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index beb22d43930..c4916b9182f 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -583,6 +583,9 @@ set(ICON_NAMES uv_facesel uv_islandsel uv_sync_select + gp_caps_flat + gp_caps_round + fixed_size transform_origins gizmo orientation_cursor diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index d6f6dbb2b10..aaea1c0ddaf 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -996,6 +996,9 @@ static void gpencil_stroke_newfrombuffer(tGPsdata *p) gps->inittime = p->inittime; gps->uv_scale = 1.0f; + /* Set stroke caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + /* allocate enough memory for a continuous array for storage points */ const int subdivide = brush->gpencil_settings->draw_subdivide; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index cf49aefe2ea..27374f21b66 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -335,6 +335,9 @@ static void gpencil_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) gps->uv_scale = 1.0f; gps->inittime = 0.0f; + /* Set stroke caps. */ + gps->caps[0] = gps->caps[1] = brush->gpencil_settings->caps_type; + /* Apply the vertex color to fill. */ ED_gpencil_fill_vertex_color_set(ts, brush, gps); diff --git a/source/blender/editors/include/ED_keyframes_keylist.h b/source/blender/editors/include/ED_keyframes_keylist.h index e7d1b5d4363..d3690fa3aa0 100644 --- a/source/blender/editors/include/ED_keyframes_keylist.h +++ b/source/blender/editors/include/ED_keyframes_keylist.h @@ -190,7 +190,9 @@ void gpencil_to_keylist(struct bDopeSheet *ads, /* Grease Pencil Layer */ void gpl_to_keylist(struct bDopeSheet *ads, struct bGPDlayer *gpl, struct AnimKeylist *keylist); /* Mask */ -void mask_to_keylist(struct bDopeSheet *ads, struct MaskLayer *masklay, struct AnimKeylist *keylist); +void mask_to_keylist(struct bDopeSheet *ads, + struct MaskLayer *masklay, + struct AnimKeylist *keylist); /* ActKeyColumn API ---------------- */ /* Comparator callback used for ActKeyColumns and cframe float-value pointer */ diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 888dcd9d428..3141c8f707b 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -53,6 +53,7 @@ struct uiLayout; struct wmKeyConfig; struct wmOperator; struct wmOperatorType; +struct wmEvent; /* object_edit.c */ /* context.object */ @@ -199,6 +200,9 @@ void ED_object_parent(struct Object *ob, struct Object *parent, const int type, const char *substr); +char *ED_object_ot_drop_named_material_tooltip(struct bContext *C, + struct PointerRNA *properties, + const struct wmEvent *event); /* bitflags for enter/exit editmode */ enum { diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 7ccdc49d291..1708c3598b1 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -713,9 +713,9 @@ DEF_ICON(UV_EDGESEL) DEF_ICON(UV_FACESEL) DEF_ICON(UV_ISLANDSEL) DEF_ICON(UV_SYNC_SELECT) -DEF_ICON_BLANK(240) -DEF_ICON_BLANK(241) -DEF_ICON_BLANK(242) +DEF_ICON(GP_CAPS_FLAT) +DEF_ICON(GP_CAPS_ROUND) +DEF_ICON(FIXED_SIZE) DEF_ICON(TRANSFORM_ORIGINS) DEF_ICON(GIZMO) DEF_ICON(ORIENTATION_CURSOR) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d3a3df98d99..fd75be5b847 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -6173,7 +6173,7 @@ int UI_but_return_value_get(uiBut *but) void UI_but_drag_set_id(uiBut *but, ID *id) { but->dragtype = WM_DRAG_ID; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6200,7 +6200,7 @@ void UI_but_drag_set_asset(uiBut *but, but->dragtype = WM_DRAG_ASSET; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); } but->dragpoin = asset_drag; @@ -6212,7 +6212,7 @@ void UI_but_drag_set_asset(uiBut *but, void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr) { but->dragtype = WM_DRAG_RNA; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6222,7 +6222,7 @@ void UI_but_drag_set_rna(uiBut *but, PointerRNA *ptr) void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free) { but->dragtype = WM_DRAG_PATH; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6235,7 +6235,7 @@ void UI_but_drag_set_path(uiBut *but, const char *path, const bool use_free) void UI_but_drag_set_name(uiBut *but, const char *name) { but->dragtype = WM_DRAG_NAME; - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } @@ -6253,7 +6253,7 @@ void UI_but_drag_set_image( { but->dragtype = WM_DRAG_PATH; ui_def_but_icon(but, icon, 0); /* no flag UI_HAS_ICON, so icon doesn't draw in button */ - if ((but->dragflag & UI_BUT_DRAGPOIN_FREE)) { + if (but->dragflag & UI_BUT_DRAGPOIN_FREE) { WM_drag_data_free(but->dragtype, but->dragpoin); but->dragflag &= ~UI_BUT_DRAGPOIN_FREE; } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index bfc03a95949..d920ebbe11a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6779,7 +6779,7 @@ static bool ui_numedit_but_HSVCIRCLE(uiBut *but, ui_color_picker_hsv_to_rgb(hsv, rgb); - if ((cpicker->use_luminosity_lock)) { + if (cpicker->use_luminosity_lock) { if (!is_zero_v3(rgb)) { normalize_v3_length(rgb, cpicker->luminosity_lock_value); } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 6755eded05c..2d59bfb92c8 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1014,7 +1014,7 @@ static void init_iconfile_list(struct ListBase *list) int index = 1; for (int i = 0; i < totfile; i++) { - if ((dir[i].type & S_IFREG)) { + if (dir[i].type & S_IFREG) { const char *filename = dir[i].relname; if (BLI_path_extension_check(filename, ".png")) { diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index ad71f4d9da7..110f4541e8f 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -521,7 +521,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) MaskLayer *mask_layer = BKE_mask_layer_active(mask); - if (mask_layer && mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer && mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { mask_layer = NULL; } diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c index de8ea8e21eb..22232e9c87e 100644 --- a/source/blender/editors/mask/mask_draw.c +++ b/source/blender/editors/mask/mask_draw.c @@ -191,7 +191,7 @@ static void draw_spline_points(const bContext *C, const char draw_type) { const bool is_spline_sel = (spline->flag & SELECT) && - (mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0; + (mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; uchar rgb_spline[4]; @@ -529,7 +529,7 @@ static void draw_spline_curve(const bContext *C, uchar rgb_tmp[4]; const bool is_spline_sel = (spline->flag & SELECT) && - (mask_layer->restrictflag & MASK_RESTRICT_SELECT) == 0; + (mask_layer->visibility_flag & MASK_HIDE_SELECT) == 0; const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0; const bool is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0; @@ -604,7 +604,7 @@ static void draw_mask_layers(const bContext *C, mask_layer = mask_layer->next, i++) { const bool is_active = (i == mask->masklay_act); - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -613,7 +613,7 @@ static void draw_mask_layers(const bContext *C, /* draw curve itself first... */ draw_spline_curve(C, mask_layer, spline, draw_flag, draw_type, is_active, width, height); - if (!(mask_layer->restrictflag & MASK_RESTRICT_SELECT)) { + if (!(mask_layer->visibility_flag & MASK_HIDE_SELECT)) { /* ...and then handles over the curve so they're nicely visible */ draw_spline_points(C, mask_layer, spline, draw_flag, draw_type); } diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 6fa7457ce14..fd5925bbd0c 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -287,7 +287,7 @@ static bool spline_under_mouse_get(const bContext *C, } for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } @@ -1322,7 +1322,7 @@ static int cyclic_toggle_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1403,7 +1403,7 @@ static int delete_exec(bContext *C, wmOperator *UNUSED(op)) MaskSpline *spline; int mask_layer_shape_ofs = 0; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1523,7 +1523,7 @@ static int mask_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { bool changed_layer = false; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1581,7 +1581,7 @@ static int mask_normals_make_consistent_exec(bContext *C, wmOperator *UNUSED(op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { bool changed_layer = false; - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1642,7 +1642,7 @@ static int set_handle_type_exec(bContext *C, wmOperator *op) bool changed = false; LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -1724,9 +1724,9 @@ static int mask_hide_view_clear_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & OB_RESTRICT_VIEWPORT) { + if (mask_layer->visibility_flag & OB_HIDE_VIEWPORT) { ED_mask_layer_select_set(mask_layer, select); - mask_layer->restrictflag &= ~OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag &= ~OB_HIDE_VIEWPORT; changed = true; } } @@ -1766,7 +1766,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } @@ -1774,7 +1774,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) if (ED_mask_layer_select_check(mask_layer)) { ED_mask_layer_select_set(mask_layer, false); - mask_layer->restrictflag |= OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag |= OB_HIDE_VIEWPORT; changed = true; if (mask_layer == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); @@ -1783,7 +1783,7 @@ static int mask_hide_view_set_exec(bContext *C, wmOperator *op) } else { if (!ED_mask_layer_select_check(mask_layer)) { - mask_layer->restrictflag |= OB_RESTRICT_VIEWPORT; + mask_layer->visibility_flag |= OB_HIDE_VIEWPORT; changed = true; if (mask_layer == BKE_mask_layer_active(mask)) { BKE_mask_layer_active_set(mask, NULL); @@ -1825,7 +1825,7 @@ static int mask_feather_weight_clear_exec(bContext *C, wmOperator *UNUSED(op)) bool changed = false; LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_SELECT | MASK_RESTRICT_VIEW)) { + if (mask_layer->visibility_flag & (MASK_HIDE_SELECT | MASK_HIDE_VIEW)) { continue; } diff --git a/source/blender/editors/mask/mask_query.c b/source/blender/editors/mask/mask_query.c index cd51026d20c..e66c4e45e27 100644 --- a/source/blender/editors/mask/mask_query.c +++ b/source/blender/editors/mask/mask_query.c @@ -85,7 +85,7 @@ bool ED_mask_find_nearest_diff_point(const bContext *C, *mask_layer_eval = mask_eval->masklayers.first; mask_layer_orig != NULL; mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -245,7 +245,7 @@ MaskSplinePoint *ED_mask_point_find_nearest(const bContext *C, mask_layer_orig != NULL; mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next) { - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -409,7 +409,7 @@ bool ED_mask_feather_find_nearest(const bContext *C, int i, tot_feather_point; float(*feather_points)[2], (*fp)[2]; - if (mask_layer_orig->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -638,7 +638,7 @@ bool ED_mask_selected_minmax(const bContext *C, INIT_MINMAX2(min, max); for (MaskLayer *mask_layer = mask_eval->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } for (MaskSpline *spline = mask_layer->splines.first; spline != NULL; spline = spline->next) { diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 971e1c948c9..9c4740b3087 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -46,7 +46,7 @@ static int mask_parent_clear_exec(bContext *C, wmOperator *UNUSED(op)) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -138,7 +138,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) } LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index 3bb05a27c54..6a1be8dcef3 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -68,7 +68,7 @@ bool ED_mask_spline_select_check(const MaskSpline *spline) bool ED_mask_layer_select_check(const MaskLayer *mask_layer) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { return false; } @@ -110,7 +110,7 @@ void ED_mask_spline_select_set(MaskSpline *spline, const bool do_select) void ED_mask_layer_select_set(MaskLayer *mask_layer, const bool do_select) { - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { if (do_select == true) { return; } @@ -134,7 +134,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -142,7 +142,7 @@ void ED_mask_select_toggle_all(Mask *mask, int action) /* we don't have generic functions for this, its restricted to this operator * if one day we need to re-use such functionality, they can be split out */ - if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) { + if (mask_layer->visibility_flag & MASK_HIDE_SELECT) { continue; } LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { @@ -164,9 +164,9 @@ void ED_mask_select_flush_all(Mask *mask) LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { spline->flag &= ~SELECT; - /* intentionally _dont_ do this in the mask layer loop - * so we clear flags on all splines */ - if (mask_layer->restrictflag & MASK_RESTRICT_VIEW) { + /* Intentionally *don't* do this in the mask layer loop + * so we clear flags on all splines. */ + if (mask_layer->visibility_flag & MASK_HIDE_VIEW) { continue; } @@ -465,7 +465,7 @@ static int box_select_exec(bContext *C, wmOperator *op) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -550,7 +550,7 @@ static bool do_lasso_select_mask(bContext *C, /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -691,7 +691,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -820,7 +820,7 @@ static int mask_select_linked_exec(bContext *C, wmOperator *UNUSED(op)) /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -870,7 +870,7 @@ static int mask_select_more_less(bContext *C, bool more) Mask *mask = CTX_data_edit_mask(C); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c index a5a3489c143..6620096c39a 100644 --- a/source/blender/editors/mask/mask_shapekey.c +++ b/source/blender/editors/mask/mask_shapekey.c @@ -144,7 +144,7 @@ static int mask_shape_key_feather_reset_exec(bContext *C, wmOperator *UNUSED(op) LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -238,7 +238,7 @@ static int mask_shape_key_rekey_exec(bContext *C, wmOperator *op) const bool do_location = RNA_boolean_get(op->ptr, "location"); LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/mesh/editmesh_preselect_edgering.c b/source/blender/editors/mesh/editmesh_preselect_edgering.c index 43e36957dc9..c58f29917b1 100644 --- a/source/blender/editors/mesh/editmesh_preselect_edgering.c +++ b/source/blender/editors/mesh/editmesh_preselect_edgering.c @@ -20,6 +20,8 @@ #include "MEM_guardedalloc.h" +#include "DNA_userdef_types.h" + #include "BLI_math.h" #include "BLI_stack.h" @@ -160,16 +162,21 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } GPU_depth_test(GPU_DEPTH_NONE); + GPU_blend(GPU_BLEND_ALPHA); GPU_matrix_push(); GPU_matrix_mul(matrix); uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); - immUniformThemeColor3(TH_GIZMO_PRIMARY); - if (psel->edges_len > 0) { + float viewport[4]; + GPU_viewport_size_get_f(viewport); + + immBindBuiltinProgram(GPU_SHADER_3D_POLYLINE_UNIFORM_COLOR); + immUniform2fv("viewportSize", &viewport[2]); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + immUniform1f("lineWidth", U.pixelsize); immBegin(GPU_PRIM_LINES, psel->edges_len * 2); for (int i = 0; i < psel->edges_len; i++) { @@ -178,10 +185,18 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); } if (psel->verts_len > 0) { - GPU_point_size(3.0f); + GPU_program_point_size(true); + immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + immUniformThemeColor3(TH_GIZMO_PRIMARY); + + /* Same size as an edit mode vertex */ + immUniform1f("size", + 2.0 * U.pixelsize * + (max_ff(1.0f, UI_GetThemeValuef(TH_VERTEX_SIZE) * (float)M_SQRT2 / 2.0f))); immBegin(GPU_PRIM_POINTS, psel->verts_len); @@ -190,14 +205,15 @@ void EDBM_preselect_edgering_draw(struct EditMesh_PreSelEdgeRing *psel, const fl } immEnd(); + immUnbindProgram(); + GPU_program_point_size(false); } - immUnbindProgram(); - GPU_matrix_pop(); /* Reset default */ GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + GPU_blend(GPU_BLEND_NONE); } static void view3d_preselect_mesh_edgering_update_verts_from_edge( diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 215ce0185f1..1b6643da1aa 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -2748,9 +2748,6 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot) static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) { - BMIter fiter; - BMFace *f; - int tot_invalid = 0; int tot_unselected = 0; ViewLayer *view_layer = CTX_data_view_layer(C); @@ -2777,22 +2774,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) if (em->bm->totvertsel == 0) { tot_unselected++; - tot_invalid++; - continue; - } - - bool is_invalid = false; - /* Check if select faces are triangles. */ - BM_ITER_MESH (f, &fiter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(f, BM_ELEM_SELECT)) { - if (f->len > 4) { - tot_invalid++; - is_invalid = true; - break; - } - } - } - if (is_invalid) { continue; } @@ -2841,10 +2822,6 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_WARNING, "No selected vertex"); return OPERATOR_CANCELLED; } - if (tot_invalid == objects_len) { - BKE_report(op->reports, RPT_WARNING, "Selected faces must be triangles or quads"); - return OPERATOR_CANCELLED; - } return OPERATOR_FINISHED; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 8ae74fbfafa..f98f3242163 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -3530,7 +3530,7 @@ static int object_add_named_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT; + basen->object->visibility_flag &= ~OB_HIDE_VIEWPORT; int mval[2]; if (object_add_drop_xy_get(C, op, &mval)) { diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 43358f51396..0a2df655395 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -1311,7 +1311,7 @@ static int bake(const BakeAPIRender *bkr, } else { ob_cage_eval = DEG_get_evaluated_object(depsgraph, ob_cage); - ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); } } @@ -1411,7 +1411,7 @@ static int bake(const BakeAPIRender *bkr, /* initialize highpoly_data */ highpoly[i].ob = ob_iter; highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter); - highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER; + highpoly[i].ob_eval->visibility_flag &= ~OB_HIDE_RENDER; highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); highpoly[i].me = BKE_mesh_new_from_object(NULL, highpoly[i].ob_eval, false, false); @@ -1427,10 +1427,10 @@ static int bake(const BakeAPIRender *bkr, BLI_assert(i == tot_highpoly); if (ob_cage != NULL) { - ob_cage_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_cage_eval->visibility_flag |= OB_HIDE_RENDER; ob_cage_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); } - ob_low_eval->restrictflag |= OB_RESTRICT_RENDER; + ob_low_eval->visibility_flag |= OB_HIDE_RENDER; ob_low_eval->base_flag &= ~(BASE_VISIBLE_DEPSGRAPH | BASE_ENABLED_RENDER); /* populate the pixel arrays with the corresponding face data for each high poly object */ @@ -1473,7 +1473,7 @@ static int bake(const BakeAPIRender *bkr, } else { /* If low poly is not renderable it should have failed long ago. */ - BLI_assert((ob_low_eval->restrictflag & OB_RESTRICT_RENDER) == 0); + BLI_assert((ob_low_eval->visibility_flag & OB_HIDE_RENDER) == 0); if (RE_bake_has_engine(re)) { ok = RE_bake_engine(re, diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 4970338973d..3d0213f1830 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -432,11 +432,8 @@ static void test_constraint( * free the points array and request a rebind... */ if ((data->points == NULL) || (data->numpoints != data->chainlen + 1)) { - /* free the points array */ - if (data->points) { - MEM_freeN(data->points); - data->points = NULL; - } + MEM_SAFE_FREE(data->points); + data->numpoints = 0; /* clear the bound flag, forcing a rebind next time this is evaluated */ data->flag &= ~CONSTRAINT_SPLINEIK_BOUND; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 6108691b2f1..5697c2c973d 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -384,7 +384,7 @@ static int object_hide_collection_exec(bContext *C, wmOperator *op) DEG_id_tag_update(&scene->id, ID_RECALC_BASE_FLAGS); if (v3d->flag & V3D_LOCAL_COLLECTIONS) { - if (lc->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) { + if (lc->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) { return OPERATOR_CANCELLED; } if (toggle) { @@ -421,7 +421,7 @@ void ED_collection_hide_menu_draw(const bContext *C, uiLayout *layout) continue; } - if (lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) { + if (lc->collection->flag & COLLECTION_HIDE_VIEWPORT) { continue; } @@ -926,7 +926,7 @@ static bool editmode_toggle_poll(bContext *C) } /* if hidden but in edit mode, we still display */ - if ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { + if ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)) { return false; } diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f576c0c8517..92d0deb49d0 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2723,6 +2723,35 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) /** \name Drop Named Material on Object Operator * \{ */ +char *ED_object_ot_drop_named_material_tooltip(bContext *C, + PointerRNA *properties, + const wmEvent *event) +{ + Base *base = ED_view3d_give_base_under_cursor(C, event->mval); + + char name[MAX_ID_NAME - 2]; + RNA_string_get(properties, "name", name); + + if (base == NULL) { + return BLI_strdup(""); + } + + Object *ob = base->object; + int active_mat_slot = max_ii(ob->actcol, 1); + Material *prev_mat = BKE_object_material_get(ob, active_mat_slot); + + char *result; + if (prev_mat) { + const char *tooltip = TIP_("Drop %s on %s (slot %d, replacing %s)."); + result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot, prev_mat->id.name + 2); + } + else { + const char *tooltip = TIP_("Drop %s on %s (slot %d)."); + result = BLI_sprintfN(tooltip, name, ob->id.name + 2, active_mat_slot); + } + return result; +} + static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index fe1e850dcba..bd4c83c107e 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -273,10 +273,10 @@ static void switch_preview_collection_visibilty(ViewLayer *view_layer, const ePr for (lc = lc->layer_collections.first; lc; lc = lc->next) { if (STREQ(lc->collection->id.name + 2, collection_name)) { - lc->collection->flag &= ~COLLECTION_RESTRICT_RENDER; + lc->collection->flag &= ~COLLECTION_HIDE_RENDER; } else { - lc->collection->flag |= COLLECTION_RESTRICT_RENDER; + lc->collection->flag |= COLLECTION_HIDE_RENDER; } } } @@ -288,10 +288,10 @@ static void switch_preview_floor_visibility(ViewLayer *view_layer, LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { if (STREQ(base->object->id.name + 2, "Floor")) { if (pr_method == PR_ICON_RENDER) { - base->object->restrictflag |= OB_RESTRICT_RENDER; + base->object->visibility_flag |= OB_HIDE_RENDER; } else { - base->object->restrictflag &= ~OB_RESTRICT_RENDER; + base->object->visibility_flag &= ~OB_HIDE_RENDER; } } } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 107466a8a0b..d8cef889a40 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -381,7 +381,7 @@ bool ED_operator_console_active(bContext *C) static bool ed_object_hidden(const Object *ob) { /* if hidden but in edit mode, we still display, can happen with animation */ - return ((ob->restrictflag & OB_RESTRICT_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); + return ((ob->visibility_flag & OB_HIDE_VIEWPORT) && !(ob->mode & OB_MODE_EDIT)); } bool ED_operator_object_active(bContext *C) @@ -2906,7 +2906,7 @@ static void areas_do_frame_follow(bContext *C, bool middle) LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { /* do follow here if editor type supports it */ - if ((screen_ctx->redraws_flag & TIME_FOLLOW)) { + if (screen_ctx->redraws_flag & TIME_FOLLOW) { if ((region->regiontype == RGN_TYPE_WINDOW && ELEM(area->spacetype, SPACE_SEQ, SPACE_GRAPH, SPACE_ACTION, SPACE_NLA)) || (area->spacetype == SPACE_CLIP && region->regiontype == RGN_TYPE_PREVIEW)) { diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 83388c1aef2..8264affc465 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -7887,6 +7887,9 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f sculpt_update_cache_invariants(C, sd, ss, op, mouse); + SculptCursorGeometryInfo sgi; + SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false); + SCULPT_undo_push_begin(ob, sculpt_tool_name(sd)); return true; diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index eabbfe43e03..38165b7622f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -88,7 +88,7 @@ void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); /* Do not modify corner vertices. */ - if (neighbor_count <= 2) { + if (neighbor_count <= 2 && is_boundary) { copy_v3_v3(result, SCULPT_vertex_co_get(ss, index)); return; } diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 771e0e1e47b..e5ca5e4defd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -190,7 +190,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em, /* This is supposed to happen only if "Pin Edges" is on, * since we have initialization on stroke start. * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) { + if (sculptdata->uv[i].flag & MARK_BOUNDARY) { continue; } @@ -268,7 +268,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, /* This is supposed to happen only if "Pin Edges" is on, * since we have initialization on stroke start. * If ever uv brushes get their own mode we should check for toolsettings option too. */ - if ((sculptdata->uv[i].flag & MARK_BOUNDARY)) { + if (sculptdata->uv[i].flag & MARK_BOUNDARY) { continue; } diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 7194e78e940..23dd290e13f 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -492,7 +492,7 @@ static bool mask_has_selection(const bContext *C) } LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { - if (mask_layer->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) { diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 2d1151c8f4d..776bb0b3bb7 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -969,7 +969,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) BLI_join_dirfile(name, sizeof(name), xdg_runtime_dir, "gvfs/"); const uint dir_len = BLI_filelist_dir_contents(name, &dir); for (uint i = 0; i < dir_len; i++) { - if ((dir[i].type & S_IFDIR)) { + if (dir[i].type & S_IFDIR) { const char *dirname = dir[i].relname; if (dirname[0] != '.') { /* Dir names contain a lot of unwanted text. diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 6538f5709b7..1ec1afe86fc 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -1263,22 +1263,22 @@ static bool collection_flag_poll(bContext *C, bool clear, int flag) static bool collection_enable_poll(bContext *C) { - return collection_flag_poll(C, true, COLLECTION_RESTRICT_VIEWPORT); + return collection_flag_poll(C, true, COLLECTION_HIDE_VIEWPORT); } static bool collection_disable_poll(bContext *C) { - return collection_flag_poll(C, false, COLLECTION_RESTRICT_VIEWPORT); + return collection_flag_poll(C, false, COLLECTION_HIDE_VIEWPORT); } static bool collection_enable_render_poll(bContext *C) { - return collection_flag_poll(C, true, COLLECTION_RESTRICT_RENDER); + return collection_flag_poll(C, true, COLLECTION_HIDE_RENDER); } static bool collection_disable_render_poll(bContext *C) { - return collection_flag_poll(C, false, COLLECTION_RESTRICT_RENDER); + return collection_flag_poll(C, false, COLLECTION_HIDE_RENDER); } static int collection_flag_exec(bContext *C, wmOperator *op) @@ -1288,7 +1288,7 @@ static int collection_flag_exec(bContext *C, wmOperator *op) SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); const bool is_render = strstr(op->idname, "render"); const bool clear = strstr(op->idname, "show") || strstr(op->idname, "enable"); - int flag = is_render ? COLLECTION_RESTRICT_RENDER : COLLECTION_RESTRICT_VIEWPORT; + int flag = is_render ? COLLECTION_HIDE_RENDER : COLLECTION_HIDE_VIEWPORT; struct CollectionEditData data = { .scene = scene, .space_outliner = space_outliner, diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c index 36b2966dc43..a82f516b125 100644 --- a/source/blender/editors/space_outliner/outliner_dragdrop.c +++ b/source/blender/editors/space_outliner/outliner_dragdrop.c @@ -868,7 +868,8 @@ static bool datastack_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) static char *datastack_drop_tooltip(bContext *UNUSED(C), wmDrag *drag, - const wmEvent *UNUSED(event)) + const wmEvent *UNUSED(event), + struct wmDropBox *UNUSED(drop)) { StackDropData *drop_data = drag->poin; switch (drop_data->drop_action) { @@ -1103,10 +1104,6 @@ static bool collection_drop_init(bContext *C, if (ID_IS_LINKED(to_collection)) { return false; } - /* Currently this should not be allowed (might be supported in the future though...). */ - if (ID_IS_OVERRIDE_LIBRARY(to_collection)) { - return false; - } /* Get drag datablocks. */ if (drag->type != WM_DRAG_ID) { @@ -1130,6 +1127,11 @@ static bool collection_drop_init(bContext *C, from_collection = NULL; } + /* Currently this should not be allowed, cannot edit items in an override of a Collection. */ + if (from_collection != NULL && ID_IS_OVERRIDE_LIBRARY(from_collection)) { + return false; + } + /* Get collections. */ if (GS(id->name) == ID_GR) { if (id == &to_collection->id) { @@ -1140,6 +1142,12 @@ static bool collection_drop_init(bContext *C, insert_type = TE_INSERT_INTO; } + /* Currently this should not be allowed, cannot edit items in an override of a Collection. */ + if (ID_IS_OVERRIDE_LIBRARY(to_collection) && + !ELEM(insert_type, TE_INSERT_AFTER, TE_INSERT_BEFORE)) { + return false; + } + data->from = from_collection; data->to = to_collection; data->te = te; @@ -1191,7 +1199,10 @@ static bool collection_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event return false; } -static char *collection_drop_tooltip(bContext *C, wmDrag *drag, const wmEvent *event) +static char *collection_drop_tooltip(bContext *C, + wmDrag *drag, + const wmEvent *event, + wmDropBox *UNUSED(drop)) { CollectionDrop data; if (!event->shift && collection_drop_init(C, drag, event, &data)) { diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 3edb12c5503..e3aec572bd3 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -845,8 +845,20 @@ static void id_override_library_create_fn(bContext *C, if (!ID_IS_LINKED(te->store_elem->id)) { break; } + /* If we'd need to override that arent ID, but it is not overridable, abort. */ + if (!ID_IS_OVERRIDABLE_LIBRARY(te->store_elem->id)) { + BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false); + BKE_reportf(reports, + RPT_WARNING, + "Could not create library override from data-block '%s', one of its parents " + "is not overridable ('%s')", + id_root->name, + te->store_elem->id->name); + return; + } te->store_elem->id->tag |= LIB_TAG_DOIT; } + success = BKE_lib_override_library_create( bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, id_reference, NULL); } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 3f8dea8b533..0472e1264ce 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1139,7 +1139,7 @@ static void draw_seq_strip(const bContext *C, } /* Draw strip offsets when flag is enabled or during "solo preview". */ - if ((sseq->flag & SEQ_SHOW_STRIP_OVERLAY)) { + if (sseq->flag & SEQ_SHOW_STRIP_OVERLAY) { if (!is_single_image && (seq->startofs || seq->endofs) && pixely > 0) { if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) { draw_sequence_extensions_overlay(scene, seq, pos, pixely); diff --git a/source/blender/editors/space_sequencer/sequencer_proxy.c b/source/blender/editors/space_sequencer/sequencer_proxy.c index 2dcc2d389d9..16d14b5fa72 100644 --- a/source/blender/editors/space_sequencer/sequencer_proxy.c +++ b/source/blender/editors/space_sequencer/sequencer_proxy.c @@ -131,7 +131,7 @@ static int sequencer_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list"); LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { ListBase queue = {NULL, NULL}; LinkData *link; short stop = 0, do_update; @@ -197,7 +197,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op) } LISTBASE_FOREACH (Sequence *, seq, SEQ_active_seqbase_get(ed)) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE)) { SEQ_proxy_set(seq, turnon); if (seq->strip->proxy == NULL) { diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index c5385e24d2c..a0a9cdd96b1 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -292,7 +292,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op) } for (seq = ed->seqbasep->first; seq; seq = seq->next) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { xmin = min_ii(xmin, seq->startdisp); xmax = max_ii(xmax, seq->enddisp); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index a2564469c16..72d0c11e192 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -53,6 +53,7 @@ #include "BKE_screen.h" #include "BKE_workspace.h" +#include "ED_object.h" #include "ED_render.h" #include "ED_screen.h" #include "ED_space_api.h" @@ -528,6 +529,16 @@ static bool view3d_mat_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA); } +static char *view3d_mat_drop_tooltip(bContext *C, + wmDrag *drag, + const wmEvent *event, + struct wmDropBox *drop) +{ + const char *name = WM_drag_get_item_name(drag); + RNA_string_set(drop->ptr, "name", name); + return ED_object_ot_drop_named_material_tooltip(C, drop->ptr, event); +} + static bool view3d_object_data_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ID_Type id_type = view3d_drop_id_in_main_region_poll_get_id_type(C, drag, event); @@ -539,7 +550,8 @@ static bool view3d_object_data_drop_poll(bContext *C, wmDrag *drag, const wmEven static char *view3d_object_data_drop_tooltip(bContext *UNUSED(C), wmDrag *UNUSED(drag), - const wmEvent *UNUSED(event)) + const wmEvent *UNUSED(event), + wmDropBox *UNUSED(drop)) { return BLI_strdup(TIP_("Create object instance from object-data")); } @@ -689,7 +701,7 @@ static void view3d_dropboxes(void) view3d_mat_drop_poll, view3d_id_drop_copy, WM_drag_free_imported_drag_ID, - NULL); + view3d_mat_drop_tooltip); WM_dropbox_add(lb, "VIEW3D_OT_background_image_add", view3d_ima_bg_drop_poll, diff --git a/source/blender/editors/space_view3d/view3d_navigate_walk.c b/source/blender/editors/space_view3d/view3d_navigate_walk.c index 09936b41a74..1ac241013ed 100644 --- a/source/blender/editors/space_view3d/view3d_navigate_walk.c +++ b/source/blender/editors/space_view3d/view3d_navigate_walk.c @@ -548,7 +548,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->teleport.duration = U.walk_navigation.teleport_time; walk->mouse_speed = U.walk_navigation.mouse_speed; - if ((U.walk_navigation.flag & USER_WALK_GRAVITY)) { + if (U.walk_navigation.flag & USER_WALK_GRAVITY) { walk_navigation_mode_set(walk, WALK_MODE_GRAVITY); } else { @@ -563,7 +563,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op) walk->gravity_state = WALK_GRAVITY_STATE_OFF; - if ((walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY)) { + if (walk->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { walk->gravity = fabsf(walk->scene->physics_settings.gravity[2]); } else { @@ -1199,11 +1199,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_FORWARD)) { + if (walk->active_directions & WALK_BIT_FORWARD) { direction += 1; } - if ((walk->active_directions & WALK_BIT_BACKWARD)) { + if (walk->active_directions & WALK_BIT_BACKWARD) { direction -= 1; } @@ -1223,11 +1223,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_LEFT)) { + if (walk->active_directions & WALK_BIT_LEFT) { direction += 1; } - if ((walk->active_directions & WALK_BIT_RIGHT)) { + if (walk->active_directions & WALK_BIT_RIGHT) { direction -= 1; } @@ -1245,11 +1245,11 @@ static int walkApply(bContext *C, WalkInfo *walk, bool is_confirm) direction = 0; - if ((walk->active_directions & WALK_BIT_UP)) { + if (walk->active_directions & WALK_BIT_UP) { direction -= 1; } - if ((walk->active_directions & WALK_BIT_DOWN)) { + if (walk->active_directions & WALK_BIT_DOWN) { direction = 1; } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 5ec3e9cae5a..2ce5684e874 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2156,7 +2156,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc, for (a = 0; a < hits; a++) { if (has_bones) { /* skip non-bone objects */ - if ((buffer[4 * a + 3] & 0xFFFF0000)) { + if (buffer[4 * a + 3] & 0xFFFF0000) { if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) { basact = base; } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index efcf7d587e1..96b84bd2a35 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1828,7 +1828,7 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { - if ((((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH)) { + if (((Mesh *)(tc->obedit->data))->flag & ME_AUTOSMOOTH) { BMEditMesh *em = NULL; /* BKE_editmesh_from_object(t->obedit); */ bool do_skip = false; diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 00fd008151d..e77fedfe143 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -861,10 +861,13 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list) /* The Action constraint only does this in the Before mode. */ bActionConstraint *data = (bActionConstraint *)con->data; - if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE) && + if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE, ACTCON_MIX_BEFORE_FULL) && ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) { return true; } + if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE_SPLIT) && ELEM(t->mode, TFM_ROTATION)) { + return true; + } } else if (con->type == CONSTRAINT_TYPE_TRANSFORM) { /* Transform constraint needs it for rotation at least (r.57309), diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 1f1b1f8db97..f56d60b7376 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -1515,7 +1515,7 @@ int transform_convert_pose_transflags_update(Object *ob, for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { bone = pchan->bone; if (PBONE_VISIBLE(arm, bone)) { - if ((bone->flag & BONE_SELECTED)) { + if (bone->flag & BONE_SELECTED) { bone->flag |= BONE_TRANSFORM; } else { diff --git a/source/blender/editors/transform/transform_convert_mask.c b/source/blender/editors/transform/transform_convert_mask.c index 54df8270702..1a25cfd1efb 100644 --- a/source/blender/editors/transform/transform_convert_mask.c +++ b/source/blender/editors/transform/transform_convert_mask.c @@ -293,7 +293,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } @@ -351,7 +351,7 @@ void createTransMaskingData(bContext *C, TransInfo *t) for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { MaskSpline *spline; - if (masklay->restrictflag & (MASK_RESTRICT_VIEW | MASK_RESTRICT_SELECT)) { + if (masklay->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) { continue; } diff --git a/source/blender/editors/transform/transform_snap_sequencer.c b/source/blender/editors/transform/transform_snap_sequencer.c index a1f396eb503..6e926f36fba 100644 --- a/source/blender/editors/transform/transform_snap_sequencer.c +++ b/source/blender/editors/transform/transform_snap_sequencer.c @@ -141,7 +141,7 @@ static SeqCollection *query_snap_targets(const TransInfo *t, SeqCollection *snap const short snap_flag = SEQ_tool_settings_snap_flag_get(t->scene); SeqCollection *snap_targets = SEQ_collection_create(__func__); LISTBASE_FOREACH (Sequence *, seq, seqbase) { - if ((seq->flag & SELECT)) { + if (seq->flag & SELECT) { continue; /* Selected are being transformed. */ } if ((seq->flag & SEQ_MUTE) && (snap_flag & SEQ_SNAP_IGNORE_MUTED)) { diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c index 4c597d80534..5a82cd31112 100644 --- a/source/blender/editors/uvedit/uvedit_select.c +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -3912,7 +3912,7 @@ BMLoop **ED_uvedit_selected_verts(Scene *scene, BMesh *bm, int len_max, int *r_v BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) { if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) { const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); - if ((luv->flag & MLOOPUV_VERTSEL)) { + if (luv->flag & MLOOPUV_VERTSEL) { BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG); verts[verts_len++] = l_iter; diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 535a0e00347..1bcd1fad9d6 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -1769,7 +1769,7 @@ static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void GPU_blend(GPU_BLEND_ALPHA); - /* Static Tris */ + /* Static Triangles. */ if (stitch_preview->static_tris) { UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col); vbo = GPU_vertbuf_create_with_format(&format); diff --git a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp index db85292c6c0..2d0021a1fe8 100644 --- a/source/blender/freestyle/intern/python/BPy_Freestyle.cpp +++ b/source/blender/freestyle/intern/python/BPy_Freestyle.cpp @@ -266,7 +266,7 @@ static PyObject *Freestyle_evaluateCurveMappingF(PyObject * /*self*/, PyObject * cumap = (CurveMapping *)py_srna->ptr.data; BKE_curvemapping_init(cumap); /* disable extrapolation if enabled */ - if ((cumap->flag & CUMA_EXTEND_EXTRAPOLATE)) { + if (cumap->flag & CUMA_EXTEND_EXTRAPOLATE) { cumap->flag &= ~CUMA_EXTEND_EXTRAPOLATE; BKE_curvemapping_changed(cumap, false); } diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index afb23690a84..b1aea8bf6cf 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -527,7 +527,7 @@ static void computeCumulativeVisibility(ViewMap *ioViewMap, fe = fe->nextEdge(); continue; } - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility<G, I>( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -725,7 +725,7 @@ static void computeDetailedVisibility(ViewMap *ioViewMap, fe = fe->nextEdge(); continue; } - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility<G, I>( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -891,7 +891,7 @@ static void computeFastVisibility(ViewMap *ioViewMap, G &grid, real epsilon) continue; } if (even_test) { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { // ARB: change &wFace to wFace and use reference in called function tmpQI = computeVisibility<G, I>( ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); @@ -1607,7 +1607,7 @@ void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilo memset(qiClasses, 0, 256 * sizeof(*qiClasses)); set<ViewShape *> occluders; do { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); #if LOGGING @@ -1763,7 +1763,7 @@ void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real ep fe = (*ve)->fedgeA(); do { if (even_test) { - if ((maxCard < qiMajority)) { + if (maxCard < qiMajority) { tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); // ARB: This is an error condition, not an alert condition. diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c index fd94ac92bc3..857c683d95a 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillength.c @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -12,14 +10,11 @@ * 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, + * 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 * This is a new part of Blender - * - * ***** END GPL LICENSE BLOCK ***** - * */ /** \file diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c index 8762ca1f384..f02b73e8430 100644 --- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c +++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c @@ -1968,8 +1968,8 @@ static int lineart_usage_check(Collection *c, Object *ob, bool is_render) if (c->gobject.first) { if (BKE_collection_has_object(c, (Object *)(ob->id.orig_id))) { - if ((is_render && (c->flag & COLLECTION_RESTRICT_RENDER)) || - ((!is_render) && (c->flag & COLLECTION_RESTRICT_VIEWPORT))) { + if ((is_render && (c->flag & COLLECTION_HIDE_RENDER)) || + ((!is_render) && (c->flag & COLLECTION_HIDE_VIEWPORT))) { return OBJECT_LRT_EXCLUDE; } if (ob->lineart.usage == OBJECT_LRT_INHERIT) { diff --git a/source/blender/gpu/intern/gpu_matrix.cc b/source/blender/gpu/intern/gpu_matrix.cc index 6eb9cb823d5..efa04568401 100644 --- a/source/blender/gpu/intern/gpu_matrix.cc +++ b/source/blender/gpu/intern/gpu_matrix.cc @@ -532,17 +532,17 @@ static void gpu_mul_invert_projmat_m4_unmapped_v3_with_precalc( const struct GPUMatrixUnproject_Precalc *precalc, float co[3]) { /* 'precalc->dims' is the result of 'projmat_dimensions(proj, ...)'. */ - co[0] = precalc->dims.xmin + co[0] * (precalc->dims.xmax - precalc->dims.xmin); - co[1] = precalc->dims.ymin + co[1] * (precalc->dims.ymax - precalc->dims.ymin); + co[0] = (float)scalenormd(precalc->dims.xmin, precalc->dims.xmax, co[0]); + co[1] = (float)scalenormd(precalc->dims.ymin, precalc->dims.ymax, co[1]); if (precalc->is_persp) { - co[2] = precalc->dims.zmax * precalc->dims.zmin / + co[2] = (precalc->dims.zmax * precalc->dims.zmin) / (precalc->dims.zmax + co[2] * (precalc->dims.zmin - precalc->dims.zmax)); - co[0] *= co[2]; - co[1] *= co[2]; + co[0] *= co[2] / precalc->dims.zmin; + co[1] *= co[2] / precalc->dims.zmin; } else { - co[2] = precalc->dims.zmin + co[2] * (precalc->dims.zmax - precalc->dims.zmin); + co[2] = (float)scalenormd(precalc->dims.zmin, precalc->dims.zmax, co[2]); } co[2] *= -1; } diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc index 42b85da1f93..772fc19d919 100644 --- a/source/blender/gpu/opengl/gl_backend.cc +++ b/source/blender/gpu/opengl/gl_backend.cc @@ -283,7 +283,8 @@ static void detect_workarounds() } /* We have issues with this specific renderer. (see T74024) */ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE) && - strstr(renderer, "AMD VERDE")) { + (strstr(renderer, "AMD VERDE") || strstr(renderer, "AMD KAVERI") || + strstr(renderer, "AMD TAHITI"))) { GLContext::unused_fb_slot_workaround = true; GCaps.shader_image_load_store_support = false; GCaps.broken_amd_driver = true; diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl index f5b6d2ea3ed..5d67658c639 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl @@ -14,14 +14,14 @@ void main() gl_Position = ModelViewProjectionMatrix * pos_4d; gl_PointSize = size; - // calculate concentric radii in pixels + /* Calculate concentric radii in pixels. */ float radius = 0.5 * size; - // start at the outside and progress toward the center + /* Start at the outside and progress toward the center. */ radii[0] = radius; radii[1] = radius - 1.0; - // convert to PointCoord units + /* Convert to PointCoord units. */ radii /= size; #ifdef USE_WORLD_CLIP_PLANES diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 158695cfbf3..934837bb129 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -25,7 +25,7 @@ * Original license from NVIDIA follows. */ -// This code is in the public domain -- <castanyo@yahoo.es> +/* This code is in the public domain -- <castanyo@yahoo.es> */ #pragma once diff --git a/source/blender/imbuf/intern/metadata.c b/source/blender/imbuf/intern/metadata.c index c59997b34f5..5a01c42cf00 100644 --- a/source/blender/imbuf/intern/metadata.c +++ b/source/blender/imbuf/intern/metadata.c @@ -44,7 +44,7 @@ void IMB_metadata_ensure(struct IDProperty **metadata) return; } - IDPropertyTemplate val; + IDPropertyTemplate val = {0}; *metadata = IDP_New(IDP_GROUP, &val, "metadata"); } diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index d1fa26e1a3e..a465c6b92bc 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -69,7 +69,7 @@ extern "C" { -// The following prevents a linking error in debug mode for MSVC using the libs in CVS +/* The following prevents a linking error in debug mode for MSVC using the libs in SVN. */ #if defined(WITH_OPENEXR) && defined(_WIN32) && defined(DEBUG) && _MSC_VER < 1900 _CRTIMP void __cdecl _invalid_parameter_noinfo(void) { diff --git a/source/blender/io/avi/intern/avi_endian.c b/source/blender/io/avi/intern/avi_endian.c index 146206cd917..36cee7bcadc 100644 --- a/source/blender/io/avi/intern/avi_endian.c +++ b/source/blender/io/avi/intern/avi_endian.c @@ -42,7 +42,7 @@ static void invert(int *val) { int tval = *val; - *val = ((tval >> 24)) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | ((tval << 24)); + *val = (tval >> 24) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | (tval << 24); } static void sinvert(short int *val) diff --git a/source/blender/io/usd/intern/usd_capi_import.cc b/source/blender/io/usd/intern/usd_capi_import.cc index 8255fca284c..789ff20ba82 100644 --- a/source/blender/io/usd/intern/usd_capi_import.cc +++ b/source/blender/io/usd/intern/usd_capi_import.cc @@ -365,8 +365,7 @@ bool USD_import(struct bContext *C, { blender::io::usd::ensure_usd_plugin_path_registered(); - /* Using new here since MEM_* funcs do not call ctor to properly initialize - * data. */ + /* Using new here since `MEM_*` functions do not call constructor to properly initialize data. */ ImportJobData *job = new ImportJobData(); job->bmain = CTX_data_main(C); job->scene = CTX_data_scene(C); @@ -496,7 +495,7 @@ CacheReader *CacheReader_open_usd_object(CacheArchiveHandle *handle, USDPrimReader *usd_reader = archive->create_reader(prim); if (usd_reader == nullptr) { - /* This object is not supported */ + /* This object is not supported. */ return nullptr; } usd_reader->object(object); diff --git a/source/blender/io/usd/intern/usd_reader_material.h b/source/blender/io/usd/intern/usd_reader_material.h index 3e8fc675931..a17504bd590 100644 --- a/source/blender/io/usd/intern/usd_reader_material.h +++ b/source/blender/io/usd/intern/usd_reader_material.h @@ -55,28 +55,29 @@ struct NodePlacementContext { /* Converts USD materials to Blender representation. */ -/* By default, the USDMaterialReader creates a Blender material with +/** + By default, the #USDMaterialReader creates a Blender material with * the same name as the USD material. If the USD material has a - * UsdPreviewSurface source, the Blender material's viewport display + * #UsdPreviewSurface source, the Blender material's viewport display * color, roughness and metallic properties are set to the corresponding - * UsdPreoviewSurface inputs. + * #UsdPreoviewSurface inputs. * * If the Import USD Preview option is enabled, the current implementation - * converts UsdPreviewSurface to Blender nodes as follows: + * converts #UsdPreviewSurface to Blender nodes as follows: * - * UsdPreviewSurface -> Pricipled BSDF - * UsdUVTexture -> Texture Image + Normal Map - * UsdPrimvarReader_float2 -> UV Map + * - #UsdPreviewSurface -> Principled BSDF + * - #UsdUVTexture -> Texture Image + Normal Map + * - UsdPrimvarReader_float2 -> UV Map * * Limitations: arbitrary primvar readers or UsdTransform2d not yet - * supported. For UsdUVTexture, only the file, st and sourceColorSpace + * supported. For #UsdUVTexture, only the file, st and #sourceColorSpace * inputs are handled. * * TODO(makowalski): Investigate adding support for converting additional * shaders and inputs. Supporting certain types of inputs, such as texture * scale and bias, will probably require creating Blender Group nodes with - * the corresponding inputs. */ - + * the corresponding inputs. + */ class USDMaterialReader { protected: USDImportParams params_; diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index f13da4680e2..9c75bc8afae 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -61,7 +61,7 @@ static const pxr::TfToken normalsPrimvar("normals", pxr::TfToken::Immortal); } // namespace usdtokens namespace utils { -/* Very similar to abc mesh utils. */ +/* Very similar to #blender::io::alembic::utils. */ static void build_mat_map(const Main *bmain, std::map<std::string, Material *> *r_mat_map) { if (r_mat_map == nullptr) { @@ -71,7 +71,7 @@ static void build_mat_map(const Main *bmain, std::map<std::string, Material *> * Material *material = static_cast<Material *>(bmain->materials.first); for (; material; material = static_cast<Material *>(material->id.next)) { - /* We have to do this because the stored material name is coming directly from usd. */ + /* We have to do this because the stored material name is coming directly from USD. */ (*r_mat_map)[pxr::TfMakeValidIdentifier(material->id.name + 2)] = material; } } @@ -212,7 +212,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime) is_initial_load_ = false; if (read_mesh != mesh) { - /* XXX fixme after 2.80; mesh->flag isn't copied by BKE_mesh_nomain_to_mesh() */ + /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ short autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true); @@ -334,7 +334,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo pxr::TfToken uv_token; - /* If first time seeing uv token, store in map of <layer->uid, TfToken> */ + /* If first time seeing uv token, store in map of `<layer->uid, TfToken>`. */ if (uv_token_map_.find(layer_name) == uv_token_map_.end()) { uv_token = pxr::TfToken(layer_name); uv_token_map_.insert(std::make_pair(layer_name, uv_token)); @@ -347,7 +347,7 @@ void USDMeshReader::read_uvs(Mesh *mesh, const double motionSampleTime, const bo if (uv_token.IsEmpty()) { continue; } - /* Early out if not first load and uvs arent animated. */ + /* Early out if not first load and UVs aren't animated. */ if (!load_uvs && primvar_varying_map_.find(uv_token) != primvar_varying_map_.end() && !primvar_varying_map_.at(uv_token)) { continue; @@ -630,7 +630,7 @@ void USDMeshReader::read_mesh_sample(ImportSettings *settings, const bool new_mesh) { /* Note that for new meshes we always want to read verts and polys, - * regradless of the value of the read_flag, to avoid a crash downstream + * regardless of the value of the read_flag, to avoid a crash downstream * in code that expect this data to be there. */ if (new_mesh || (settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) { @@ -684,7 +684,7 @@ void USDMeshReader::assign_facesets_to_mpoly(double motionSampleTime, } /* Find the geom subsets that have bound materials. - * We don't call pxr::UsdShadeMaterialBindingAPI::GetMaterialBindSubsets() + * We don't call #pxr::UsdShadeMaterialBindingAPI::GetMaterialBindSubsets() * because this function returns only those subsets that are in the 'materialBind' * family, but, in practice, applications (like Houdini) might export subsets * in different families that are bound to materials. @@ -780,7 +780,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, bool is_uv = false; - /* Assume all uvs are stored in one of these primvar types */ + /* Assume all UVs are stored in one of these primvar types */ if (type == pxr::SdfValueTypeNames->TexCoord2hArray || type == pxr::SdfValueTypeNames->TexCoord2fArray || type == pxr::SdfValueTypeNames->TexCoord2dArray) { @@ -817,7 +817,7 @@ Mesh *USDMeshReader::read_mesh(Mesh *existing_mesh, Mesh *active_mesh = existing_mesh; bool new_mesh = false; - /* TODO(makowalski): inmplement the optimization of only updating the mesh points when + /* TODO(makowalski): implement the optimization of only updating the mesh points when * the topology is consistent, as in the Alembic importer. */ ImportSettings settings; diff --git a/source/blender/io/usd/intern/usd_reader_stage.cc b/source/blender/io/usd/intern/usd_reader_stage.cc index d3693f783ec..233b3d9da4d 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.cc +++ b/source/blender/io/usd/intern/usd_reader_stage.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2021 Tangent Animation and diff --git a/source/blender/io/usd/intern/usd_reader_stage.h b/source/blender/io/usd/intern/usd_reader_stage.h index 7cc557f7802..ba223962c0c 100644 --- a/source/blender/io/usd/intern/usd_reader_stage.h +++ b/source/blender/io/usd/intern/usd_reader_stage.h @@ -10,7 +10,7 @@ * 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, + * 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) 2021 Tangent Animation and diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index c9d652ad03d..f7f4b0e6104 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -429,7 +429,8 @@ typedef struct PreviewImage { * BKE_library_override typically (especially due to the check on LIB_TAG_EXTERN). */ #define ID_IS_OVERRIDABLE_LIBRARY(_id) \ (ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0 && \ - (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) + (BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0 && \ + !ELEM(GS(((ID *)(_id))->name), ID_SCE)) /* NOTE: The three checks below do not take into account whether given ID is linked or not (when * chaining overrides over several libraries). User must ensure the ID is not linked itself diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 986c009ac26..634ebdff253 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -76,7 +76,9 @@ typedef struct BrushGpencilSettings { float fill_threshold; /** Number of pixel to consider the leak is too small (x 2). */ short fill_leak; - char _pad2[2]; + /* Type of caps: eGPDstroke_Caps. */ + int8_t caps_type; + char _pad; int flag2; diff --git a/source/blender/makesdna/DNA_collection_types.h b/source/blender/makesdna/DNA_collection_types.h index 1defa8b782b..3eba02de2a3 100644 --- a/source/blender/makesdna/DNA_collection_types.h +++ b/source/blender/makesdna/DNA_collection_types.h @@ -102,10 +102,10 @@ typedef struct Collection { /* Collection->flag */ enum { - COLLECTION_RESTRICT_VIEWPORT = (1 << 0), /* Disable in viewports. */ - COLLECTION_RESTRICT_SELECT = (1 << 1), /* Not selectable in viewport. */ + COLLECTION_HIDE_VIEWPORT = (1 << 0), /* Disable in viewports. */ + COLLECTION_HIDE_SELECT = (1 << 1), /* Not selectable in viewport. */ /* COLLECTION_DISABLED_DEPRECATED = (1 << 2), */ /* Not used anymore */ - COLLECTION_RESTRICT_RENDER = (1 << 3), /* Disable in renders. */ + COLLECTION_HIDE_RENDER = (1 << 3), /* Disable in renders. */ COLLECTION_HAS_OBJECT_CACHE = (1 << 4), /* Runtime: object_cache is populated. */ COLLECTION_IS_MASTER = (1 << 5), /* Is master collection embedded in the scene. */ COLLECTION_HAS_OBJECT_CACHE_INSTANCED = (1 << 6), /* for object_cache_instanced. */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index a77fbc9e45e..822b8705c9b 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -901,10 +901,16 @@ typedef enum eActionConstraint_Flags { typedef enum eActionConstraint_MixMode { /* Multiply the action transformation on the right. */ ACTCON_MIX_AFTER_FULL = 0, + /* Multiply the action transformation on the left. */ + ACTCON_MIX_BEFORE_FULL = 3, /* Multiply the action transformation on the right, with anti-shear scale handling. */ ACTCON_MIX_AFTER = 1, /* Multiply the action transformation on the left, with anti-shear scale handling. */ ACTCON_MIX_BEFORE = 2, + /* Separately combine Translation, Rotation and Scale, with rotation on the right. */ + ACTCON_MIX_AFTER_SPLIT = 4, + /* Separately combine Translation, Rotation and Scale, with rotation on the left. */ + ACTCON_MIX_BEFORE_SPLIT = 5, } eActionConstraint_MixMode; /* Locked-Axis Values (Locked Track) */ diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 828c6ff2a51..63e4597150c 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -222,7 +222,7 @@ enum { enum { LAYER_COLLECTION_HAS_OBJECTS = (1 << 0), /* LAYER_COLLECTION_VISIBLE_DEPSGRAPH = (1 << 1), */ /* UNUSED */ - LAYER_COLLECTION_RESTRICT_VIEWPORT = (1 << 2), + LAYER_COLLECTION_HIDE_VIEWPORT = (1 << 2), LAYER_COLLECTION_VISIBLE_VIEW_LAYER = (1 << 4), }; diff --git a/source/blender/makesdna/DNA_lineart_types.h b/source/blender/makesdna/DNA_lineart_types.h index e93cf050e18..cdb09c3af50 100644 --- a/source/blender/makesdna/DNA_lineart_types.h +++ b/source/blender/makesdna/DNA_lineart_types.h @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -17,12 +15,6 @@ * * The Original Code is Copyright (C) 2010 Blender Foundation. * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** */ #pragma once diff --git a/source/blender/makesdna/DNA_mask_types.h b/source/blender/makesdna/DNA_mask_types.h index e6a7c004078..419118a38f4 100644 --- a/source/blender/makesdna/DNA_mask_types.h +++ b/source/blender/makesdna/DNA_mask_types.h @@ -174,7 +174,7 @@ typedef struct MaskLayer { /** For animation. */ char flag; /** Matching 'Object' flag of the same name - eventually use in the outliner. */ - char restrictflag; + char visibility_flag; } MaskLayer; /* MaskParent->flag */ @@ -206,10 +206,10 @@ enum { MASK_SPLINE_OFFSET_SMOOTH = 1, }; -/* ob->restrictflag */ -#define MASK_RESTRICT_VIEW (1 << 0) -#define MASK_RESTRICT_SELECT (1 << 1) -#define MASK_RESTRICT_RENDER (1 << 2) +/* MaskLayer->visibility_flag */ +#define MASK_HIDE_VIEW (1 << 0) +#define MASK_HIDE_SELECT (1 << 1) +#define MASK_HIDE_RENDER (1 << 2) /* SpaceClip->mask_draw_flag */ #define MASK_DRAWFLAG_SMOOTH (1 << 0) diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 5152098f57a..4b08aeb2008 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1355,6 +1355,11 @@ typedef struct NodeSwitch { uint8_t input_type; } NodeSwitch; +typedef struct NodeGeometryCurveSplineType { + /* GeometryNodeSplineType. */ + uint8_t spline_type; +} NodeGeometryCurveSplineType; + typedef struct NodeGeometryCurveSetHandles { /* GeometryNodeCurveHandleType. */ uint8_t handle_type; @@ -1828,6 +1833,12 @@ typedef enum GeometryNodeBooleanOperation { GEO_NODE_BOOLEAN_DIFFERENCE = 2, } GeometryNodeBooleanOperation; +typedef enum GeometryNodeSplineType { + GEO_NODE_SPLINE_TYPE_BEZIER = 0, + GEO_NODE_SPLINE_TYPE_NURBS = 1, + GEO_NODE_SPLINE_TYPE_POLY = 2, +} GeometryNodeSplineType; + typedef enum GeometryNodeCurvePrimitiveCircleMode { GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_POINTS = 0, GEO_NODE_CURVE_PRIMITIVE_CIRCLE_TYPE_RADIUS = 1 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 60a34fef899..e7091c78f71 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -385,14 +385,14 @@ typedef struct Object { short softflag; /** For restricting view, select, render etc. accessible in outliner. */ - char restrictflag; + short visibility_flag; - /** Flag for pinning. */ - char shapeflag; /** Current shape key for menu or pinned. */ short shapenr; + /** Flag for pinning. */ + char shapeflag; - char _pad3[2]; + char _pad3[1]; /** Object constraints. */ ListBase constraints; @@ -670,11 +670,19 @@ enum { # define OB_FLAG_UNUSED_12 (1 << 12) /* cleared */ #endif -/* ob->restrictflag */ +/* ob->visibility_flag */ enum { - OB_RESTRICT_VIEWPORT = 1 << 0, - OB_RESTRICT_SELECT = 1 << 1, - OB_RESTRICT_RENDER = 1 << 2, + OB_HIDE_VIEWPORT = 1 << 0, + OB_HIDE_SELECT = 1 << 1, + OB_HIDE_RENDER = 1 << 2, + OB_HIDE_CAMERA = 1 << 3, + OB_HIDE_DIFFUSE = 1 << 4, + OB_HIDE_GLOSSY = 1 << 5, + OB_HIDE_TRANSMISSION = 1 << 6, + OB_HIDE_VOLUME_SCATTER = 1 << 7, + OB_HIDE_SHADOW = 1 << 8, + OB_HOLDOUT = 1 << 9, + OB_SHADOW_CATCHER = 1 << 10 }; /* ob->shapeflag */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 7290647dbc6..27d5d83c7cb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -754,13 +754,7 @@ typedef struct FileSelectParams { /** Max number of levels in dirtree to show at once, 0 to disable recursion. */ short recursion_level; - /* XXX --- still unused -- */ - /** Show font preview. */ - short f_fp; - /** String to use for font preview. */ - char fp_str[8]; - - /* XXX --- end unused -- */ + char _pad4[2]; } FileSelectParams; /** diff --git a/source/blender/makesdna/DNA_view3d_defaults.h b/source/blender/makesdna/DNA_view3d_defaults.h index 9dfc37e57b1..c4d0c83b346 100644 --- a/source/blender/makesdna/DNA_view3d_defaults.h +++ b/source/blender/makesdna/DNA_view3d_defaults.h @@ -71,6 +71,7 @@ .gpencil_paper_opacity = 0.5f, \ .gpencil_grid_opacity = 0.9f, \ .gpencil_vertex_paint_opacity = 1.0f, \ + .normals_constant_screen_size = 7.0f, \ } #define _DNA_DEFAULT_View3DCursor \ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 08b29c82707..4d88f6f0c15 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -204,6 +204,7 @@ typedef struct View3DOverlay { /** Edit mode settings. */ int edit_flag; float normals_length; + float normals_constant_screen_size; float backwire_opacity; /** Paint mode settings. */ @@ -238,6 +239,8 @@ typedef struct View3DOverlay { float gpencil_vertex_paint_opacity; /** Handles display type for curves. */ int handle_display; + + char _pad[4]; } View3DOverlay; /* View3DOverlay->handle_display */ @@ -551,6 +554,7 @@ enum { // V3D_OVERLAY_EDIT_CU_HANDLES = (1 << 20), V3D_OVERLAY_EDIT_CU_NORMALS = (1 << 21), + V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS = (1 << 22), }; /** #View3DOverlay.paint_flag */ diff --git a/source/blender/makesdna/DNA_xr_types.h b/source/blender/makesdna/DNA_xr_types.h index fc00d5eb839..a9d427777f7 100644 --- a/source/blender/makesdna/DNA_xr_types.h +++ b/source/blender/makesdna/DNA_xr_types.h @@ -26,13 +26,15 @@ extern "C" { #endif +/* -------------------------------------------------------------------- */ + typedef struct XrSessionSettings { /** Shading settings, struct shared with 3D-View so settings are the same. */ struct View3DShading shading; char _pad[7]; - char base_pose_type; /* eXRSessionBasePoseType */ + char base_pose_type; /* #eXRSessionBasePoseType */ /** Object to take the location and rotation as base position from. */ Object *base_pose_object; float base_pose_location[3]; @@ -68,12 +70,126 @@ typedef enum eXrActionType { XR_VIBRATION_OUTPUT = 100, } eXrActionType; +/** Determines how XR action operators are executed. */ typedef enum eXrOpFlag { XR_OP_PRESS = 0, XR_OP_RELEASE = 1, XR_OP_MODAL = 2, } eXrOpFlag; +typedef enum eXrActionFlag { + /** Action depends on two sub-action paths (i.e. two-handed/bi-manual action). */ + XR_ACTION_BIMANUAL = (1 << 0), +} eXrActionFlag; + +typedef enum eXrHapticFlag { + /** Whether to apply haptics to corresponding user paths for an action and its haptic action. */ + XR_HAPTIC_MATCHUSERPATHS = (1 << 0), + /** + * Determines how haptics will be applied + * ("repeat" is mutually exclusive with "press"/"release"). + */ + XR_HAPTIC_PRESS = (1 << 1), + XR_HAPTIC_RELEASE = (1 << 2), + XR_HAPTIC_REPEAT = (1 << 3), +} eXrHapticFlag; + +/** + * For axis-based inputs (thumb-stick/track-pad/etc). + * Determines the region for action execution (mutually exclusive per axis). + */ +typedef enum eXrAxisFlag { + XR_AXIS0_POS = (1 << 0), + XR_AXIS0_NEG = (1 << 1), + XR_AXIS1_POS = (1 << 2), + XR_AXIS1_NEG = (1 << 3), +} eXrAxisFlag; + +typedef enum eXrPoseFlag { + /* Pose represents controller grip/aim. */ + XR_POSE_GRIP = (1 << 0), + XR_POSE_AIM = (1 << 1), +} eXrPoseFlag; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMapBinding { + struct XrActionMapBinding *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + + /** OpenXR interaction profile path. */ + char profile[256]; + /** OpenXR component paths. */ + char component_path0[192]; + char component_path1[192]; + + /** Input threshold/region. */ + float float_threshold; + short axis_flag; /* eXrAxisFlag */ + char _pad[2]; + + /** Pose action properties. */ + float pose_location[3]; + float pose_rotation[3]; +} XrActionMapBinding; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMapItem { + struct XrActionMapItem *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + /** Type. */ + char type; /** eXrActionType */ + char _pad[7]; + + /** OpenXR user paths. */ + char user_path0[64]; + char user_path1[64]; + + /** Operator to be called on XR events. */ + char op[64]; /* OP_MAX_TYPENAME */ + /** Operator properties, assigned to ptr->data and can be written to a file. */ + IDProperty *op_properties; + /** RNA pointer to access properties. */ + struct PointerRNA *op_properties_ptr; + + short op_flag; /* eXrOpFlag */ + short action_flag; /* eXrActionFlag */ + short haptic_flag; /* eXrHapticFlag */ + + /** Pose action properties. */ + short pose_flag; /* eXrPoseFlag */ + + /** Haptic properties. */ + char haptic_name[64]; /* MAX_NAME */ + float haptic_duration; + float haptic_frequency; + float haptic_amplitude; + + short selbinding; + char _pad3[2]; + ListBase bindings; /* XrActionMapBinding */ +} XrActionMapItem; + +/* -------------------------------------------------------------------- */ + +typedef struct XrActionMap { + struct XrActionMap *next, *prev; + + /** Unique name. */ + char name[64]; /* MAX_NAME */ + + ListBase items; /* XrActionMapItem */ + short selitem; + char _pad[6]; +} XrActionMap; + +/* -------------------------------------------------------------------- */ + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/intern/dna_rename_defs.h b/source/blender/makesdna/intern/dna_rename_defs.h index d363e40e4f0..2feebbfd4f4 100644 --- a/source/blender/makesdna/intern/dna_rename_defs.h +++ b/source/blender/makesdna/intern/dna_rename_defs.h @@ -82,11 +82,13 @@ DNA_STRUCT_RENAME_ELEM(FluidDomainSettings, guiding_vel_factor, guide_vel_factor DNA_STRUCT_RENAME_ELEM(FluidEffectorSettings, guiding_mode, guide_mode) DNA_STRUCT_RENAME_ELEM(Image, name, filepath) DNA_STRUCT_RENAME_ELEM(Library, name, filepath) +DNA_STRUCT_RENAME_ELEM(MaskLayer, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(MovieClip, name, filepath) DNA_STRUCT_RENAME_ELEM(Object, col, color) DNA_STRUCT_RENAME_ELEM(Object, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(Object, dupfacesca, instance_faces_scale) DNA_STRUCT_RENAME_ELEM(Object, size, scale) +DNA_STRUCT_RENAME_ELEM(Object, restrictflag, visibility_flag) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_group, instance_collection) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dup_ob, instance_object) DNA_STRUCT_RENAME_ELEM(ParticleSettings, dupliweights, instance_weights) diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6df03d19538..8f8ad077935 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -741,6 +741,58 @@ static void rna_ID_override_template_create(ID *id, ReportList *reports) BKE_lib_override_library_template_create(id); } +static void rna_ID_override_library_operations_update(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); + return; + } + + BKE_lib_override_library_operations_create(bmain, id); +} + +static void rna_ID_override_library_reset(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports, + bool do_hierarchy) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); + return; + } + + if (do_hierarchy) { + BKE_lib_override_library_id_hierarchy_reset(bmain, id); + } + else { + BKE_lib_override_library_id_reset(bmain, id); + } +} + +static void rna_ID_override_library_destroy(ID *id, + IDOverrideLibrary *UNUSED(override_library), + Main *bmain, + ReportList *reports, + bool do_hierarchy) +{ + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name); + return; + } + + if (do_hierarchy) { + BKE_lib_override_library_delete(bmain, id); + } + else { + BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE); + BKE_id_delete(bmain, id); + } +} + static IDOverrideLibraryProperty *rna_ID_override_library_properties_add( IDOverrideLibrary *override_library, ReportList *reports, const char rna_path[]) { @@ -755,6 +807,18 @@ static IDOverrideLibraryProperty *rna_ID_override_library_properties_add( return result; } +static void rna_ID_override_library_properties_remove(IDOverrideLibrary *override_library, + ReportList *reports, + IDOverrideLibraryProperty *override_property) +{ + if (BLI_findindex(&override_library->properties, override_property) == -1) { + BKE_report(reports, RPT_ERROR, "Override property cannot be removed"); + return; + } + + BKE_lib_override_library_property_delete(override_library, override_property); +} + static IDOverrideLibraryPropertyOperation *rna_ID_override_library_property_operations_add( IDOverrideLibraryProperty *override_property, ReportList *reports, @@ -782,6 +846,19 @@ static IDOverrideLibraryPropertyOperation *rna_ID_override_library_property_oper return result; } +static void rna_ID_override_library_property_operations_remove( + IDOverrideLibraryProperty *override_property, + ReportList *reports, + IDOverrideLibraryPropertyOperation *override_operation) +{ + if (BLI_findindex(&override_property->operations, override_operation) == -1) { + BKE_report(reports, RPT_ERROR, "Override operation cannot be removed"); + return; + } + + BKE_lib_override_library_property_operation_delete(override_property, override_operation); +} + static void rna_ID_update_tag(ID *id, Main *bmain, ReportList *reports, int flag) { /* XXX, new function for this! */ @@ -1633,6 +1710,16 @@ static void rna_def_ID_override_library_property_operations(BlenderRNA *brna, Pr "New Operation", "Created operation"); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_ID_override_library_property_operations_remove"); + RNA_def_function_ui_description(func, "Remove and delete an operation"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, + "operation", + "IDOverrideLibraryPropertyOperation", + "Operation", + "Override operation to be deleted"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_ID_override_library_property(BlenderRNA *brna) @@ -1689,12 +1776,23 @@ static void rna_def_ID_override_library_properties(BlenderRNA *brna, PropertyRNA parm = RNA_def_string( func, "rna_path", NULL, 256, "RNA Path", "RNA-Path of the property to add"); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + + func = RNA_def_function(srna, "remove", "rna_ID_override_library_properties_remove"); + RNA_def_function_ui_description(func, "Remove and delete a property"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, + "property", + "IDOverrideLibraryProperty", + "Property", + "Override property to be deleted"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } static void rna_def_ID_override_library(BlenderRNA *brna) { StructRNA *srna; PropertyRNA *prop; + FunctionRNA *func; srna = RNA_def_struct(brna, "IDOverrideLibrary", NULL); RNA_def_struct_ui_text( @@ -1710,6 +1808,35 @@ static void rna_def_ID_override_library(BlenderRNA *brna) "List of overridden properties"); rna_def_ID_override_library_properties(brna, prop); + /* Update function. */ + func = RNA_def_function(srna, "operations_update", "rna_ID_override_library_operations_update"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, + "Update the library override operations based on the " + "differences between this override ID and its reference"); + + func = RNA_def_function(srna, "reset", "rna_ID_override_library_reset"); + RNA_def_function_ui_description(func, + "Reset this override to match again its linked reference ID"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_boolean( + func, + "do_hierarchy", + true, + "", + "Also reset all the dependencies of this override to match their reference linked IDs"); + + func = RNA_def_function(srna, "destroy", "rna_ID_override_library_destroy"); + RNA_def_function_ui_description( + func, "Delete this override ID and remap its usages to its linked reference ID instead"); + RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID | FUNC_USE_REPORTS); + RNA_def_boolean(func, + "do_hierarchy", + true, + "", + "Also delete all the dependencies of this override and remap their usages to " + "their reference linked IDs"); + rna_def_ID_override_library_property(brna); } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 46d60bf0da9..c991216da11 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -36,6 +36,7 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLF_api.h" @@ -3676,6 +3677,8 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) PointerPropertyRNA *pprop = (PointerPropertyRNA *)prop; IDProperty *idprop; + static ThreadMutex lock = BLI_MUTEX_INITIALIZER; + BLI_assert(RNA_property_type(prop) == PROP_POINTER); if ((idprop = rna_idproperty_check(&prop, ptr))) { @@ -3695,9 +3698,14 @@ PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop) return pprop->get(ptr); } if (prop->flag & PROP_IDPROPERTY) { - /* XXX temporary hack to add it automatically, reading should - * never do any write ops, to ensure thread safety etc. */ + /* NOTE: While creating/writing data in an accessor is really bad design-wise, this is + * currently very difficult to avoid in that case. So a global mutex is used to keep ensuring + * thread safety. */ + BLI_mutex_lock(&lock); + /* NOTE: We do not need to check again for existence of the pointer after locking here, since + * this is also done in #RNA_property_pointer_add itself. */ RNA_property_pointer_add(ptr, prop); + BLI_mutex_unlock(&lock); return RNA_property_pointer_get(ptr, prop); } return PointerRNA_NULL; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2b09ea51a84..cdca58df4b0 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1281,6 +1281,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static EnumPropertyItem rna_enum_gpencil_brush_caps_types_items[] = { + {GP_STROKE_CAP_ROUND, "ROUND", ICON_GP_CAPS_ROUND, "Round", ""}, + {GP_STROKE_CAP_FLAT, "FLAT", ICON_GP_CAPS_FLAT, "Flat", ""}, + {0, NULL, 0, NULL, NULL}, + }; + srna = RNA_def_struct(brna, "BrushGpencilSettings", NULL); RNA_def_struct_sdna(srna, "BrushGpencilSettings"); RNA_def_struct_path_func(srna, "rna_BrushGpencilSettings_path"); @@ -1750,6 +1756,12 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_update( prop, NC_GPENCIL | ND_DATA, "rna_BrushGpencilSettings_eraser_mode_update"); + prop = RNA_def_property(srna, "caps_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "caps_type"); + RNA_def_property_enum_items(prop, rna_enum_gpencil_brush_caps_types_items); + RNA_def_property_ui_text(prop, "Caps Type", "The shape of the start and end of the stroke"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "fill_draw_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "fill_draw_mode"); RNA_def_property_enum_items(prop, rna_enum_gpencil_fill_draw_modes_items); diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c index 608a8e51b09..77276f47689 100644 --- a/source/blender/makesrna/intern/rna_collection.c +++ b/source/blender/makesrna/intern/rna_collection.c @@ -322,17 +322,17 @@ static void rna_Collection_flag_set(PointerRNA *ptr, const bool value, const int static void rna_Collection_hide_select_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_SELECT); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_SELECT); } static void rna_Collection_hide_viewport_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_VIEWPORT); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_VIEWPORT); } static void rna_Collection_hide_render_set(PointerRNA *ptr, bool value) { - rna_Collection_flag_set(ptr, value, COLLECTION_RESTRICT_RENDER); + rna_Collection_flag_set(ptr, value, COLLECTION_HIDE_RENDER); } static void rna_Collection_flag_update(Main *bmain, Scene *scene, PointerRNA *ptr) @@ -496,7 +496,7 @@ void RNA_def_collections(BlenderRNA *brna) /* Flags */ prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_SELECT); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_select_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); @@ -504,7 +504,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_VIEWPORT); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_VIEWPORT); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_viewport_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); @@ -512,7 +512,7 @@ void RNA_def_collections(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_Collection_flag_update"); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_RESTRICT_RENDER); + RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_HIDE_RENDER); RNA_def_property_boolean_funcs(prop, NULL, "rna_Collection_hide_render_set"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 3064703b02e..e36d052d27c 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -679,7 +679,7 @@ static void rna_ActionConstraint_mix_mode_set(PointerRNA *ptr, int value) acon->mix_mode = value; /* The After mode can be computed in world space for efficiency - * and backward compatibility, while Before requires Local. */ + * and backward compatibility, while Before or Split requires Local. */ if (ELEM(value, ACTCON_MIX_AFTER, ACTCON_MIX_AFTER_FULL)) { con->ownspace = CONSTRAINT_SPACE_WORLD; } @@ -715,7 +715,7 @@ static int rna_SplineIKConstraint_joint_bindings_get_length(PointerRNA *ptr, length[0] = ikData->numpoints; } else { - length[0] = 256; /* for raw_access, untested */ + length[0] = 0; } return length[0]; @@ -1773,25 +1773,47 @@ static void rna_def_constraint_action(BlenderRNA *brna) }; static const EnumPropertyItem mix_mode_items[] = { + {ACTCON_MIX_BEFORE_FULL, + "BEFORE_FULL", + 0, + "Before Original (Full)", + "Apply the action channels before the original transformation, as if applied to an " + "imaginary parent in Full Inherit Scale mode. Will create shear when combining rotation " + "and non-uniform scale"}, {ACTCON_MIX_BEFORE, "BEFORE", 0, - "Before Original", - "Apply the action channels before the original transformation, " - "as if applied to an imaginary parent with Aligned Inherit Scale"}, - {ACTCON_MIX_AFTER, - "AFTER", + "Before Original (Aligned)", + "Apply the action channels before the original transformation, as if applied to an " + "imaginary parent in Aligned Inherit Scale mode. This effectively uses Full for location " + "and Split Channels for rotation and scale"}, + {ACTCON_MIX_BEFORE_SPLIT, + "BEFORE_SPLIT", 0, - "After Original", - "Apply the action channels after the original transformation, " - "as if applied to an imaginary child with Aligned Inherit Scale"}, + "Before Original (Split Channels)", + "Apply the action channels before the original transformation, handling location, rotation " + "and scale separately"}, + {0, "", 0, NULL, NULL}, {ACTCON_MIX_AFTER_FULL, "AFTER_FULL", 0, - "After Original (Full Scale)", - "Apply the action channels after the original transformation, as if " - "applied to an imaginary child with Full Inherit Scale. This mode " - "can create shear and is provided only for backward compatibility"}, + "After Original (Full)", + "Apply the action channels after the original transformation, as if applied to an " + "imaginary child in Full Inherit Scale mode. Will create shear when combining rotation " + "and non-uniform scale"}, + {ACTCON_MIX_AFTER, + "AFTER", + 0, + "After Original (Aligned)", + "Apply the action channels after the original transformation, as if applied to an " + "imaginary child in Aligned Inherit Scale mode. This effectively uses Full for location " + "and Split Channels for rotation and scale"}, + {ACTCON_MIX_AFTER_SPLIT, + "AFTER_SPLIT", + 0, + "After Original (Split Channels)", + "Apply the action channels after the original transformation, handling location, rotation " + "and scale separately"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 1f187382980..a38bbd3d6d2 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -809,7 +809,7 @@ static int rna_FModifierGenerator_coefficients_get_length(PointerRNA *ptr, length[0] = gen->arraysize; } else { - length[0] = 100; /* for raw_access, untested */ + length[0] = 0; } return length[0]; diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 0414afe1514..ab4cbc429ce 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -134,7 +134,7 @@ static bool rna_LayerCollection_visible_get(LayerCollection *layer_collection, b } if (v3d->local_collections_uuid & layer_collection->local_collections_bits) { - return (layer_collection->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0; + return (layer_collection->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) == 0; } return false; diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 8c7d9698a67..9c90c209389 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -991,19 +991,19 @@ static void rna_def_mask_layer(BlenderRNA *brna) /* restrict */ prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_VIEW); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_VIEW); RNA_def_property_ui_text(prop, "Restrict View", "Restrict visibility in the viewport"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_SELECT); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_SELECT); RNA_def_property_ui_text(prop, "Restrict Select", "Restrict selection in the viewport"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); RNA_def_property_update(prop, NC_MASK | ND_DRAW, NULL); prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", MASK_RESTRICT_RENDER); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", MASK_HIDE_RENDER); RNA_def_property_ui_text(prop, "Restrict Render", "Restrict renderability"); RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); RNA_def_property_update(prop, NC_MASK | NA_EDITED, NULL); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index ea3c92b4c56..01e0f84f87e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -9441,6 +9441,23 @@ static void def_geo_attribute_vector_rotate(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); } +static void def_geo_curve_spline_type(StructRNA *srna) +{ + static const EnumPropertyItem type_items[] = { + {GEO_NODE_SPLINE_TYPE_BEZIER, "BEZIER", ICON_NONE, "Bezier", "Set the splines to Bezier"}, + {GEO_NODE_SPLINE_TYPE_NURBS, "NURBS", ICON_NONE, "NURBS", "Set the splines to NURBS"}, + {GEO_NODE_SPLINE_TYPE_POLY, "POLY", ICON_NONE, "Poly", "Set the splines to Poly"}, + {0, NULL, 0, NULL, NULL}}; + + PropertyRNA *prop; + RNA_def_struct_sdna_from(srna, "NodeGeometryCurveSplineType", "storage"); + + prop = RNA_def_property(srna, "spline_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "spline_type"); + RNA_def_property_enum_items(prop, type_items); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update"); +} + static void def_geo_curve_set_handles(StructRNA *srna) { static const EnumPropertyItem type_items[] = { diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index ed681291e29..bef430b0314 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -2927,6 +2927,97 @@ static void rna_def_object_lineart(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_object_lineart_update"); } +static void rna_def_object_visibility(StructRNA *srna) +{ + PropertyRNA *prop; + + /* Hide options. */ + prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_VIEWPORT); + RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_SELECT); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HIDE_RENDER); + RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); + RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + /* Instancer options. */ + prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER); + RNA_def_property_ui_text(prop, "Render Instancer", "Make instancer visible when rendering"); + RNA_def_property_update( + prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + + prop = RNA_def_property(srna, "show_instancer_for_viewport", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); + RNA_def_property_ui_text(prop, "Display Instancer", "Make instancer visible in the viewport"); + RNA_def_property_update( + prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + + /* Ray visibility. */ + prop = RNA_def_property(srna, "visible_camera", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_CAMERA); + RNA_def_property_ui_text(prop, "Camera Visibility", "Object visibility to camera rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_diffuse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_DIFFUSE); + RNA_def_property_ui_text(prop, "Diffuse Visibility", "Object visibility to diffuse rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_glossy", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_GLOSSY); + RNA_def_property_ui_text(prop, "Glossy Visibility", "Object visibility to glossy rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_transmission", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_TRANSMISSION); + RNA_def_property_ui_text( + prop, "Transmission Visibility", "Object visibility to transmission rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_volume_scatter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_VOLUME_SCATTER); + RNA_def_property_ui_text( + prop, "Volume Scatter Visibility", "Object visibility to volume scattering rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + prop = RNA_def_property(srna, "visible_shadow", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "visibility_flag", OB_HIDE_SHADOW); + RNA_def_property_ui_text(prop, "Shadow Visibility", "Object visibility to shadow rays"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); + + /* Holdout and shadow catcher. */ + prop = RNA_def_property(srna, "is_holdout", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_HOLDOUT); + RNA_def_property_ui_text( + prop, + "Holdout", + "Render objects as a holdout or matte, creating a hole in the image with zero alpha, to " + "fill out in compositing with real footage or another render"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); + + prop = RNA_def_property(srna, "is_shadow_catcher", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "visibility_flag", OB_SHADOW_CATCHER); + RNA_def_property_ui_text( + prop, + "Shadow Catcher", + "Only render shadows and reflections on this object, for compositing renders into real " + "footage. Objects with this setting are considered to already exist in the footage, " + "objects without it are synthetic objects being composited into it"); + RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw"); +} + static void rna_def_object(BlenderRNA *brna) { StructRNA *srna; @@ -3506,37 +3597,7 @@ static void rna_def_object(BlenderRNA *brna) RNA_def_property_struct_type(prop, "RigidBodyConstraint"); RNA_def_property_ui_text(prop, "Rigid Body Constraint", "Constraint constraining rigid bodies"); - /* restrict */ - prop = RNA_def_property(srna, "hide_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEWPORT); - RNA_def_property_ui_text(prop, "Disable in Viewports", "Globally disable in viewports"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "hide_select", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_SELECT); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Disable Selection", "Disable selection in viewport"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_SELECT_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "hide_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_RENDER); - RNA_def_property_ui_text(prop, "Disable in Renders", "Globally disable in renders"); - RNA_def_property_ui_icon(prop, ICON_RESTRICT_RENDER_OFF, -1); - RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_hide_update"); - - prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER); - RNA_def_property_ui_text(prop, "Render Instancer", "Make instancer visible when rendering"); - RNA_def_property_update( - prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); - - prop = RNA_def_property(srna, "show_instancer_for_viewport", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "duplicator_visibility_flag", OB_DUPLI_FLAG_VIEWPORT); - RNA_def_property_ui_text(prop, "Display Instancer", "Make instancer visible in the viewport"); - RNA_def_property_update( - prop, NC_OBJECT | ND_DRAW, "rna_Object_duplicator_visibility_flag_update"); + rna_def_object_visibility(srna); /* instancing */ prop = RNA_def_property(srna, "instance_type", PROP_ENUM, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 796e62c8b2a..c7a5c43255a 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -4363,6 +4363,21 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_float_default(prop, 0.02); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "normals_constant_screen_size", PROP_FLOAT, PROP_PIXEL); + RNA_def_property_float_sdna(prop, NULL, "overlay.normals_constant_screen_size"); + RNA_def_property_ui_text(prop, "Normal Screen Size", "Screen size for normals in the 3D view"); + RNA_def_property_range(prop, 0.0, 100000.0); + RNA_def_property_ui_range(prop, 1.0, 100.0, 50, 0); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + + prop = RNA_def_property(srna, "use_normals_constant_screen_size", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna( + prop, NULL, "overlay.edit_flag", V3D_OVERLAY_EDIT_CONSTANT_SCREEN_SIZE_NORMALS); + RNA_def_property_ui_text(prop, + "Constant Screen Size Normals", + "Keep size of normals constant in relation to 3D view"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "backwire_opacity", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "overlay.backwire_opacity"); RNA_def_property_ui_text(prop, "Backwire Opacity", "Opacity when rendering transparent wires"); diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index 42b3e4420c1..83c1efd55bc 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -59,14 +59,36 @@ void RNA_api_texture(StructRNA *srna) PropertyRNA *parm; func = RNA_def_function(srna, "evaluate", "texture_evaluate"); - RNA_def_function_ui_description(func, "Evaluate the texture at the coordinates given"); + RNA_def_function_ui_description( + func, "Evaluate the texture at the a given coordinate and returns the result"); - parm = RNA_def_float_vector(func, "value", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); + parm = RNA_def_float_vector( + func, + "value", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "The coordinates (x,y,z) of the texture, in case of a 3D texture, the z value is the slice " + "of the texture that is evaluated. For 2D textures such as images, the z value is ignored", + "", + -1e4, + 1e4); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); /* return location and normal */ parm = RNA_def_float_vector( - func, "result", 4, NULL, -FLT_MAX, FLT_MAX, "Result", NULL, -1e4, 1e4); + func, + "result", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "The result of the texture where (x,y,z,w) are (red, green, blue, intensity). For greyscale " + "textures, often intensity only will be used", + NULL, + -1e4, + 1e4); RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); RNA_def_function_output(func, parm); } diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index 56e8418972c..9a512e351cb 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -18,9 +18,14 @@ * \ingroup RNA */ +#include "BLI_math.h" + +#include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" #include "DNA_xr_types.h" +#include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -30,10 +35,462 @@ #ifdef RNA_RUNTIME -# include "BLI_math.h" +# include "BLI_listbase.h" # include "WM_api.h" +/* -------------------------------------------------------------------- */ +/** \name XR Action Map + * \{ */ + +static XrActionMapBinding *rna_XrActionMapBinding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_new(ami, name, replace_existing); +# else + UNUSED_VARS(ami, name, replace_existing); + return NULL; +# endif +} + +static XrActionMapBinding *rna_XrActionMapBinding_new_from_binding(XrActionMapItem *ami, + XrActionMapBinding *amb_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_add_copy(ami, amb_src); +# else + UNUSED_VARS(ami, amb_src); + return NULL; +# endif +} + +static void rna_XrActionMapBinding_remove(XrActionMapItem *ami, + ReportList *reports, + PointerRNA *amb_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = amb_ptr->data; + if (WM_xr_actionmap_binding_remove(ami, amb) == false) { + BKE_reportf(reports, + RPT_ERROR, + "ActionMapBinding '%s' cannot be removed from '%s'", + amb->name, + ami->name); + return; + } + RNA_POINTER_INVALIDATE(amb_ptr); +# else + UNUSED_VARS(ami, reports, amb_ptr); +# endif +} + +static XrActionMapBinding *rna_XrActionMapBinding_find(XrActionMapItem *ami, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_binding_find(ami, name); +# else + UNUSED_VARS(ami, name); + return NULL; +# endif +} + +static int rna_XrActionMapBinding_axis0_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + if ((amb->axis_flag & XR_AXIS0_POS) != 0) { + return XR_AXIS0_POS; + } + if ((amb->axis_flag & XR_AXIS0_NEG) != 0) { + return XR_AXIS0_NEG; + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static void rna_XrActionMapBinding_axis0_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + amb->axis_flag &= ~(XR_AXIS0_POS | XR_AXIS0_NEG); + amb->axis_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static int rna_XrActionMapBinding_axis1_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + if ((amb->axis_flag & XR_AXIS1_POS) != 0) { + return XR_AXIS1_POS; + } + if ((amb->axis_flag & XR_AXIS1_NEG) != 0) { + return XR_AXIS1_NEG; + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static void rna_XrActionMapBinding_axis1_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapBinding *amb = ptr->data; + amb->axis_flag &= ~(XR_AXIS1_POS | XR_AXIS1_NEG); + amb->axis_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static void rna_XrActionMapBinding_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + ListBase *actionmaps = WM_xr_actionmaps_get(wm->xr.runtime); + short idx = WM_xr_actionmap_selected_index_get(wm->xr.runtime); + XrActionMap *actionmap = BLI_findlink(actionmaps, idx); + if (actionmap) { + XrActionMapItem *ami = BLI_findlink(&actionmap->items, actionmap->selitem); + if (ami) { + XrActionMapBinding *amb = ptr->data; + WM_xr_actionmap_binding_ensure_unique(ami, amb); + } + } + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_new(XrActionMap *am, + const char *name, + bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_new(am, name, replace_existing); +# else + UNUSED_VARS(am, name, replace_existing); + return NULL; +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_new_from_item(XrActionMap *am, + XrActionMapItem *ami_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_add_copy(am, ami_src); +# else + UNUSED_VARS(am, ami_src); + return NULL; +# endif +} + +static void rna_XrActionMapItem_remove(XrActionMap *am, ReportList *reports, PointerRNA *ami_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ami_ptr->data; + if (WM_xr_actionmap_item_remove(am, ami) == false) { + BKE_reportf( + reports, RPT_ERROR, "ActionMapItem '%s' cannot be removed from '%s'", ami->name, am->name); + return; + } + RNA_POINTER_INVALIDATE(ami_ptr); +# else + UNUSED_VARS(am, reports, ami_ptr); +# endif +} + +static XrActionMapItem *rna_XrActionMapItem_find(XrActionMap *am, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_item_find(am, name); +# else + UNUSED_VARS(am, name); + return NULL; +# endif +} + +static void rna_XrActionMapItem_op_name_get(PointerRNA *ptr, char *value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op[0]) { + if (ami->op_properties_ptr) { + wmOperatorType *ot = WM_operatortype_find(ami->op, 1); + if (ot) { + strcpy(value, WM_operatortype_name(ot, ami->op_properties_ptr)); + return; + } + } + strcpy(value, ami->op); + return; + } +# else + UNUSED_VARS(ptr); +# endif + value[0] = '\0'; +} + +static int rna_XrActionMapItem_op_name_length(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op[0]) { + if (ami->op_properties_ptr) { + wmOperatorType *ot = WM_operatortype_find(ami->op, 1); + if (ot) { + return strlen(WM_operatortype_name(ot, ami->op_properties_ptr)); + } + } + return strlen(ami->op); + } +# else + UNUSED_VARS(ptr); +# endif + return 0; +} + +static PointerRNA rna_XrActionMapItem_op_properties_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (ami->op_properties_ptr) { + return *(ami->op_properties_ptr); + } +# else + UNUSED_VARS(ptr); +# endif + return PointerRNA_NULL; +} + +static bool rna_XrActionMapItem_bimanual_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->action_flag & XR_ACTION_BIMANUAL) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_bimanual_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (value) { + ami->action_flag |= XR_ACTION_BIMANUAL; + } + else { + ami->action_flag &= ~XR_ACTION_BIMANUAL; + } +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_haptic_match_user_paths_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->haptic_flag & XR_HAPTIC_MATCHUSERPATHS) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_haptic_match_user_paths_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if (value) { + ami->haptic_flag |= XR_HAPTIC_MATCHUSERPATHS; + } + else { + ami->haptic_flag &= ~XR_HAPTIC_MATCHUSERPATHS; + } +# else + UNUSED_VARS(ptr, value); +# endif +} + +static int rna_XrActionMapItem_haptic_flag_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->haptic_flag & XR_HAPTIC_RELEASE) != 0) { + return ((ami->haptic_flag & XR_HAPTIC_PRESS) != 0) ? (XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE) : + XR_HAPTIC_RELEASE; + } + if ((ami->haptic_flag & XR_HAPTIC_REPEAT) != 0) { + return XR_HAPTIC_REPEAT; + } +# else + UNUSED_VARS(ptr); +# endif + return XR_HAPTIC_PRESS; +} + +static void rna_XrActionMapItem_haptic_flag_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + ami->haptic_flag &= ~(XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE | XR_HAPTIC_REPEAT); + ami->haptic_flag |= value; +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_pose_is_controller_grip_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->pose_flag & XR_POSE_GRIP) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_pose_is_controller_grip_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + SET_FLAG_FROM_TEST(ami->pose_flag, value, XR_POSE_GRIP); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static bool rna_XrActionMapItem_pose_is_controller_aim_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + if ((ami->pose_flag & XR_POSE_AIM) != 0) { + return true; + } +# else + UNUSED_VARS(ptr); +# endif + return false; +} + +static void rna_XrActionMapItem_pose_is_controller_aim_set(PointerRNA *ptr, bool value) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + SET_FLAG_FROM_TEST(ami->pose_flag, value, XR_POSE_AIM); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static void rna_XrActionMapItem_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + ListBase *actionmaps = WM_xr_actionmaps_get(wm->xr.runtime); + short idx = WM_xr_actionmap_selected_index_get(wm->xr.runtime); + XrActionMap *actionmap = BLI_findlink(actionmaps, idx); + if (actionmap) { + XrActionMapItem *ami = ptr->data; + WM_xr_actionmap_item_ensure_unique(actionmap, ami); + } + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +static void rna_XrActionMapItem_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMapItem *ami = ptr->data; + WM_xr_actionmap_item_properties_update_ot(ami); +# else + UNUSED_VARS(ptr); +# endif +} + +static XrActionMap *rna_XrActionMap_new(wmXrData *xr, const char *name, bool replace_existing) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_new(xr->runtime, name, replace_existing); +# else + UNUSED_VARS(xr, name, replace_existing); + return NULL; +# endif +} + +static XrActionMap *rna_XrActionMap_new_from_actionmap(wmXrData *xr, XrActionMap *am_src) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_add_copy(xr->runtime, am_src); +# else + UNUSED_VARS(xr, am_src); + return NULL; +# endif +} + +static void rna_XrActionMap_remove(wmXrData *xr, ReportList *reports, PointerRNA *actionmap_ptr) +{ +# ifdef WITH_XR_OPENXR + XrActionMap *actionmap = actionmap_ptr->data; + if (WM_xr_actionmap_remove(xr->runtime, actionmap) == false) { + BKE_reportf(reports, RPT_ERROR, "ActionMap '%s' cannot be removed", actionmap->name); + return; + } + RNA_POINTER_INVALIDATE(actionmap_ptr); +# else + UNUSED_VARS(xr, reports, actionmap_ptr); +# endif +} + +static XrActionMap *rna_XrActionMap_find(wmXrData *xr, const char *name) +{ +# ifdef WITH_XR_OPENXR + return WM_xr_actionmap_find(xr->runtime, name); +# else + UNUSED_VARS(xr, name); + return NULL; +# endif +} + +static void rna_XrActionMap_name_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = bmain->wm.first; + if (wm && wm->xr.runtime) { + XrActionMap *actionmap = ptr->data; + WM_xr_actionmap_ensure_unique(wm->xr.runtime, actionmap); + } +# else + UNUSED_VARS(bmain, ptr); +# endif +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + # ifdef WITH_XR_OPENXR static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) { @@ -49,6 +506,10 @@ static wmXrData *rna_XrSession_wm_xr_data_get(PointerRNA *ptr) } # endif +/* -------------------------------------------------------------------- */ +/** \name XR Session Settings + * \{ */ + static bool rna_XrSessionSettings_use_positional_tracking_get(PointerRNA *ptr) { # ifdef WITH_XR_OPENXR @@ -91,6 +552,12 @@ static void rna_XrSessionSettings_use_absolute_tracking_set(PointerRNA *ptr, boo # endif } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session State + * \{ */ + static bool rna_XrSessionState_is_running(bContext *C) { # ifdef WITH_XR_OPENXR @@ -112,6 +579,306 @@ static void rna_XrSessionState_reset_to_base_pose(bContext *C) # endif } +static bool rna_XrSessionState_action_set_create(bContext *C, XrActionMap *actionmap) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_action_set_create(&wm->xr, actionmap->name); +# else + UNUSED_VARS(C, actionmap); + return false; +# endif +} + +static bool rna_XrSessionState_action_create(bContext *C, + XrActionMap *actionmap, + XrActionMapItem *ami) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + unsigned int count_subaction_paths = 0; + const char *subaction_paths[2]; + + if (ami->user_path0[0]) { + subaction_paths[0] = ami->user_path0; + ++count_subaction_paths; + + if (ami->user_path1[0]) { + subaction_paths[1] = ami->user_path1; + ++count_subaction_paths; + } + } + else { + if (ami->user_path1[0]) { + subaction_paths[0] = ami->user_path1; + ++count_subaction_paths; + } + else { + return false; + } + } + + const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); + wmOperatorType *ot = NULL; + IDProperty *op_properties = NULL; + const char *haptic_name = NULL; + int64_t haptic_duration_msec; + + if (is_button_action) { + if (ami->op[0]) { + char idname[OP_MAX_TYPENAME]; + WM_operator_bl_idname(idname, ami->op); + ot = WM_operatortype_find(idname, true); + if (ot) { + op_properties = ami->op_properties; + } + } + + haptic_name = &ami->haptic_name[0]; + haptic_duration_msec = (int64_t)(ami->haptic_duration * 1000.0f); + } + + return WM_xr_action_create(&wm->xr, + actionmap->name, + ami->name, + ami->type, + count_subaction_paths, + subaction_paths, + ot, + op_properties, + is_button_action ? &haptic_name : NULL, + is_button_action ? &haptic_duration_msec : NULL, + is_button_action ? &ami->haptic_frequency : NULL, + is_button_action ? &ami->haptic_amplitude : NULL, + ami->op_flag, + ami->action_flag, + ami->haptic_flag); +# else + UNUSED_VARS(C, actionmap, ami); + return false; +# endif +} + +static bool rna_XrSessionState_action_binding_create(bContext *C, + XrActionMap *actionmap, + XrActionMapItem *ami, + XrActionMapBinding *amb) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + unsigned int count_subaction_paths = 0; + const char *subaction_paths[2]; + const char *component_paths[2]; + + if (ami->user_path0[0]) { + subaction_paths[0] = ami->user_path0; + component_paths[0] = amb->component_path0; + ++count_subaction_paths; + + if (ami->user_path1[0]) { + subaction_paths[1] = ami->user_path1; + component_paths[1] = amb->component_path1; + ++count_subaction_paths; + } + } + else { + if (ami->user_path1[0]) { + subaction_paths[0] = ami->user_path1; + component_paths[0] = amb->component_path1; + ++count_subaction_paths; + } + else { + return false; + } + } + + const bool is_float_action = (ami->type == XR_FLOAT_INPUT || ami->type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || ami->type == XR_BOOLEAN_INPUT); + const bool is_pose_action = (ami->type == XR_POSE_INPUT); + float float_thresholds[2]; + eXrAxisFlag axis_flags[2]; + wmXrPose poses[2]; + + if (is_float_action) { + float_thresholds[0] = float_thresholds[1] = amb->float_threshold; + } + if (is_button_action) { + axis_flags[0] = axis_flags[1] = amb->axis_flag; + } + if (is_pose_action) { + copy_v3_v3(poses[0].position, amb->pose_location); + eul_to_quat(poses[0].orientation_quat, amb->pose_rotation); + normalize_qt(poses[0].orientation_quat); + memcpy(&poses[1], &poses[0], sizeof(poses[1])); + } + + return WM_xr_action_binding_create(&wm->xr, + actionmap->name, + ami->name, + amb->profile, + count_subaction_paths, + subaction_paths, + component_paths, + is_float_action ? float_thresholds : NULL, + is_button_action ? axis_flags : NULL, + is_pose_action ? poses : NULL); +# else + UNUSED_VARS(C, actionmap, ami, amb); + return false; +# endif +} + +bool rna_XrSessionState_active_action_set_set(bContext *C, const char *action_set_name) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_active_action_set_set(&wm->xr, action_set_name); +# else + UNUSED_VARS(C, action_set_name); + return false; +# endif +} + +bool rna_XrSessionState_controller_pose_actions_set(bContext *C, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + return WM_xr_controller_pose_actions_set( + &wm->xr, action_set_name, grip_action_name, aim_action_name); +# else + UNUSED_VARS(C, action_set_name, grip_action_name, aim_action_name); + return false; +# endif +} + +void rna_XrSessionState_action_state_get(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path, + float r_state[2]) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + wmXrActionState state; + if (WM_xr_action_state_get(&wm->xr, action_set_name, action_name, user_path, &state)) { + switch (state.type) { + case XR_BOOLEAN_INPUT: + r_state[0] = (float)state.state_boolean; + r_state[1] = 0.0f; + return; + case XR_FLOAT_INPUT: + r_state[0] = state.state_float; + r_state[1] = 0.0f; + return; + case XR_VECTOR2F_INPUT: + copy_v2_v2(r_state, state.state_vector2f); + return; + case XR_POSE_INPUT: + case XR_VIBRATION_OUTPUT: + BLI_assert_unreachable(); + break; + } + } +# else + UNUSED_VARS(C, action_set_name, action_name, user_path); +# endif + zero_v2(r_state); +} + +bool rna_XrSessionState_haptic_action_apply(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path, + float duration, + float frequency, + float amplitude) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + int64_t duration_msec = (int64_t)(duration * 1000.0f); + return WM_xr_haptic_action_apply(&wm->xr, + action_set_name, + action_name, + user_path[0] ? &user_path : NULL, + &duration_msec, + &frequency, + &litude); +# else + UNUSED_VARS(C, action_set_name, action_name, user_path, duration, frequency, amplitude); + return false; +# endif +} + +void rna_XrSessionState_haptic_action_stop(bContext *C, + const char *action_set_name, + const char *action_name, + const char *user_path) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_haptic_action_stop( + &wm->xr, action_set_name, action_name, user_path[0] ? &user_path : NULL); +# else + UNUSED_VARS(C, action_set_name, action_name, user_path); +# endif +} + +static void rna_XrSessionState_controller_grip_location_get(bContext *C, + int *index, + float r_values[3]) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_grip_location_get(&wm->xr, *index, r_values); +# else + UNUSED_VARS(C, index); + zero_v3(r_values); +# endif +} + +static void rna_XrSessionState_controller_grip_rotation_get(bContext *C, + int index, + float r_values[4]) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_grip_rotation_get(&wm->xr, index, r_values); +# else + UNUSED_VARS(C, index); + unit_qt(r_values); +# endif +} + +static void rna_XrSessionState_controller_aim_location_get(bContext *C, + int *index, + float r_values[3]) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_aim_location_get(&wm->xr, *index, r_values); +# else + UNUSED_VARS(C, index); + zero_v3(r_values); +# endif +} + +static void rna_XrSessionState_controller_aim_rotation_get(bContext *C, + int index, + float r_values[4]) +{ +# ifdef WITH_XR_OPENXR + const wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_state_controller_aim_rotation_get(&wm->xr, index, r_values); +# else + UNUSED_VARS(C, index); + unit_qt(r_values); +# endif +} + static void rna_XrSessionState_viewer_pose_location_get(PointerRNA *ptr, float *r_values) { # ifdef WITH_XR_OPENXR @@ -134,8 +901,490 @@ static void rna_XrSessionState_viewer_pose_rotation_get(PointerRNA *ptr, float * # endif } +static void rna_XrSessionState_actionmaps_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + ListBase *lb = WM_xr_actionmaps_get(xr->runtime); + rna_iterator_listbase_begin(iter, lb, NULL); +# else + UNUSED_VARS(iter, ptr); +# endif +} + +static int rna_XrSessionState_active_actionmap_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return WM_xr_actionmap_active_index_get(xr->runtime); +# else + UNUSED_VARS(ptr); + return -1; +# endif +} + +static void rna_XrSessionState_active_actionmap_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + WM_xr_actionmap_active_index_set(xr->runtime, (short)value); +# else + UNUSED_VARS(ptr, value); +# endif +} + +static int rna_XrSessionState_selected_actionmap_get(PointerRNA *ptr) +{ +# ifdef WITH_XR_OPENXR + const wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + return WM_xr_actionmap_selected_index_get(xr->runtime); +# else + UNUSED_VARS(ptr); + return -1; +# endif +} + +static void rna_XrSessionState_selected_actionmap_set(PointerRNA *ptr, int value) +{ +# ifdef WITH_XR_OPENXR + wmXrData *xr = rna_XrSession_wm_xr_data_get(ptr); + WM_xr_actionmap_selected_index_set(xr->runtime, (short)value); +# else + UNUSED_VARS(ptr, value); +# endif +} + +/** \} */ + #else /* RNA_RUNTIME */ +/* -------------------------------------------------------------------- */ + +static const EnumPropertyItem rna_enum_xr_action_types[] = { + {XR_FLOAT_INPUT, + "FLOAT", + 0, + "Float", + "Float action, representing either a digital or analog button"}, + {XR_VECTOR2F_INPUT, + "VECTOR2D", + 0, + "Vector2D", + "2D float vector action, representing a thumbstick or trackpad"}, + {XR_POSE_INPUT, + "POSE", + 0, + "Pose", + "3D pose action, representing a controller's location and rotation"}, + {XR_VIBRATION_OUTPUT, + "VIBRATION", + 0, + "Vibration", + "Haptic vibration output action, to be applied with a duration, frequency, and amplitude"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_op_flags[] = { + {XR_OP_PRESS, + "PRESS", + 0, + "Press", + "Execute operator on button press (non-modal operators only)"}, + {XR_OP_RELEASE, + "RELEASE", + 0, + "Release", + "Execute operator on button release (non-modal operators only)"}, + {XR_OP_MODAL, "MODAL", 0, "Modal", "Use modal execution (modal operators only)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_haptic_flags[] = { + {XR_HAPTIC_PRESS, "PRESS", 0, "Press", "Apply haptics on button press"}, + {XR_HAPTIC_RELEASE, "RELEASE", 0, "Release", "Apply haptics on button release"}, + {XR_HAPTIC_PRESS | XR_HAPTIC_RELEASE, + "PRESS_RELEASE", + 0, + "Press Release", + "Apply haptics on button press and release"}, + {XR_HAPTIC_REPEAT, + "REPEAT", + 0, + "Repeat", + "Apply haptics repeatedly for the duration of the button press"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_axis0_flags[] = { + {0, "ANY", 0, "Any", "Use any axis region for operator execution"}, + {XR_AXIS0_POS, + "POSITIVE", + 0, + "Positive", + "Use positive axis region only for operator execution"}, + {XR_AXIS0_NEG, + "NEGATIVE", + 0, + "Negative", + "Use negative axis region only for operator execution"}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem rna_enum_xr_axis1_flags[] = { + {0, "ANY", 0, "Any", "Use any axis region for operator execution"}, + {XR_AXIS1_POS, + "POSITIVE", + 0, + "Positive", + "Use positive axis region only for operator execution"}, + {XR_AXIS1_NEG, + "NEGATIVE", + 0, + "Negative", + "Use negative axis region only for operator execution"}, + {0, NULL, 0, NULL, NULL}, +}; + +/* -------------------------------------------------------------------- */ +/** \name XR Action Map + * \{ */ + +static void rna_def_xr_actionmap_bindings(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMapBindings"); + srna = RNA_def_struct(brna, "XrActionMapBindings", NULL); + RNA_def_struct_sdna(srna, "XrActionMapItem"); + RNA_def_struct_ui_text(srna, "XR Action Map Bindings", "Collection of XR action map bindings"); + + func = RNA_def_function(srna, "new", "rna_XrActionMapBinding_new"); + parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map binding", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing binding with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "binding", "XrActionMapBinding", "Binding", "Added action map binding"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_binding", "rna_XrActionMapBinding_new_from_binding"); + parm = RNA_def_pointer( + func, "binding", "XrActionMapBinding", "Binding", "Binding to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "result", "XrActionMapBinding", "Binding", "Added action map binding"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMapBinding_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "binding", "XrActionMapBinding", "Binding", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMapBinding_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, + "binding", + "XrActionMapBinding", + "Binding", + "The action map binding with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmap_items(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMapItems"); + srna = RNA_def_struct(brna, "XrActionMapItems", NULL); + RNA_def_struct_sdna(srna, "XrActionMap"); + RNA_def_struct_ui_text(srna, "XR Action Map Items", "Collection of XR action map items"); + + func = RNA_def_function(srna, "new", "rna_XrActionMapItem_new"); + parm = RNA_def_string(func, "name", NULL, 0, "Name of the action map item", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing item with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", "Added action map item"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_item", "rna_XrActionMapItem_new_from_item"); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", "Item to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "XrActionMapItem", "Item", "Added action map item"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMapItem_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "item", "XrActionMapItem", "Item", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMapItem_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "item", "XrActionMapItem", "Item", "The action map item with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmaps(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "XrActionMaps"); + srna = RNA_def_struct(brna, "XrActionMaps", NULL); + RNA_def_struct_sdna(srna, "wmXrData"); + RNA_def_struct_ui_text(srna, "XR Action Maps", "Collection of XR action maps"); + + func = RNA_def_function(srna, "new", "rna_XrActionMap_new"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, + "replace_existing", + true, + "Replace Existing", + "Replace any existing actionmap with the same name"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "Action Map", "Added action map"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "new_from_actionmap", "rna_XrActionMap_new_from_actionmap"); + parm = RNA_def_pointer( + func, "actionmap", "XrActionMap", "Action Map", "Action map to use as a reference"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "result", "XrActionMap", "Action Map", "Added action map"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_XrActionMap_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "Action Map", "Removed action map"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + + func = RNA_def_function(srna, "find", "rna_XrActionMap_find"); + parm = RNA_def_string(func, "name", NULL, MAX_NAME, "Name", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_pointer( + func, "actionmap", "XrActionMap", "Action Map", "The action map with the given name"); + RNA_def_function_return(func, parm); +} + +static void rna_def_xr_actionmap(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + /* XrActionMap */ + srna = RNA_def_struct(brna, "XrActionMap", NULL); + RNA_def_struct_sdna(srna, "XrActionMap"); + RNA_def_struct_ui_text(srna, "XR Action Map", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map"); + RNA_def_property_update(prop, 0, "rna_XrActionMap_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "actionmap_items", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_sdna(prop, NULL, "items", NULL); + RNA_def_property_struct_type(prop, "XrActionMapItem"); + RNA_def_property_ui_text( + prop, + "Items", + "Items in the action map, mapping an XR event to an operator, pose, or haptic output"); + rna_def_xr_actionmap_items(brna, prop); + + prop = RNA_def_property(srna, "selected_item", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "selitem"); + RNA_def_property_ui_text(prop, "Selected Item", ""); + + /* XrActionMapItem */ + srna = RNA_def_struct(brna, "XrActionMapItem", NULL); + RNA_def_struct_sdna(srna, "XrActionMapItem"); + RNA_def_struct_ui_text(srna, "XR Action Map Item", ""); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map item"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_action_types); + RNA_def_property_ui_text(prop, "Type", "Action type"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "user_path0", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 64); + RNA_def_property_ui_text(prop, "User Path 0", "OpenXR user path"); + + prop = RNA_def_property(srna, "user_path1", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 64); + RNA_def_property_ui_text(prop, "User Path 1", "OpenXR user path"); + + prop = RNA_def_property(srna, "op", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, OP_MAX_TYPENAME); + RNA_def_property_ui_text(prop, "Operator", "Identifier of operator to call on action event"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "op_name", PROP_STRING, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, "Operator Name", "Name of operator (translated) to call on action event"); + RNA_def_property_string_funcs( + prop, "rna_XrActionMapItem_op_name_get", "rna_XrActionMapItem_op_name_length", NULL); + + prop = RNA_def_property(srna, "op_properties", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "OperatorProperties"); + RNA_def_property_pointer_funcs(prop, "rna_XrActionMapItem_op_properties_get", NULL, NULL, NULL); + RNA_def_property_ui_text( + prop, "Operator Properties", "Properties to set when the operator is called"); + RNA_def_property_update(prop, 0, "rna_XrActionMapItem_update"); + + prop = RNA_def_property(srna, "op_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "op_flag"); + RNA_def_property_enum_items(prop, rna_enum_xr_op_flags); + RNA_def_property_ui_text(prop, "Operator Mode", "Operator execution mode"); + + prop = RNA_def_property(srna, "bimanual", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs( + prop, "rna_XrActionMapItem_bimanual_get", "rna_XrActionMapItem_bimanual_set"); + RNA_def_property_ui_text( + prop, "Bimanual", "The action depends on the states/poses of both user paths"); + + prop = RNA_def_property(srna, "pose_is_controller_grip", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_pose_is_controller_grip_get", + "rna_XrActionMapItem_pose_is_controller_grip_set"); + RNA_def_property_ui_text( + prop, "Is Controller Grip", "The action poses will be used for the VR controller grips"); + + prop = RNA_def_property(srna, "pose_is_controller_aim", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_pose_is_controller_aim_get", + "rna_XrActionMapItem_pose_is_controller_aim_set"); + RNA_def_property_ui_text( + prop, "Is Controller Aim", "The action poses will be used for the VR controller aims"); + + prop = RNA_def_property(srna, "haptic_name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text( + prop, "Haptic Name", "Name of the haptic action to apply when executing this action"); + + prop = RNA_def_property(srna, "haptic_match_user_paths", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_funcs(prop, + "rna_XrActionMapItem_haptic_match_user_paths_get", + "rna_XrActionMapItem_haptic_match_user_paths_set"); + RNA_def_property_ui_text( + prop, + "Haptic Match User Paths", + "Apply haptics to the same user paths for the haptic action and this action"); + + prop = RNA_def_property(srna, "haptic_duration", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_text(prop, + "Haptic Duration", + "Haptic duration in seconds. 0.0 is the minimum supported duration"); + + prop = RNA_def_property(srna, "haptic_frequency", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_text(prop, + "Haptic Frequency", + "Frequency of the haptic vibration in hertz. 0.0 specifies the OpenXR " + "runtime's default frequency"); + + prop = RNA_def_property(srna, "haptic_amplitude", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text( + prop, "Haptic Amplitude", "Intensity of the haptic vibration, ranging from 0.0 to 1.0"); + + prop = RNA_def_property(srna, "haptic_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_haptic_flags); + RNA_def_property_enum_funcs( + prop, "rna_XrActionMapItem_haptic_flag_get", "rna_XrActionMapItem_haptic_flag_set", NULL); + RNA_def_property_ui_text(prop, "Haptic mode", "Haptic application mode"); + + prop = RNA_def_property(srna, "bindings", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "XrActionMapBinding"); + RNA_def_property_ui_text( + prop, "Bindings", "Bindings for the action map item, mapping the action to an XR input"); + rna_def_xr_actionmap_bindings(brna, prop); + + prop = RNA_def_property(srna, "selected_binding", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "selbinding"); + RNA_def_property_ui_text(prop, "Selected Binding", "Currently selected binding"); + + /* XrActionMapBinding */ + srna = RNA_def_struct(brna, "XrActionMapBinding", NULL); + RNA_def_struct_sdna(srna, "XrActionMapBinding"); + RNA_def_struct_ui_text(srna, "XR Action Map Binding", "Binding in an XR action map item"); + + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text(prop, "Name", "Name of the action map binding"); + RNA_def_property_update(prop, 0, "rna_XrActionMapBinding_name_update"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "profile", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 256); + RNA_def_property_ui_text(prop, "Profile", "OpenXR interaction profile path"); + + prop = RNA_def_property(srna, "component_path0", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 192); + RNA_def_property_ui_text(prop, "Component Path 0", "OpenXR component path"); + + prop = RNA_def_property(srna, "component_path1", PROP_STRING, PROP_NONE); + RNA_def_property_string_maxlength(prop, 192); + RNA_def_property_ui_text(prop, "Component Path 1", "OpenXR component path"); + + prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "float_threshold"); + RNA_def_property_range(prop, 0.0, 1.0); + RNA_def_property_ui_text(prop, "Threshold", "Input threshold for button/axis actions"); + + prop = RNA_def_property(srna, "axis0_region", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_axis0_flags); + RNA_def_property_enum_funcs(prop, + "rna_XrActionMapBinding_axis0_flag_get", + "rna_XrActionMapBinding_axis0_flag_set", + NULL); + RNA_def_property_ui_text( + prop, "Axis 0 Region", "Action execution region for the first input axis"); + + prop = RNA_def_property(srna, "axis1_region", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, rna_enum_xr_axis1_flags); + RNA_def_property_enum_funcs(prop, + "rna_XrActionMapBinding_axis1_flag_get", + "rna_XrActionMapBinding_axis1_flag_set", + NULL); + RNA_def_property_ui_text( + prop, "Axis 1 Region", "Action execution region for the second input axis"); + + prop = RNA_def_property(srna, "pose_location", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_ui_text(prop, "Pose Location Offset", ""); + + prop = RNA_def_property(srna, "pose_rotation", PROP_FLOAT, PROP_EULER); + RNA_def_property_ui_text(prop, "Pose Rotation Offset", ""); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session Settings + * \{ */ + static void rna_def_xr_session_settings(BlenderRNA *brna) { StructRNA *srna; @@ -241,6 +1490,12 @@ static void rna_def_xr_session_settings(BlenderRNA *brna) RNA_def_property_update(prop, NC_WM | ND_XR_DATA_CHANGED, NULL); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name XR Session State + * \{ */ + static void rna_def_xr_session_state(BlenderRNA *brna) { StructRNA *srna; @@ -265,6 +1520,260 @@ static void rna_def_xr_session_state(BlenderRNA *brna) parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + func = RNA_def_function(srna, "action_set_create", "rna_XrSessionState_action_set_create"); + RNA_def_function_ui_description(func, "Create a VR action set"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "action_create", "rna_XrSessionState_action_create"); + RNA_def_function_ui_description(func, "Create a VR action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_item", "XrActionMapItem", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "action_binding_create", "rna_XrSessionState_action_binding_create"); + RNA_def_function_ui_description(func, "Create a VR action binding"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap", "XrActionMap", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_item", "XrActionMapItem", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_pointer(func, "actionmap_binding", "XrActionMapBinding", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "active_action_set_set", "rna_XrSessionState_active_action_set_set"); + RNA_def_function_ui_description(func, "Set the active VR action set"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function( + srna, "controller_pose_actions_set", "rna_XrSessionState_controller_pose_actions_set"); + RNA_def_function_ui_description(func, "Set the actions that determine the VR controller poses"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, + "grip_action", + NULL, + 64, + "Grip Action", + "Name of the action representing the controller grips"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, + "aim_action", + NULL, + 64, + "Aim Action", + "Name of the action representing the controller aims"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "action_state_get", "rna_XrSessionState_action_state_get"); + RNA_def_function_ui_description(func, "Get the current state of a VR action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "user_path", NULL, 64, "User Path", "OpenXR user path"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float_array( + func, + "state", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Action State", + "Current state of the VR action. Second float value is only set for 2D vector type actions", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function(srna, "haptic_action_apply", "rna_XrSessionState_haptic_action_apply"); + RNA_def_function_ui_description(func, "Apply a VR haptic action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string( + func, + "user_path", + NULL, + 64, + "User Path", + "Optional OpenXR user path. If not set, the action will be applied to all paths"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_float(func, + "duration", + 0.0f, + 0.0f, + FLT_MAX, + "Duration", + "Haptic duration in seconds. 0.0 is the minimum supported duration", + 0.0f, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "frequency", + 0.0f, + 0.0f, + FLT_MAX, + "Frequency", + "Frequency of the haptic vibration in hertz. 0.0 specifies the OpenXR " + "runtime's default frequency", + 0.0f, + FLT_MAX); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float(func, + "amplitude", + 1.0f, + 0.0f, + 1.0f, + "Amplitude", + "Haptic amplitude, ranging from 0.0 to 1.0", + 0.0f, + 1.0f); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_boolean(func, "result", 0, "Result", ""); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "haptic_action_stop", "rna_XrSessionState_haptic_action_stop"); + RNA_def_function_ui_description(func, "Stop a VR haptic action"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_set_name", NULL, 64, "Action Set", "Action set name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string(func, "action_name", NULL, 64, "Action", "Action name"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_string( + func, + "user_path", + NULL, + 64, + "User Path", + "Optional OpenXR user path. If not set, the action will be stopped for all paths"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + + func = RNA_def_function( + srna, "controller_grip_location_get", "rna_XrSessionState_controller_grip_location_get"); + RNA_def_function_ui_description(func, + "Get the last known controller grip location in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_float_translation(func, + "location", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Controller grip location", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_grip_rotation_get", "rna_XrSessionState_controller_grip_rotation_get"); + RNA_def_function_ui_description( + func, "Get the last known controller grip rotation (quaternion) in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float_vector(func, + "rotation", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "Rotation", + "Controller grip quaternion rotation", + -FLT_MAX, + FLT_MAX); + parm->subtype = PROP_QUATERNION; + RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_aim_location_get", "rna_XrSessionState_controller_aim_location_get"); + RNA_def_function_ui_description(func, + "Get the last known controller aim location in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + RNA_def_float_translation(func, + "location", + 3, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Controller aim location", + -FLT_MAX, + FLT_MAX); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + + func = RNA_def_function( + srna, "controller_aim_rotation_get", "rna_XrSessionState_controller_aim_rotation_get"); + RNA_def_function_ui_description( + func, "Get the last known controller aim rotation (quaternion) in world space"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + parm = RNA_def_int(func, "index", 0, 0, 255, "Index", "Controller index", 0, 255); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + parm = RNA_def_float_vector(func, + "rotation", + 4, + NULL, + -FLT_MAX, + FLT_MAX, + "Rotation", + "Controller aim quaternion rotation", + -FLT_MAX, + FLT_MAX); + parm->subtype = PROP_QUATERNION; + RNA_def_property_ui_range(parm, -FLT_MAX, FLT_MAX, 1, 5); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_OUTPUT); + prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 3); RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL); @@ -282,12 +1791,43 @@ static void rna_def_xr_session_state(BlenderRNA *brna) prop, "Viewer Pose Rotation", "Last known rotation of the viewer pose (center between the eyes) in world space"); + + prop = RNA_def_property(srna, "actionmaps", PROP_COLLECTION, PROP_NONE); + RNA_def_property_collection_funcs(prop, + "rna_XrSessionState_actionmaps_begin", + "rna_iterator_listbase_next", + "rna_iterator_listbase_end", + "rna_iterator_listbase_get", + NULL, + NULL, + NULL, + NULL); + RNA_def_property_struct_type(prop, "XrActionMap"); + RNA_def_property_ui_text(prop, "XR Action Maps", ""); + rna_def_xr_actionmaps(brna, prop); + + prop = RNA_def_property(srna, "active_actionmap", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, + "rna_XrSessionState_active_actionmap_get", + "rna_XrSessionState_active_actionmap_set", + NULL); + RNA_def_property_ui_text(prop, "Active Action Map", ""); + + prop = RNA_def_property(srna, "selected_actionmap", PROP_INT, PROP_NONE); + RNA_def_property_int_funcs(prop, + "rna_XrSessionState_selected_actionmap_get", + "rna_XrSessionState_selected_actionmap_set", + NULL); + RNA_def_property_ui_text(prop, "Selected Action Map", ""); } +/** \} */ + void RNA_def_xr(BlenderRNA *brna) { RNA_define_animate_sdna(false); + rna_def_xr_actionmap(brna); rna_def_xr_session_settings(brna); rna_def_xr_session_state(brna); diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 63495c4104e..a36a8c386b4 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -66,7 +66,7 @@ struct BLaplacianSystem { int numVerts; /* Number of verts. */ short *numNeFa; /* Number of neighbors faces around vertice. */ short *numNeEd; /* Number of neighbors Edges around vertice. */ - short *zerola; /* Is zero area or length. */ + bool *zerola; /* Is zero area or length. */ /* Pointers to data. */ float (*vertexCos)[3]; @@ -130,7 +130,7 @@ static void memset_laplacian_system(LaplacianSystem *sys, int val) memset(sys->ring_areas, val, sizeof(float) * sys->numVerts); memset(sys->vlengths, val, sizeof(float) * sys->numVerts); memset(sys->vweights, val, sizeof(float) * sys->numVerts); - memset(sys->zerola, val, sizeof(short) * sys->numVerts); + memset(sys->zerola, val, sizeof(bool) * sys->numVerts); } static LaplacianSystem *init_laplacian_system(int a_numEdges, @@ -152,7 +152,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, sys->ring_areas = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); sys->vlengths = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); sys->vweights = MEM_calloc_arrayN(sys->numVerts, sizeof(float), __func__); - sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(short), __func__); + sys->zerola = MEM_calloc_arrayN(sys->numVerts, sizeof(bool), __func__); return sys; } @@ -225,8 +225,8 @@ static void init_laplacian_matrix(LaplacianSystem *sys) sys->numNeEd[idv2] = sys->numNeEd[idv2] + 1; w1 = len_v3v3(v1, v2); if (w1 < sys->min_area) { - sys->zerola[idv1] = 1; - sys->zerola[idv2] = 1; + sys->zerola[idv1] = true; + sys->zerola[idv2] = true; } else { w1 = 1.0f / w1; @@ -253,7 +253,7 @@ static void init_laplacian_matrix(LaplacianSystem *sys) areaf = area_tri_v3(v_prev, v_curr, v_next); if (areaf < sys->min_area) { - sys->zerola[l_curr->v] = 1; + sys->zerola[l_curr->v] = true; } sys->ring_areas[l_prev->v] += areaf; @@ -300,7 +300,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) const uint l_curr_index = l_curr - sys->mloop; /* Is ring if number of faces == number of edges around vertice. */ - if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == 0) { + if (sys->numNeEd[l_curr->v] == sys->numNeFa[l_curr->v] && sys->zerola[l_curr->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_curr->v, l_next->v, @@ -310,7 +310,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) l_prev->v, sys->fweights[l_curr_index][1] * sys->vweights[l_curr->v]); } - if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == 0) { + if (sys->numNeEd[l_next->v] == sys->numNeFa[l_next->v] && sys->zerola[l_next->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_next->v, l_curr->v, @@ -320,7 +320,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) l_prev->v, sys->fweights[l_curr_index][0] * sys->vweights[l_next->v]); } - if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == 0) { + if (sys->numNeEd[l_prev->v] == sys->numNeFa[l_prev->v] && sys->zerola[l_prev->v] == false) { EIG_linear_solver_matrix_add(sys->context, l_prev->v, l_curr->v, @@ -338,7 +338,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) idv2 = sys->medges[i].v2; /* Is boundary */ if (sys->numNeEd[idv1] != sys->numNeFa[idv1] && sys->numNeEd[idv2] != sys->numNeFa[idv2] && - sys->zerola[idv1] == 0 && sys->zerola[idv2] == 0) { + sys->zerola[idv1] == false && sys->zerola[idv2] == false) { EIG_linear_solver_matrix_add( sys->context, idv1, idv2, sys->eweights[i] * sys->vlengths[idv1]); EIG_linear_solver_matrix_add( @@ -358,7 +358,7 @@ static void validate_solution(LaplacianSystem *sys, short flag, float lambda, fl sys->vert_centroid, sys->vertexCos, sys->mpoly, sys->numPolys, sys->mloop); } for (i = 0; i < sys->numVerts; i++) { - if (sys->zerola[i] == 0) { + if (sys->zerola[i] == false) { lam = sys->numNeEd[i] == sys->numNeFa[i] ? (lambda >= 0.0f ? 1.0f : -1.0f) : (lambda_border >= 0.0f ? 1.0f : -1.0f); if (flag & MOD_LAPLACIANSMOOTH_X) { @@ -442,7 +442,7 @@ static void laplaciansmoothModifier_do( wpaint = 1.0f; } - if (sys->zerola[i] == 0) { + if (sys->zerola[i] == false) { if (smd->flag & MOD_LAPLACIANSMOOTH_NORMALIZED) { w = sys->vweights[i]; sys->vweights[i] = (w == 0.0f) ? 0.0f : -fabsf(smd->lambda) * wpaint / w; diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc index 1391587fa7d..47dfd9bc8f6 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.cc +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.cc @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh index f4ee6242dcb..d8c60d31986 100644 --- a/source/blender/modifiers/intern/MOD_nodes_evaluator.hh +++ b/source/blender/modifiers/intern/MOD_nodes_evaluator.hh @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 8f3206da5be..1c502b94bdb 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -95,8 +95,9 @@ static void initData(ModifierData *md) BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); omd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution); - simulate_ocean_modifier(omd); + if (BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution)) { + simulate_ocean_modifier(omd); + } #else /* WITH_OCEANSIM */ UNUSED_VARS(md); #endif /* WITH_OCEANSIM */ @@ -132,8 +133,9 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tomd->oceancache = NULL; tomd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution); - simulate_ocean_modifier(tomd); + if (BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution)) { + simulate_ocean_modifier(tomd); + } #else /* WITH_OCEANSIM */ /* unused */ (void)md; @@ -323,6 +325,10 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, co static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { OceanModifierData *omd = (OceanModifierData *)md; + if (omd->ocean && !BKE_ocean_is_valid(omd->ocean)) { + BKE_modifier_set_error(ctx->object, md, "Failed to allocate memory"); + return mesh; + } int cfra_scene = (int)DEG_get_ctime(ctx->depsgraph); Object *ob = ctx->object; bool allocated_ocean = false; diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 6adb25ccc01..7668d0f4f04 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -176,6 +176,7 @@ set(SRC geometry/nodes/node_geo_curve_resample.cc geometry/nodes/node_geo_curve_reverse.cc geometry/nodes/node_geo_curve_set_handles.cc + geometry/nodes/node_geo_curve_spline_type.cc geometry/nodes/node_geo_curve_subdivide.cc geometry/nodes/node_geo_curve_to_mesh.cc geometry/nodes/node_geo_curve_to_points.cc diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h index cc458e6bece..868c79ed2f6 100644 --- a/source/blender/nodes/NOD_geometry.h +++ b/source/blender/nodes/NOD_geometry.h @@ -63,6 +63,7 @@ void register_node_type_geo_curve_primitive_star(void); void register_node_type_geo_curve_resample(void); void register_node_type_geo_curve_reverse(void); void register_node_type_geo_curve_set_handles(void); +void register_node_type_geo_curve_spline_type(void); void register_node_type_geo_curve_subdivide(void); void register_node_type_geo_curve_to_mesh(void); void register_node_type_geo_curve_to_points(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 955f8393d43..16ba3000fba 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -61,7 +61,7 @@ DefNode(ShaderNode, SH_NODE_COMBRGB, 0, "COMBRG DefNode(ShaderNode, SH_NODE_HUE_SAT, 0, "HUE_SAT", HueSaturation, "Hue/Saturation", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_MATERIAL, def_sh_output, "OUTPUT_MATERIAL", OutputMaterial, "Material Output", "" ) -DefNode(ShaderNode, SH_NODE_EEVEE_SPECULAR, 0, "EEVEE_SPECULAR", EeveeSpecular, "Specular", "" ) +DefNode(ShaderNode, SH_NODE_EEVEE_SPECULAR, 0, "EEVEE_SPECULAR", EeveeSpecular, "Specular BSDF", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_LIGHT, def_sh_output, "OUTPUT_LIGHT", OutputLight, "Light Output", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_WORLD, def_sh_output, "OUTPUT_WORLD", OutputWorld, "World Output", "" ) DefNode(ShaderNode, SH_NODE_OUTPUT_LINESTYLE, def_sh_output_linestyle,"OUTPUT_LINESTYLE", OutputLineStyle, "Line Style Output", "" ) @@ -303,6 +303,7 @@ DefNode(GeometryNode, GEO_NODE_CURVE_PRIMITIVE_STAR, 0, "CURVE_PRIMITIVE_STAR", DefNode(GeometryNode, GEO_NODE_CURVE_RESAMPLE, def_geo_curve_resample, "CURVE_RESAMPLE", CurveResample, "Resample Curve", "") DefNode(GeometryNode, GEO_NODE_CURVE_REVERSE, 0, "CURVE_REVERSE", CurveReverse, "Curve Reverse", "") DefNode(GeometryNode, GEO_NODE_CURVE_SET_HANDLES, def_geo_curve_set_handles, "CURVE_SET_HANDLES", CurveSetHandles, "Set Handle Type", "") +DefNode(GeometryNode, GEO_NODE_CURVE_SPLINE_TYPE, def_geo_curve_spline_type, "CURVE_SPLINE_TYPE", CurveSplineType, "Set Spline Type", "") DefNode(GeometryNode, GEO_NODE_CURVE_SUBDIVIDE, def_geo_curve_subdivide, "CURVE_SUBDIVIDE", CurveSubdivide, "Curve Subdivide", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_MESH, 0, "CURVE_TO_MESH", CurveToMesh, "Curve to Mesh", "") DefNode(GeometryNode, GEO_NODE_CURVE_TO_POINTS, def_geo_curve_to_points, "CURVE_TO_POINTS", CurveToPoints, "Curve to Points", "") diff --git a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c index 81e2408fcf9..a5906c31093 100644 --- a/source/blender/nodes/composite/nodes/node_composite_antialiasing.c +++ b/source/blender/nodes/composite/nodes/node_composite_antialiasing.c @@ -1,6 +1,4 @@ /* - * ***** 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 @@ -19,10 +17,6 @@ * All rights reserved. * * The Original Code is: all of this file. - * - * Contributor(s): IRIE Shinsuke - * - * ***** END GPL LICENSE BLOCK ***** */ /** \file diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c index 3ffad8216de..ec5c79cc087 100644 --- a/source/blender/nodes/composite/nodes/node_composite_switchview.c +++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c @@ -132,7 +132,7 @@ static void init_switch_view(const bContext *C, PointerRNA *ptr) for (nr = 0, srv = rd->views.first; srv; srv = srv->next, nr++) { sock = ntreeCompositSwitchViewAddSocket(ntree, node, srv->name); - if ((srv->viewflag & SCE_VIEW_DISABLE)) { + if (srv->viewflag & SCE_VIEW_DISABLE) { sock->flag |= SOCK_HIDDEN; } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc new file mode 100644 index 00000000000..fe3f42625ae --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc @@ -0,0 +1,307 @@ +/* + * 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. + */ + +#include "BKE_spline.hh" + +#include "BLI_task.hh" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "node_geometry_util.hh" + +static bNodeSocketTemplate geo_node_curve_spline_type_in[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {SOCK_STRING, N_("Selection")}, + {-1, ""}, +}; + +static bNodeSocketTemplate geo_node_curve_spline_type_out[] = { + {SOCK_GEOMETRY, N_("Curve")}, + {-1, ""}, +}; + +static void geo_node_curve_spline_type_layout(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "spline_type", 0, "", ICON_NONE); +} + +namespace blender::nodes { + +static void geo_node_curve_spline_type_init(bNodeTree *UNUSED(tree), bNode *node) +{ + NodeGeometryCurveSplineType *data = (NodeGeometryCurveSplineType *)MEM_callocN( + sizeof(NodeGeometryCurveSplineType), __func__); + + data->spline_type = GEO_NODE_SPLINE_TYPE_POLY; + node->storage = data; +} + +template<class T> +static void scale_input_assign(const Span<T> input, + const int scale, + const int offset, + const MutableSpan<T> r_output) +{ + for (const int i : IndexRange(r_output.size())) { + r_output[i] = input[i * scale + offset]; + } +} + +template<class T> +static void scale_output_assign(const Span<T> input, + const int scale, + const int offset, + const MutableSpan<T> &r_output) +{ + for (const int i : IndexRange(input.size())) { + r_output[i * scale + offset] = input[i]; + } +} + +template<typename CopyFn> +static void copy_attributes(const Spline &input_spline, Spline &output_spline, CopyFn copy_fn) +{ + input_spline.attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + std::optional<GSpan> src = input_spline.attributes.get_for_read(name); + BLI_assert(src); + if (!output_spline.attributes.create(name, meta_data.data_type)) { + BLI_assert_unreachable(); + return false; + } + std::optional<GMutableSpan> dst = output_spline.attributes.get_for_write(name); + if (!dst) { + BLI_assert_unreachable(); + return false; + } + + copy_fn(*src, *dst); + + return true; + }, + ATTR_DOMAIN_POINT); +} + +static SplinePtr convert_to_poly_spline(const Spline &input) +{ + std::unique_ptr<PolySpline> output = std::make_unique<PolySpline>(); + output->resize(input.positions().size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + Spline::copy_base_settings(input, *output); + output->attributes = input.attributes; + return output; +} + +static SplinePtr poly_to_nurbs(const Spline &input) +{ + std::unique_ptr<NURBSpline> output = std::make_unique<NURBSpline>(); + output->resize(input.positions().size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + output->weights().fill(1.0f); + output->set_resolution(12); + output->set_order(4); + Spline::copy_base_settings(input, *output); + output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->attributes = input.attributes; + return output; +} + +static SplinePtr bezier_to_nurbs(const Spline &input) +{ + const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(input); + std::unique_ptr<NURBSpline> output = std::make_unique<NURBSpline>(); + output->resize(input.size() * 3); + + scale_output_assign(bezier_spline.handle_positions_left(), 3, 0, output->positions()); + scale_output_assign(input.radii(), 3, 0, output->radii()); + scale_output_assign(input.tilts(), 3, 0, output->tilts()); + + scale_output_assign(bezier_spline.positions(), 3, 1, output->positions()); + scale_output_assign(input.radii(), 3, 1, output->radii()); + scale_output_assign(input.tilts(), 3, 1, output->tilts()); + + scale_output_assign(bezier_spline.handle_positions_right(), 3, 2, output->positions()); + scale_output_assign(input.radii(), 3, 2, output->radii()); + scale_output_assign(input.tilts(), 3, 2, output->tilts()); + + Spline::copy_base_settings(input, *output); + output->weights().fill(1.0f); + output->set_resolution(12); + output->set_order(4); + output->set_cyclic(input.is_cyclic()); + output->knots_mode = NURBSpline::KnotsMode::Bezier; + output->attributes.reallocate(output->size()); + copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + scale_output_assign<T>(src.typed<T>(), 3, 0, dst.typed<T>()); + scale_output_assign<T>(src.typed<T>(), 3, 1, dst.typed<T>()); + scale_output_assign<T>(src.typed<T>(), 3, 2, dst.typed<T>()); + }); + }); + return output; +} + +static SplinePtr poly_to_bezier(const Spline &input) +{ + std::unique_ptr<BezierSpline> output = std::make_unique<BezierSpline>(); + output->resize(input.size()); + output->positions().copy_from(input.positions()); + output->radii().copy_from(input.radii()); + output->tilts().copy_from(input.tilts()); + output->handle_types_left().fill(BezierSpline::HandleType::Vector); + output->handle_types_right().fill(BezierSpline::HandleType::Vector); + output->set_resolution(12); + Spline::copy_base_settings(input, *output); + output->attributes = input.attributes; + return output; +} + +static SplinePtr nurbs_to_bezier(const Spline &input) +{ + const NURBSpline &nurbs_spline = static_cast<const NURBSpline &>(input); + std::unique_ptr<BezierSpline> output = std::make_unique<BezierSpline>(); + output->resize(input.size() / 3); + scale_input_assign<float3>(input.positions(), 3, 1, output->positions()); + scale_input_assign<float3>(input.positions(), 3, 0, output->handle_positions_left()); + scale_input_assign<float3>(input.positions(), 3, 2, output->handle_positions_right()); + scale_input_assign<float>(input.radii(), 3, 2, output->radii()); + scale_input_assign<float>(input.tilts(), 3, 2, output->tilts()); + output->handle_types_left().fill(BezierSpline::HandleType::Align); + output->handle_types_right().fill(BezierSpline::HandleType::Align); + output->set_resolution(nurbs_spline.resolution()); + Spline::copy_base_settings(input, *output); + output->attributes.reallocate(output->size()); + copy_attributes(input, *output, [](GSpan src, GMutableSpan dst) { + attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { + using T = decltype(dummy); + scale_input_assign<T>(src.typed<T>(), 3, 1, dst.typed<T>()); + }); + }); + return output; +} + +static SplinePtr convert_to_bezier(const Spline &input, GeoNodeExecParams params) +{ + switch (input.type()) { + case Spline::Type::Bezier: + return input.copy(); + case Spline::Type::Poly: + return poly_to_bezier(input); + case Spline::Type::NURBS: + if (input.size() < 6) { + params.error_message_add( + NodeWarningType::Info, + TIP_("NURBS must have minimum of 6 points for Bezier Conversion")); + return input.copy(); + } + else { + if (input.size() % 3 != 0) { + params.error_message_add(NodeWarningType::Info, + TIP_("NURBS must have multiples of 3 points for full Bezier " + "conversion, curve truncated")); + } + return nurbs_to_bezier(input); + } + } + BLI_assert_unreachable(); + return {}; +} + +static SplinePtr convert_to_nurbs(const Spline &input) +{ + switch (input.type()) { + case Spline::Type::NURBS: + return input.copy(); + case Spline::Type::Bezier: + return bezier_to_nurbs(input); + case Spline::Type::Poly: + return poly_to_nurbs(input); + } + BLI_assert_unreachable(); + return {}; +} + +static void geo_node_curve_spline_type_exec(GeoNodeExecParams params) +{ + const NodeGeometryCurveSplineType *storage = + (const NodeGeometryCurveSplineType *)params.node().storage; + const GeometryNodeSplineType output_type = (const GeometryNodeSplineType)storage->spline_type; + + GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve"); + geometry_set = bke::geometry_set_realize_instances(geometry_set); + if (!geometry_set.has_curve()) { + params.set_output("Curve", geometry_set); + return; + } + + const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>(); + const CurveEval &curve = *curve_component->get_for_read(); + + const std::string selection_name = params.extract_input<std::string>("Selection"); + GVArray_Typed<bool> selection = curve_component->attribute_get_for_read( + selection_name, ATTR_DOMAIN_CURVE, true); + + std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>(); + for (const int i : curve.splines().index_range()) { + if (selection[i]) { + switch (output_type) { + case GEO_NODE_SPLINE_TYPE_POLY: + new_curve->add_spline(convert_to_poly_spline(*curve.splines()[i])); + break; + case GEO_NODE_SPLINE_TYPE_BEZIER: + new_curve->add_spline(convert_to_bezier(*curve.splines()[i], params)); + break; + case GEO_NODE_SPLINE_TYPE_NURBS: + new_curve->add_spline(convert_to_nurbs(*curve.splines()[i])); + break; + } + } + else { + new_curve->add_spline(curve.splines()[i]->copy()); + } + } + + new_curve->attributes = curve.attributes; + params.set_output("Curve", GeometrySet::create_with_curve(new_curve.release())); +} + +} // namespace blender::nodes + +void register_node_type_geo_curve_spline_type() +{ + static bNodeType ntype; + geo_node_type_base( + &ntype, GEO_NODE_CURVE_SPLINE_TYPE, "Set Spline Type", NODE_CLASS_GEOMETRY, 0); + node_type_socket_templates( + &ntype, geo_node_curve_spline_type_in, geo_node_curve_spline_type_out); + ntype.geometry_node_execute = blender::nodes::geo_node_curve_spline_type_exec; + node_type_init(&ntype, blender::nodes::geo_node_curve_spline_type_init); + node_type_storage(&ntype, + "NodeGeometryCurveSplineType", + node_free_standard_storage, + node_copy_standard_storage); + ntype.draw_buttons = geo_node_curve_spline_type_layout; + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc index 667e1c931bd..96c6f073ab3 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_circle.cc @@ -211,6 +211,7 @@ static void geo_node_mesh_primitive_circle_exec(GeoNodeExecParams params) const float radius = params.extract_input<float>("Radius"); const int verts_num = params.extract_input<int>("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc index d46ea2d2050..790a518e584 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cone.cc @@ -551,6 +551,7 @@ static void geo_node_mesh_primitive_cone_exec(GeoNodeExecParams params) const int verts_num = params.extract_input<int>("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc index 1767f765da4..b40cb478b03 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_cylinder.cc @@ -70,6 +70,7 @@ static void geo_node_mesh_primitive_cylinder_exec(GeoNodeExecParams params) const float depth = params.extract_input<float>("Depth"); const int verts_num = params.extract_input<int>("Vertices"); if (verts_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3")); params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc index ac2f5a23a4d..7a97ae8e318 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_grid.cc @@ -162,6 +162,12 @@ static void geo_node_mesh_primitive_grid_exec(GeoNodeExecParams params) const int verts_x = params.extract_input<int>("Vertices X"); const int verts_y = params.extract_input<int>("Vertices Y"); if (verts_x < 2 || verts_y < 2) { + if (verts_x < 2) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices X must be at least 2")); + } + if (verts_y < 2) { + params.error_message_add(NodeWarningType::Info, TIP_("Vertices Y must be at least 2")); + } params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc index 599c59e4a2e..fe456dc4564 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_primitive_uv_sphere.cc @@ -291,6 +291,12 @@ static void geo_node_mesh_primitive_uv_sphere_exec(GeoNodeExecParams params) const int segments_num = params.extract_input<int>("Segments"); const int rings_num = params.extract_input<int>("Rings"); if (segments_num < 3 || rings_num < 2) { + if (segments_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Segments must be at least 3")); + } + if (rings_num < 3) { + params.error_message_add(NodeWarningType::Info, TIP_("Rings must be at least 3")); + } params.set_output("Geometry", GeometrySet()); return; } diff --git a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c index 56169b9be5e..015af19abb2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c +++ b/source/blender/nodes/shader/nodes/node_shader_eevee_specular.c @@ -91,7 +91,7 @@ void register_node_type_sh_eevee_specular(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular", NODE_CLASS_SHADER, 0); + sh_node_type_base(&ntype, SH_NODE_EEVEE_SPECULAR, "Specular BSDF", NODE_CLASS_SHADER, 0); node_type_socket_templates(&ntype, sh_node_eevee_specular_in, sh_node_eevee_specular_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 612446e6d19..e5e601e0eb6 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -3241,9 +3241,11 @@ static PyObject *bpy_bmelemseq_subscript(BPy_BMElemSeq *self, PyObject *key) const Py_ssize_t len = bpy_bmelemseq_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index ff06cf43026..0aa92158524 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -843,9 +843,11 @@ static PyObject *bpy_bmlayercollection_subscript(BPy_BMLayerCollection *self, Py const Py_ssize_t len = bpy_bmlayercollection_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c index 8f4e07c30d3..d0c745e6a1d 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c @@ -443,7 +443,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, } if (value) { - /* dvert[group_index] = 0.5 */ + /* Handle `dvert[group_index] = 0.5`. */ if (i < 0) { PyErr_SetString(PyExc_KeyError, "BMDeformVert[key] = x: " @@ -453,7 +453,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, MDeformWeight *dw = BKE_defvert_ensure_index(self->data, i); const float f = PyFloat_AsDouble(value); - if (f == -1 && PyErr_Occurred()) { // parsed key not a number + if (f == -1 && PyErr_Occurred()) { /* Parsed key not a number. */ PyErr_SetString(PyExc_TypeError, "BMDeformVert[key] = x: " "assigned value not a number"); @@ -463,7 +463,7 @@ static int bpy_bmdeformvert_ass_subscript(BPy_BMDeformVert *self, PyObject *key, dw->weight = clamp_f(f, 0.0f, 1.0f); } else { - /* del dvert[group_index] */ + /* Handle `del dvert[group_index]`. */ MDeformWeight *dw = BKE_defvert_find_index(self->data, i); if (dw == NULL) { diff --git a/source/blender/python/bmesh/bmesh_py_types_select.c b/source/blender/python/bmesh/bmesh_py_types_select.c index 9bb9815f731..b89822a080c 100644 --- a/source/blender/python/bmesh/bmesh_py_types_select.c +++ b/source/blender/python/bmesh/bmesh_py_types_select.c @@ -205,7 +205,6 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, Py_ssize_t stop) { int count = 0; - bool ok; PyObject *list; BMEditSelection *ese; @@ -214,30 +213,22 @@ static PyObject *bpy_bmeditselseq_subscript_slice(BPy_BMEditSelSeq *self, list = PyList_New(0); - ese = self->bm->selected.first; - - ok = (ese != NULL); - - if (UNLIKELY(ok == false)) { - return list; - } - - /* first loop up-until the start */ - for (ok = true; ok; ok = ((ese = ese->next) != NULL)) { + /* First loop up-until the start. */ + for (ese = self->bm->selected.first; ese; ese = ese->next) { if (count == start) { break; } count++; } - /* add items until stop */ - do { + /* Add items until stop. */ + for (; ese; ese = ese->next) { PyList_APPEND(list, BPy_BMElem_CreatePyObject(self->bm, &ese->ele->head)); count++; if (count == stop) { break; } - } while ((ese = ese->next)); + } return list; } @@ -282,9 +273,11 @@ static PyObject *bpy_bmeditselseq_subscript(BPy_BMEditSelSeq *self, PyObject *ke const Py_ssize_t len = bpy_bmeditselseq_length(self); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h index 1591413530c..bfe0e66e393 100644 --- a/source/blender/python/generic/py_capi_utils.h +++ b/source/blender/python/generic/py_capi_utils.h @@ -42,13 +42,13 @@ void PyC_Err_PrintWithFunc(PyObject *py_func); void PyC_FileAndNum(const char **r_filename, int *r_lineno); void PyC_FileAndNum_Safe(const char **r_filename, int *r_lineno); /* checks python is running */ int PyC_AsArray_FAST(void *array, - const size_t array_elem_size, + const size_t array_item_size, PyObject *value_fast, const Py_ssize_t length, const PyTypeObject *type, const char *error_prefix); int PyC_AsArray(void *array, - const size_t array_elem_size, + const size_t array_item_size, PyObject *value, const Py_ssize_t length, const PyTypeObject *type, diff --git a/source/blender/python/gpu/gpu_py_offscreen.c b/source/blender/python/gpu/gpu_py_offscreen.c index 457f00b1267..32053df5e97 100644 --- a/source/blender/python/gpu/gpu_py_offscreen.c +++ b/source/blender/python/gpu/gpu_py_offscreen.c @@ -279,7 +279,8 @@ static PyObject *pygpu_offscreen_texture_color_get(BPyGPUOffScreen *self, void * PyDoc_STRVAR( pygpu_offscreen_draw_view3d_doc, - ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix)\n" + ".. method:: draw_view3d(scene, view_layer, view3d, region, view_matrix, projection_matrix, " + "do_color_management=False)\n" "\n" " Draw the 3d viewport in the offscreen object.\n" "\n" @@ -294,7 +295,9 @@ PyDoc_STRVAR( " :arg view_matrix: View Matrix (e.g. ``camera.matrix_world.inverted()``).\n" " :type view_matrix: :class:`mathutils.Matrix`\n" " :arg projection_matrix: Projection Matrix (e.g. ``camera.calc_matrix_camera(...)``).\n" - " :type projection_matrix: :class:`mathutils.Matrix`\n"); + " :type projection_matrix: :class:`mathutils.Matrix`\n" + " :arg do_color_management: Color manage the output.\n" + " :type do_color_management: bool\n"); static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *args, PyObject *kwds) { MatrixObject *py_mat_view, *py_mat_projection; @@ -306,12 +309,20 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar View3D *v3d; ARegion *region; + bool do_color_management = false; + BPY_GPU_OFFSCREEN_CHECK_OBJ(self); - static const char *_keywords[] = { - "scene", "view_layer", "view3d", "region", "view_matrix", "projection_matrix", NULL}; + static const char *_keywords[] = {"scene", + "view_layer", + "view3d", + "region", + "view_matrix", + "projection_matrix", + "do_color_management", + NULL}; - static _PyArg_Parser _parser = {"OOOOO&O&:draw_view3d", _keywords, 0}; + static _PyArg_Parser _parser = {"OOOOO&O&|$O&:draw_view3d", _keywords, 0}; if (!_PyArg_ParseTupleAndKeywordsFast(args, kwds, &_parser, @@ -322,7 +333,9 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar Matrix_Parse4x4, &py_mat_view, Matrix_Parse4x4, - &py_mat_projection) || + &py_mat_projection, + PyC_ParseBool, + &do_color_management) || (!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) || !(view_layer = PyC_RNA_AsPointer(py_view_layer, "ViewLayer")) || !(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) || @@ -354,7 +367,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPyGPUOffScreen *self, PyObject *ar true, true, "", - false, + do_color_management, true, self->ofs, NULL); diff --git a/source/blender/python/intern/bpy_gizmo_wrap.c b/source/blender/python/intern/bpy_gizmo_wrap.c index 42e0c7d0003..a05ec6b7000 100644 --- a/source/blender/python/intern/bpy_gizmo_wrap.c +++ b/source/blender/python/intern/bpy_gizmo_wrap.c @@ -79,7 +79,7 @@ static bool bpy_gizmotype_target_property_def(wmGizmoType *gzt, PyObject *item) goto fail; } - if ((params.array_length < 1 || params.array_length > RNA_MAX_ARRAY_LENGTH)) { + if ((params.array_length < 1) || (params.array_length > RNA_MAX_ARRAY_LENGTH)) { PyErr_SetString(PyExc_ValueError, "'array_length' out of range"); goto fail; } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index dff96f74d62..ec2e70ad262 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -2825,9 +2825,11 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject const Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } @@ -2955,9 +2957,11 @@ static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, Py_ssize_t len = (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop); if (start < 0) { start += len; + CLAMP_MIN(start, 0); } if (stop < 0) { stop += len; + CLAMP_MIN(stop, 0); } } diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c index aa8cf8f2a9f..62f5a17c4dd 100644 --- a/source/blender/python/intern/bpy_utils_units.c +++ b/source/blender/python/intern/bpy_utils_units.c @@ -114,7 +114,7 @@ static PyObject *py_structseq_from_strings(PyTypeObject *py_type, BLI_assert(py_struct_seq != NULL); for (str_iter = str_items; *str_iter; str_iter++) { - PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString((*str_iter))); + PyStructSequence_SET_ITEM(py_struct_seq, pos++, PyUnicode_FromString(*str_iter)); } return py_struct_seq; diff --git a/source/blender/render/intern/pipeline.c b/source/blender/render/intern/pipeline.c index 333ee9ecd33..479ad9209f0 100644 --- a/source/blender/render/intern/pipeline.c +++ b/source/blender/render/intern/pipeline.c @@ -2524,7 +2524,7 @@ void RE_RenderAnim(Render *re, if (G.is_break == true) { /* remove touched file */ if (is_movie == false && do_write_file) { - if ((rd.mode & R_TOUCH)) { + if (rd.mode & R_TOUCH) { if (!is_multiview_name) { if ((BLI_file_size(name) == 0)) { /* BLI_exists(name) is implicit */ diff --git a/source/blender/render/intern/render_result.c b/source/blender/render/intern/render_result.c index 693cddbebbe..091f5964291 100644 --- a/source/blender/render/intern/render_result.c +++ b/source/blender/render/intern/render_result.c @@ -784,7 +784,7 @@ void render_result_views_new(RenderResult *rr, const RenderData *rd) render_result_views_free(rr); /* check renderdata for amount of views */ - if ((rd->scemode & R_MULTIVIEW)) { + if (rd->scemode & R_MULTIVIEW) { for (srv = rd->views.first; srv; srv = srv->next) { if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) { continue; diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index e513c49c11b..b7fbb9bb82b 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -203,7 +203,8 @@ if(WITH_XR_OPENXR) list(APPEND SRC xr/intern/wm_xr.c - xr/intern/wm_xr_actions.c + xr/intern/wm_xr_action.c + xr/intern/wm_xr_actionmap.c xr/intern/wm_xr_draw.c xr/intern/wm_xr_session.c diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 136c639caea..02e8d42e0ff 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -74,8 +74,7 @@ struct wmNDOFMotionData; #endif #ifdef WITH_XR_OPENXR -struct wmXrActionState; -struct wmXrPose; +struct wmXrRuntimeData; #endif typedef struct wmGizmo wmGizmo; @@ -728,6 +727,8 @@ void WM_drag_free_imported_drag_ID(struct Main *bmain, struct wmDrag *drag, struct wmDropBox *drop); +const char *WM_drag_get_item_name(struct wmDrag *drag); + /* Set OpenGL viewport and scissor */ void wmViewport(const struct rcti *winrct); void wmPartialViewport(rcti *drawrct, const rcti *winrct, const rcti *partialrct); @@ -960,12 +961,18 @@ bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_ro bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, float r_viewmat[4][4], float *r_focal_len); -bool WM_xr_session_state_controller_pose_location_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3]); -bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4]); +bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_location[3]); +bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_rotation[4]); /* wm_xr_actions.c */ /* XR action functions to be called pre-XR session start. @@ -978,41 +985,38 @@ bool WM_xr_action_create(wmXrData *xr, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, struct wmOperatorType *ot, struct IDProperty *op_properties, - eXrOpFlag op_flag); + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag); void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char *action_name); -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const struct wmXrPose *poses); -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths); bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses); void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths); + const char *profile_path); /* If action_set_name is NULL, then all action sets will be treated as active. */ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name); -bool WM_xr_controller_pose_action_set(wmXrData *xr, - const char *action_set_name, - const char *action_name); +bool WM_xr_controller_pose_actions_set(wmXrData *xr, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name); /* XR action functions to be called post-XR session start. */ bool WM_xr_action_state_get(const wmXrData *xr, @@ -1023,10 +1027,48 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude); -void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name); +void WM_xr_haptic_action_stop(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char **subaction_path); + +/* wm_xr_actionmap.c */ +XrActionMap *WM_xr_actionmap_new(struct wmXrRuntimeData *runtime, + const char *name, + bool replace_existing); +void WM_xr_actionmap_ensure_unique(struct wmXrRuntimeData *runtime, XrActionMap *actionmap); +XrActionMap *WM_xr_actionmap_add_copy(struct wmXrRuntimeData *runtime, XrActionMap *am_src); +bool WM_xr_actionmap_remove(struct wmXrRuntimeData *runtime, XrActionMap *actionmap); +XrActionMap *WM_xr_actionmap_find(struct wmXrRuntimeData *runtime, const char *name); +void WM_xr_actionmap_clear(XrActionMap *actionmap); +void WM_xr_actionmaps_clear(struct wmXrRuntimeData *runtime); +ListBase *WM_xr_actionmaps_get(struct wmXrRuntimeData *runtime); +short WM_xr_actionmap_active_index_get(const struct wmXrRuntimeData *runtime); +void WM_xr_actionmap_active_index_set(struct wmXrRuntimeData *runtime, short idx); +short WM_xr_actionmap_selected_index_get(const struct wmXrRuntimeData *runtime); +void WM_xr_actionmap_selected_index_set(struct wmXrRuntimeData *runtime, short idx); + +XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap, + const char *name, + bool replace_existing); +void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami); +XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src); +bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami); +XrActionMapItem *WM_xr_actionmap_item_find(XrActionMap *actionmap, const char *name); +void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami); + +XrActionMapBinding *WM_xr_actionmap_binding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing); +void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb); +XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami, + XrActionMapBinding *amb_src); +bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *amb); +XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const char *name); #endif /* WITH_XR_OPENXR */ #ifdef __cplusplus diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 4d6cb941347..485d8e5a162 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -115,6 +115,7 @@ struct wmEvent; struct wmOperator; struct wmWindowManager; struct wmDrag; +struct wmDropBox; #include "BLI_compiler_attrs.h" #include "DNA_listBase.h" @@ -937,7 +938,8 @@ typedef struct wmDragAsset { typedef char *(*WMDropboxTooltipFunc)(struct bContext *, struct wmDrag *, - const struct wmEvent *event); + const struct wmEvent *event, + struct wmDropBox *drop); typedef struct wmDrag { struct wmDrag *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index c58d3c53e03..76bb93b681c 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -220,14 +220,11 @@ void WM_drag_free_list(struct ListBase *lb) } } -static char *dropbox_tooltip(bContext *C, - wmDrag *drag, - const wmEvent *event, - const wmDropBox *drop) +static char *dropbox_tooltip(bContext *C, wmDrag *drag, const wmEvent *event, wmDropBox *drop) { char *tooltip = NULL; if (drop->tooltip) { - tooltip = drop->tooltip(C, drag, event); + tooltip = drop->tooltip(C, drag, event, drop); } if (!tooltip) { tooltip = BLI_strdup(WM_operatortype_name(drop->ot, drop->ptr)); @@ -472,7 +469,7 @@ static void wm_drop_operator_draw(const char *name, int x, int y) UI_fontstyle_draw_simple_backdrop(fstyle, x, y, name, col_fg, col_bg); } -static const char *wm_drag_name(wmDrag *drag) +const char *WM_drag_get_item_name(wmDrag *drag) { switch (drag->type) { case WM_DRAG_ID: { @@ -586,11 +583,11 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) } if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + int w = UI_fontstyle_string_width(fstyle, WM_drag_get_item_name(drag)); drag_rect_minmax(rect, x, y, x + w, y + iconsize); } else { - UI_fontstyle_draw_simple(fstyle, x, y, wm_drag_name(drag), text_col); + UI_fontstyle_draw_simple(fstyle, x, y, WM_drag_get_item_name(drag), text_col); } /* operator name with roundbox */ @@ -617,7 +614,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) } if (rect) { - int w = UI_fontstyle_string_width(fstyle, wm_drag_name(drag)); + int w = UI_fontstyle_string_width(fstyle, WM_drag_get_item_name(drag)); drag_rect_minmax(rect, x, y, x + w, y + iconsize); } else { diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 92ca0b87527..1c736647084 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -585,7 +585,7 @@ void wm_tweakevent_test(bContext *C, const wmEvent *event, int action) } else { /* no tweaks if event was handled */ - if ((action & WM_HANDLER_BREAK)) { + if (action & WM_HANDLER_BREAK) { WM_gesture_end(win, win->tweak); } else { diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 8f37e7f34a9..93417213a65 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -1058,7 +1058,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win) BLI_assert(GPU_framebuffer_active_get() == GPU_framebuffer_back_get()); if (win != wm->windrawable && win->ghostwin) { - // win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */ + // win->lmbut = 0; /* Keeps hanging when mouse-pressed while other window opened. */ wm_window_clear_drawable(wm); if (G.debug & G_DEBUG_EVENTS) { diff --git a/source/blender/windowmanager/xr/intern/wm_xr.c b/source/blender/windowmanager/xr/intern/wm_xr.c index 2a67c2bee9f..716a0936a24 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr.c +++ b/source/blender/windowmanager/xr/intern/wm_xr.c @@ -115,6 +115,7 @@ bool wm_xr_init(wmWindowManager *wm) void wm_xr_exit(wmWindowManager *wm) { if (wm->xr.runtime != NULL) { + WM_xr_actionmaps_clear(wm->xr.runtime); wm_xr_runtime_data_free(&wm->xr.runtime); } if (wm->xr.session_settings.shading.prop) { diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actions.c b/source/blender/windowmanager/xr/intern/wm_xr_action.c index 7eabd29baa0..2712fde51a8 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_actions.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_action.c @@ -23,6 +23,7 @@ * All functions are designed to be usable by RNA / the Python API. */ +#include "BLI_listbase.h" #include "BLI_math.h" #include "GHOST_C-api.h" @@ -56,6 +57,9 @@ static void action_set_destroy(void *val) MEM_SAFE_FREE(action_set->name); + BLI_freelistN(&action_set->active_modal_actions); + BLI_freelistN(&action_set->active_haptic_actions); + MEM_freeN(action_set); } @@ -68,10 +72,15 @@ static wmXrAction *action_create(const char *action_name, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, wmOperatorType *ot, IDProperty *op_properties, - eXrOpFlag op_flag) + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag) { wmXrAction *action = MEM_callocN(sizeof(*action), __func__); action->name = MEM_mallocN(strlen(action_name) + 1, "XrAction_Name"); @@ -109,15 +118,32 @@ static wmXrAction *action_create(const char *action_name, action->states = MEM_calloc_arrayN(count, size, "XrAction_States"); action->states_prev = MEM_calloc_arrayN(count, size, "XrAction_StatesPrev"); - if (float_threshold) { - BLI_assert(type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); - action->float_threshold = *float_threshold; - CLAMP(action->float_threshold, 0.0f, 1.0f); + const bool is_float_action = (type == XR_FLOAT_INPUT || type == XR_VECTOR2F_INPUT); + const bool is_button_action = (is_float_action || type == XR_BOOLEAN_INPUT); + if (is_float_action) { + action->float_thresholds = MEM_calloc_arrayN( + count, sizeof(*action->float_thresholds), "XrAction_FloatThresholds"); + } + if (is_button_action) { + action->axis_flags = MEM_calloc_arrayN( + count, sizeof(*action->axis_flags), "XrAction_AxisFlags"); } action->ot = ot; action->op_properties = op_properties; + + if (haptic_name) { + BLI_assert(is_button_action); + action->haptic_name = MEM_mallocN(strlen(*haptic_name) + 1, "XrAction_HapticName"); + strcpy(action->haptic_name, *haptic_name); + action->haptic_duration = *haptic_duration; + action->haptic_frequency = *haptic_frequency; + action->haptic_amplitude = *haptic_amplitude; + } + action->op_flag = op_flag; + action->action_flag = action_flag; + action->haptic_flag = haptic_flag; return action; } @@ -140,6 +166,11 @@ static void action_destroy(void *val) MEM_SAFE_FREE(action->states); MEM_SAFE_FREE(action->states_prev); + MEM_SAFE_FREE(action->float_thresholds); + MEM_SAFE_FREE(action->axis_flags); + + MEM_SAFE_FREE(action->haptic_name); + MEM_freeN(action); } @@ -179,13 +210,14 @@ void WM_xr_action_set_destroy(wmXrData *xr, const char *action_set_name) wmXrSessionState *session_state = &xr->runtime->session_state; if (action_set == session_state->active_action_set) { - if (action_set->controller_pose_action) { + if (action_set->controller_grip_action || action_set->controller_aim_action) { wm_xr_session_controller_data_clear(session_state); - action_set->controller_pose_action = NULL; - } - if (action_set->active_modal_action) { - action_set->active_modal_action = NULL; + action_set->controller_grip_action = action_set->controller_aim_action = NULL; } + + BLI_freelistN(&action_set->active_modal_actions); + BLI_freelistN(&action_set->active_haptic_actions); + session_state->active_action_set = NULL; } @@ -198,10 +230,15 @@ bool WM_xr_action_create(wmXrData *xr, eXrActionType type, unsigned int count_subaction_paths, const char **subaction_paths, - const float *float_threshold, wmOperatorType *ot, IDProperty *op_properties, - eXrOpFlag op_flag) + const char **haptic_name, + const int64_t *haptic_duration, + const float *haptic_frequency, + const float *haptic_amplitude, + eXrOpFlag op_flag, + eXrActionFlag action_flag, + eXrHapticFlag haptic_flag) { if (action_find(xr, action_set_name, action_name)) { return false; @@ -211,16 +248,23 @@ bool WM_xr_action_create(wmXrData *xr, type, count_subaction_paths, subaction_paths, - float_threshold, ot, op_properties, - op_flag); + haptic_name, + haptic_duration, + haptic_frequency, + haptic_amplitude, + op_flag, + action_flag, + haptic_flag); GHOST_XrActionInfo info = { .name = action_name, .count_subaction_paths = count_subaction_paths, .subaction_paths = subaction_paths, .states = action->states, + .float_thresholds = action->float_thresholds, + .axis_flags = (int16_t *)action->axis_flags, .customdata_free_fn = action_destroy, .customdata = action, }; @@ -257,110 +301,88 @@ void WM_xr_action_destroy(wmXrData *xr, const char *action_set_name, const char return; } - if (action_set->controller_pose_action && - STREQ(action_set->controller_pose_action->name, action_name)) { - if (action_set == xr->runtime->session_state.active_action_set) { - wm_xr_session_controller_data_clear(&xr->runtime->session_state); - } - action_set->controller_pose_action = NULL; - } - if (action_set->active_modal_action && - STREQ(action_set->active_modal_action->name, action_name)) { - action_set->active_modal_action = NULL; - } - wmXrAction *action = action_find(xr, action_set_name, action_name); if (!action) { return; } -} - -bool WM_xr_action_space_create(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths, - const wmXrPose *poses) -{ - GHOST_XrActionSpaceInfo info = { - .action_name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - }; - GHOST_XrPose *ghost_poses = MEM_malloc_arrayN( - count_subaction_paths, sizeof(*ghost_poses), __func__); - for (unsigned int i = 0; i < count_subaction_paths; ++i) { - const wmXrPose *pose = &poses[i]; - GHOST_XrPose *ghost_pose = &ghost_poses[i]; - copy_v3_v3(ghost_pose->position, pose->position); - copy_qt_qt(ghost_pose->orientation_quat, pose->orientation_quat); + if ((action_set->controller_grip_action && + STREQ(action_set->controller_grip_action->name, action_name)) || + (action_set->controller_aim_action && + STREQ(action_set->controller_aim_action->name, action_name))) { + if (action_set == xr->runtime->session_state.active_action_set) { + wm_xr_session_controller_data_clear(&xr->runtime->session_state); + } + action_set->controller_grip_action = action_set->controller_aim_action = NULL; } - info.poses = ghost_poses; - bool ret = GHOST_XrCreateActionSpaces(xr->runtime->context, action_set_name, 1, &info) ? true : - false; - MEM_freeN(ghost_poses); - return ret; -} + LISTBASE_FOREACH (LinkData *, ld, &action_set->active_modal_actions) { + wmXrAction *active_modal_action = ld->data; + if (STREQ(active_modal_action->name, action_name)) { + BLI_freelinkN(&action_set->active_modal_actions, ld); + break; + } + } -void WM_xr_action_space_destroy(wmXrData *xr, - const char *action_set_name, - const char *action_name, - unsigned int count_subaction_paths, - const char **subaction_paths) -{ - GHOST_XrActionSpaceInfo info = { - .action_name = action_name, - .count_subaction_paths = count_subaction_paths, - .subaction_paths = subaction_paths, - }; + LISTBASE_FOREACH_MUTABLE (wmXrHapticAction *, ha, &action_set->active_haptic_actions) { + if (STREQ(ha->action->name, action_name)) { + BLI_freelinkN(&action_set->active_haptic_actions, ha); + } + } - GHOST_XrDestroyActionSpaces(xr->runtime->context, action_set_name, 1, &info); + GHOST_XrDestroyActions(xr->runtime->context, action_set_name, 1, &action_name); } bool WM_xr_action_binding_create(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) + const char *profile_path, + unsigned int count_subaction_paths, + const char **subaction_paths, + const char **component_paths, + const float *float_thresholds, + const eXrAxisFlag *axis_flags, + const struct wmXrPose *poses) { - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; + GHOST_XrActionBindingInfo *binding_infos = MEM_calloc_arrayN( + count_subaction_paths, sizeof(*binding_infos), __func__); + + for (unsigned int i = 0; i < count_subaction_paths; ++i) { + GHOST_XrActionBindingInfo *binding_info = &binding_infos[i]; + binding_info->component_path = component_paths[i]; + if (float_thresholds) { + binding_info->float_threshold = float_thresholds[i]; + } + if (axis_flags) { + binding_info->axis_flag = axis_flags[i]; + } + if (poses) { + copy_v3_v3(binding_info->pose.position, poses[i].position); + copy_qt_qt(binding_info->pose.orientation_quat, poses[i].orientation_quat); + } + } GHOST_XrActionProfileInfo profile_info = { + .action_name = action_name, .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, + .count_subaction_paths = count_subaction_paths, + .subaction_paths = subaction_paths, + .bindings = binding_infos, }; - return GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + bool ret = GHOST_XrCreateActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + + MEM_freeN(binding_infos); + return ret; } void WM_xr_action_binding_destroy(wmXrData *xr, const char *action_set_name, - const char *profile_path, const char *action_name, - unsigned int count_interaction_paths, - const char **interaction_paths) + const char *profile_path) { - GHOST_XrActionBindingInfo binding_info = { - .action_name = action_name, - .count_interaction_paths = count_interaction_paths, - .interaction_paths = interaction_paths, - }; - - GHOST_XrActionProfileInfo profile_info = { - .profile_path = profile_path, - .count_bindings = 1, - .bindings = &binding_info, - }; - - GHOST_XrDestroyActionBindings(xr->runtime->context, action_set_name, 1, &profile_info); + GHOST_XrDestroyActionBindings( + xr->runtime->context, action_set_name, 1, &action_name, &profile_path); } bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) @@ -371,46 +393,64 @@ bool WM_xr_active_action_set_set(wmXrData *xr, const char *action_set_name) } { - /* Unset active modal action (if any). */ + /* Clear any active modal/haptic actions. */ wmXrActionSet *active_action_set = xr->runtime->session_state.active_action_set; if (active_action_set) { - wmXrAction *active_modal_action = active_action_set->active_modal_action; - if (active_modal_action) { - if (active_modal_action->active_modal_path) { - active_modal_action->active_modal_path = NULL; - } - active_action_set->active_modal_action = NULL; - } + BLI_freelistN(&active_action_set->active_modal_actions); + BLI_freelistN(&active_action_set->active_haptic_actions); } } xr->runtime->session_state.active_action_set = action_set; - if (action_set->controller_pose_action) { - wm_xr_session_controller_data_populate(action_set->controller_pose_action, xr); + if (action_set->controller_grip_action && action_set->controller_aim_action) { + wm_xr_session_controller_data_populate( + action_set->controller_grip_action, action_set->controller_aim_action, xr); + } + else { + wm_xr_session_controller_data_clear(&xr->runtime->session_state); } return true; } -bool WM_xr_controller_pose_action_set(wmXrData *xr, - const char *action_set_name, - const char *action_name) +bool WM_xr_controller_pose_actions_set(wmXrData *xr, + const char *action_set_name, + const char *grip_action_name, + const char *aim_action_name) { wmXrActionSet *action_set = action_set_find(xr, action_set_name); if (!action_set) { return false; } - wmXrAction *action = action_find(xr, action_set_name, action_name); - if (!action) { + wmXrAction *grip_action = action_find(xr, action_set_name, grip_action_name); + if (!grip_action) { return false; } - action_set->controller_pose_action = action; + wmXrAction *aim_action = action_find(xr, action_set_name, aim_action_name); + if (!aim_action) { + return false; + } + + /* Ensure consistent subaction paths. */ + const unsigned int count = grip_action->count_subaction_paths; + if (count != aim_action->count_subaction_paths) { + return false; + } + + for (unsigned int i = 0; i < count; ++i) { + if (!STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i])) { + return false; + } + } + + action_set->controller_grip_action = grip_action; + action_set->controller_aim_action = aim_action; if (action_set == xr->runtime->session_state.active_action_set) { - wm_xr_session_controller_data_populate(action, xr); + wm_xr_session_controller_data_populate(grip_action, aim_action, xr); } return true; @@ -427,12 +467,12 @@ bool WM_xr_action_state_get(const wmXrData *xr, return false; } - BLI_assert(action->type == (eXrActionType)r_state->type); + r_state->type = (int)action->type; /* Find the action state corresponding to the subaction path. */ for (unsigned int i = 0; i < action->count_subaction_paths; ++i) { if (STREQ(subaction_path, action->subaction_paths[i])) { - switch ((eXrActionType)r_state->type) { + switch (action->type) { case XR_BOOLEAN_INPUT: r_state->state_boolean = ((bool *)action->states)[i]; break; @@ -462,19 +502,28 @@ bool WM_xr_action_state_get(const wmXrData *xr, bool WM_xr_haptic_action_apply(wmXrData *xr, const char *action_set_name, const char *action_name, + const char **subaction_path, const int64_t *duration, const float *frequency, const float *amplitude) { - return GHOST_XrApplyHapticAction( - xr->runtime->context, action_set_name, action_name, duration, frequency, amplitude) ? + return GHOST_XrApplyHapticAction(xr->runtime->context, + action_set_name, + action_name, + subaction_path, + duration, + frequency, + amplitude) ? true : false; } -void WM_xr_haptic_action_stop(wmXrData *xr, const char *action_set_name, const char *action_name) +void WM_xr_haptic_action_stop(wmXrData *xr, + const char *action_set_name, + const char *action_name, + const char **subaction_path) { - GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name); + GHOST_XrStopHapticAction(xr->runtime->context, action_set_name, action_name, subaction_path); } /** \} */ /* XR-Action API */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c new file mode 100644 index 00000000000..7673f2aa212 --- /dev/null +++ b/source/blender/windowmanager/xr/intern/wm_xr_actionmap.c @@ -0,0 +1,565 @@ +/* + * 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 wm + * + * \name Window-Manager XR Action Maps + * + * XR actionmap API, similar to WM keymap API. + */ + +#include <math.h> +#include <string.h> + +#include "BKE_context.h" +#include "BKE_idprop.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "GHOST_Types.h" + +#include "MEM_guardedalloc.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "wm_xr_intern.h" + +#define WM_XR_ACTIONMAP_STR_DEFAULT "actionmap" +#define WM_XR_ACTIONMAP_ITEM_STR_DEFAULT "action" +#define WM_XR_ACTIONMAP_BINDING_STR_DEFAULT "binding" + +/* -------------------------------------------------------------------- */ +/** \name Action Map Binding + * + * Binding in an XR action map item, that maps an action to an XR input. + * \{ */ + +XrActionMapBinding *WM_xr_actionmap_binding_new(XrActionMapItem *ami, + const char *name, + bool replace_existing) +{ + XrActionMapBinding *amb_prev = WM_xr_actionmap_binding_find(ami, name); + if (amb_prev && replace_existing) { + return amb_prev; + } + + XrActionMapBinding *amb = MEM_callocN(sizeof(XrActionMapBinding), __func__); + BLI_strncpy(amb->name, name, MAX_NAME); + if (amb_prev) { + WM_xr_actionmap_binding_ensure_unique(ami, amb); + } + + BLI_addtail(&ami->bindings, amb); + + /* Set non-zero threshold by default. */ + amb->float_threshold = 0.3f; + + return amb; +} + +static XrActionMapBinding *wm_xr_actionmap_binding_find_except(XrActionMapItem *ami, + const char *name, + XrActionMapBinding *ambexcept) +{ + LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami->bindings) { + if (STREQLEN(name, amb->name, MAX_NAME) && (amb != ambexcept)) { + return amb; + } + } + return NULL; +} + +/** + * Ensure unique name among all action map bindings. + */ +void WM_xr_actionmap_binding_ensure_unique(XrActionMapItem *ami, XrActionMapBinding *amb) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, amb->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_binding_find_except(ami, name, amb)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_BINDING_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(amb->name, name, MAX_NAME); +} + +static XrActionMapBinding *wm_xr_actionmap_binding_copy(XrActionMapBinding *amb_src) +{ + XrActionMapBinding *amb_dst = MEM_dupallocN(amb_src); + + amb_dst->prev = amb_dst->next = NULL; + + return amb_dst; +} + +XrActionMapBinding *WM_xr_actionmap_binding_add_copy(XrActionMapItem *ami, + XrActionMapBinding *amb_src) +{ + XrActionMapBinding *amb_dst = wm_xr_actionmap_binding_copy(amb_src); + + WM_xr_actionmap_binding_ensure_unique(ami, amb_dst); + + BLI_addtail(&ami->bindings, amb_dst); + + return amb_dst; +} + +bool WM_xr_actionmap_binding_remove(XrActionMapItem *ami, XrActionMapBinding *amb) +{ + int idx = BLI_findindex(&ami->bindings, amb); + + if (idx != -1) { + BLI_freelinkN(&ami->bindings, amb); + + if (BLI_listbase_is_empty(&ami->bindings)) { + ami->selbinding = -1; + } + else { + if (idx <= ami->selbinding) { + if (--ami->selbinding < 0) { + ami->selbinding = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMapBinding *WM_xr_actionmap_binding_find(XrActionMapItem *ami, const char *name) +{ + LISTBASE_FOREACH (XrActionMapBinding *, amb, &ami->bindings) { + if (STREQLEN(name, amb->name, MAX_NAME)) { + return amb; + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Action Map Item + * + * Item in an XR action map, that maps an XR event to an operator, pose, or haptic output. + * \{ */ + +static void wm_xr_actionmap_item_properties_set(XrActionMapItem *ami) +{ + WM_operator_properties_alloc(&(ami->op_properties_ptr), &(ami->op_properties), ami->op); + WM_operator_properties_sanitize(ami->op_properties_ptr, 1); +} + +static void wm_xr_actionmap_item_properties_free(XrActionMapItem *ami) +{ + if (ami->op_properties_ptr) { + WM_operator_properties_free(ami->op_properties_ptr); + MEM_freeN(ami->op_properties_ptr); + ami->op_properties_ptr = NULL; + ami->op_properties = NULL; + } + else { + BLI_assert(ami->op_properties == NULL); + } +} + +/** + * Similar to #wm_xr_actionmap_item_properties_set() + * but checks for the #eXrActionType and #wmOperatorType having changed. + */ +void WM_xr_actionmap_item_properties_update_ot(XrActionMapItem *ami) +{ + switch (ami->type) { + case XR_BOOLEAN_INPUT: + case XR_FLOAT_INPUT: + case XR_VECTOR2F_INPUT: + break; + case XR_POSE_INPUT: + case XR_VIBRATION_OUTPUT: + wm_xr_actionmap_item_properties_free(ami); + memset(ami->op, 0, sizeof(ami->op)); + return; + } + + if (ami->op[0] == 0) { + wm_xr_actionmap_item_properties_free(ami); + return; + } + + if (ami->op_properties_ptr == NULL) { + wm_xr_actionmap_item_properties_set(ami); + } + else { + wmOperatorType *ot = WM_operatortype_find(ami->op, 0); + if (ot) { + if (ot->srna != ami->op_properties_ptr->type) { + /* Matches wm_xr_actionmap_item_properties_set() but doesn't alloc new ptr. */ + WM_operator_properties_create_ptr(ami->op_properties_ptr, ot); + if (ami->op_properties) { + ami->op_properties_ptr->data = ami->op_properties; + } + WM_operator_properties_sanitize(ami->op_properties_ptr, 1); + } + } + else { + wm_xr_actionmap_item_properties_free(ami); + } + } +} + +XrActionMapItem *WM_xr_actionmap_item_new(XrActionMap *actionmap, + const char *name, + bool replace_existing) +{ + XrActionMapItem *ami_prev = WM_xr_actionmap_item_find(actionmap, name); + if (ami_prev && replace_existing) { + wm_xr_actionmap_item_properties_free(ami_prev); + return ami_prev; + } + + XrActionMapItem *ami = MEM_callocN(sizeof(XrActionMapItem), __func__); + BLI_strncpy(ami->name, name, MAX_NAME); + if (ami_prev) { + WM_xr_actionmap_item_ensure_unique(actionmap, ami); + } + + BLI_addtail(&actionmap->items, ami); + + /* Set type to float (button) input by default. */ + ami->type = XR_FLOAT_INPUT; + + return ami; +} + +static XrActionMapItem *wm_xr_actionmap_item_find_except(XrActionMap *actionmap, + const char *name, + const XrActionMapItem *amiexcept) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + if (STREQLEN(name, ami->name, MAX_NAME) && (ami != amiexcept)) { + return ami; + } + } + return NULL; +} + +/** + * Ensure unique name among all action map items. + */ +void WM_xr_actionmap_item_ensure_unique(XrActionMap *actionmap, XrActionMapItem *ami) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, ami->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_item_find_except(actionmap, name, ami)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_ITEM_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(ami->name, name, MAX_NAME); +} + +static XrActionMapItem *wm_xr_actionmap_item_copy(XrActionMapItem *ami) +{ + XrActionMapItem *amin = MEM_dupallocN(ami); + + amin->prev = amin->next = NULL; + + if (amin->op_properties) { + amin->op_properties_ptr = MEM_callocN(sizeof(PointerRNA), "wmOpItemPtr"); + WM_operator_properties_create(amin->op_properties_ptr, amin->op); + + amin->op_properties = IDP_CopyProperty(amin->op_properties); + amin->op_properties_ptr->data = amin->op_properties; + } + else { + amin->op_properties = NULL; + amin->op_properties_ptr = NULL; + } + + return amin; +} + +XrActionMapItem *WM_xr_actionmap_item_add_copy(XrActionMap *actionmap, XrActionMapItem *ami_src) +{ + XrActionMapItem *ami_dst = wm_xr_actionmap_item_copy(ami_src); + + WM_xr_actionmap_item_ensure_unique(actionmap, ami_dst); + + BLI_addtail(&actionmap->items, ami_dst); + + return ami_dst; +} + +bool WM_xr_actionmap_item_remove(XrActionMap *actionmap, XrActionMapItem *ami) +{ + int idx = BLI_findindex(&actionmap->items, ami); + + if (idx != -1) { + if (ami->op_properties_ptr) { + WM_operator_properties_free(ami->op_properties_ptr); + MEM_freeN(ami->op_properties_ptr); + } + BLI_freelinkN(&actionmap->items, ami); + + if (BLI_listbase_is_empty(&actionmap->items)) { + actionmap->selitem = -1; + } + else { + if (idx <= actionmap->selitem) { + if (--actionmap->selitem < 0) { + actionmap->selitem = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMapItem *WM_xr_actionmap_item_find(XrActionMap *actionmap, const char *name) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + if (STREQLEN(name, ami->name, MAX_NAME)) { + return ami; + } + } + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Action Map + * + * List of XR action map items. + * \{ */ + +XrActionMap *WM_xr_actionmap_new(wmXrRuntimeData *runtime, const char *name, bool replace_existing) +{ + XrActionMap *am_prev = WM_xr_actionmap_find(runtime, name); + if (am_prev && replace_existing) { + WM_xr_actionmap_clear(am_prev); + return am_prev; + } + + XrActionMap *am = MEM_callocN(sizeof(struct XrActionMap), __func__); + BLI_strncpy(am->name, name, MAX_NAME); + if (am_prev) { + WM_xr_actionmap_ensure_unique(runtime, am); + } + + BLI_addtail(&runtime->actionmaps, am); + + return am; +} + +static XrActionMap *wm_xr_actionmap_find_except(wmXrRuntimeData *runtime, + const char *name, + const XrActionMap *am_except) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + if (STREQLEN(name, am->name, MAX_NAME) && (am != am_except)) { + return am; + } + } + + return NULL; +} + +/** + * Ensure unique name among all action maps. + */ +void WM_xr_actionmap_ensure_unique(wmXrRuntimeData *runtime, XrActionMap *actionmap) +{ + char name[MAX_NAME]; + char *suffix; + size_t baselen; + size_t idx = 0; + + BLI_strncpy(name, actionmap->name, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + + while (wm_xr_actionmap_find_except(runtime, name, actionmap)) { + if ((baselen + 1) + (log10(++idx) + 1) > MAX_NAME) { + /* Use default base name. */ + BLI_strncpy(name, WM_XR_ACTIONMAP_STR_DEFAULT, MAX_NAME); + baselen = BLI_strnlen(name, MAX_NAME); + suffix = &name[baselen]; + idx = 0; + } + else { + BLI_snprintf(suffix, MAX_NAME, "%zu", idx); + } + } + + BLI_strncpy(actionmap->name, name, MAX_NAME); +} + +static XrActionMap *wm_xr_actionmap_copy(XrActionMap *am_src) +{ + XrActionMap *am_dst = MEM_dupallocN(am_src); + + am_dst->prev = am_dst->next = NULL; + BLI_listbase_clear(&am_dst->items); + + LISTBASE_FOREACH (XrActionMapItem *, ami, &am_src->items) { + XrActionMapItem *ami_new = wm_xr_actionmap_item_copy(ami); + BLI_addtail(&am_dst->items, ami_new); + } + + return am_dst; +} + +XrActionMap *WM_xr_actionmap_add_copy(wmXrRuntimeData *runtime, XrActionMap *am_src) +{ + XrActionMap *am_dst = wm_xr_actionmap_copy(am_src); + + WM_xr_actionmap_ensure_unique(runtime, am_dst); + + BLI_addtail(&runtime->actionmaps, am_dst); + + return am_dst; +} + +bool WM_xr_actionmap_remove(wmXrRuntimeData *runtime, XrActionMap *actionmap) +{ + int idx = BLI_findindex(&runtime->actionmaps, actionmap); + + if (idx != -1) { + WM_xr_actionmap_clear(actionmap); + BLI_freelinkN(&runtime->actionmaps, actionmap); + + if (BLI_listbase_is_empty(&runtime->actionmaps)) { + runtime->actactionmap = runtime->selactionmap = -1; + } + else { + if (idx <= runtime->actactionmap) { + if (--runtime->actactionmap < 0) { + runtime->actactionmap = 0; + } + } + if (idx <= runtime->selactionmap) { + if (--runtime->selactionmap < 0) { + runtime->selactionmap = 0; + } + } + } + + return true; + } + + return false; +} + +XrActionMap *WM_xr_actionmap_find(wmXrRuntimeData *runtime, const char *name) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + if (STREQLEN(name, am->name, MAX_NAME)) { + return am; + } + } + return NULL; +} + +void WM_xr_actionmap_clear(XrActionMap *actionmap) +{ + LISTBASE_FOREACH (XrActionMapItem *, ami, &actionmap->items) { + wm_xr_actionmap_item_properties_free(ami); + } + + BLI_freelistN(&actionmap->items); + + actionmap->selitem = -1; +} + +void WM_xr_actionmaps_clear(wmXrRuntimeData *runtime) +{ + LISTBASE_FOREACH (XrActionMap *, am, &runtime->actionmaps) { + WM_xr_actionmap_clear(am); + } + + BLI_freelistN(&runtime->actionmaps); + + runtime->actactionmap = runtime->selactionmap = -1; +} + +ListBase *WM_xr_actionmaps_get(wmXrRuntimeData *runtime) +{ + return &runtime->actionmaps; +} + +short WM_xr_actionmap_active_index_get(const wmXrRuntimeData *runtime) +{ + return runtime->actactionmap; +} + +void WM_xr_actionmap_active_index_set(wmXrRuntimeData *runtime, short idx) +{ + BLI_assert(idx < BLI_listbase_count(&runtime->actionmaps)); + runtime->actactionmap = idx; +} + +short WM_xr_actionmap_selected_index_get(const wmXrRuntimeData *runtime) +{ + return runtime->selactionmap; +} + +void WM_xr_actionmap_selected_index_set(wmXrRuntimeData *runtime, short idx) +{ + BLI_assert(idx < BLI_listbase_count(&runtime->actionmaps)); + runtime->selactionmap = idx; +} + +/** \} */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c index 4ac05e339b9..bbb73fc2007 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c @@ -38,18 +38,18 @@ #include "wm_surface.h" #include "wm_xr_intern.h" -void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]) +void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]) { - float iquat[4]; - invert_qt_qt_normalized(iquat, pose->orientation_quat); - quat_to_mat4(r_viewmat, iquat); - translate_m4(r_viewmat, -pose->position[0], -pose->position[1], -pose->position[2]); + quat_to_mat4(r_mat, pose->orientation_quat); + copy_v3_v3(r_mat[3], pose->position); } -void wm_xr_controller_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]) +void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]) { - quat_to_mat4(r_mat, pose->orientation_quat); - copy_v3_v3(r_mat[3], pose->position); + float iquat[4]; + invert_qt_qt_normalized(iquat, pose->orientation_quat); + quat_to_mat4(r_imat, iquat); + translate_m4(r_imat, -pose->position[0], -pose->position[1], -pose->position[2]); } static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, @@ -59,6 +59,7 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, float r_proj_mat[4][4]) { GHOST_XrPose eye_pose; + float eye_inv[4][4], base_inv[4][4]; copy_qt_qt(eye_pose.orientation_quat, draw_view->eye_pose.orientation_quat); copy_v3_v3(eye_pose.position, draw_view->eye_pose.position); @@ -69,6 +70,12 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, sub_v3_v3(eye_pose.position, draw_data->eye_position_ofs); } + wm_xr_pose_to_imat(&eye_pose, eye_inv); + /* Calculate the base pose matrix (in world space!). */ + wm_xr_pose_to_imat(&draw_data->base_pose, base_inv); + + mul_m4_m4m4(r_view_mat, eye_inv, base_inv); + perspective_m4_fov(r_proj_mat, draw_view->fov.angle_left, draw_view->fov.angle_right, @@ -76,15 +83,6 @@ static void wm_xr_draw_matrices_create(const wmXrDrawData *draw_data, draw_view->fov.angle_down, session_settings->clip_start, session_settings->clip_end); - - float eye_mat[4][4]; - float base_mat[4][4]; - - wm_xr_pose_to_viewmat(&eye_pose, eye_mat); - /* Calculate the base pose matrix (in world space!). */ - wm_xr_pose_to_viewmat(&draw_data->base_pose, base_mat); - - mul_m4_m4m4(r_view_mat, eye_mat, base_mat); } static void wm_xr_draw_viewport_buffers_to_active_framebuffer( diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index 6415f96e322..4b1605d0f68 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -26,19 +26,6 @@ struct wmXrActionSet; -typedef struct wmXrControllerData { - /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). - This subaction path will later be combined with a component path, and that combined path should - also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = - /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). - */ - char subaction_path[64]; - /** Last known controller pose (in world space) stored for queries. */ - GHOST_XrPose pose; - /** The last known controller matrix, calculated from above's controller pose. */ - float mat[4][4]; -} wmXrControllerData; - typedef struct wmXrSessionState { bool is_started; @@ -65,7 +52,7 @@ typedef struct wmXrSessionState { bool is_view_data_set; /** Last known controller data. */ - wmXrControllerData controllers[2]; + ListBase controllers; /* wmXrController */ /** The currently active action set that will be updated on calls to * wm_xr_session_actions_update(). If NULL, all action sets will be treated as active and @@ -83,6 +70,10 @@ typedef struct wmXrRuntimeData { /** Although this struct is internal, RNA gets a handle to this for state information queries. */ wmXrSessionState session_state; wmXrSessionExitFn exit_fn; + + ListBase actionmaps; /* XrActionMap */ + short actactionmap; + short selactionmap; } wmXrRuntimeData; typedef struct wmXrViewportPair { @@ -112,6 +103,22 @@ typedef struct wmXrDrawData { float eye_position_ofs[3]; /* Local/view space. */ } wmXrDrawData; +typedef struct wmXrController { + struct wmXrController *next, *prev; + /** OpenXR path identifier. Length is dependent on OpenXR's XR_MAX_PATH_LENGTH (256). + This subaction path will later be combined with a component path, and that combined path should + also have a max of XR_MAX_PATH_LENGTH (e.g. subaction_path = /user/hand/left, component_path = + /input/trigger/value, interaction_path = /user/hand/left/input/trigger/value). + */ + char subaction_path[64]; + /* Pose (in world space) that represents the user's hand when holding the controller.*/ + GHOST_XrPose grip_pose; + float grip_mat[4][4]; + /* Pose (in world space) that represents the controller's aiming source. */ + GHOST_XrPose aim_pose; + float aim_mat[4][4]; +} wmXrController; + typedef struct wmXrAction { char *name; eXrActionType type; @@ -122,8 +129,9 @@ typedef struct wmXrAction { /** Previous states, stored to determine XR events. */ void *states_prev; - /** Input threshold for float/vector2f actions. */ - float float_threshold; + /** Input thresholds/regions for each subaction path. */ + float *float_thresholds; + eXrAxisFlag *axis_flags; /** The currently active subaction path (if any) for modal actions. */ char **active_modal_path; @@ -131,19 +139,37 @@ typedef struct wmXrAction { /** Operator to be called on XR events. */ struct wmOperatorType *ot; IDProperty *op_properties; + + /** Haptics. */ + char *haptic_name; + int64_t haptic_duration; + float haptic_frequency; + float haptic_amplitude; + + /** Flags. */ eXrOpFlag op_flag; + eXrActionFlag action_flag; + eXrHapticFlag haptic_flag; } wmXrAction; +typedef struct wmXrHapticAction { + struct wmXrHapticAction *next, *prev; + wmXrAction *action; + const char **subaction_path; + int64_t time_start; +} wmXrHapticAction; + typedef struct wmXrActionSet { char *name; - /** The XR pose action that determines the controller - * transforms. This is usually identified by the OpenXR path "/grip/pose" or "/aim/pose", - * although it could differ depending on the specification and hardware. */ - wmXrAction *controller_pose_action; + /** XR pose actions that determine the controller grip/aim transforms. */ + wmXrAction *controller_grip_action; + wmXrAction *controller_aim_action; - /** The currently active modal action (if any). */ - wmXrAction *active_modal_action; + /** Currently active modal actions. */ + ListBase active_modal_actions; + /** Currently active haptic actions. */ + ListBase active_haptic_actions; } wmXrActionSet; wmXrRuntimeData *wm_xr_runtime_data_create(void); @@ -164,10 +190,11 @@ void wm_xr_session_gpu_binding_context_destroy(GHOST_ContextHandle context); void wm_xr_session_actions_init(wmXrData *xr); void wm_xr_session_actions_update(wmXrData *xr); -void wm_xr_session_controller_data_populate(const wmXrAction *controller_pose_action, +void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, + const wmXrAction *aim_action, wmXrData *xr); void wm_xr_session_controller_data_clear(wmXrSessionState *state); -void wm_xr_pose_to_viewmat(const GHOST_XrPose *pose, float r_viewmat[4][4]); -void wm_xr_controller_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]); +void wm_xr_pose_to_mat(const GHOST_XrPose *pose, float r_mat[4][4]); +void wm_xr_pose_to_imat(const GHOST_XrPose *pose, float r_imat[4][4]); void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata); diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index 252f358c798..dd9cac2bb16 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -63,6 +63,16 @@ static void wm_xr_session_create_cb(void) wm_xr_session_actions_init(xr_data); } +static void wm_xr_session_controller_data_free(wmXrSessionState *state) +{ + BLI_freelistN(&state->controllers); +} + +static void wm_xr_session_data_free(wmXrSessionState *state) +{ + wm_xr_session_controller_data_free(state); +} + static void wm_xr_session_exit_cb(void *customdata) { wmXrData *xr_data = customdata; @@ -74,6 +84,7 @@ static void wm_xr_session_exit_cb(void *customdata) } /* Free the entire runtime data (including session state and context), to play safe. */ + wm_xr_session_data_free(&xr_data->runtime->session_state); wm_xr_runtime_data_free(&xr_data->runtime); } @@ -338,7 +349,7 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(state->viewer_pose.position, viewer_pose.position); copy_qt_qt(state->viewer_pose.orientation_quat, viewer_pose.orientation_quat); - wm_xr_pose_to_viewmat(&viewer_pose, state->viewer_viewmat); + wm_xr_pose_to_imat(&viewer_pose, state->viewer_viewmat); /* No idea why, but multiplying by two seems to make it match the VR view more. */ state->focal_len = 2.0f * fov_to_focallength(draw_view->fov.angle_right - draw_view->fov.angle_left, @@ -398,32 +409,71 @@ bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, return true; } -bool WM_xr_session_state_controller_pose_location_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_location_get(const wmXrData *xr, unsigned int subaction_idx, float r_location[3]) { if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || - subaction_idx >= ARRAY_SIZE(xr->runtime->session_state.controllers)) { + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { zero_v3(r_location); return false; } - copy_v3_v3(r_location, xr->runtime->session_state.controllers[subaction_idx].pose.position); + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_v3_v3(r_location, controller->grip_pose.position); return true; } -bool WM_xr_session_state_controller_pose_rotation_get(const wmXrData *xr, +bool WM_xr_session_state_controller_grip_rotation_get(const wmXrData *xr, unsigned int subaction_idx, float r_rotation[4]) { if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || - subaction_idx >= ARRAY_SIZE(xr->runtime->session_state.controllers)) { + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { unit_qt(r_rotation); return false; } - copy_v4_v4(r_rotation, - xr->runtime->session_state.controllers[subaction_idx].pose.orientation_quat); + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_qt_qt(r_rotation, controller->grip_pose.orientation_quat); + return true; +} + +bool WM_xr_session_state_controller_aim_location_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_location[3]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { + zero_v3(r_location); + return false; + } + + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_v3_v3(r_location, controller->aim_pose.position); + return true; +} + +bool WM_xr_session_state_controller_aim_rotation_get(const wmXrData *xr, + unsigned int subaction_idx, + float r_rotation[4]) +{ + if (!WM_xr_session_is_ready(xr) || !xr->runtime->session_state.is_view_data_set || + (subaction_idx >= BLI_listbase_count(&xr->runtime->session_state.controllers))) { + unit_qt(r_rotation); + return false; + } + + const wmXrController *controller = BLI_findlink(&xr->runtime->session_state.controllers, + subaction_idx); + BLI_assert(controller); + copy_qt_qt(r_rotation, controller->aim_pose.orientation_quat); return true; } @@ -443,16 +493,34 @@ void wm_xr_session_actions_init(wmXrData *xr) GHOST_XrAttachActionSets(xr->runtime->context); } -static void wm_xr_session_controller_mats_update(const XrSessionSettings *settings, - const wmXrAction *controller_pose_action, +static void wm_xr_session_controller_pose_calc(const GHOST_XrPose *raw_pose, + const float view_ofs[3], + const float base_mat[4][4], + GHOST_XrPose *r_pose, + float r_mat[4][4]) +{ + float m[4][4]; + /* Calculate controller matrix in world space. */ + wm_xr_pose_to_mat(raw_pose, m); + + /* Apply eye position and base pose offsets. */ + sub_v3_v3(m[3], view_ofs); + mul_m4_m4m4(r_mat, base_mat, m); + + /* Save final pose. */ + mat4_to_loc_quat(r_pose->position, r_pose->orientation_quat, r_mat); +} + +static void wm_xr_session_controller_data_update(const XrSessionSettings *settings, + const wmXrAction *grip_action, + const wmXrAction *aim_action, wmXrSessionState *state) { - const unsigned int count = (unsigned int)min_ii( - (int)controller_pose_action->count_subaction_paths, (int)ARRAY_SIZE(state->controllers)); + BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths); + BLI_assert(grip_action->count_subaction_paths == BLI_listbase_count(&state->controllers)); - float view_ofs[3]; - float base_inv[4][4]; - float tmp[4][4]; + unsigned int subaction_idx = 0; + float view_ofs[3], base_mat[4][4]; if ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) { copy_v3_v3(view_ofs, state->prev_local_pose.position); @@ -464,22 +532,19 @@ static void wm_xr_session_controller_mats_update(const XrSessionSettings *settin add_v3_v3(view_ofs, state->prev_eye_position_ofs); } - wm_xr_pose_to_viewmat(&state->prev_base_pose, base_inv); - invert_m4(base_inv); - - for (unsigned int i = 0; i < count; ++i) { - wmXrControllerData *controller = &state->controllers[i]; - - /* Calculate controller matrix in world space. */ - wm_xr_controller_pose_to_mat(&((GHOST_XrPose *)controller_pose_action->states)[i], tmp); - - /* Apply eye position and base pose offsets. */ - sub_v3_v3(tmp[3], view_ofs); - mul_m4_m4m4(controller->mat, base_inv, tmp); + wm_xr_pose_to_mat(&state->prev_base_pose, base_mat); - /* Save final pose. */ - mat4_to_loc_quat( - controller->pose.position, controller->pose.orientation_quat, controller->mat); + LISTBASE_FOREACH_INDEX (wmXrController *, controller, &state->controllers, subaction_idx) { + wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)grip_action->states)[subaction_idx], + view_ofs, + base_mat, + &controller->grip_pose, + controller->grip_mat); + wm_xr_session_controller_pose_calc(&((GHOST_XrPose *)aim_action->states)[subaction_idx], + view_ofs, + base_mat, + &controller->aim_pose, + controller->aim_mat); } } @@ -498,33 +563,44 @@ void wm_xr_session_actions_update(wmXrData *xr) return; } - /* Only update controller mats for active action set. */ + /* Only update controller data for active action set. */ if (active_action_set) { - if (active_action_set->controller_pose_action) { - wm_xr_session_controller_mats_update( - &xr->session_settings, active_action_set->controller_pose_action, state); + if (active_action_set->controller_grip_action && active_action_set->controller_aim_action) { + wm_xr_session_controller_data_update(&xr->session_settings, + active_action_set->controller_grip_action, + active_action_set->controller_aim_action, + state); } } } -void wm_xr_session_controller_data_populate(const wmXrAction *controller_pose_action, wmXrData *xr) +void wm_xr_session_controller_data_populate(const wmXrAction *grip_action, + const wmXrAction *aim_action, + wmXrData *xr) { + UNUSED_VARS(aim_action); /* Only used for asserts. */ + wmXrSessionState *state = &xr->runtime->session_state; + ListBase *controllers = &state->controllers; + + BLI_assert(grip_action->count_subaction_paths == aim_action->count_subaction_paths); + const unsigned int count = grip_action->count_subaction_paths; - const unsigned int count = (unsigned int)min_ii( - (int)ARRAY_SIZE(state->controllers), (int)controller_pose_action->count_subaction_paths); + wm_xr_session_controller_data_free(state); for (unsigned int i = 0; i < count; ++i) { - wmXrControllerData *c = &state->controllers[i]; - strcpy(c->subaction_path, controller_pose_action->subaction_paths[i]); - memset(&c->pose, 0, sizeof(c->pose)); - zero_m4(c->mat); + wmXrController *controller = MEM_callocN(sizeof(*controller), __func__); + + BLI_assert(STREQ(grip_action->subaction_paths[i], aim_action->subaction_paths[i])); + strcpy(controller->subaction_path, grip_action->subaction_paths[i]); + + BLI_addtail(controllers, controller); } } void wm_xr_session_controller_data_clear(wmXrSessionState *state) { - memset(state->controllers, 0, sizeof(state->controllers)); + wm_xr_session_controller_data_free(state); } /** \} */ /* XR-Session Actions */ diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index f7179dfb7e9..e928be571a2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -349,8 +349,7 @@ elseif(APPLE) set(MAC_BLENDER_TARGET_DYLIBS_DIR "${TARGETDIR_VER}/lib") else() set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION}) - # Dylibs folder for Blender executable. @executable_path is a default - # rpath, so dropping libraries next to Blender is enough. + # Dylibs folder for Blender executable. @executable_path is an rpath. set(MAC_BLENDER_TARGET_DYLIBS_DIR "$<TARGET_FILE_DIR:blender>") endif() # Skip relinking on cpack / install diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c index c75174dfff0..0f450624691 100644 --- a/source/creator/creator_args.c +++ b/source/creator/creator_args.c @@ -121,7 +121,7 @@ static bool parse_int_relative(const char *str, *r_err_msg = msg; return false; } - if ((errno == ERANGE) || ((value < INT_MIN || value > INT_MAX))) { + if ((errno == ERANGE) || ((value < INT_MIN) || (value > INT_MAX))) { static const char *msg = "exceeds range"; *r_err_msg = msg; return false; @@ -225,7 +225,7 @@ static bool parse_int_strict_range(const char *str, *r_err_msg = msg; return false; } - if ((errno == ERANGE) || ((value < min || value > max))) { + if ((errno == ERANGE) || ((value < min) || (value > max))) { static const char *msg = "exceeds range"; *r_err_msg = msg; return false; diff --git a/tests/python/bl_blendfile_library_overrides.py b/tests/python/bl_blendfile_library_overrides.py index c9c89c01cee..b44e4d48564 100644 --- a/tests/python/bl_blendfile_library_overrides.py +++ b/tests/python/bl_blendfile_library_overrides.py @@ -45,10 +45,6 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): bpy.ops.wm.save_as_mainfile(filepath=str(self.output_path), check_existing=False, compress=False) - def __ensure_override_library_updated(self): - # During save the override_library is updated. - bpy.ops.wm.save_as_mainfile(filepath=str(self.test_output_path), check_existing=False, compress=False) - def test_link_and_override_property(self): bpy.ops.wm.read_homefile(use_empty=True, use_factory_startup=True) bpy.data.orphans_purge() @@ -63,9 +59,26 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): self.assertIsNone(local_id.data.override_library) assert(len(local_id.override_library.properties) == 0) + ##### Generate an override property & operation automaticaly by editing the local override data. local_id.location.y = 1.0 + local_id.override_library.operations_update() + assert(len(local_id.override_library.properties) == 1) + override_prop = local_id.override_library.properties[0] + assert(override_prop.rna_path == "location") + assert(len(override_prop.operations) == 1) + override_operation = override_prop.operations[0] + assert(override_operation.operation == 'REPLACE') + # Setting location.y overridded all elements in the location array. -1 is a wildcard. + assert(override_operation.subitem_local_index == -1) + + ##### Reset the override to its linked reference data. + local_id.override_library.reset() + assert(len(local_id.override_library.properties) == 0) + assert(local_id.location == local_id.override_library.reference.location) - self.__ensure_override_library_updated() + ##### Generate an override property & operation manually using the API. + override_property = local_id.override_library.properties.add(rna_path="location") + override_property.operations.add(operation='REPLACE') assert(len(local_id.override_library.properties) == 1) override_prop = local_id.override_library.properties[0] @@ -76,6 +89,18 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): # Setting location.y overridded all elements in the location array. -1 is a wildcard. assert(override_operation.subitem_local_index == -1) + override_property = local_id.override_library.properties[0] + override_property.operations.remove(override_property.operations[0]) + local_id.override_library.properties.remove(override_property) + + assert(len(local_id.override_library.properties) == 0) + + ##### Delete the override. + local_id_name = local_id.name + assert(bpy.data.objects.get((local_id_name, None), None) == local_id) + local_id.override_library.destroy() + assert(bpy.data.objects.get((local_id_name, None), None) == None) + def test_link_permissive(self): """ Linked assets with a permissive template. @@ -101,7 +126,6 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): override_operation = override_prop.operations[0] assert(override_operation.operation == 'NOOP') assert(override_operation.subitem_local_index == -1) - local_id.location.y = 1.0 local_id.scale.x = 0.5 # `scale.x` will apply, but will be reverted when the library overrides @@ -110,7 +134,7 @@ class TestLibraryOverrides(TestHelper, unittest.TestCase): assert(local_id.scale.x == 0.5) assert(local_id.location.y == 1.0) - self.__ensure_override_library_updated() + local_id.override_library.operations_update() assert(local_id.scale.x == 1.0) assert(local_id.location.y == 1.0) |