Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_files/build_environment/CMakeLists.txt1
-rw-r--r--build_files/build_environment/cmake/harvest.cmake4
-rw-r--r--build_files/build_environment/cmake/nanovdb.cmake54
-rw-r--r--build_files/build_environment/cmake/openvdb.cmake28
-rw-r--r--build_files/build_environment/cmake/options.cmake1
-rw-r--r--build_files/build_environment/cmake/versions.cmake16
-rw-r--r--build_files/build_environment/patches/openvdb_nanovdb.diff135
-rw-r--r--extern/mantaflow/preprocessed/plugin/apic.cpp377
-rw-r--r--intern/cycles/blender/blender_device.cpp3
-rw-r--r--intern/cycles/blender/blender_id_map.h28
-rw-r--r--intern/cycles/blender/blender_light.cpp6
-rw-r--r--intern/cycles/blender/blender_object.cpp10
-rw-r--r--intern/cycles/blender/blender_particles.cpp3
-rw-r--r--intern/cycles/blender/blender_session.cpp6
-rw-r--r--intern/cycles/blender/blender_shader.cpp4
-rw-r--r--intern/cycles/blender/blender_sync.cpp12
-rw-r--r--intern/cycles/bvh/bvh.cpp1
-rw-r--r--intern/cycles/device/CMakeLists.txt1
-rw-r--r--intern/cycles/device/device.cpp22
-rw-r--r--intern/cycles/device/device.h3
-rw-r--r--intern/cycles/device/device_dummy.cpp83
-rw-r--r--intern/cycles/device/device_intern.h1
-rw-r--r--intern/cycles/render/nodes.cpp1
-rw-r--r--intern/cycles/render/scene.cpp54
-rw-r--r--intern/cycles/render/scene.h22
-rw-r--r--intern/cycles/render/session.cpp38
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm12
-rw-r--r--intern/mantaflow/intern/MANTA_main.cpp8
-rw-r--r--intern/mantaflow/intern/strings/fluid_script.h2
-rw-r--r--intern/mantaflow/intern/strings/liquid_script.h25
-rw-r--r--release/scripts/startup/bl_operators/presets.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_material_gpencil.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py3
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py8
-rw-r--r--source/blender/blenkernel/BKE_collection.h22
-rw-r--r--source/blender/blenkernel/BKE_layer.h9
-rw-r--r--source/blender/blenkernel/BKE_particle.h9
-rw-r--r--source/blender/blenkernel/BKE_screen.h17
-rw-r--r--source/blender/blenkernel/BKE_undo_system.h9
-rw-r--r--source/blender/blenkernel/intern/collection.c179
-rw-r--r--source/blender/blenkernel/intern/constraint.c7
-rw-r--r--source/blender/blenkernel/intern/fluid.c1
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c3
-rw-r--r--source/blender/blenkernel/intern/lattice_deform.c16
-rw-r--r--source/blender/blenkernel/intern/layer.c93
-rw-r--r--source/blender/blenkernel/intern/modifier.c3
-rw-r--r--source/blender/blenkernel/intern/particle.c287
-rw-r--r--source/blender/blenkernel/intern/screen.c844
-rw-r--r--source/blender/blenkernel/intern/shader_fx.c3
-rw-r--r--source/blender/blenkernel/intern/undo_system.c51
-rw-r--r--source/blender/blenkernel/intern/workspace.c102
-rw-r--r--source/blender/blenloader/BLO_read_write.h12
-rw-r--r--source/blender/blenloader/intern/readfile.c1115
-rw-r--r--source/blender/blenloader/intern/readfile.h1
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/writefile.c435
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_data.c4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl8
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c20
-rw-r--r--source/blender/editors/curve/editcurve.c2
-rw-r--r--source/blender/editors/curve/editfont.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c221
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c6
-rw-r--r--source/blender/editors/include/ED_curve.h2
-rw-r--r--source/blender/editors/include/ED_undo.h3
-rw-r--r--source/blender/editors/interface/interface_handlers.c34
-rw-r--r--source/blender/editors/interface/interface_layout.c8
-rw-r--r--source/blender/editors/interface/view2d_ops.c14
-rw-r--r--source/blender/editors/object/object_modes.c58
-rw-r--r--source/blender/editors/object/object_relations.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c103
-rw-r--r--source/blender/editors/space_text/text_ops.c20
-rw-r--r--source/blender/editors/transform/transform_gizmo_2d.c2
-rw-r--r--source/blender/editors/undo/ed_undo.c38
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c2
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h2
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_material_types.h3
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_screen_types.h28
-rw-r--r--source/blender/makesdna/DNA_shader_fx_types.h2
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c13
-rw-r--r--source/blender/makesrna/intern/rna_material.c12
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c9
-rw-r--r--source/blender/makesrna/intern/rna_space.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c3
-rw-r--r--source/blender/modifiers/intern/MOD_array.c2
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c1
-rw-r--r--source/creator/creator.c6
-rw-r--r--source/creator/creator_args.c4
95 files changed, 2733 insertions, 2118 deletions
diff --git a/build_files/build_environment/CMakeLists.txt b/build_files/build_environment/CMakeLists.txt
index 59c15a03119..0bc85f20c16 100644
--- a/build_files/build_environment/CMakeLists.txt
+++ b/build_files/build_environment/CMakeLists.txt
@@ -85,6 +85,7 @@ include(cmake/flexbison.cmake)
include(cmake/osl.cmake)
include(cmake/tbb.cmake)
include(cmake/openvdb.cmake)
+include(cmake/nanovdb.cmake)
include(cmake/python.cmake)
include(cmake/python_site_packages.cmake)
include(cmake/package_python.cmake)
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
index 1fb56c4d568..1c5354aeb42 100644
--- a/build_files/build_environment/cmake/harvest.cmake
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -146,10 +146,8 @@ harvest(openjpeg/lib openjpeg/lib "*.a")
harvest(opensubdiv/include opensubdiv/include "*.h")
harvest(opensubdiv/lib opensubdiv/lib "*.a")
harvest(openvdb/include/openvdb openvdb/include/openvdb "*.h")
-if(WITH_NANOVDB)
- harvest(openvdb/nanovdb nanovdb/include/nanovdb "*.h")
-endif()
harvest(openvdb/lib openvdb/lib "*.a")
+harvest(nanovdb/nanovdb nanovdb/include/nanovdb "*.h")
harvest(xr_openxr_sdk/include/openxr xr_openxr_sdk/include/openxr "*.h")
harvest(xr_openxr_sdk/lib xr_openxr_sdk/lib "*.a")
harvest(osl/bin osl/bin "oslc")
diff --git a/build_files/build_environment/cmake/nanovdb.cmake b/build_files/build_environment/cmake/nanovdb.cmake
new file mode 100644
index 00000000000..89e7c38642d
--- /dev/null
+++ b/build_files/build_environment/cmake/nanovdb.cmake
@@ -0,0 +1,54 @@
+# ***** 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 *****
+
+set(NANOVDB_EXTRA_ARGS
+ # NanoVDB is header-only, so only need the install target
+ -DNANOVDB_BUILD_UNITTESTS=OFF
+ -DNANOVDB_BUILD_EXAMPLES=OFF
+ -DNANOVDB_BUILD_BENCHMARK=OFF
+ -DNANOVDB_BUILD_DOCS=OFF
+ -DNANOVDB_BUILD_TOOLS=OFF
+ -DNANOVDB_CUDA_KEEP_PTX=OFF
+ # Do not need to include any of the dependencies because of this
+ -DNANOVDB_USE_OPENVDB=OFF
+ -DNANOVDB_USE_OPENGL=OFF
+ -DNANOVDB_USE_OPENCL=OFF
+ -DNANOVDB_USE_CUDA=OFF
+ -DNANOVDB_USE_TBB=OFF
+ -DNANOVDB_USE_BLOSC=OFF
+ -DNANOVDB_USE_ZLIB=OFF
+ -DNANOVDB_USE_OPTIX=OFF
+ -DNANOVDB_ALLOW_FETCHCONTENT=OFF
+)
+
+ExternalProject_Add(nanovdb
+ URL ${NANOVDB_URI}
+ DOWNLOAD_DIR ${DOWNLOAD_DIR}
+ URL_HASH MD5=${NANOVDB_HASH}
+ PREFIX ${BUILD_DIR}/nanovdb
+ SOURCE_SUBDIR nanovdb
+ CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/nanovdb ${DEFAULT_CMAKE_FLAGS} ${NANOVDB_EXTRA_ARGS}
+ INSTALL_DIR ${LIBDIR}/nanovdb
+)
+
+if(WIN32)
+ ExternalProject_Add_Step(nanovdb after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/nanovdb/nanovdb ${HARVEST_TARGET}/nanovdb/include/nanovdb
+ DEPENDEES install
+ )
+endif()
diff --git a/build_files/build_environment/cmake/openvdb.cmake b/build_files/build_environment/cmake/openvdb.cmake
index 07d0297d5aa..2962f085e1b 100644
--- a/build_files/build_environment/cmake/openvdb.cmake
+++ b/build_files/build_environment/cmake/openvdb.cmake
@@ -54,20 +54,6 @@ set(OPENVDB_EXTRA_ARGS
-DOPENVDB_CORE_STATIC=${OPENVDB_STATIC}
-DOPENVDB_BUILD_BINARIES=Off
-DCMAKE_DEBUG_POSTFIX=_d
- # NanoVDB is header-only, so only need the install target
- -DNANOVDB_BUILD_UNITTESTS=OFF
- -DNANOVDB_BUILD_EXAMPLES=OFF
- -DNANOVDB_BUILD_BENCHMARK=OFF
- -DNANOVDB_BUILD_DOCS=OFF
- -DNANOVDB_BUILD_TOOLS=OFF
- -DNANOVDB_CUDA_KEEP_PTX=OFF
- -DNANOVDB_USE_OPENGL=OFF
- -DNANOVDB_USE_OPENGL=OFF
- -DNANOVDB_USE_CUDA=OFF
- -DNANOVDB_USE_TBB=OFF
- -DNANOVDB_USE_OPTIX=OFF
- -DNANOVDB_USE_OPENVDB=OFF
- -DNANOVDB_ALLOW_FETCHCONTENT=OFF
)
if(WIN32)
@@ -88,18 +74,12 @@ else()
)
endif()
-if(WITH_NANOVDB)
- set(OPENVDB_PATCH_FILE openvdb_nanovdb.diff)
-else()
- set(OPENVDB_PATCH_FILE openvdb.diff)
-endif()
-
ExternalProject_Add(openvdb
URL ${OPENVDB_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${OPENVDB_HASH}
PREFIX ${BUILD_DIR}/openvdb
- PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/${OPENVDB_PATCH_FILE}
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openvdb ${DEFAULT_CMAKE_FLAGS} ${OPENVDB_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openvdb
)
@@ -121,12 +101,6 @@ if(WIN32)
COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openvdb/bin/openvdb.dll ${HARVEST_TARGET}/openvdb/bin/openvdb.dll
DEPENDEES install
)
- if(WITH_NANOVDB)
- ExternalProject_Add_Step(openvdb nanovdb_install
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/openvdb/nanovdb ${HARVEST_TARGET}/nanovdb/include/nanovdb
- DEPENDEES after_install
- )
- endif()
endif()
if(BUILD_MODE STREQUAL Debug)
ExternalProject_Add_Step(openvdb after_install
diff --git a/build_files/build_environment/cmake/options.cmake b/build_files/build_environment/cmake/options.cmake
index d6b5762ccbc..29e2ffc7ed8 100644
--- a/build_files/build_environment/cmake/options.cmake
+++ b/build_files/build_environment/cmake/options.cmake
@@ -21,7 +21,6 @@ if(WIN32)
endif()
option(WITH_WEBP "Enable building of oiio with webp support" OFF)
option(WITH_BOOST_PYTHON "Enable building of boost with python support" OFF)
-option(WITH_NANOVDB "Enable building of OpenVDB with NanoVDB included" OFF)
set(MAKE_THREADS 1 CACHE STRING "Number of threads to run make with")
if(NOT BUILD_MODE)
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index 244ca6dd49f..653db9f740c 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -145,15 +145,13 @@ set(TBB_VERSION 2019_U9)
set(TBB_URI https://github.com/oneapi-src/oneTBB/archive/${TBB_VERSION}.tar.gz)
set(TBB_HASH 26263622e9187212ec240dcf01b66207)
-if(WITH_NANOVDB)
- set(OPENVDB_GIT_UID e62f7a0bf1e27397223c61ddeaaf57edf111b77f)
- set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/${OPENVDB_GIT_UID}.tar.gz)
- set(OPENVDB_HASH 90919510bc6ccd630fedc56f748cb199)
-else()
- set(OPENVDB_VERSION 7.0.0)
- set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
- set(OPENVDB_HASH fd6c4f168282f7e0e494d290cd531fa8)
-endif()
+set(OPENVDB_VERSION 7.0.0)
+set(OPENVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/v${OPENVDB_VERSION}.tar.gz)
+set(OPENVDB_HASH fd6c4f168282f7e0e494d290cd531fa8)
+
+set(NANOVDB_GIT_UID e62f7a0bf1e27397223c61ddeaaf57edf111b77f)
+set(NANOVDB_URI https://github.com/AcademySoftwareFoundation/openvdb/archive/${NANOVDB_GIT_UID}.tar.gz)
+set(NANOVDB_HASH 90919510bc6ccd630fedc56f748cb199)
set(IDNA_VERSION 2.9)
set(CHARDET_VERSION 3.0.4)
diff --git a/build_files/build_environment/patches/openvdb_nanovdb.diff b/build_files/build_environment/patches/openvdb_nanovdb.diff
deleted file mode 100644
index 50984e91f37..00000000000
--- a/build_files/build_environment/patches/openvdb_nanovdb.diff
+++ /dev/null
@@ -1,135 +0,0 @@
-diff -Naur orig/cmake/FindIlmBase.cmake openvdb/cmake/FindIlmBase.cmake
---- orig/cmake/FindIlmBase.cmake 2019-12-06 12:11:33 -0700
-+++ openvdb/cmake/FindIlmBase.cmake 2020-08-12 12:48:44 -0600
-@@ -217,6 +217,8 @@
- set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
- endif()
- list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "${_IlmBase_Version_Suffix}.lib")
-+ list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "_s.lib")
-+ list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "_s_d.lib")
- else()
- if(ILMBASE_USE_STATIC_LIBS)
- set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
-diff -Naur orig/cmake/FindOpenEXR.cmake openvdb/cmake/FindOpenEXR.cmake
---- orig/cmake/FindOpenEXR.cmake 2019-12-06 12:11:33 -0700
-+++ openvdb/cmake/FindOpenEXR.cmake 2020-08-12 12:48:44 -0600
-@@ -210,6 +210,8 @@
- set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib")
- endif()
- list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "${_OpenEXR_Version_Suffix}.lib")
-+ list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "_s.lib")
-+ list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES "_s_d.lib")
- else()
- if(OPENEXR_USE_STATIC_LIBS)
- set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
-diff -Naur orig/openvdb/openvdb/CMakeLists.txt openvdb/openvdb/openvdb/CMakeLists.txt
---- orig/openvdb/openvdb/CMakeLists.txt 2019-12-06 12:11:33 -0700
-+++ openvdb/openvdb/openvdb/CMakeLists.txt 2020-08-12 14:12:26 -0600
-@@ -105,7 +105,9 @@
- # http://boost.2283326.n4.nabble.com/CMake-config-scripts-broken-in-1-70-td4708957.html
- # https://github.com/boostorg/boost_install/commit/160c7cb2b2c720e74463865ef0454d4c4cd9ae7c
- set(BUILD_SHARED_LIBS ON)
-- set(Boost_USE_STATIC_LIBS OFF)
-+ if(NOT WIN32) # blender links boost statically on windows
-+ set(Boost_USE_STATIC_LIBS OFF)
-+ endif()
- endif()
-
- find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS iostreams system)
-@@ -193,6 +195,7 @@
- if(OPENVDB_DISABLE_BOOST_IMPLICIT_LINKING)
- add_definitions(-DBOOST_ALL_NO_LIB)
- endif()
-+ add_definitions(-D__TBB_NO_IMPLICIT_LINKAGE -DOPENVDB_OPENEXR_STATICLIB)
- endif()
-
- # @todo Should be target definitions
-@@ -383,7 +386,12 @@
- # imported targets.
-
- if(OPENVDB_CORE_SHARED)
-- add_library(openvdb_shared SHARED ${OPENVDB_LIBRARY_SOURCE_FILES})
-+ if(WIN32)
-+ configure_file(version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
-+ add_library(openvdb_shared SHARED ${OPENVDB_LIBRARY_SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-+ else()
-+ add_library(openvdb_shared SHARED ${OPENVDB_LIBRARY_SOURCE_FILES})
-+ endif()
- endif()
-
- if(OPENVDB_CORE_STATIC)
-diff -Naur orig/openvdb/openvdb/version.rc.in openvdb/openvdb/openvdb/version.rc.in
---- orig/openvdb/openvdb/version.rc.in 1969-12-31 17:00:00 -0700
-+++ openvdb/openvdb/openvdb/version.rc.in 2020-08-12 14:15:01 -0600
-@@ -0,0 +1,48 @@
-+#include <winver.h>
-+
-+#define VER_FILEVERSION @OpenVDB_MAJOR_VERSION@,@OpenVDB_MINOR_VERSION@,@OpenVDB_PATCH_VERSION@,0
-+#define VER_FILEVERSION_STR "@OpenVDB_MAJOR_VERSION@.@OpenVDB_MINOR_VERSION@.@OpenVDB_PATCH_VERSION@.0\0"
-+
-+#define VER_PRODUCTVERSION @OpenVDB_MAJOR_VERSION@,@OpenVDB_MINOR_VERSION@,@OpenVDB_PATCH_VERSION@,0
-+#define VER_PRODUCTVERSION_STR "@OpenVDB_MAJOR_VERSION@.@OpenVDB_MINOR_VERSION@\0"
-+
-+#ifndef DEBUG
-+#define VER_DEBUG 0
-+#else
-+#define VER_DEBUG VS_FF_DEBUG
-+#endif
-+
-+VS_VERSION_INFO VERSIONINFO
-+FILEVERSION VER_FILEVERSION
-+PRODUCTVERSION VER_PRODUCTVERSION
-+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-+FILEFLAGS (VER_DEBUG)
-+FILEOS VOS__WINDOWS32
-+FILETYPE VFT_DLL
-+FILESUBTYPE VFT2_UNKNOWN
-+BEGIN
-+ BLOCK "StringFileInfo"
-+ BEGIN
-+ BLOCK "040904E4"
-+ BEGIN
-+ VALUE "FileDescription", "OpenVDB"
-+ VALUE "FileVersion", VER_FILEVERSION_STR
-+ VALUE "InternalName", "OpenVDB"
-+ VALUE "ProductName", "OpenVDB"
-+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
-+ END
-+ END
-+
-+ BLOCK "VarFileInfo"
-+ BEGIN
-+ /* The following line should only be modified for localized versions. */
-+ /* It consists of any number of WORD,WORD pairs, with each pair */
-+ /* describing a language,codepage combination supported by the file. */
-+ /* */
-+ /* For example, a file might have values "0x409,1252" indicating that it */
-+ /* supports English language (0x409) in the Windows ANSI codepage (1252). */
-+
-+ VALUE "Translation", 0x409, 1252
-+
-+ END
-+END
-diff -Naur openvdb-original/CMakeLists.txt openvdb/CMakeLists.txt
---- openvdb-original/CMakeLists.txt 2020-08-27 03:34:02.000000000 +0200
-+++ openvdb/CMakeLists.txt 2020-09-02 10:56:21.665735244 +0200
-@@ -68,6 +68,7 @@
- option(OPENVDB_INSTALL_HOUDINI_PYTHONRC [=[Install a Houdini startup script that sets
- the visibilty of OpenVDB nodes and their native equivalents.]=] OFF)
- option(OPENVDB_BUILD_MAYA_PLUGIN "Build the Maya plugin" OFF)
-+option(OPENVDB_BUILD_NANOVDB "Build nanovdb" ON)
- option(OPENVDB_ENABLE_RPATH "Build with RPATH information" ON)
- option(OPENVDB_CXX_STRICT "Enable or disable pre-defined compiler warnings" OFF)
- option(OPENVDB_CODE_COVERAGE "Enable code coverage. This also overrides CMAKE_BUILD_TYPE to Debug" OFF)
-@@ -740,6 +741,10 @@
- add_subdirectory(openvdb_maya)
- endif()
-
-+if(OPENVDB_BUILD_NANOVDB)
-+ add_subdirectory(nanovdb)
-+endif()
-+
- ##########################################################################
-
- add_custom_target(uninstall
- \ No newline at end of file
diff --git a/extern/mantaflow/preprocessed/plugin/apic.cpp b/extern/mantaflow/preprocessed/plugin/apic.cpp
index 6ff893014c9..460c6459916 100644
--- a/extern/mantaflow/preprocessed/plugin/apic.cpp
+++ b/extern/mantaflow/preprocessed/plugin/apic.cpp
@@ -6,7 +6,7 @@
// ----------------------------------------------------------------------------
//
// MantaFlow fluid solver framework
-// Copyright 2016-2017 Kiwon Um, Nils Thuerey
+// Copyright 2016-2020 Kiwon Um, Nils Thuerey
//
// This program is free software, distributed under the terms of the
// Apache License, Version 2.0
@@ -21,6 +21,46 @@
namespace Manta {
+#define FOR_INT_IJK(num) \
+ for (int i = 0; i < num; ++i) \
+ for (int j = 0; j < num; ++j) \
+ for (int k = 0; k < num; ++k)
+
+static inline IndexInt indexUFace(const Vec3 &pos, const MACGrid &ref)
+{
+ const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
+ const IndexInt index = f.x * ref.getStrideX() + c.y * ref.getStrideY() + c.z * ref.getStrideZ();
+ assertDeb(ref.isInBounds(index), "Grid index out of bounds");
+ return (ref.isInBounds(index)) ? index : -1;
+}
+
+static inline IndexInt indexVFace(const Vec3 &pos, const MACGrid &ref)
+{
+ const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
+ const IndexInt index = c.x * ref.getStrideX() + f.y * ref.getStrideY() + c.z * ref.getStrideZ();
+ assertDeb(ref.isInBounds(index), "Grid index out of bounds");
+ return (ref.isInBounds(index)) ? index : -1;
+}
+
+static inline IndexInt indexWFace(const Vec3 &pos, const MACGrid &ref)
+{
+ const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
+ const IndexInt index = c.x * ref.getStrideX() + c.y * ref.getStrideY() + f.z * ref.getStrideZ();
+ assertDeb(ref.isInBounds(index), "Grid index out of bounds");
+ return (ref.isInBounds(index)) ? index : -1;
+}
+
+static inline IndexInt indexOffset(
+ const IndexInt gidx, const int i, const int j, const int k, const MACGrid &ref)
+{
+ const IndexInt dX[2] = {0, ref.getStrideX()};
+ const IndexInt dY[2] = {0, ref.getStrideY()};
+ const IndexInt dZ[2] = {0, ref.getStrideZ()};
+ const IndexInt index = gidx + dX[i] + dY[j] + dZ[k];
+ assertDeb(ref.isInBounds(index), "Grid index out of bounds");
+ return (ref.isInBounds(index)) ? index : -1;
+}
+
struct knApicMapLinearVec3ToMACGrid : public KernelBase {
knApicMapLinearVec3ToMACGrid(const BasicParticleSystem &p,
MACGrid &mg,
@@ -30,7 +70,8 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
const ParticleDataImpl<Vec3> &cpy,
const ParticleDataImpl<Vec3> &cpz,
const ParticleDataImpl<int> *ptype,
- const int exclude)
+ const int exclude,
+ const int boundaryWidth)
: KernelBase(p.size()),
p(p),
mg(mg),
@@ -40,7 +81,8 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
cpy(cpy),
cpz(cpz),
ptype(ptype),
- exclude(exclude)
+ exclude(exclude),
+ boundaryWidth(boundaryWidth)
{
runMessage();
run();
@@ -54,73 +96,91 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
const ParticleDataImpl<Vec3> &cpy,
const ParticleDataImpl<Vec3> &cpz,
const ParticleDataImpl<int> *ptype,
- const int exclude)
+ const int exclude,
+ const int boundaryWidth)
{
if (!p.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
return;
- const IndexInt dX[2] = {0, vg.getStrideX()};
- const IndexInt dY[2] = {0, vg.getStrideY()};
- const IndexInt dZ[2] = {0, vg.getStrideZ()};
-
- const Vec3 &pos = p[idx].pos, &vel = vp[idx];
- const IndexInt fi = static_cast<IndexInt>(pos.x), fj = static_cast<IndexInt>(pos.y),
- fk = static_cast<IndexInt>(pos.z);
- const IndexInt ci = static_cast<IndexInt>(pos.x - 0.5),
- cj = static_cast<IndexInt>(pos.y - 0.5),
- ck = static_cast<IndexInt>(pos.z - 0.5);
- const Real wfi = clamp(pos.x - fi, Real(0), Real(1)),
- wfj = clamp(pos.y - fj, Real(0), Real(1)),
- wfk = clamp(pos.z - fk, Real(0), Real(1));
- const Real wci = clamp(Real(pos.x - ci - 0.5), Real(0), Real(1)),
- wcj = clamp(Real(pos.y - cj - 0.5), Real(0), Real(1)),
- wck = clamp(Real(pos.z - ck - 0.5), Real(0), Real(1));
- // TODO: check index for safety
+ if (!vg.isInBounds(p.getPos(idx), boundaryWidth)) {
+ debMsg("Skipping particle at index " << idx
+ << ". Is out of bounds and cannot be applied to grid.",
+ 1);
+ return;
+ }
+
+ const Vec3 &pos = p.getPos(idx), &vel = vp[idx];
+ const Vec3i f = toVec3i(pos);
+ const Vec3i c = toVec3i(pos - 0.5);
+ const Vec3 wf = clamp(pos - toVec3(f), Vec3(0.), Vec3(1.));
+ const Vec3 wc = clamp(pos - toVec3(c) - 0.5, Vec3(0.), Vec3(1.));
+
{ // u-face
- const IndexInt gidx = fi * dX[1] + cj * dY[1] + ck * dZ[1];
- const Vec3 gpos(fi, cj + 0.5, ck + 0.5);
- const Real wi[2] = {Real(1) - wfi, wfi};
- const Real wj[2] = {Real(1) - wcj, wcj};
- const Real wk[2] = {Real(1) - wck, wck};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const Real w = wi[i] * wj[j] * wk[k];
- mg[gidx + dX[i] + dY[j] + dZ[k]].x += w;
- vg[gidx + dX[i] + dY[j] + dZ[k]].x += w * vel.x;
- vg[gidx + dX[i] + dY[j] + dZ[k]].x += w * dot(cpx[idx], gpos + Vec3(i, j, k) - pos);
- }
+ const IndexInt gidx = indexUFace(pos, vg);
+ if (gidx < 0)
+ return; // debug will fail before
+
+ const Vec3 gpos(f.x, c.y + 0.5, c.z + 0.5);
+ const Real wi[2] = {Real(1) - wf.x, wf.x};
+ const Real wj[2] = {Real(1) - wc.y, wc.y};
+ const Real wk[2] = {Real(1) - wc.z, wc.z};
+
+ FOR_INT_IJK(2)
+ {
+ const Real w = wi[i] * wj[j] * wk[k];
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue; // debug will fail before
+
+ mg[vidx].x += w;
+ vg[vidx].x += w * vel.x;
+ vg[vidx].x += w * dot(cpx[idx], gpos + Vec3(i, j, k) - pos);
+ }
}
{ // v-face
- const IndexInt gidx = ci * dX[1] + fj * dY[1] + ck * dZ[1];
- const Vec3 gpos(ci + 0.5, fj, ck + 0.5);
- const Real wi[2] = {Real(1) - wci, wci};
- const Real wj[2] = {Real(1) - wfj, wfj};
- const Real wk[2] = {Real(1) - wck, wck};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const Real w = wi[i] * wj[j] * wk[k];
- mg[gidx + dX[i] + dY[j] + dZ[k]].y += w;
- vg[gidx + dX[i] + dY[j] + dZ[k]].y += w * vel.y;
- vg[gidx + dX[i] + dY[j] + dZ[k]].y += w * dot(cpy[idx], gpos + Vec3(i, j, k) - pos);
- }
+ const IndexInt gidx = indexVFace(pos, vg);
+ if (gidx < 0)
+ return;
+
+ const Vec3 gpos(c.x + 0.5, f.y, c.z + 0.5);
+ const Real wi[2] = {Real(1) - wc.x, wc.x};
+ const Real wj[2] = {Real(1) - wf.y, wf.y};
+ const Real wk[2] = {Real(1) - wc.z, wc.z};
+
+ FOR_INT_IJK(2)
+ {
+ const Real w = wi[i] * wj[j] * wk[k];
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue;
+
+ mg[vidx].y += w;
+ vg[vidx].y += w * vel.y;
+ vg[vidx].y += w * dot(cpy[idx], gpos + Vec3(i, j, k) - pos);
+ }
}
if (!vg.is3D())
return;
{ // w-face
- const IndexInt gidx = ci * dX[1] + cj * dY[1] + fk * dZ[1];
- const Vec3 gpos(ci + 0.5, cj + 0.5, fk);
- const Real wi[2] = {Real(1) - wci, wci};
- const Real wj[2] = {Real(1) - wcj, wcj};
- const Real wk[2] = {Real(1) - wfk, wfk};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const Real w = wi[i] * wj[j] * wk[k];
- mg[gidx + dX[i] + dY[j] + dZ[k]].z += w;
- vg[gidx + dX[i] + dY[j] + dZ[k]].z += w * vel.z;
- vg[gidx + dX[i] + dY[j] + dZ[k]].z += w * dot(cpz[idx], gpos + Vec3(i, j, k) - pos);
- }
+ const IndexInt gidx = indexWFace(pos, vg);
+ if (gidx < 0)
+ return;
+
+ const Vec3 gpos(c.x + 0.5, c.y + 0.5, f.z);
+ const Real wi[2] = {Real(1) - wc.x, wc.x};
+ const Real wj[2] = {Real(1) - wc.y, wc.y};
+ const Real wk[2] = {Real(1) - wf.z, wf.z};
+
+ FOR_INT_IJK(2)
+ {
+ const Real w = wi[i] * wj[j] * wk[k];
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue;
+
+ mg[vidx].z += w;
+ vg[vidx].z += w * vel.z;
+ vg[vidx].z += w * dot(cpz[idx], gpos + Vec3(i, j, k) - pos);
+ }
}
}
inline const BasicParticleSystem &getArg0()
@@ -168,6 +228,11 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
return exclude;
}
typedef int type8;
+ inline const int &getArg9()
+ {
+ return boundaryWidth;
+ }
+ typedef int type9;
void runMessage()
{
debMsg("Executing kernel knApicMapLinearVec3ToMACGrid ", 3);
@@ -179,7 +244,7 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
{
const IndexInt _sz = size;
for (IndexInt i = 0; i < _sz; i++)
- op(i, p, mg, vg, vp, cpx, cpy, cpz, ptype, exclude);
+ op(i, p, mg, vg, vp, cpx, cpy, cpz, ptype, exclude, boundaryWidth);
}
const BasicParticleSystem &p;
MACGrid &mg;
@@ -190,6 +255,7 @@ struct knApicMapLinearVec3ToMACGrid : public KernelBase {
const ParticleDataImpl<Vec3> &cpz;
const ParticleDataImpl<int> *ptype;
const int exclude;
+ const int boundaryWidth;
};
void apicMapPartsToMAC(const FlagGrid &flags,
@@ -201,23 +267,22 @@ void apicMapPartsToMAC(const FlagGrid &flags,
const ParticleDataImpl<Vec3> &cpz,
MACGrid *mass = NULL,
const ParticleDataImpl<int> *ptype = NULL,
- const int exclude = 0)
+ const int exclude = 0,
+ const int boundaryWidth = 0)
{
- // affine map
- // let's assume that the particle mass is constant, 1.0
- const bool freeMass = !mass;
- if (!mass)
- mass = new MACGrid(flags.getParent());
- else
- mass->clear();
+ // affine map: let's assume that the particle mass is constant, 1.0
+ if (!mass) {
+ MACGrid tmpmass(vel.getParent());
+ mass = &tmpmass;
+ }
+ mass->clear();
vel.clear();
- knApicMapLinearVec3ToMACGrid(parts, *mass, vel, partVel, cpx, cpy, cpz, ptype, exclude);
+
+ knApicMapLinearVec3ToMACGrid(
+ parts, *mass, vel, partVel, cpx, cpy, cpz, ptype, exclude, boundaryWidth);
mass->stomp(VECTOR_EPSILON);
vel.safeDivide(*mass);
-
- if (freeMass)
- delete mass;
}
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
@@ -241,8 +306,10 @@ static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
"ptype", 8, NULL, &_lock);
const int exclude = _args.getOpt<int>("exclude", 9, 0, &_lock);
+ const int boundaryWidth = _args.getOpt<int>("boundaryWidth", 10, 0, &_lock);
_retval = getPyNone();
- apicMapPartsToMAC(flags, vel, parts, partVel, cpx, cpy, cpz, mass, ptype, exclude);
+ apicMapPartsToMAC(
+ flags, vel, parts, partVel, cpx, cpy, cpz, mass, ptype, exclude, boundaryWidth);
_args.check();
}
pbFinalizePlugin(parent, "apicMapPartsToMAC", !noTiming);
@@ -270,7 +337,8 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
const MACGrid &vg,
const FlagGrid &flags,
const ParticleDataImpl<int> *ptype,
- const int exclude)
+ const int exclude,
+ const int boundaryWidth)
: KernelBase(vp.size()),
vp(vp),
cpx(cpx),
@@ -280,7 +348,8 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
vg(vg),
flags(flags),
ptype(ptype),
- exclude(exclude)
+ exclude(exclude),
+ boundaryWidth(boundaryWidth)
{
runMessage();
run();
@@ -294,78 +363,94 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
const MACGrid &vg,
const FlagGrid &flags,
const ParticleDataImpl<int> *ptype,
- const int exclude) const
+ const int exclude,
+ const int boundaryWidth) const
{
if (!p.isActive(idx) || (ptype && ((*ptype)[idx] & exclude)))
return;
+ if (!vg.isInBounds(p.getPos(idx), boundaryWidth)) {
+ debMsg("Skipping particle at index " << idx
+ << ". Is out of bounds and cannot get value from grid.",
+ 1);
+ return;
+ }
vp[idx] = cpx[idx] = cpy[idx] = cpz[idx] = Vec3(Real(0));
- const IndexInt dX[2] = {0, vg.getStrideX()}, dY[2] = {0, vg.getStrideY()},
- dZ[2] = {0, vg.getStrideZ()};
const Real gw[2] = {-Real(1), Real(1)};
- const Vec3 &pos = p[idx].pos;
- const IndexInt fi = static_cast<IndexInt>(pos.x), fj = static_cast<IndexInt>(pos.y),
- fk = static_cast<IndexInt>(pos.z);
- const IndexInt ci = static_cast<IndexInt>(pos.x - 0.5),
- cj = static_cast<IndexInt>(pos.y - 0.5),
- ck = static_cast<IndexInt>(pos.z - 0.5);
- const Real wfi = clamp(pos.x - fi, Real(0), Real(1)),
- wfj = clamp(pos.y - fj, Real(0), Real(1)),
- wfk = clamp(pos.z - fk, Real(0), Real(1));
- const Real wci = clamp(Real(pos.x - ci - 0.5), Real(0), Real(1)),
- wcj = clamp(Real(pos.y - cj - 0.5), Real(0), Real(1)),
- wck = clamp(Real(pos.z - ck - 0.5), Real(0), Real(1));
- // TODO: check index for safety
- { // u
- const IndexInt gidx = fi * dX[1] + cj * dY[1] + ck * dZ[1];
- const Real wx[2] = {Real(1) - wfi, wfi};
- const Real wy[2] = {Real(1) - wcj, wcj};
- const Real wz[2] = {Real(1) - wck, wck};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const IndexInt vidx = gidx + dX[i] + dY[j] + dZ[k];
- Real vgx = vg[vidx].x;
- vp[idx].x += wx[i] * wy[j] * wz[k] * vgx;
- cpx[idx].x += gw[i] * wy[j] * wz[k] * vgx;
- cpx[idx].y += wx[i] * gw[j] * wz[k] * vgx;
- cpx[idx].z += wx[i] * wy[j] * gw[k] * vgx;
- }
+ const Vec3 &pos = p.getPos(idx);
+ const Vec3i f = toVec3i(pos);
+ const Vec3i c = toVec3i(pos - 0.5);
+ const Vec3 wf = clamp(pos - toVec3(f), Vec3(0.), Vec3(1.));
+ const Vec3 wc = clamp(pos - toVec3(c) - 0.5, Vec3(0.), Vec3(1.));
+
+ { // u-face
+ const IndexInt gidx = indexUFace(pos, vg);
+ if (gidx < 0)
+ return; // debug will fail before
+
+ const Real wx[2] = {Real(1) - wf.x, wf.x};
+ const Real wy[2] = {Real(1) - wc.y, wc.y};
+ const Real wz[2] = {Real(1) - wc.z, wc.z};
+
+ FOR_INT_IJK(2)
+ {
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue; // debug will fail before
+
+ const Real vgx = vg[vidx].x;
+ vp[idx].x += wx[i] * wy[j] * wz[k] * vgx;
+ cpx[idx].x += gw[i] * wy[j] * wz[k] * vgx;
+ cpx[idx].y += wx[i] * gw[j] * wz[k] * vgx;
+ cpx[idx].z += wx[i] * wy[j] * gw[k] * vgx;
+ }
}
- { // v
- const IndexInt gidx = ci * dX[1] + fj * dY[1] + ck * dZ[1];
- const Real wx[2] = {Real(1) - wci, wci};
- const Real wy[2] = {Real(1) - wfj, wfj};
- const Real wz[2] = {Real(1) - wck, wck};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const IndexInt vidx = gidx + dX[i] + dY[j] + dZ[k];
- Real vgy = vg[vidx].y;
- vp[idx].y += wx[i] * wy[j] * wz[k] * vgy;
- cpy[idx].x += gw[i] * wy[j] * wz[k] * vgy;
- cpy[idx].y += wx[i] * gw[j] * wz[k] * vgy;
- cpy[idx].z += wx[i] * wy[j] * gw[k] * vgy;
- }
+ { // v-face
+ const IndexInt gidx = indexVFace(pos, vg);
+ if (gidx < 0)
+ return;
+
+ const Real wx[2] = {Real(1) - wc.x, wc.x};
+ const Real wy[2] = {Real(1) - wf.y, wf.y};
+ const Real wz[2] = {Real(1) - wc.z, wc.z};
+
+ FOR_INT_IJK(2)
+ {
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue;
+
+ const Real vgy = vg[vidx].y;
+ vp[idx].y += wx[i] * wy[j] * wz[k] * vgy;
+ cpy[idx].x += gw[i] * wy[j] * wz[k] * vgy;
+ cpy[idx].y += wx[i] * gw[j] * wz[k] * vgy;
+ cpy[idx].z += wx[i] * wy[j] * gw[k] * vgy;
+ }
}
if (!vg.is3D())
return;
- { // w
- const IndexInt gidx = ci * dX[1] + cj * dY[1] + fk * dZ[1];
- const Real wx[2] = {Real(1) - wci, wci};
- const Real wy[2] = {Real(1) - wcj, wcj};
- const Real wz[2] = {Real(1) - wfk, wfk};
- for (int i = 0; i < 2; ++i)
- for (int j = 0; j < 2; ++j)
- for (int k = 0; k < 2; ++k) {
- const IndexInt vidx = gidx + dX[i] + dY[j] + dZ[k];
- Real vgz = vg[vidx].z;
- vp[idx].z += wx[i] * wy[j] * wz[k] * vgz;
- cpz[idx].x += gw[i] * wy[j] * wz[k] * vgz;
- cpz[idx].y += wx[i] * gw[j] * wz[k] * vgz;
- cpz[idx].z += wx[i] * wy[j] * gw[k] * vgz;
- }
+ { // w-face
+ const IndexInt gidx = indexWFace(pos, vg);
+ if (gidx < 0)
+ return;
+
+ const Real wx[2] = {Real(1) - wc.x, wc.x};
+ const Real wy[2] = {Real(1) - wc.y, wc.y};
+ const Real wz[2] = {Real(1) - wf.z, wf.z};
+
+ FOR_INT_IJK(2)
+ {
+ const IndexInt vidx = indexOffset(gidx, i, j, k, vg);
+ if (vidx < 0)
+ continue;
+
+ const Real vgz = vg[vidx].z;
+ vp[idx].z += wx[i] * wy[j] * wz[k] * vgz;
+ cpz[idx].x += gw[i] * wy[j] * wz[k] * vgz;
+ cpz[idx].y += wx[i] * gw[j] * wz[k] * vgz;
+ cpz[idx].z += wx[i] * wy[j] * gw[k] * vgz;
+ }
}
}
inline ParticleDataImpl<Vec3> &getArg0()
@@ -413,6 +498,11 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
return exclude;
}
typedef int type8;
+ inline const int &getArg9()
+ {
+ return boundaryWidth;
+ }
+ typedef int type9;
void runMessage()
{
debMsg("Executing kernel knApicMapLinearMACGridToVec3 ", 3);
@@ -423,7 +513,7 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
void operator()(const tbb::blocked_range<IndexInt> &__r) const
{
for (IndexInt idx = __r.begin(); idx != (IndexInt)__r.end(); idx++)
- op(idx, vp, cpx, cpy, cpz, p, vg, flags, ptype, exclude);
+ op(idx, vp, cpx, cpy, cpz, p, vg, flags, ptype, exclude, boundaryWidth);
}
void run()
{
@@ -438,6 +528,7 @@ struct knApicMapLinearMACGridToVec3 : public KernelBase {
const FlagGrid &flags;
const ParticleDataImpl<int> *ptype;
const int exclude;
+ const int boundaryWidth;
};
void apicMapMACGridToParts(ParticleDataImpl<Vec3> &partVel,
@@ -448,9 +539,11 @@ void apicMapMACGridToParts(ParticleDataImpl<Vec3> &partVel,
const MACGrid &vel,
const FlagGrid &flags,
const ParticleDataImpl<int> *ptype = NULL,
- const int exclude = 0)
+ const int exclude = 0,
+ const int boundaryWidth = 0)
{
- knApicMapLinearMACGridToVec3(partVel, cpx, cpy, cpz, parts, vel, flags, ptype, exclude);
+ knApicMapLinearMACGridToVec3(
+ partVel, cpx, cpy, cpz, parts, vel, flags, ptype, exclude, boundaryWidth);
}
static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{
@@ -473,8 +566,10 @@ static PyObject *_W_1(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
const ParticleDataImpl<int> *ptype = _args.getPtrOpt<ParticleDataImpl<int>>(
"ptype", 7, NULL, &_lock);
const int exclude = _args.getOpt<int>("exclude", 8, 0, &_lock);
+ const int boundaryWidth = _args.getOpt<int>("boundaryWidth", 9, 0, &_lock);
_retval = getPyNone();
- apicMapMACGridToParts(partVel, cpx, cpy, cpz, parts, vel, flags, ptype, exclude);
+ apicMapMACGridToParts(
+ partVel, cpx, cpy, cpz, parts, vel, flags, ptype, exclude, boundaryWidth);
_args.check();
}
pbFinalizePlugin(parent, "apicMapMACGridToParts", !noTiming);
diff --git a/intern/cycles/blender/blender_device.cpp b/intern/cycles/blender/blender_device.cpp
index 0293223864d..ffcaef0b2a9 100644
--- a/intern/cycles/blender/blender_device.cpp
+++ b/intern/cycles/blender/blender_device.cpp
@@ -47,8 +47,7 @@ DeviceInfo blender_device_info(BL::Preferences &b_preferences, BL::Scene &b_scen
vector<DeviceInfo> devices = Device::available_devices(BlenderSession::device_override);
if (devices.empty()) {
- printf("Found no Cycles device of the specified type, falling back to CPU...\n");
- return Device::available_devices(DEVICE_MASK_CPU).front();
+ return Device::dummy_device("Found no Cycles device of the specified type");
}
int threads = blender_device_threads(b_scene);
diff --git a/intern/cycles/blender/blender_id_map.h b/intern/cycles/blender/blender_id_map.h
index 8ce1d23665d..198cfb4b29a 100644
--- a/intern/cycles/blender/blender_id_map.h
+++ b/intern/cycles/blender/blender_id_map.h
@@ -35,10 +35,22 @@ CCL_NAMESPACE_BEGIN
template<typename K, typename T> class id_map {
public:
- id_map()
+ id_map(Scene *scene_) : scene(scene_)
{
}
+ ~id_map()
+ {
+ set<T *> nodes;
+
+ typename map<K, T *>::iterator jt;
+ for (jt = b_map.begin(); jt != b_map.end(); jt++) {
+ nodes.insert(jt->second);
+ }
+
+ scene->delete_nodes(nodes);
+ }
+
T *find(const BL::ID &id)
{
return find(id.ptr.owner_id);
@@ -98,16 +110,15 @@ template<typename K, typename T> class id_map {
}
/* Combined add and update as needed. */
- bool add_or_update(Scene *scene, T **r_data, const BL::ID &id)
+ bool add_or_update(T **r_data, const BL::ID &id)
{
- return add_or_update(scene, r_data, id, id, id.ptr.owner_id);
+ return add_or_update(r_data, id, id, id.ptr.owner_id);
}
- bool add_or_update(Scene *scene, T **r_data, const BL::ID &id, const K &key)
+ bool add_or_update(T **r_data, const BL::ID &id, const K &key)
{
- return add_or_update(scene, r_data, id, id, key);
+ return add_or_update(r_data, id, id, key);
}
- bool add_or_update(
- Scene *scene, T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
+ bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
{
T *data = find(key);
bool recalc;
@@ -146,7 +157,7 @@ template<typename K, typename T> class id_map {
b_map[NULL] = data;
}
- void post_sync(Scene *scene, bool do_delete = true)
+ void post_sync(bool do_delete = true)
{
map<K, T *> new_map;
typedef pair<const K, T *> TMapPair;
@@ -177,6 +188,7 @@ template<typename K, typename T> class id_map {
map<K, T *> b_map;
set<T *> used_set;
set<void *> b_recalc;
+ Scene *scene;
};
/* Object Key
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index 117e9214e5a..6f95821e31e 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -39,9 +39,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
BL::Light b_light(b_ob.data());
/* Update if either object or light data changed. */
- if (!light_map.add_or_update(scene, &light, b_ob, b_parent, key)) {
+ if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
Shader *shader;
- if (!shader_map.add_or_update(scene, &shader, b_light)) {
+ if (!shader_map.add_or_update(&shader, b_light)) {
if (light->is_portal)
*use_portal = true;
return;
@@ -176,7 +176,7 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
Light *light;
ObjectKey key(b_world, 0, b_world, false);
- if (light_map.add_or_update(scene, &light, b_world, b_world, key) || world_recalc ||
+ if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
b_world.ptr.data != world_map) {
light->type = LIGHT_BACKGROUND;
if (sampling_method == SAMPLING_MANUAL) {
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 23faacc15da..d8c4ce9c5df 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -218,7 +218,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* test if we need to sync */
bool object_updated = false;
- if (object_map.add_or_update(scene, &object, b_ob, b_parent, key))
+ if (object_map.add_or_update(&object, b_ob, b_parent, key))
object_updated = true;
/* mesh sync */
@@ -435,10 +435,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
sync_background_light(b_v3d, use_portal);
/* handle removed data and modified pointers */
- light_map.post_sync(scene);
- geometry_map.post_sync(scene);
- object_map.post_sync(scene);
- particle_system_map.post_sync(scene);
+ light_map.post_sync();
+ geometry_map.post_sync();
+ object_map.post_sync();
+ particle_system_map.post_sync();
}
if (motion)
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index ee14217988b..e5eab1ae62b 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -53,8 +53,7 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
ParticleSystem *psys;
bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.add_or_update(
- scene, &psys, b_ob, b_instance.object(), key);
+ bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key);
/* no update needed? */
if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update)
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index c2bdec0e53d..7abfc6d81bc 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -238,6 +238,7 @@ void BlenderSession::reset_session(BL::BlendData &b_data, BL::Depsgraph &b_depsg
* See note on create_session().
*/
/* sync object should be re-created */
+ delete sync;
sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress);
BL::SpaceView3D b_null_space_view3d(PointerRNA_NULL);
@@ -472,6 +473,11 @@ void BlenderSession::render(BL::Depsgraph &b_depsgraph_)
{
b_depsgraph = b_depsgraph_;
+ if (session->progress.get_cancel()) {
+ update_status_progress();
+ return;
+ }
+
/* set callback to write out render results */
session->write_render_tile_cb = function_bind(&BlenderSession::write_render_tile, this, _1);
session->update_render_tile_cb = function_bind(
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 03ed88ea9ec..c171982b29d 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -1241,7 +1241,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(scene, &shader, b_mat) || update_all) {
+ if (shader_map.add_or_update(&shader, b_mat) || update_all) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@@ -1467,7 +1467,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(scene, &shader, b_light) || update_all) {
+ if (shader_map.add_or_update(&shader, b_light) || update_all) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index d2760d55f2d..0139afb711d 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -56,11 +56,11 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
: b_engine(b_engine),
b_data(b_data),
b_scene(b_scene),
- shader_map(),
- object_map(),
- geometry_map(),
- light_map(),
- particle_system_map(),
+ shader_map(scene),
+ object_map(scene),
+ geometry_map(scene),
+ light_map(scene),
+ particle_system_map(scene),
world_map(NULL),
world_recalc(false),
scene(scene),
@@ -247,7 +247,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
/* Shader sync done at the end, since object sync uses it.
* false = don't delete unused shaders, not supported. */
- shader_map.post_sync(scene, false);
+ shader_map.post_sync(false);
free_data_after_sync(b_depsgraph);
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 2a1114229da..222c1c40f92 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -108,6 +108,7 @@ BVH *BVH::create(const BVHParams &params,
#ifdef WITH_EMBREE
return new BVHEmbree(params, geometry, objects, device);
#else
+ (void)device;
break;
#endif
case BVH_LAYOUT_OPTIX:
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index cc54f64b1bb..928249931a3 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
device_cpu.cpp
device_cuda.cpp
device_denoising.cpp
+ device_dummy.cpp
device_memory.cpp
device_multi.cpp
device_opencl.cpp
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 407f73e8451..eb8fb8040e3 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -375,7 +375,7 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
}
#endif
- Device *device;
+ Device *device = NULL;
switch (info.type) {
case DEVICE_CPU:
@@ -385,16 +385,12 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
case DEVICE_CUDA:
if (device_cuda_init())
device = device_cuda_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
#ifdef WITH_OPTIX
case DEVICE_OPTIX:
if (device_optix_init())
device = device_optix_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
#ifdef WITH_NETWORK
@@ -406,12 +402,14 @@ Device *Device::create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool
case DEVICE_OPENCL:
if (device_opencl_init())
device = device_opencl_create(info, stats, profiler, background);
- else
- device = NULL;
break;
#endif
default:
- return NULL;
+ break;
+ }
+
+ if (device == NULL) {
+ device = device_dummy_create(info, stats, profiler, background);
}
return device;
@@ -549,6 +547,14 @@ vector<DeviceInfo> Device::available_devices(uint mask)
return devices;
}
+DeviceInfo Device::dummy_device(const string &error_msg)
+{
+ DeviceInfo info;
+ info.type = DEVICE_DUMMY;
+ info.error_msg = error_msg;
+ return info;
+}
+
string Device::device_capabilities(uint mask)
{
thread_scoped_lock lock(device_mutex);
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index ddf608aa430..2006db02ce7 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -48,6 +48,7 @@ enum DeviceType {
DEVICE_NETWORK,
DEVICE_MULTI,
DEVICE_OPTIX,
+ DEVICE_DUMMY,
};
enum DeviceTypeMask {
@@ -87,6 +88,7 @@ class DeviceInfo {
int cpu_threads;
vector<DeviceInfo> multi_devices;
vector<DeviceInfo> denoising_devices;
+ string error_msg;
DeviceInfo()
{
@@ -471,6 +473,7 @@ class Device {
static string string_from_type(DeviceType type);
static vector<DeviceType> available_types();
static vector<DeviceInfo> available_devices(uint device_type_mask = DEVICE_MASK_ALL);
+ static DeviceInfo dummy_device(const string &error_msg = "");
static string device_capabilities(uint device_type_mask = DEVICE_MASK_ALL);
static DeviceInfo get_multi_device(const vector<DeviceInfo> &subdevices,
int threads,
diff --git a/intern/cycles/device/device_dummy.cpp b/intern/cycles/device/device_dummy.cpp
new file mode 100644
index 00000000000..5112fc152e5
--- /dev/null
+++ b/intern/cycles/device/device_dummy.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2011-2020 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device/device.h"
+#include "device/device_intern.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Dummy device for when creating an appropriate rendering device fails. */
+
+class DummyDevice : public Device {
+ public:
+ DummyDevice(DeviceInfo &info_, Stats &stats_, Profiler &profiler_, bool background_)
+ : Device(info_, stats_, profiler_, background_)
+ {
+ error_msg = info.error_msg;
+ }
+
+ ~DummyDevice()
+ {
+ }
+
+ virtual BVHLayoutMask get_bvh_layout_mask() const override
+ {
+ return 0;
+ }
+
+ virtual void mem_alloc(device_memory &) override
+ {
+ }
+
+ virtual void mem_copy_to(device_memory &) override
+ {
+ }
+
+ virtual void mem_copy_from(device_memory &, int, int, int, int) override
+ {
+ }
+
+ virtual void mem_zero(device_memory &) override
+ {
+ }
+
+ virtual void mem_free(device_memory &) override
+ {
+ }
+
+ virtual void const_copy_to(const char *, void *, size_t) override
+ {
+ }
+
+ virtual void task_add(DeviceTask &) override
+ {
+ }
+
+ virtual void task_wait() override
+ {
+ }
+
+ virtual void task_cancel() override
+ {
+ }
+};
+
+Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background)
+{
+ return new DummyDevice(info, stats, profiler, background);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h
index 94d63e8f333..ecc79c5d7ee 100644
--- a/intern/cycles/device/device_intern.h
+++ b/intern/cycles/device/device_intern.h
@@ -35,6 +35,7 @@ bool device_cuda_init();
Device *device_cuda_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
bool device_optix_init();
Device *device_optix_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
+Device *device_dummy_create(DeviceInfo &info, Stats &stats, Profiler &profiler, bool background);
Device *device_network_create(DeviceInfo &info,
Stats &stats,
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 281285f959c..500496dc738 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -5769,6 +5769,7 @@ NODE_DEFINE(MapRangeNode)
SOCKET_IN_FLOAT(to_min, "To Min", 0.0f);
SOCKET_IN_FLOAT(to_max, "To Max", 1.0f);
SOCKET_IN_FLOAT(steps, "Steps", 4.0f);
+ SOCKET_IN_BOOLEAN(clamp, "Clamp", false);
SOCKET_OUT_FLOAT(result, "Result");
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index e98b2c76e88..3fb6c9620e6 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -707,4 +707,58 @@ template<> void Scene::delete_node_impl(Shader * /*node*/)
/* don't delete unused shaders, not supported */
}
+template<typename T>
+static void remove_nodes_in_set(const set<T *> &nodes_set,
+ vector<T *> &nodes_array,
+ const NodeOwner *owner)
+{
+ size_t new_size = nodes_array.size();
+
+ for (size_t i = 0; i < new_size; ++i) {
+ T *node = nodes_array[i];
+
+ if (nodes_set.find(node) != nodes_set.end()) {
+ std::swap(nodes_array[i], nodes_array[new_size - 1]);
+
+ assert(node->get_owner() == owner);
+ delete node;
+
+ i -= 1;
+ new_size -= 1;
+ }
+ }
+
+ nodes_array.resize(new_size);
+ (void)owner;
+}
+
+template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner)
+{
+ remove_nodes_in_set(nodes, lights, owner);
+ light_manager->tag_update(this);
+}
+
+template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner)
+{
+ remove_nodes_in_set(nodes, geometry, owner);
+ geometry_manager->tag_update(this);
+}
+
+template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner)
+{
+ remove_nodes_in_set(nodes, objects, owner);
+ object_manager->tag_update(this);
+}
+
+template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner)
+{
+ remove_nodes_in_set(nodes, particle_systems, owner);
+ particle_system_manager->tag_update(this);
+}
+
+template<> void Scene::delete_nodes(const set<Shader *> & /*nodes*/, const NodeOwner * /*owner*/)
+{
+ /* don't delete unused shaders, not supported */
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index cc2ef8da589..6686327dc49 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -322,6 +322,18 @@ class Scene : public NodeOwner {
(void)owner;
}
+ /* Remove all nodes in the set from the appropriate data arrays, and tag the
+ * specific managers for an update. This assumes that the scene owns the nodes.
+ */
+ template<typename T> void delete_nodes(const set<T *> &nodes)
+ {
+ delete_nodes(nodes, this);
+ }
+
+ /* Same as above, but specify the actual owner of all the nodes in the set.
+ */
+ template<typename T> void delete_nodes(const set<T *> &nodes, const NodeOwner *owner);
+
protected:
/* Check if some heavy data worth logging was updated.
* Mainly used to suppress extra annoying logging.
@@ -381,6 +393,16 @@ template<> void Scene::delete_node_impl(ParticleSystem *node);
template<> void Scene::delete_node_impl(Shader *node);
+template<> void Scene::delete_nodes(const set<Light *> &nodes, const NodeOwner *owner);
+
+template<> void Scene::delete_nodes(const set<Geometry *> &nodes, const NodeOwner *owner);
+
+template<> void Scene::delete_nodes(const set<Object *> &nodes, const NodeOwner *owner);
+
+template<> void Scene::delete_nodes(const set<ParticleSystem *> &nodes, const NodeOwner *owner);
+
+template<> void Scene::delete_nodes(const set<Shader *> &nodes, const NodeOwner *owner);
+
CCL_NAMESPACE_END
#endif /* __SCENE_H__ */
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index c22e29043d3..fa3fd06ab27 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -61,22 +61,6 @@ Session::Session(const SessionParams &params_)
TaskScheduler::init(params.threads);
- /* Create CPU/GPU devices. */
- device = Device::create(params.device, stats, profiler, params.background);
-
- /* Create buffers for interactive rendering. */
- if (params.background && !params.write_render_cb) {
- buffers = NULL;
- display = NULL;
- }
- else {
- buffers = new RenderBuffers(device);
- display = new DisplayBuffer(device, params.display_buffer_linear);
- }
-
- /* Validate denoising parameters. */
- set_denoising(params.denoising);
-
session_thread = NULL;
scene = NULL;
@@ -90,6 +74,26 @@ Session::Session(const SessionParams &params_)
gpu_draw_ready = false;
gpu_need_display_buffer_update = false;
pause = false;
+
+ buffers = NULL;
+ display = NULL;
+
+ /* Validate denoising parameters. */
+ set_denoising(params.denoising);
+
+ /* Create CPU/GPU devices. */
+ device = Device::create(params.device, stats, profiler, params.background);
+
+ if (!device->error_message().empty()) {
+ progress.set_error(device->error_message());
+ return;
+ }
+
+ /* Create buffers for interactive rendering. */
+ if (!(params.background && !params.write_render_cb)) {
+ buffers = new RenderBuffers(device);
+ display = new DisplayBuffer(device, params.display_buffer_linear);
+ }
}
Session::~Session()
@@ -110,7 +114,7 @@ Session::~Session()
wait();
}
- if (params.write_render_cb) {
+ if (buffers && params.write_render_cb) {
/* Copy to display buffer and write out image if requested */
delete display;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index c22651e2752..152dae48905 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -1589,7 +1589,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
case GHOST_kGrabWrap: // Wrap cursor at area/window boundaries
{
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x_mouse = mousePos.x;
GHOST_TInt32 y_mouse = mousePos.y;
GHOST_Rect bounds, windowBounds, correctedBounds;
@@ -1639,7 +1639,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
}
default: {
// Normal cursor operation: send mouse position in window
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
@@ -1699,7 +1699,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
pushEvent(new GHOST_EventWheel([event timestamp] * 1000, window, delta));
}
else {
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x, y;
double dx;
double dy;
@@ -1722,7 +1722,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
} break;
case NSEventTypeMagnify: {
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000,
@@ -1735,7 +1735,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
} break;
case NSEventTypeSmartMagnify: {
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad(
@@ -1743,7 +1743,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
} break;
case NSEventTypeRotate: {
- NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
+ NSPoint mousePos = [event locationInWindow];
GHOST_TInt32 x, y;
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventTrackpad([event timestamp] * 1000,
diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp
index e15fe809b2d..729cb151a39 100644
--- a/intern/mantaflow/intern/MANTA_main.cpp
+++ b/intern/mantaflow/intern/MANTA_main.cpp
@@ -697,12 +697,6 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
if ((fds->border_collisions & FLUID_DOMAIN_BORDER_TOP) == 0)
borderCollisions += "Z";
- string simulationMethod = "";
- if (fds->simulation_method & FLUID_DOMAIN_METHOD_FLIP)
- simulationMethod += "'FLIP'";
- else if (fds->simulation_method & FLUID_DOMAIN_METHOD_APIC)
- simulationMethod += "'APIC'";
-
string particleTypesStr = "";
if (fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY)
particleTypesStr += "PtypeSpray";
@@ -837,7 +831,7 @@ void MANTA::initializeRNAMap(FluidModifierData *fmd)
mRNAMap["CACHE_MESH_FORMAT"] = getCacheFileEnding(fds->cache_mesh_format);
mRNAMap["CACHE_NOISE_FORMAT"] = getCacheFileEnding(fds->cache_noise_format);
mRNAMap["CACHE_PARTICLE_FORMAT"] = getCacheFileEnding(fds->cache_particle_format);
- mRNAMap["SIMULATION_METHOD"] = simulationMethod;
+ mRNAMap["USING_APIC"] = getBooleanString(fds->simulation_method == FLUID_DOMAIN_METHOD_APIC);
mRNAMap["FLIP_RATIO"] = to_string(fds->flip_ratio);
mRNAMap["PARTICLE_RANDOMNESS"] = to_string(fds->particle_randomness);
mRNAMap["PARTICLE_NUMBER"] = to_string(fds->particle_number);
diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h
index dfc751e45db..e3dea46c157 100644
--- a/intern/mantaflow/intern/strings/fluid_script.h
+++ b/intern/mantaflow/intern/strings/fluid_script.h
@@ -43,7 +43,7 @@ isWindows = platform.system() != 'Darwin' and platform.system() != 'Linux'\n\
\n\
bpy = sys.modules.get('bpy')\n\
if bpy is not None:\n\
- sys.executable = bpy.app.binary_path_python\n";
+ sys.executable = bpy.app.binary_path\n";
//////////////////////////////////////////////////////////////////////
// DEBUG
diff --git a/intern/mantaflow/intern/strings/liquid_script.h b/intern/mantaflow/intern/strings/liquid_script.h
index 7622fc5a602..8e0d113d680 100644
--- a/intern/mantaflow/intern/strings/liquid_script.h
+++ b/intern/mantaflow/intern/strings/liquid_script.h
@@ -50,7 +50,8 @@ smoothenPos_s$ID$ = $MESH_SMOOTHEN_POS$\n\
smoothenNeg_s$ID$ = $MESH_SMOOTHEN_NEG$\n\
randomness_s$ID$ = $PARTICLE_RANDOMNESS$\n\
surfaceTension_s$ID$ = $LIQUID_SURFACE_TENSION$\n\
-maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n";
+maxSysParticles_s$ID$ = $PP_PARTICLE_MAXIMUM$\n\
+using_apic_s$ID$ = $USING_APIC$\n";
const std::string liquid_variables_particles =
"\n\
@@ -91,6 +92,14 @@ curvature_s$ID$ = None\n\
pp_s$ID$ = s$ID$.create(BasicParticleSystem, name='$NAME_PARTS$')\n\
pVel_pp$ID$ = pp_s$ID$.create(PdataVec3, name='$NAME_PARTSVELOCITY$')\n\
\n\
+pCx_pp$ID$ = None\n\
+pCy_pp$ID$ = None\n\
+pCz_pp$ID$ = None\n\
+if using_apic_s$ID$:\n\
+ pCx_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+ pCy_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+ pCz_pp$ID$ = pp_s$ID$.create(PdataVec3)\n\
+\n\
# Acceleration data for particle nbs\n\
pindex_s$ID$ = s$ID$.create(ParticleIndexSystem, name='$NAME_PINDEX$')\n\
gpi_s$ID$ = s$ID$.create(IntGrid, name='$NAME_GPI$')\n\
@@ -275,8 +284,12 @@ def liquid_step_$ID$():\n\
resetOutflow(flags=flags_s$ID$, phi=phi_s$ID$, parts=pp_s$ID$, index=gpi_s$ID$, indexSys=pindex_s$ID$)\n\
flags_s$ID$.updateFromLevelset(phi_s$ID$)\n\
\n\
- # combine particles velocities with advected grid velocities\n\
- mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\
+ # combine particle velocities with advected grid velocities\n\
+ if using_apic_s$ID$:\n\
+ apicMapPartsToMAC(flags=flags_s$ID$, vel=vel_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$)\n\
+ else:\n\
+ mapPartsToMAC(vel=velParts_s$ID$, flags=flags_s$ID$, velOld=velOld_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, weight=mapWeights_s$ID$)\n\
+ \n\
extrapolateMACFromWeight(vel=velParts_s$ID$, distance=2, weight=mapWeights_s$ID$)\n\
combineGridVel(vel=velParts_s$ID$, weight=mapWeights_s$ID$, combineVel=vel_s$ID$, phi=phi_s$ID$, narrowBand=combineBandWidth_s$ID$, thresh=0)\n\
velOld_s$ID$.copyFrom(vel_s$ID$)\n\
@@ -319,7 +332,11 @@ def liquid_step_$ID$():\n\
# set source grids for resampling, used in adjustNumber!\n\
pVel_pp$ID$.setSource(grid=vel_s$ID$, isMAC=True)\n\
adjustNumber(parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$, minParticles=minParticles_s$ID$, maxParticles=maxParticles_s$ID$, phi=phi_s$ID$, exclude=phiObs_s$ID$, radiusFactor=radiusFactor_s$ID$, narrowBand=adjustedNarrowBandWidth_s$ID$)\n\
- flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
+ \n\
+ if using_apic_s$ID$:\n\
+ apicMapMACGridToParts(partVel=pVel_pp$ID$, cpx=pCx_pp$ID$, cpy=pCy_pp$ID$, cpz=pCz_pp$ID$, parts=pp_s$ID$, vel=vel_s$ID$, flags=flags_s$ID$)\n\
+ else:\n\
+ flipVelocityUpdate(vel=vel_s$ID$, velOld=velOld_s$ID$, flags=flags_s$ID$, parts=pp_s$ID$, partVel=pVel_pp$ID$, flipRatio=flipRatio_s$ID$)\n";
const std::string liquid_step_mesh =
"\n\
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index ca8999e9588..5da7a3270d9 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -676,6 +676,7 @@ class AddPresetGpencilMaterial(AddPresetBase, Operator):
"gpcolor.pixel_size",
"gpcolor.mix_stroke_factor",
"gpcolor.alignment_mode",
+ "gpcolor.alignment_rotation",
"gpcolor.fill_style",
"gpcolor.fill_color",
"gpcolor.fill_image",
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py
index da54ff1a137..7c8f6b2309a 100644
--- a/release/scripts/startup/bl_ui/properties_material_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py
@@ -165,6 +165,7 @@ class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
if gpcolor.mode in {'DOTS', 'BOX'}:
col.prop(gpcolor, "alignment_mode")
+ col.prop(gpcolor, "alignment_rotation")
if gpcolor.mode == 'LINE':
col.prop(gpcolor, "use_overlap_strokes")
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 15c5e70d8b2..3afe7a47028 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -486,7 +486,8 @@ class PHYSICS_PT_liquid(PhysicButtonsPanel, Panel):
col = flow.column()
col.prop(domain, "simulation_method", expand=False)
- col.prop(domain, "flip_ratio", text="FLIP Ratio")
+ if domain.simulation_method == 'FLIP':
+ col.prop(domain, "flip_ratio", text="FLIP Ratio")
col.prop(domain, "sys_particle_maximum", text="System Maximum")
col = col.column(align=True)
col.prop(domain, "particle_radius", text="Particle Radius")
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index cb2ead39e2a..9aa825c5854 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -693,7 +693,7 @@ class VIEW3D_HT_header(Header):
text="Multiframe",
)
- if gpd.use_stroke_edit_mode:
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_paint_mode:
row = layout.row(align=True)
row.popover(
panel="VIEW3D_PT_tools_grease_pencil_interpolate",
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 701c98ce489..8c0103d10e6 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1683,7 +1683,8 @@ class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
return False
gpd = context.gpencil_data
- return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+ valid_mode = bool(gpd.use_stroke_edit_mode or gpd.is_stroke_paint_mode)
+ return bool(context.editable_gpencil_strokes) and valid_mode
def draw(self, context):
layout = self.layout
@@ -1698,7 +1699,10 @@ class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
col = layout.column(align=True)
col.label(text="Options:")
col.prop(settings, "interpolate_all_layers")
- col.prop(settings, "interpolate_selected_only")
+
+ gpd = context.gpencil_data
+ if gpd.use_stroke_edit_mode:
+ col.prop(settings, "interpolate_selected_only")
col = layout.column(align=True)
col.label(text="Sequence Options:")
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index f4393742dff..06fcc038f69 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -40,6 +40,12 @@ struct Main;
struct Object;
struct Scene;
struct ViewLayer;
+struct BlendWriter;
+struct BlendDataReader;
+struct BlendLibReader;
+struct BlendExpander;
+struct SceneCollection;
+struct Library;
typedef struct CollectionParent {
struct CollectionParent *next, *prev;
@@ -160,6 +166,22 @@ bool BKE_collection_has_collection(struct Collection *parent, struct Collection
void BKE_collection_parent_relations_rebuild(struct Collection *collection);
void BKE_main_collections_parent_relations_rebuild(struct Main *bmain);
+/* .blend file I/O */
+
+void BKE_collection_blend_write_nolib(struct BlendWriter *writer, struct Collection *collection);
+void BKE_collection_blend_read_data(struct BlendDataReader *reader, struct Collection *collection);
+void BKE_collection_blend_read_lib(struct BlendLibReader *reader, struct Collection *collection);
+void BKE_collection_blend_read_expand(struct BlendExpander *expander,
+ struct Collection *collection);
+
+void BKE_collection_compat_blend_read_data(struct BlendDataReader *reader,
+ struct SceneCollection *sc);
+void BKE_collection_compat_blend_read_lib(struct BlendLibReader *reader,
+ struct Library *lib,
+ struct SceneCollection *sc);
+void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander,
+ struct SceneCollection *sc);
+
/* Iteration callbacks. */
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 024d58174e8..39ba417c988 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -42,6 +42,8 @@ struct Object;
struct Scene;
struct View3D;
struct ViewLayer;
+struct BlendDataReader;
+struct BlendLibReader;
typedef enum eViewLayerCopyMethod {
VIEWLAYER_ADD_NEW = 0,
@@ -147,6 +149,13 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
struct Scene *scene,
int view_layer_index);
+/* .blend file I/O */
+
+void BKE_view_layer_blend_read_data(struct BlendDataReader *reader, struct ViewLayer *view_layer);
+void BKE_view_layer_blend_read_lib(struct BlendLibReader *reader,
+ struct Library *lib,
+ struct ViewLayer *view_layer);
+
/* iterators */
typedef struct ObjectsVisibleIteratorData {
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 6ed3b94b8e5..755fca5a2dc 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -60,6 +60,8 @@ struct ModifierData;
struct Object;
struct RNG;
struct Scene;
+struct BlendDataReader;
+struct BlendLibReader;
#define PARTICLE_COLLISION_MAX_COLLISIONS 10
@@ -625,6 +627,13 @@ void BKE_particle_batch_cache_free(struct ParticleSystem *psys);
extern void (*BKE_particle_batch_cache_dirty_tag_cb)(struct ParticleSystem *psys, int mode);
extern void (*BKE_particle_batch_cache_free_cb)(struct ParticleSystem *psys);
+/* .blend file I/O */
+void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader,
+ struct PartDeflect *pd);
+void BKE_particle_partdeflect_blend_read_lib(struct BlendLibReader *reader,
+ struct ID *id,
+ struct PartDeflect *pd);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 35a3d0415a8..da87ff3e969 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -58,6 +58,9 @@ struct wmMsgBus;
struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
+struct BlendWriter;
+struct BlendDataReader;
+struct BlendLibReader;
/* spacetype has everything stored to get an editor working, it gets initialized via
* ED_spacetypes_init() in editors/space_api/spacetypes.c */
@@ -449,6 +452,20 @@ void BKE_screen_remove_unused_scrverts(struct bScreen *screen);
void BKE_screen_header_alignment_reset(struct bScreen *screen);
+/* .blend file I/O */
+void BKE_screen_view3d_shading_blend_write(struct BlendWriter *writer,
+ struct View3DShading *shading);
+void BKE_screen_view3d_shading_blend_read_data(struct BlendDataReader *reader,
+ struct View3DShading *shading);
+
+void BKE_screen_area_map_blend_write(struct BlendWriter *writer, struct ScrAreaMap *area_map);
+bool BKE_screen_area_map_blend_read_data(struct BlendDataReader *reader,
+ struct ScrAreaMap *area_map);
+void BKE_screen_view3d_do_versions_250(struct View3D *v3d, ListBase *regions);
+void BKE_screen_area_blend_read_lib(struct BlendLibReader *reader,
+ struct ID *parent_id,
+ struct ScrArea *area);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_undo_system.h b/source/blender/blenkernel/BKE_undo_system.h
index 4f933ca7a87..58872d6be58 100644
--- a/source/blender/blenkernel/BKE_undo_system.h
+++ b/source/blender/blenkernel/BKE_undo_system.h
@@ -70,6 +70,12 @@ typedef struct UndoStack {
* That is done once end is called.
*/
struct UndoStep *step_init;
+
+ /**
+ * Keep track of nested group begin/end calls,
+ * within which all but the last undo-step is marked for skipping.
+ */
+ int group_level;
} UndoStack;
typedef struct UndoStep {
@@ -156,6 +162,9 @@ void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size
#define BKE_undosys_stack_limit_steps_and_memory_defaults(ustack) \
BKE_undosys_stack_limit_steps_and_memory(ustack, U.undosteps, (size_t)U.undomemory * 1024 * 1024)
+void BKE_undosys_stack_group_begin(UndoStack *ustack);
+void BKE_undosys_stack_group_end(UndoStack *ustack);
+
/* Only some UndoType's require init. */
UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack,
struct bContext *C,
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 0ed6f94ce79..870a137ede9 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -18,6 +18,9 @@
* \ingroup bke
*/
+/* Allow using deprecated functionality for .blend file I/O. */
+#define DNA_DEPRECATED_ALLOW
+
#include <string.h>
#include "BLI_blenlib.h"
@@ -55,6 +58,8 @@
#include "MEM_guardedalloc.h"
+#include "BLO_read_write.h"
+
/* -------------------------------------------------------------------- */
/** \name Prototypes
* \{ */
@@ -167,6 +172,172 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection)
+{
+ /* Shared function for collection data-blocks and scene master collection. */
+ BKE_previewimg_blend_write(writer, collection->preview);
+
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ BLO_write_struct(writer, CollectionObject, cob);
+ }
+
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ BLO_write_struct(writer, CollectionChild, child);
+ }
+}
+
+static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address)
+{
+ Collection *collection = (Collection *)id;
+ if (collection->id.us > 0 || BLO_write_is_undo(writer)) {
+ /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ collection->tag = 0;
+ BLI_listbase_clear(&collection->object_cache);
+ BLI_listbase_clear(&collection->parents);
+
+ /* write LibData */
+ BLO_write_id_struct(writer, Collection, id_address, &collection->id);
+ BKE_id_blend_write(writer, &collection->id);
+
+ BKE_collection_blend_write_nolib(writer, collection);
+ }
+}
+
+#ifdef USE_COLLECTION_COMPAT_28
+void BKE_collection_compat_blend_read_data(BlendDataReader *reader, SceneCollection *sc)
+{
+ BLO_read_list(reader, &sc->objects);
+ BLO_read_list(reader, &sc->scene_collections);
+
+ LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
+ BKE_collection_compat_blend_read_data(reader, nsc);
+ }
+}
+#endif
+
+void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection)
+{
+ BLO_read_list(reader, &collection->gobject);
+ BLO_read_list(reader, &collection->children);
+
+ BLO_read_data_address(reader, &collection->preview);
+ BKE_previewimg_blend_read(reader, collection->preview);
+
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ collection->tag = 0;
+ BLI_listbase_clear(&collection->object_cache);
+ BLI_listbase_clear(&collection->parents);
+
+#ifdef USE_COLLECTION_COMPAT_28
+ /* This runs before the very first doversion. */
+ BLO_read_data_address(reader, &collection->collection);
+ if (collection->collection != NULL) {
+ BKE_collection_compat_blend_read_data(reader, collection->collection);
+ }
+
+ BLO_read_data_address(reader, &collection->view_layer);
+ if (collection->view_layer != NULL) {
+ BKE_view_layer_blend_read_data(reader, collection->view_layer);
+ }
+#endif
+}
+
+static void collection_blend_read_data(BlendDataReader *reader, ID *id)
+{
+ Collection *collection = (Collection *)id;
+ BKE_collection_blend_read_data(reader, collection);
+}
+
+static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection)
+{
+ LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
+ BLO_read_id_address(reader, lib, &cob->ob);
+
+ if (cob->ob == NULL) {
+ BLI_freelinkN(&collection->gobject, cob);
+ }
+ }
+
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ BLO_read_id_address(reader, lib, &child->collection);
+ }
+}
+
+#ifdef USE_COLLECTION_COMPAT_28
+void BKE_collection_compat_blend_read_lib(BlendLibReader *reader,
+ Library *lib,
+ SceneCollection *sc)
+{
+ LISTBASE_FOREACH (LinkData *, link, &sc->objects) {
+ BLO_read_id_address(reader, lib, &link->data);
+ BLI_assert(link->data);
+ }
+
+ LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
+ BKE_collection_compat_blend_read_lib(reader, lib, nsc);
+ }
+}
+#endif
+
+void BKE_collection_blend_read_lib(BlendLibReader *reader, Collection *collection)
+{
+#ifdef USE_COLLECTION_COMPAT_28
+ if (collection->collection) {
+ BKE_collection_compat_blend_read_lib(reader, collection->id.lib, collection->collection);
+ }
+
+ if (collection->view_layer) {
+ BKE_view_layer_blend_read_lib(reader, collection->id.lib, collection->view_layer);
+ }
+#endif
+
+ lib_link_collection_data(reader, collection->id.lib, collection);
+}
+
+static void collection_blend_read_lib(BlendLibReader *reader, ID *id)
+{
+ Collection *collection = (Collection *)id;
+ BKE_collection_blend_read_lib(reader, collection);
+}
+
+#ifdef USE_COLLECTION_COMPAT_28
+void BKE_collection_compat_blend_read_expand(struct BlendExpander *expander,
+ struct SceneCollection *sc)
+{
+ LISTBASE_FOREACH (LinkData *, link, &sc->objects) {
+ BLO_expand(expander, link->data);
+ }
+
+ LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
+ BKE_collection_compat_blend_read_expand(expander, nsc);
+ }
+}
+#endif
+
+void BKE_collection_blend_read_expand(BlendExpander *expander, Collection *collection)
+{
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ BLO_expand(expander, cob->ob);
+ }
+
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ BLO_expand(expander, child->collection);
+ }
+
+#ifdef USE_COLLECTION_COMPAT_28
+ if (collection->collection != NULL) {
+ BKE_collection_compat_blend_read_expand(expander, collection->collection);
+ }
+#endif
+}
+
+static void collection_blend_read_expand(BlendExpander *expander, ID *id)
+{
+ Collection *collection = (Collection *)id;
+ BKE_collection_blend_read_expand(expander, collection);
+}
+
IDTypeInfo IDType_ID_GR = {
.id_code = ID_GR,
.id_filter = FILTER_ID_GR,
@@ -184,10 +355,10 @@ IDTypeInfo IDType_ID_GR = {
.foreach_id = collection_foreach_id,
.foreach_cache = NULL,
- .blend_write = NULL,
- .blend_read_data = NULL,
- .blend_read_lib = NULL,
- .blend_read_expand = NULL,
+ .blend_write = collection_blend_write,
+ .blend_read_data = collection_blend_read_data,
+ .blend_read_lib = collection_blend_read_lib,
+ .blend_read_expand = collection_blend_read_expand,
};
/** \} */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 2301267cd21..d21529467a1 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -45,6 +45,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
#include "DNA_lattice_types.h"
#include "DNA_movieclip_types.h"
@@ -5408,7 +5409,7 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool
void BKE_constraint_panel_expand(bConstraint *con)
{
- con->ui_expand_flag |= (1 << 0);
+ con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
}
/* ......... */
@@ -5426,10 +5427,10 @@ static bConstraint *add_new_constraint_internal(const char *name, short type)
con->enforce = 1.0f;
/* Only open the main panel when constraints are created, not the sub-panels. */
- con->ui_expand_flag = (1 << 0);
+ con->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT;
if (ELEM(type, CONSTRAINT_TYPE_ACTION, CONSTRAINT_TYPE_SPLINEIK)) {
/* Expand the two sub-panels in the cases where the main panel barely has any properties. */
- con->ui_expand_flag |= (1 << 1) | (1 << 2);
+ con->ui_expand_flag |= UI_SUBPANEL_DATA_EXPAND_1 | UI_SUBPANEL_DATA_EXPAND_2;
}
/* Determine a basic name, and info */
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index fa1b1997625..af4b98e1c8d 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -4993,6 +4993,7 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd,
tfds->fractions_threshold = fds->fractions_threshold;
tfds->fractions_distance = fds->fractions_distance;
tfds->sys_particle_maximum = fds->sys_particle_maximum;
+ tfds->simulation_method = fds->simulation_method;
/* diffusion options*/
tfds->surface_tension = fds->surface_tension;
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index f4041fae047..934791ccc35 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -39,6 +39,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
@@ -413,7 +414,7 @@ void BKE_gpencil_modifierType_panel_id(GpencilModifierType type, char *r_idname)
void BKE_gpencil_modifier_panel_expand(GpencilModifierData *md)
{
- md->ui_expand_flag |= (1 << 0);
+ md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
}
/**
diff --git a/source/blender/blenkernel/intern/lattice_deform.c b/source/blender/blenkernel/intern/lattice_deform.c
index 43965813b84..14c600caa46 100644
--- a/source/blender/blenkernel/intern/lattice_deform.c
+++ b/source/blender/blenkernel/intern/lattice_deform.c
@@ -169,7 +169,7 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data,
int ui, vi, wi, uu, vv, ww;
/* vgroup influence */
- float co_prev[3], weight_blend = 0.0f;
+ float co_prev[4] = {0}, weight_blend = 0.0f;
copy_v3_v3(co_prev, co);
#ifdef __SSE2__
__m128 co_vec = _mm_loadu_ps(co_prev);
@@ -235,10 +235,16 @@ void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data,
#ifdef __SSE2__
{
__m128 weight_vec = _mm_set1_ps(u);
- /* This will load one extra element, this is ok because
- * we ignore that part of register anyway.
- */
- __m128 lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]);
+ /* We need to address special case for last item to avoid accessing invalid memory. */
+ __m128 lattice_vec;
+ if (idx * 3 == idx_w_max) {
+ copy_v3_v3((float *)&lattice_vec, &latticedata[idx * 3]);
+ }
+ else {
+ /* When not on last item, we can safely access one extra float, it will be ignored
+ * anyway. */
+ lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]);
+ }
co_vec = _mm_add_ps(co_vec, _mm_mul_ps(lattice_vec, weight_vec));
}
#else
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 6efc9d0753e..5b88a68b921 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -18,6 +18,9 @@
* \ingroup bke
*/
+/* Allow using deprecated functionality for .blend file I/O. */
+#define DNA_DEPRECATED_ALLOW
+
#include <string.h>
#include "BLI_listbase.h"
@@ -56,6 +59,8 @@
#include "MEM_guardedalloc.h"
+#include "BLO_read_write.h"
+
/* Set of flags which are dependent on a collection settings. */
static const short g_base_collection_flags = (BASE_VISIBLE_DEPSGRAPH | BASE_VISIBLE_VIEWLAYER |
BASE_SELECTABLE | BASE_ENABLED_VIEWPORT |
@@ -1830,3 +1835,91 @@ void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph,
BLI_assert(view_layer != NULL);
layer_eval_view_layer(depsgraph, scene, view_layer);
}
+
+static void direct_link_layer_collections(BlendDataReader *reader, ListBase *lb, bool master)
+{
+ BLO_read_list(reader, lb);
+ LISTBASE_FOREACH (LayerCollection *, lc, lb) {
+#ifdef USE_COLLECTION_COMPAT_28
+ BLO_read_data_address(reader, &lc->scene_collection);
+#endif
+
+ /* Master collection is not a real data-lock. */
+ if (master) {
+ BLO_read_data_address(reader, &lc->collection);
+ }
+
+ direct_link_layer_collections(reader, &lc->layer_collections, false);
+ }
+}
+
+void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_layer)
+{
+ view_layer->stats = NULL;
+ BLO_read_list(reader, &view_layer->object_bases);
+ BLO_read_data_address(reader, &view_layer->basact);
+
+ direct_link_layer_collections(reader, &view_layer->layer_collections, true);
+ BLO_read_data_address(reader, &view_layer->active_collection);
+
+ BLO_read_data_address(reader, &view_layer->id_properties);
+ IDP_BlendDataRead(reader, &view_layer->id_properties);
+
+ BLO_read_list(reader, &(view_layer->freestyle_config.modules));
+ BLO_read_list(reader, &(view_layer->freestyle_config.linesets));
+
+ BLI_listbase_clear(&view_layer->drawdata);
+ view_layer->object_bases_array = NULL;
+ view_layer->object_bases_hash = NULL;
+}
+
+static void lib_link_layer_collection(BlendLibReader *reader,
+ Library *lib,
+ LayerCollection *layer_collection,
+ bool master)
+{
+ /* Master collection is not a real data-lock. */
+ if (!master) {
+ BLO_read_id_address(reader, lib, &layer_collection->collection);
+ }
+
+ LISTBASE_FOREACH (
+ LayerCollection *, layer_collection_nested, &layer_collection->layer_collections) {
+ lib_link_layer_collection(reader, lib, layer_collection_nested, false);
+ }
+}
+
+void BKE_view_layer_blend_read_lib(BlendLibReader *reader, Library *lib, ViewLayer *view_layer)
+{
+ LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) {
+ BLO_read_id_address(reader, lib, &fmc->script);
+ }
+
+ LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
+ BLO_read_id_address(reader, lib, &fls->linestyle);
+ BLO_read_id_address(reader, lib, &fls->group);
+ }
+
+ for (Base *base = view_layer->object_bases.first, *base_next = NULL; base; base = base_next) {
+ base_next = base->next;
+
+ /* we only bump the use count for the collection objects */
+ BLO_read_id_address(reader, lib, &base->object);
+
+ if (base->object == NULL) {
+ /* Free in case linked object got lost. */
+ BLI_freelinkN(&view_layer->object_bases, base);
+ if (view_layer->basact == base) {
+ view_layer->basact = NULL;
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
+ lib_link_layer_collection(reader, lib, layer_collection, true);
+ }
+
+ BLO_read_id_address(reader, lib, &view_layer->mat_override);
+
+ IDP_BlendReadLib(reader, view_layer->id_properties);
+}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 1ac63e653c0..0054d2f76d1 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -38,6 +38,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BLI_linklist.h"
#include "BLI_listbase.h"
@@ -132,7 +133,7 @@ void BKE_modifier_type_panel_id(ModifierType type, char *r_idname)
void BKE_modifier_panel_expand(ModifierData *md)
{
- md->ui_expand_flag |= (1 << 0);
+ md->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
}
/***/
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 7b8ee7343ee..71f78592bc5 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -21,6 +21,9 @@
* \ingroup bke
*/
+/* Allow using deprecated functionality for .blend file I/O. */
+#define DNA_DEPRECATED_ALLOW
+
#include <math.h>
#include <stdlib.h>
#include <string.h>
@@ -52,6 +55,7 @@
#include "BLT_translation.h"
+#include "BKE_anim_data.h"
#include "BKE_anim_path.h"
#include "BKE_boids.h"
#include "BKE_cloth.h"
@@ -80,6 +84,8 @@
#include "RE_render_ext.h"
+#include "BLO_read_write.h"
+
#include "particle_private.h"
static void fluid_free_settings(SPHFluidSettings *fluid);
@@ -206,6 +212,279 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+static void write_boid_state(BlendWriter *writer, BoidState *state)
+{
+ BLO_write_struct(writer, BoidState, state);
+
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ switch (rule->type) {
+ case eBoidRuleType_Goal:
+ case eBoidRuleType_Avoid:
+ BLO_write_struct(writer, BoidRuleGoalAvoid, rule);
+ break;
+ case eBoidRuleType_AvoidCollision:
+ BLO_write_struct(writer, BoidRuleAvoidCollision, rule);
+ break;
+ case eBoidRuleType_FollowLeader:
+ BLO_write_struct(writer, BoidRuleFollowLeader, rule);
+ break;
+ case eBoidRuleType_AverageSpeed:
+ BLO_write_struct(writer, BoidRuleAverageSpeed, rule);
+ break;
+ case eBoidRuleType_Fight:
+ BLO_write_struct(writer, BoidRuleFight, rule);
+ break;
+ default:
+ BLO_write_struct(writer, BoidRule, rule);
+ break;
+ }
+ }
+#if 0
+ BoidCondition *cond = state->conditions.first;
+ for (; cond; cond = cond->next) {
+ BLO_write_struct(writer, BoidCondition, cond);
+ }
+#endif
+}
+
+static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address)
+{
+ ParticleSettings *part = (ParticleSettings *)id;
+ if (part->id.us > 0 || BLO_write_is_undo(writer)) {
+ /* write LibData */
+ BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
+ BKE_id_blend_write(writer, &part->id);
+
+ if (part->adt) {
+ BKE_animdata_blend_write(writer, part->adt);
+ }
+ BLO_write_struct(writer, PartDeflect, part->pd);
+ BLO_write_struct(writer, PartDeflect, part->pd2);
+ BLO_write_struct(writer, EffectorWeights, part->effector_weights);
+
+ if (part->clumpcurve) {
+ BKE_curvemapping_blend_write(writer, part->clumpcurve);
+ }
+ if (part->roughcurve) {
+ BKE_curvemapping_blend_write(writer, part->roughcurve);
+ }
+ if (part->twistcurve) {
+ BKE_curvemapping_blend_write(writer, part->twistcurve);
+ }
+
+ LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
+ /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
+ if (dw->ob != NULL) {
+ dw->index = 0;
+ if (part->instance_collection) { /* can be NULL if lining fails or set to None */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
+ if (object == dw->ob) {
+ break;
+ }
+ dw->index++;
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ }
+ BLO_write_struct(writer, ParticleDupliWeight, dw);
+ }
+
+ if (part->boids && part->phystype == PART_PHYS_BOIDS) {
+ BLO_write_struct(writer, BoidSettings, part->boids);
+
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ write_boid_state(writer, state);
+ }
+ }
+ if (part->fluid && part->phystype == PART_PHYS_FLUID) {
+ BLO_write_struct(writer, SPHFluidSettings, part->fluid);
+ }
+
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part->mtex[a]) {
+ BLO_write_struct(writer, MTex, part->mtex[a]);
+ }
+ }
+ }
+}
+
+void BKE_particle_partdeflect_blend_read_data(BlendDataReader *UNUSED(reader), PartDeflect *pd)
+{
+ if (pd) {
+ pd->rng = NULL;
+ }
+}
+
+static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id)
+{
+ ParticleSettings *part = (ParticleSettings *)id;
+ BLO_read_data_address(reader, &part->adt);
+ BLO_read_data_address(reader, &part->pd);
+ BLO_read_data_address(reader, &part->pd2);
+
+ BKE_animdata_blend_read_data(reader, part->adt);
+ BKE_particle_partdeflect_blend_read_data(reader, part->pd);
+ BKE_particle_partdeflect_blend_read_data(reader, part->pd2);
+
+ BLO_read_data_address(reader, &part->clumpcurve);
+ if (part->clumpcurve) {
+ BKE_curvemapping_blend_read(reader, part->clumpcurve);
+ }
+ BLO_read_data_address(reader, &part->roughcurve);
+ if (part->roughcurve) {
+ BKE_curvemapping_blend_read(reader, part->roughcurve);
+ }
+ BLO_read_data_address(reader, &part->twistcurve);
+ if (part->twistcurve) {
+ BKE_curvemapping_blend_read(reader, part->twistcurve);
+ }
+
+ BLO_read_data_address(reader, &part->effector_weights);
+ if (!part->effector_weights) {
+ part->effector_weights = BKE_effector_add_weights(part->force_group);
+ }
+
+ BLO_read_list(reader, &part->instance_weights);
+
+ BLO_read_data_address(reader, &part->boids);
+ BLO_read_data_address(reader, &part->fluid);
+
+ if (part->boids) {
+ BLO_read_list(reader, &part->boids->states);
+
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ BLO_read_list(reader, &state->rules);
+ BLO_read_list(reader, &state->conditions);
+ BLO_read_list(reader, &state->actions);
+ }
+ }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ BLO_read_data_address(reader, &part->mtex[a]);
+ }
+
+ /* Protect against integer overflow vulnerability. */
+ CLAMP(part->trail_count, 1, 100000);
+}
+
+void BKE_particle_partdeflect_blend_read_lib(BlendLibReader *reader, ID *id, PartDeflect *pd)
+{
+ if (pd && pd->tex) {
+ BLO_read_id_address(reader, id->lib, &pd->tex);
+ }
+ if (pd && pd->f_source) {
+ BLO_read_id_address(reader, id->lib, &pd->f_source);
+ }
+}
+
+static void particle_settings_blend_read_lib(BlendLibReader *reader, ID *id)
+{
+ ParticleSettings *part = (ParticleSettings *)id;
+ BLO_read_id_address(
+ reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */
+
+ BLO_read_id_address(reader, part->id.lib, &part->instance_object);
+ BLO_read_id_address(reader, part->id.lib, &part->instance_collection);
+ BLO_read_id_address(reader, part->id.lib, &part->force_group);
+ BLO_read_id_address(reader, part->id.lib, &part->bb_ob);
+ BLO_read_id_address(reader, part->id.lib, &part->collision_group);
+
+ BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd);
+ BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd2);
+
+ if (part->effector_weights) {
+ BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group);
+ }
+ else {
+ part->effector_weights = BKE_effector_add_weights(part->force_group);
+ }
+
+ if (part->instance_weights.first && part->instance_collection) {
+ LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
+ BLO_read_id_address(reader, part->id.lib, &dw->ob);
+ }
+ }
+ else {
+ BLI_listbase_clear(&part->instance_weights);
+ }
+
+ if (part->boids) {
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ switch (rule->type) {
+ case eBoidRuleType_Goal:
+ case eBoidRuleType_Avoid: {
+ BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule;
+ BLO_read_id_address(reader, part->id.lib, &brga->ob);
+ break;
+ }
+ case eBoidRuleType_FollowLeader: {
+ BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule;
+ BLO_read_id_address(reader, part->id.lib, &brfl->ob);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = part->mtex[a];
+ if (mtex) {
+ BLO_read_id_address(reader, part->id.lib, &mtex->tex);
+ BLO_read_id_address(reader, part->id.lib, &mtex->object);
+ }
+ }
+}
+
+static void particle_settings_blend_read_expand(BlendExpander *expander, ID *id)
+{
+ ParticleSettings *part = (ParticleSettings *)id;
+ BLO_expand(expander, part->instance_object);
+ BLO_expand(expander, part->instance_collection);
+ BLO_expand(expander, part->force_group);
+ BLO_expand(expander, part->bb_ob);
+ BLO_expand(expander, part->collision_group);
+
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part->mtex[a]) {
+ BLO_expand(expander, part->mtex[a]->tex);
+ BLO_expand(expander, part->mtex[a]->object);
+ }
+ }
+
+ if (part->effector_weights) {
+ BLO_expand(expander, part->effector_weights->group);
+ }
+
+ if (part->pd) {
+ BLO_expand(expander, part->pd->tex);
+ BLO_expand(expander, part->pd->f_source);
+ }
+ if (part->pd2) {
+ BLO_expand(expander, part->pd2->tex);
+ BLO_expand(expander, part->pd2->f_source);
+ }
+
+ if (part->boids) {
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ if (rule->type == eBoidRuleType_Avoid) {
+ BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
+ BLO_expand(expander, gabr->ob);
+ }
+ else if (rule->type == eBoidRuleType_FollowLeader) {
+ BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
+ BLO_expand(expander, flbr->ob);
+ }
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
+ BLO_expand(expander, dw->ob);
+ }
+}
+
IDTypeInfo IDType_ID_PA = {
.id_code = ID_PA,
.id_filter = FILTER_ID_PA,
@@ -223,10 +502,10 @@ IDTypeInfo IDType_ID_PA = {
.foreach_id = particle_settings_foreach_id,
.foreach_cache = NULL,
- .blend_write = NULL,
- .blend_read_data = NULL,
- .blend_read_lib = NULL,
- .blend_read_expand = NULL,
+ .blend_write = particle_settings_blend_write,
+ .blend_read_data = particle_settings_blend_read_data,
+ .blend_read_lib = particle_settings_blend_read_lib,
+ .blend_read_expand = particle_settings_blend_read_expand,
};
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index d9686eba29a..a357b5d98fb 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -21,6 +21,9 @@
* \ingroup bke
*/
+/* Allow using deprecated functionality for .blend file I/O. */
+#define DNA_DEPRECATED_ALLOW
+
#ifdef WIN32
# include "BLI_winstuff.h"
#endif
@@ -49,14 +52,18 @@
#include "BLT_translation.h"
+#include "BKE_gpencil.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_node.h"
#include "BKE_screen.h"
#include "BKE_workspace.h"
+#include "BLO_read_write.h"
+
static void screen_free_data(ID *id)
{
bScreen *screen = (bScreen *)id;
@@ -230,6 +237,40 @@ static void screen_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+static void screen_blend_write(BlendWriter *writer, ID *id, const void *id_address)
+{
+ bScreen *screen = (bScreen *)id;
+ /* Screens are reference counted, only saved if used by a workspace. */
+ if (screen->id.us > 0 || BLO_write_is_undo(writer)) {
+ /* write LibData */
+ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
+ BLO_write_struct_at_address_with_filecode(writer, ID_SCRN, bScreen, id_address, screen);
+ BKE_id_blend_write(writer, &screen->id);
+
+ BKE_previewimg_blend_write(writer, screen->preview);
+
+ /* direct data */
+ BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen));
+ }
+}
+
+/* note: file read without screens option G_FILE_NO_UI;
+ * check lib pointers in call below */
+static void screen_blend_read_lib(BlendLibReader *reader, ID *id)
+{
+ bScreen *screen = (bScreen *)id;
+ /* deprecated, but needed for versioning (will be NULL'ed then) */
+ BLO_read_id_address(reader, screen->id.lib, &screen->scene);
+
+ screen->animtimer = NULL; /* saved in rare cases */
+ screen->tool_tip = NULL;
+ screen->scrubbing = false;
+
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ BKE_screen_area_blend_read_lib(reader, &screen->id, area);
+ }
+}
+
IDTypeInfo IDType_ID_SCR = {
.id_code = ID_SCR,
.id_filter = 0,
@@ -247,9 +288,10 @@ IDTypeInfo IDType_ID_SCR = {
.foreach_id = screen_foreach_id,
.foreach_cache = NULL,
- .blend_write = NULL,
+ .blend_write = screen_blend_write,
+ /* Cannot be used yet, because #direct_link_screen has a return value. */
.blend_read_data = NULL,
- .blend_read_lib = NULL,
+ .blend_read_lib = screen_blend_read_lib,
.blend_read_expand = NULL,
};
@@ -1111,3 +1153,801 @@ void BKE_screen_header_alignment_reset(bScreen *screen)
}
screen->do_refresh = true;
}
+
+void BKE_screen_view3d_shading_blend_write(BlendWriter *writer, View3DShading *shading)
+{
+ if (shading->prop) {
+ IDP_BlendWrite(writer, shading->prop);
+ }
+}
+
+void BKE_screen_view3d_shading_blend_read_data(BlendDataReader *reader, View3DShading *shading)
+{
+ if (shading->prop) {
+ BLO_read_data_address(reader, &shading->prop);
+ IDP_BlendDataRead(reader, &shading->prop);
+ }
+}
+
+static void write_region(BlendWriter *writer, ARegion *region, int spacetype)
+{
+ BLO_write_struct(writer, ARegion, region);
+
+ if (region->regiondata) {
+ if (region->flag & RGN_FLAG_TEMP_REGIONDATA) {
+ return;
+ }
+
+ switch (spacetype) {
+ case SPACE_VIEW3D:
+ if (region->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = region->regiondata;
+ BLO_write_struct(writer, RegionView3D, rv3d);
+
+ if (rv3d->localvd) {
+ BLO_write_struct(writer, RegionView3D, rv3d->localvd);
+ }
+ if (rv3d->clipbb) {
+ BLO_write_struct(writer, BoundBox, rv3d->clipbb);
+ }
+ }
+ else {
+ printf("regiondata write missing!\n");
+ }
+ break;
+ default:
+ printf("regiondata write missing!\n");
+ }
+ }
+}
+
+static void write_uilist(BlendWriter *writer, uiList *ui_list)
+{
+ BLO_write_struct(writer, uiList, ui_list);
+
+ if (ui_list->properties) {
+ IDP_BlendWrite(writer, ui_list->properties);
+ }
+}
+
+static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner)
+{
+ BLI_mempool *ts = space_outliner->treestore;
+
+ if (ts) {
+ SpaceOutliner space_outliner_flat = *space_outliner;
+
+ int elems = BLI_mempool_len(ts);
+ /* linearize mempool to array */
+ TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
+
+ if (data) {
+ /* In this block we use the memory location of the treestore
+ * but _not_ its data, the addresses in this case are UUID's,
+ * since we can't rely on malloc giving us different values each time.
+ */
+ TreeStore ts_flat = {0};
+
+ /* we know the treestore is at least as big as a pointer,
+ * so offsetting works to give us a UUID. */
+ void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *));
+
+ ts_flat.usedelem = elems;
+ ts_flat.totelem = elems;
+ ts_flat.data = data_addr;
+
+ BLO_write_struct(writer, SpaceOutliner, space_outliner);
+
+ BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat);
+ BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data);
+
+ MEM_freeN(data);
+ }
+ else {
+ space_outliner_flat.treestore = NULL;
+ BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat);
+ }
+ }
+ else {
+ BLO_write_struct(writer, SpaceOutliner, space_outliner);
+ }
+}
+
+static void write_panel_list(BlendWriter *writer, ListBase *lb)
+{
+ LISTBASE_FOREACH (Panel *, panel, lb) {
+ BLO_write_struct(writer, Panel, panel);
+ write_panel_list(writer, &panel->children);
+ }
+}
+
+static void write_area_regions(BlendWriter *writer, ScrArea *area)
+{
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ write_region(writer, region, area->spacetype);
+ write_panel_list(writer, &region->panels);
+
+ LISTBASE_FOREACH (PanelCategoryStack *, pc_act, &region->panels_category_active) {
+ BLO_write_struct(writer, PanelCategoryStack, pc_act);
+ }
+
+ LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
+ write_uilist(writer, ui_list);
+ }
+
+ LISTBASE_FOREACH (uiPreview *, ui_preview, &region->ui_previews) {
+ BLO_write_struct(writer, uiPreview, ui_preview);
+ }
+ }
+
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) {
+ write_region(writer, region, sl->spacetype);
+ }
+
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ BLO_write_struct(writer, View3D, v3d);
+
+ if (v3d->localvd) {
+ BLO_write_struct(writer, View3D, v3d->localvd);
+ }
+
+ BKE_screen_view3d_shading_blend_write(writer, &v3d->shading);
+ }
+ else if (sl->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)sl;
+ ListBase tmpGhosts = sipo->runtime.ghost_curves;
+
+ /* temporarily disable ghost curves when saving */
+ BLI_listbase_clear(&sipo->runtime.ghost_curves);
+
+ BLO_write_struct(writer, SpaceGraph, sl);
+ if (sipo->ads) {
+ BLO_write_struct(writer, bDopeSheet, sipo->ads);
+ }
+
+ /* reenable ghost curves */
+ sipo->runtime.ghost_curves = tmpGhosts;
+ }
+ else if (sl->spacetype == SPACE_PROPERTIES) {
+ BLO_write_struct(writer, SpaceProperties, sl);
+ }
+ else if (sl->spacetype == SPACE_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ BLO_write_struct(writer, SpaceFile, sl);
+ if (sfile->params) {
+ BLO_write_struct(writer, FileSelectParams, sfile->params);
+ }
+ }
+ else if (sl->spacetype == SPACE_SEQ) {
+ BLO_write_struct(writer, SpaceSeq, sl);
+ }
+ else if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
+ write_space_outliner(writer, space_outliner);
+ }
+ else if (sl->spacetype == SPACE_IMAGE) {
+ BLO_write_struct(writer, SpaceImage, sl);
+ }
+ else if (sl->spacetype == SPACE_TEXT) {
+ BLO_write_struct(writer, SpaceText, sl);
+ }
+ else if (sl->spacetype == SPACE_SCRIPT) {
+ SpaceScript *scr = (SpaceScript *)sl;
+ scr->but_refs = NULL;
+ BLO_write_struct(writer, SpaceScript, sl);
+ }
+ else if (sl->spacetype == SPACE_ACTION) {
+ BLO_write_struct(writer, SpaceAction, sl);
+ }
+ else if (sl->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)sl;
+
+ BLO_write_struct(writer, SpaceNla, snla);
+ if (snla->ads) {
+ BLO_write_struct(writer, bDopeSheet, snla->ads);
+ }
+ }
+ else if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ BLO_write_struct(writer, SpaceNode, snode);
+
+ LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) {
+ BLO_write_struct(writer, bNodeTreePath, path);
+ }
+ }
+ else if (sl->spacetype == SPACE_CONSOLE) {
+ SpaceConsole *con = (SpaceConsole *)sl;
+
+ LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) {
+ /* 'len_alloc' is invalid on write, set from 'len' on read */
+ BLO_write_struct(writer, ConsoleLine, cl);
+ BLO_write_raw(writer, (size_t)cl->len + 1, cl->line);
+ }
+ BLO_write_struct(writer, SpaceConsole, sl);
+ }
+#ifdef WITH_GLOBAL_AREA_WRITING
+ else if (sl->spacetype == SPACE_TOPBAR) {
+ BLO_write_struct(writer, SpaceTopBar, sl);
+ }
+ else if (sl->spacetype == SPACE_STATUSBAR) {
+ BLO_write_struct(writer, SpaceStatusBar, sl);
+ }
+#endif
+ else if (sl->spacetype == SPACE_USERPREF) {
+ BLO_write_struct(writer, SpaceUserPref, sl);
+ }
+ else if (sl->spacetype == SPACE_CLIP) {
+ BLO_write_struct(writer, SpaceClip, sl);
+ }
+ else if (sl->spacetype == SPACE_INFO) {
+ BLO_write_struct(writer, SpaceInfo, sl);
+ }
+ }
+}
+
+void BKE_screen_area_map_blend_write(BlendWriter *writer, ScrAreaMap *area_map)
+{
+ BLO_write_struct_list(writer, ScrVert, &area_map->vertbase);
+ BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase);
+ LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) {
+ area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */
+
+ BLO_write_struct(writer, ScrArea, area);
+
+#ifdef WITH_GLOBAL_AREA_WRITING
+ BLO_write_struct(writer, ScrGlobalAreaData, area->global);
+#endif
+
+ write_area_regions(writer, area);
+
+ area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */
+ }
+}
+
+static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb)
+{
+ BLO_read_list(reader, lb);
+
+ LISTBASE_FOREACH (Panel *, panel, lb) {
+ panel->runtime_flag = 0;
+ panel->activedata = NULL;
+ panel->type = NULL;
+ panel->runtime.custom_data_ptr = NULL;
+ direct_link_panel_list(reader, &panel->children);
+ }
+}
+
+static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype)
+{
+ direct_link_panel_list(reader, &region->panels);
+
+ BLO_read_list(reader, &region->panels_category_active);
+
+ BLO_read_list(reader, &region->ui_lists);
+
+ /* The area's search filter is runtime only, so we need to clear the active flag on read. */
+ region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE;
+
+ LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
+ ui_list->type = NULL;
+ ui_list->dyn_data = NULL;
+ BLO_read_data_address(reader, &ui_list->properties);
+ IDP_BlendDataRead(reader, &ui_list->properties);
+ }
+
+ BLO_read_list(reader, &region->ui_previews);
+
+ if (spacetype == SPACE_EMPTY) {
+ /* unknown space type, don't leak regiondata */
+ region->regiondata = NULL;
+ }
+ else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) {
+ /* Runtime data, don't use. */
+ region->regiondata = NULL;
+ }
+ else {
+ BLO_read_data_address(reader, &region->regiondata);
+ if (region->regiondata) {
+ if (spacetype == SPACE_VIEW3D) {
+ RegionView3D *rv3d = region->regiondata;
+
+ BLO_read_data_address(reader, &rv3d->localvd);
+ BLO_read_data_address(reader, &rv3d->clipbb);
+
+ rv3d->depths = NULL;
+ rv3d->render_engine = NULL;
+ rv3d->sms = NULL;
+ rv3d->smooth_timer = NULL;
+
+ rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING);
+ rv3d->runtime_viewlock = 0;
+ }
+ }
+ }
+
+ region->v2d.sms = NULL;
+ region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */
+ BLI_listbase_clear(&region->panels_category);
+ BLI_listbase_clear(&region->handlers);
+ BLI_listbase_clear(&region->uiblocks);
+ region->headerstr = NULL;
+ region->visible = 0;
+ region->type = NULL;
+ region->do_draw = 0;
+ region->gizmo_map = NULL;
+ region->regiontimer = NULL;
+ region->draw_buffer = NULL;
+ memset(&region->drawrct, 0, sizeof(region->drawrct));
+}
+
+/* for the saved 2.50 files without regiondata */
+/* and as patch for 2.48 and older */
+void BKE_screen_view3d_do_versions_250(View3D *v3d, ListBase *regions)
+{
+ LISTBASE_FOREACH (ARegion *, region, regions) {
+ if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) {
+ RegionView3D *rv3d;
+
+ rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch");
+ rv3d->persp = (char)v3d->persp;
+ rv3d->view = (char)v3d->view;
+ rv3d->dist = v3d->dist;
+ copy_v3_v3(rv3d->ofs, v3d->ofs);
+ copy_qt_qt(rv3d->viewquat, v3d->viewquat);
+ }
+ }
+
+ /* this was not initialized correct always */
+ if (v3d->gridsubdiv == 0) {
+ v3d->gridsubdiv = 10;
+ }
+}
+
+static void direct_link_area(BlendDataReader *reader, ScrArea *area)
+{
+ BLO_read_list(reader, &(area->spacedata));
+ BLO_read_list(reader, &(area->regionbase));
+
+ BLI_listbase_clear(&area->handlers);
+ area->type = NULL; /* spacetype callbacks */
+
+ /* Should always be unset so that rna_Area_type_get works correctly. */
+ area->butspacetype = SPACE_EMPTY;
+
+ area->region_active_win = -1;
+
+ area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
+
+ BLO_read_data_address(reader, &area->global);
+
+ /* if we do not have the spacetype registered we cannot
+ * free it, so don't allocate any new memory for such spacetypes. */
+ if (!BKE_spacetype_exists(area->spacetype)) {
+ /* Hint for versioning code to replace deprecated space types. */
+ area->butspacetype = area->spacetype;
+
+ area->spacetype = SPACE_EMPTY;
+ }
+
+ LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
+ direct_link_region(reader, region, area->spacetype);
+ }
+
+ /* accident can happen when read/save new file with older version */
+ /* 2.50: we now always add spacedata for info */
+ if (area->spacedata.first == NULL) {
+ SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo");
+ area->spacetype = sinfo->spacetype = SPACE_INFO;
+ BLI_addtail(&area->spacedata, sinfo);
+ }
+ /* add local view3d too */
+ else if (area->spacetype == SPACE_VIEW3D) {
+ BKE_screen_view3d_do_versions_250(area->spacedata.first, &area->regionbase);
+ }
+
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ BLO_read_list(reader, &(sl->regionbase));
+
+ /* if we do not have the spacetype registered we cannot
+ * free it, so don't allocate any new memory for such spacetypes. */
+ if (!BKE_spacetype_exists(sl->spacetype)) {
+ sl->spacetype = SPACE_EMPTY;
+ }
+
+ LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) {
+ direct_link_region(reader, region, sl->spacetype);
+ }
+
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+
+ v3d->flag |= V3D_INVALID_BACKBUF;
+
+ if (v3d->gpd) {
+ BLO_read_data_address(reader, &v3d->gpd);
+ BKE_gpencil_blend_read_data(reader, v3d->gpd);
+ }
+ BLO_read_data_address(reader, &v3d->localvd);
+
+ /* Runtime data */
+ v3d->runtime.properties_storage = NULL;
+ v3d->runtime.flag = 0;
+
+ /* render can be quite heavy, set to solid on load */
+ if (v3d->shading.type == OB_RENDER) {
+ v3d->shading.type = OB_SOLID;
+ }
+ v3d->shading.prev_type = OB_SOLID;
+
+ BKE_screen_view3d_shading_blend_read_data(reader, &v3d->shading);
+
+ BKE_screen_view3d_do_versions_250(v3d, &sl->regionbase);
+ }
+ else if (sl->spacetype == SPACE_GRAPH) {
+ SpaceGraph *sipo = (SpaceGraph *)sl;
+
+ BLO_read_data_address(reader, &sipo->ads);
+ BLI_listbase_clear(&sipo->runtime.ghost_curves);
+ }
+ else if (sl->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)sl;
+
+ BLO_read_data_address(reader, &snla->ads);
+ }
+ else if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
+
+ /* use #BLO_read_get_new_data_address_no_us and do not free old memory avoiding double
+ * frees and use of freed memory. this could happen because of a
+ * bug fixed in revision 58959 where the treestore memory address
+ * was not unique */
+ TreeStore *ts = BLO_read_get_new_data_address_no_us(reader, space_outliner->treestore);
+ space_outliner->treestore = NULL;
+ if (ts) {
+ TreeStoreElem *elems = BLO_read_get_new_data_address_no_us(reader, ts->data);
+
+ space_outliner->treestore = BLI_mempool_create(
+ sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER);
+ if (ts->usedelem && elems) {
+ for (int i = 0; i < ts->usedelem; i++) {
+ TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore);
+ *new_elem = elems[i];
+ }
+ }
+ /* we only saved what was used */
+ space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */
+ }
+ space_outliner->treehash = NULL;
+ space_outliner->tree.first = space_outliner->tree.last = NULL;
+ }
+ else if (sl->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ sima->iuser.scene = NULL;
+ sima->iuser.ok = 1;
+ sima->scopes.waveform_1 = NULL;
+ sima->scopes.waveform_2 = NULL;
+ sima->scopes.waveform_3 = NULL;
+ sima->scopes.vecscope = NULL;
+ sima->scopes.ok = 0;
+
+ /* WARNING: gpencil data is no longer stored directly in sima after 2.5
+ * so sacrifice a few old files for now to avoid crashes with new files!
+ * committed: r28002 */
+#if 0
+ sima->gpd = newdataadr(fd, sima->gpd);
+ if (sima->gpd) {
+ BKE_gpencil_blend_read_data(fd, sima->gpd);
+ }
+#endif
+ }
+ else if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ if (snode->gpd) {
+ BLO_read_data_address(reader, &snode->gpd);
+ BKE_gpencil_blend_read_data(reader, snode->gpd);
+ }
+
+ BLO_read_list(reader, &snode->treepath);
+ snode->edittree = NULL;
+ snode->iofsd = NULL;
+ BLI_listbase_clear(&snode->linkdrag);
+ }
+ else if (sl->spacetype == SPACE_TEXT) {
+ SpaceText *st = (SpaceText *)sl;
+ memset(&st->runtime, 0, sizeof(st->runtime));
+ }
+ else if (sl->spacetype == SPACE_SEQ) {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* grease pencil data is not a direct data and can't be linked from direct_link*
+ * functions, it should be linked from lib_link* functions instead
+ *
+ * otherwise it'll lead to lost grease data on open because it'll likely be
+ * read from file after all other users of grease pencil and newdataadr would
+ * simple return NULL here (sergey)
+ */
+#if 0
+ if (sseq->gpd) {
+ sseq->gpd = newdataadr(fd, sseq->gpd);
+ BKE_gpencil_blend_read_data(fd, sseq->gpd);
+ }
+#endif
+ sseq->scopes.reference_ibuf = NULL;
+ sseq->scopes.zebra_ibuf = NULL;
+ sseq->scopes.waveform_ibuf = NULL;
+ sseq->scopes.sep_waveform_ibuf = NULL;
+ sseq->scopes.vector_ibuf = NULL;
+ sseq->scopes.histogram_ibuf = NULL;
+ }
+ else if (sl->spacetype == SPACE_PROPERTIES) {
+ SpaceProperties *sbuts = (SpaceProperties *)sl;
+
+ sbuts->path = NULL;
+ sbuts->texuser = NULL;
+ sbuts->mainbo = sbuts->mainb;
+ sbuts->mainbuser = sbuts->mainb;
+ sbuts->runtime = NULL;
+ }
+ else if (sl->spacetype == SPACE_CONSOLE) {
+ SpaceConsole *sconsole = (SpaceConsole *)sl;
+
+ BLO_read_list(reader, &sconsole->scrollback);
+ BLO_read_list(reader, &sconsole->history);
+
+ /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression,
+ * from left to right. the right-most expression sets the result of the comma
+ * expression as a whole*/
+ LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) {
+ BLO_read_data_address(reader, &cl->line);
+ if (cl->line) {
+ /* the allocted length is not written, so reset here */
+ cl->len_alloc = cl->len + 1;
+ }
+ else {
+ BLI_remlink(&sconsole->history, cl);
+ MEM_freeN(cl);
+ }
+ }
+ }
+ else if (sl->spacetype == SPACE_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ /* this sort of info is probably irrelevant for reloading...
+ * plus, it isn't saved to files yet!
+ */
+ sfile->folders_prev = sfile->folders_next = NULL;
+ sfile->files = NULL;
+ sfile->layout = NULL;
+ sfile->op = NULL;
+ sfile->previews_timer = NULL;
+ BLO_read_data_address(reader, &sfile->params);
+ }
+ else if (sl->spacetype == SPACE_CLIP) {
+ SpaceClip *sclip = (SpaceClip *)sl;
+
+ sclip->scopes.track_search = NULL;
+ sclip->scopes.track_preview = NULL;
+ sclip->scopes.ok = 0;
+ }
+ }
+
+ BLI_listbase_clear(&area->actionzones);
+
+ BLO_read_data_address(reader, &area->v1);
+ BLO_read_data_address(reader, &area->v2);
+ BLO_read_data_address(reader, &area->v3);
+ BLO_read_data_address(reader, &area->v4);
+}
+
+/**
+ * \return false on error.
+ */
+bool BKE_screen_area_map_blend_read_data(BlendDataReader *reader, ScrAreaMap *area_map)
+{
+ BLO_read_list(reader, &area_map->vertbase);
+ BLO_read_list(reader, &area_map->edgebase);
+ BLO_read_list(reader, &area_map->areabase);
+ LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) {
+ direct_link_area(reader, area);
+ }
+
+ /* edges */
+ LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) {
+ BLO_read_data_address(reader, &se->v1);
+ BLO_read_data_address(reader, &se->v2);
+ BKE_screen_sort_scrvert(&se->v1, &se->v2);
+
+ if (se->v1 == NULL) {
+ BLI_remlink(&area_map->edgebase, se);
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void BKE_screen_area_blend_read_lib(BlendLibReader *reader, ID *parent_id, ScrArea *area)
+{
+ BLO_read_id_address(reader, parent_id->lib, &area->full);
+
+ memset(&area->runtime, 0x0, sizeof(area->runtime));
+
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D: {
+ View3D *v3d = (View3D *)sl;
+
+ BLO_read_id_address(reader, parent_id->lib, &v3d->camera);
+ BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center);
+
+ if (v3d->localvd) {
+ BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera);
+ }
+ break;
+ }
+ case SPACE_GRAPH: {
+ SpaceGraph *sipo = (SpaceGraph *)sl;
+ bDopeSheet *ads = sipo->ads;
+
+ if (ads) {
+ BLO_read_id_address(reader, parent_id->lib, &ads->source);
+ BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
+ }
+ break;
+ }
+ case SPACE_PROPERTIES: {
+ SpaceProperties *sbuts = (SpaceProperties *)sl;
+ BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+ break;
+ }
+ case SPACE_FILE:
+ break;
+ case SPACE_ACTION: {
+ SpaceAction *saction = (SpaceAction *)sl;
+ bDopeSheet *ads = &saction->ads;
+
+ if (ads) {
+ BLO_read_id_address(reader, parent_id->lib, &ads->source);
+ BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
+ }
+
+ BLO_read_id_address(reader, parent_id->lib, &saction->action);
+ break;
+ }
+ case SPACE_IMAGE: {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ BLO_read_id_address(reader, parent_id->lib, &sima->image);
+ BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask);
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ BLO_read_id_address(reader, parent_id->lib, &sima->gpd);
+ break;
+ }
+ case SPACE_SEQ: {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ BLO_read_id_address(reader, parent_id->lib, &sseq->gpd);
+ break;
+ }
+ case SPACE_NLA: {
+ SpaceNla *snla = (SpaceNla *)sl;
+ bDopeSheet *ads = snla->ads;
+
+ if (ads) {
+ BLO_read_id_address(reader, parent_id->lib, &ads->source);
+ BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
+ }
+ break;
+ }
+ case SPACE_TEXT: {
+ SpaceText *st = (SpaceText *)sl;
+
+ BLO_read_id_address(reader, parent_id->lib, &st->text);
+ break;
+ }
+ case SPACE_SCRIPT: {
+ SpaceScript *scpt = (SpaceScript *)sl;
+ /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
+ if (scpt->script) {
+ BLO_read_id_address(reader, parent_id->lib, &scpt->script);
+ if (scpt->script) {
+ SCRIPT_SET_NULL(scpt->script);
+ }
+ }
+ break;
+ }
+ case SPACE_OUTLINER: {
+ SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
+ BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id);
+
+ if (space_outliner->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+
+ BLI_mempool_iternew(space_outliner->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ BLO_read_id_address(reader, NULL, &tselem->id);
+ }
+ if (space_outliner->treehash) {
+ /* rebuild hash table, because it depends on ids too */
+ space_outliner->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
+ break;
+ }
+ case SPACE_NODE: {
+ SpaceNode *snode = (SpaceNode *)sl;
+
+ /* node tree can be stored locally in id too, link this first */
+ BLO_read_id_address(reader, parent_id->lib, &snode->id);
+ BLO_read_id_address(reader, parent_id->lib, &snode->from);
+
+ bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL;
+ if (ntree) {
+ snode->nodetree = ntree;
+ }
+ else {
+ BLO_read_id_address(reader, parent_id->lib, &snode->nodetree);
+ }
+
+ bNodeTreePath *path;
+ for (path = snode->treepath.first; path; path = path->next) {
+ if (path == snode->treepath.first) {
+ /* first nodetree in path is same as snode->nodetree */
+ path->nodetree = snode->nodetree;
+ }
+ else {
+ BLO_read_id_address(reader, parent_id->lib, &path->nodetree);
+ }
+
+ if (!path->nodetree) {
+ break;
+ }
+ }
+
+ /* remaining path entries are invalid, remove */
+ bNodeTreePath *path_next;
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
+ }
+
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
+ }
+ else {
+ snode->edittree = NULL;
+ }
+ break;
+ }
+ case SPACE_CLIP: {
+ SpaceClip *sclip = (SpaceClip *)sl;
+ BLO_read_id_address(reader, parent_id->lib, &sclip->clip);
+ BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c
index 29cb574c7bc..2ae95492708 100644
--- a/source/blender/blenkernel/intern/shader_fx.c
+++ b/source/blender/blenkernel/intern/shader_fx.c
@@ -36,6 +36,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_shader_fx_types.h"
#include "BKE_gpencil.h"
@@ -177,7 +178,7 @@ void BKE_shaderfxType_panel_id(ShaderFxType type, char *r_idname)
void BKE_shaderfx_panel_expand(ShaderFxData *fx)
{
- fx->ui_expand_flag |= (1 << 0);
+ fx->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
}
void BKE_shaderfx_copydata_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst)
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 0a0f81f7829..a319c55709d 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -95,7 +95,7 @@ static bool g_undo_callback_running = false;
/** \name Public Undo Types
*
* Unfortunately we need this for a handful of places.
- */
+ * \{ */
const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL;
const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL;
const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL;
@@ -549,6 +549,8 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
BLI_strncpy(us->name, name, sizeof(us->name));
}
us->type = ut;
+ /* True by default, code needs to explicitely set it to false if necessary. */
+ us->use_old_bmain_data = true;
/* Initialized, not added yet. */
CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
@@ -580,6 +582,12 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
}
}
+ if (ustack->group_level > 0) {
+ /* Temporarily set skip for the active step.
+ * This is an invalid state which must be corrected once the last group ends. */
+ ustack->step_active->skip = true;
+ }
+
undosys_stack_validate(ustack, true);
return true;
}
@@ -849,10 +857,49 @@ void BKE_undosys_type_free_all(void)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Undo Stack Grouping
+ *
+ * This enables skip while group-level is set.
+ * In general it's not allowed that #UndoStack.step_active have 'skip' enabled.
+ *
+ * This rule is relaxed for grouping, however it's important each call to
+ * #BKE_undosys_stack_group_begin has a matching #BKE_undosys_stack_group_end.
+ *
+ * - Levels are used so nesting is supported, where the last call to #BKE_undosys_stack_group_end
+ * will set the active undo step that should not be skipped.
+ *
+ * - Correct begin/end is checked by an assert since any errors here will cause undo
+ * to consider all steps part of one large group.
+ *
+ * - Calls to begin/end with no undo steps being pushed is supported and does nothing.
+ *
+ * \{ */
+
+void BKE_undosys_stack_group_begin(UndoStack *ustack)
+{
+ BLI_assert(ustack->group_level >= 0);
+ ustack->group_level += 1;
+}
+
+void BKE_undosys_stack_group_end(UndoStack *ustack)
+{
+ ustack->group_level -= 1;
+ BLI_assert(ustack->group_level >= 0);
+
+ if (ustack->group_level == 0) {
+ if (LIKELY(ustack->step_active != NULL)) {
+ ustack->step_active->skip = false;
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name ID Reference Utilities
*
* Unfortunately we need this for a handful of places.
- */
+ * \{ */
static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(UndoStack *ustack,
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 43e03fb5165..52420810171 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -48,6 +48,8 @@
#include "MEM_guardedalloc.h"
+#include "BLO_read_write.h"
+
/* -------------------------------------------------------------------- */
static void workspace_free_data(ID *id)
@@ -75,6 +77,98 @@ static void workspace_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
+static void workspace_blend_write(BlendWriter *writer, ID *id, const void *id_address)
+{
+ WorkSpace *workspace = (WorkSpace *)id;
+
+ BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id);
+ BKE_id_blend_write(writer, &workspace->id);
+ BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts);
+ BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations);
+ BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids);
+ BLO_write_struct_list(writer, bToolRef, &workspace->tools);
+ LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
+ if (tref->properties) {
+ IDP_BlendWrite(writer, tref->properties);
+ }
+ }
+}
+
+static void workspace_blend_read_data(BlendDataReader *reader, ID *id)
+{
+ WorkSpace *workspace = (WorkSpace *)id;
+
+ BLO_read_list(reader, &workspace->layouts);
+ BLO_read_list(reader, &workspace->hook_layout_relations);
+ BLO_read_list(reader, &workspace->owner_ids);
+ BLO_read_list(reader, &workspace->tools);
+
+ LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
+ /* parent pointer does not belong to workspace data and is therefore restored in lib_link step
+ * of window manager.*/
+ BLO_read_data_address(reader, &relation->value);
+ }
+
+ LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
+ tref->runtime = NULL;
+ BLO_read_data_address(reader, &tref->properties);
+ IDP_BlendDataRead(reader, &tref->properties);
+ }
+
+ workspace->status_text = NULL;
+
+ id_us_ensure_real(&workspace->id);
+}
+
+static void workspace_blend_read_lib(BlendLibReader *reader, ID *id)
+{
+ WorkSpace *workspace = (WorkSpace *)id;
+ Main *bmain = BLO_read_lib_get_main(reader);
+
+ /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */
+ LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
+ relation->parent = NULL;
+ LISTBASE_FOREACH (wmWindowManager *, wm, &bmain->wm) {
+ LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
+ if (win->winid == relation->parentid) {
+ relation->parent = win->workspace_hook;
+ }
+ }
+ }
+ if (relation->parent == NULL) {
+ BLI_freelinkN(&workspace->hook_layout_relations, relation);
+ }
+ }
+
+ LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) {
+ BLO_read_id_address(reader, id->lib, &layout->screen);
+
+ if (layout->screen) {
+ if (ID_IS_LINKED(id)) {
+ layout->screen->winid = 0;
+ if (layout->screen->temp) {
+ /* delete temp layouts when appending */
+ BKE_workspace_layout_remove(bmain, workspace, layout);
+ }
+ }
+ }
+ else {
+ /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it
+ * around. */
+ BKE_workspace_layout_remove(bmain, workspace, layout);
+ }
+ }
+}
+
+static void workspace_blend_read_expand(BlendExpander *expander, ID *id)
+{
+ WorkSpace *workspace = (WorkSpace *)id;
+
+ LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
+ BLO_expand(expander, BKE_workspace_layout_screen_get(layout));
+ }
+}
+
IDTypeInfo IDType_ID_WS = {
.id_code = ID_WS,
.id_filter = FILTER_ID_WS,
@@ -92,10 +186,10 @@ IDTypeInfo IDType_ID_WS = {
.foreach_id = workspace_foreach_id,
.foreach_cache = NULL,
- .blend_write = NULL,
- .blend_read_data = NULL,
- .blend_read_lib = NULL,
- .blend_read_expand = NULL,
+ .blend_write = workspace_blend_write,
+ .blend_read_data = workspace_blend_read_data,
+ .blend_read_lib = workspace_blend_read_lib,
+ .blend_read_expand = workspace_blend_read_expand,
};
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenloader/BLO_read_write.h b/source/blender/blenloader/BLO_read_write.h
index 5d685cc6687..3600ae504a1 100644
--- a/source/blender/blenloader/BLO_read_write.h
+++ b/source/blender/blenloader/BLO_read_write.h
@@ -52,6 +52,8 @@ typedef struct BlendExpander BlendExpander;
typedef struct BlendLibReader BlendLibReader;
typedef struct BlendWriter BlendWriter;
+struct Main;
+
/* Blend Write API
* ===============
*
@@ -106,6 +108,14 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer,
BLO_write_struct_at_address_by_id( \
writer, BLO_get_struct_id(writer, struct_name), address, data_ptr)
+/* Write single struct at address and specify a filecode. */
+void BLO_write_struct_at_address_by_id_with_filecode(
+ BlendWriter *writer, int filecode, int struct_id, const void *address, const void *data_ptr);
+#define BLO_write_struct_at_address_with_filecode( \
+ writer, filecode, struct_name, address, data_ptr) \
+ BLO_write_struct_at_address_by_id_with_filecode( \
+ writer, filecode, BLO_get_struct_id(writer, struct_name), address, data_ptr)
+
/* Write struct array. */
void BLO_write_struct_array_by_name(BlendWriter *writer,
const char *struct_name,
@@ -177,6 +187,7 @@ bool BLO_write_is_undo(BlendWriter *writer);
*/
void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_address);
+void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address);
void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address);
#define BLO_read_data_address(reader, ptr_p) \
@@ -214,6 +225,7 @@ ID *BLO_read_get_new_id_address(BlendLibReader *reader, struct Library *lib, str
/* Misc. */
bool BLO_read_lib_is_undo(BlendLibReader *reader);
+struct Main *BLO_read_lib_get_main(BlendLibReader *reader);
/* Blend Expand API
* ===================
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5ff3d383a72..32056d03509 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -267,10 +267,6 @@ static BHead *find_bhead_from_code_name(FileData *fd, const short idcode, const
static BHead *find_bhead_from_idname(FileData *fd, const char *idname);
static bool library_link_idcode_needs_tag_check(const short idcode, const int flag);
-#ifdef USE_COLLECTION_COMPAT_28
-static void expand_scene_collection(BlendExpander *expander, SceneCollection *sc);
-#endif
-
typedef struct BHeadN {
struct BHeadN *next, *prev;
#ifdef USE_BHEAD_READ_ON_DEMAND
@@ -2261,7 +2257,6 @@ static void link_glob_list(FileData *fd, ListBase *lb) /* for glob data */
* \{ */
static void lib_link_id(BlendLibReader *reader, ID *id);
-static void lib_link_collection(BlendLibReader *reader, Collection *collection);
static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id)
{
@@ -2277,7 +2272,7 @@ static void lib_link_id_embedded_id(BlendLibReader *reader, ID *id)
Scene *scene = (Scene *)id;
if (scene->master_collection != NULL) {
lib_link_id(reader, &scene->master_collection->id);
- lib_link_collection(reader, scene->master_collection);
+ BKE_collection_blend_read_lib(reader, scene->master_collection);
}
}
}
@@ -2324,7 +2319,6 @@ static void direct_link_id_override_property_cb(BlendDataReader *reader, void *d
static void direct_link_id_common(
BlendDataReader *reader, Library *current_library, ID *id, ID *id_old, const int tag);
-static void direct_link_collection(BlendDataReader *reader, Collection *collection);
static void direct_link_id_embedded_id(BlendDataReader *reader,
Library *current_library,
@@ -2352,7 +2346,7 @@ static void direct_link_id_embedded_id(BlendDataReader *reader,
&scene->master_collection->id,
id_old != NULL ? &((Scene *)id_old)->master_collection->id : NULL,
0);
- direct_link_collection(reader, scene->master_collection);
+ BKE_collection_blend_read_data(reader, scene->master_collection);
}
}
}
@@ -2574,69 +2568,6 @@ static void lib_link_constraint_channels(BlendLibReader *reader, ID *id, ListBas
/** \name Read ID: WorkSpace
* \{ */
-static void lib_link_workspaces(BlendLibReader *reader, WorkSpace *workspace)
-{
- ID *id = (ID *)workspace;
-
- /* Restore proper 'parent' pointers to relevant data, and clean up unused/invalid entries. */
- LISTBASE_FOREACH_MUTABLE (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
- relation->parent = NULL;
- LISTBASE_FOREACH (wmWindowManager *, wm, &reader->main->wm) {
- LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
- if (win->winid == relation->parentid) {
- relation->parent = win->workspace_hook;
- }
- }
- }
- if (relation->parent == NULL) {
- BLI_freelinkN(&workspace->hook_layout_relations, relation);
- }
- }
-
- LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout, &workspace->layouts) {
- BLO_read_id_address(reader, id->lib, &layout->screen);
-
- if (layout->screen) {
- if (ID_IS_LINKED(id)) {
- layout->screen->winid = 0;
- if (layout->screen->temp) {
- /* delete temp layouts when appending */
- BKE_workspace_layout_remove(reader->main, workspace, layout);
- }
- }
- }
- else {
- /* If we're reading a layout without screen stored, it's useless and we shouldn't keep it
- * around. */
- BKE_workspace_layout_remove(reader->main, workspace, layout);
- }
- }
-}
-
-static void direct_link_workspace(BlendDataReader *reader, WorkSpace *workspace)
-{
- BLO_read_list(reader, &workspace->layouts);
- BLO_read_list(reader, &workspace->hook_layout_relations);
- BLO_read_list(reader, &workspace->owner_ids);
- BLO_read_list(reader, &workspace->tools);
-
- LISTBASE_FOREACH (WorkSpaceDataRelation *, relation, &workspace->hook_layout_relations) {
- /* parent pointer does not belong to workspace data and is therefore restored in lib_link step
- * of window manager.*/
- BLO_read_data_address(reader, &relation->value);
- }
-
- LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
- tref->runtime = NULL;
- BLO_read_data_address(reader, &tref->properties);
- IDP_BlendDataRead(reader, &tref->properties);
- }
-
- workspace->status_text = NULL;
-
- id_us_ensure_real(&workspace->id);
-}
-
static void lib_link_workspace_instance_hook(BlendLibReader *reader,
WorkSpaceInstanceHook *hook,
ID *id)
@@ -2910,132 +2841,6 @@ static void direct_link_pointcache_list(BlendDataReader *reader,
}
}
-static void lib_link_partdeflect(BlendLibReader *reader, ID *id, PartDeflect *pd)
-{
- if (pd && pd->tex) {
- BLO_read_id_address(reader, id->lib, &pd->tex);
- }
- if (pd && pd->f_source) {
- BLO_read_id_address(reader, id->lib, &pd->f_source);
- }
-}
-
-static void lib_link_particlesettings(BlendLibReader *reader, ParticleSettings *part)
-{
- BLO_read_id_address(
- reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */
-
- BLO_read_id_address(reader, part->id.lib, &part->instance_object);
- BLO_read_id_address(reader, part->id.lib, &part->instance_collection);
- BLO_read_id_address(reader, part->id.lib, &part->force_group);
- BLO_read_id_address(reader, part->id.lib, &part->bb_ob);
- BLO_read_id_address(reader, part->id.lib, &part->collision_group);
-
- lib_link_partdeflect(reader, &part->id, part->pd);
- lib_link_partdeflect(reader, &part->id, part->pd2);
-
- if (part->effector_weights) {
- BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group);
- }
- else {
- part->effector_weights = BKE_effector_add_weights(part->force_group);
- }
-
- if (part->instance_weights.first && part->instance_collection) {
- LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
- BLO_read_id_address(reader, part->id.lib, &dw->ob);
- }
- }
- else {
- BLI_listbase_clear(&part->instance_weights);
- }
-
- if (part->boids) {
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
- switch (rule->type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid: {
- BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule;
- BLO_read_id_address(reader, part->id.lib, &brga->ob);
- break;
- }
- case eBoidRuleType_FollowLeader: {
- BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule;
- BLO_read_id_address(reader, part->id.lib, &brfl->ob);
- break;
- }
- }
- }
- }
- }
-
- for (int a = 0; a < MAX_MTEX; a++) {
- MTex *mtex = part->mtex[a];
- if (mtex) {
- BLO_read_id_address(reader, part->id.lib, &mtex->tex);
- BLO_read_id_address(reader, part->id.lib, &mtex->object);
- }
- }
-}
-
-static void direct_link_partdeflect(PartDeflect *pd)
-{
- if (pd) {
- pd->rng = NULL;
- }
-}
-
-static void direct_link_particlesettings(BlendDataReader *reader, ParticleSettings *part)
-{
- BLO_read_data_address(reader, &part->adt);
- BLO_read_data_address(reader, &part->pd);
- BLO_read_data_address(reader, &part->pd2);
-
- BKE_animdata_blend_read_data(reader, part->adt);
- direct_link_partdeflect(part->pd);
- direct_link_partdeflect(part->pd2);
-
- BLO_read_data_address(reader, &part->clumpcurve);
- if (part->clumpcurve) {
- BKE_curvemapping_blend_read(reader, part->clumpcurve);
- }
- BLO_read_data_address(reader, &part->roughcurve);
- if (part->roughcurve) {
- BKE_curvemapping_blend_read(reader, part->roughcurve);
- }
- BLO_read_data_address(reader, &part->twistcurve);
- if (part->twistcurve) {
- BKE_curvemapping_blend_read(reader, part->twistcurve);
- }
-
- BLO_read_data_address(reader, &part->effector_weights);
- if (!part->effector_weights) {
- part->effector_weights = BKE_effector_add_weights(part->force_group);
- }
-
- BLO_read_list(reader, &part->instance_weights);
-
- BLO_read_data_address(reader, &part->boids);
- BLO_read_data_address(reader, &part->fluid);
-
- if (part->boids) {
- BLO_read_list(reader, &part->boids->states);
-
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- BLO_read_list(reader, &state->rules);
- BLO_read_list(reader, &state->conditions);
- BLO_read_list(reader, &state->actions);
- }
- }
- for (int a = 0; a < MAX_MTEX; a++) {
- BLO_read_data_address(reader, &part->mtex[a]);
- }
-
- /* Protect against integer overflow vulnerability. */
- CLAMP(part->trail_count, 1, 100000);
-}
-
static void lib_link_particlesystems(BlendLibReader *reader,
Object *ob,
ID *id,
@@ -3361,7 +3166,7 @@ static void lib_link_object(BlendLibReader *reader, Object *ob)
/* texture field */
if (ob->pd) {
- lib_link_partdeflect(reader, &ob->id, ob->pd);
+ BKE_particle_partdeflect_blend_read_lib(reader, &ob->id, ob->pd);
}
if (ob->soft) {
@@ -3945,7 +3750,7 @@ static void direct_link_object(BlendDataReader *reader, Object *ob)
}
BLO_read_data_address(reader, &ob->pd);
- direct_link_partdeflect(ob->pd);
+ BKE_particle_partdeflect_blend_read_data(reader, ob->pd);
BLO_read_data_address(reader, &ob->soft);
if (ob->soft) {
SoftBody *sb = ob->soft;
@@ -4061,187 +3866,6 @@ static void direct_link_view_settings(BlendDataReader *reader,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Read View Layer (Collection Data)
- * \{ */
-
-static void direct_link_layer_collections(BlendDataReader *reader, ListBase *lb, bool master)
-{
- BLO_read_list(reader, lb);
- LISTBASE_FOREACH (LayerCollection *, lc, lb) {
-#ifdef USE_COLLECTION_COMPAT_28
- BLO_read_data_address(reader, &lc->scene_collection);
-#endif
-
- /* Master collection is not a real data-lock. */
- if (master) {
- BLO_read_data_address(reader, &lc->collection);
- }
-
- direct_link_layer_collections(reader, &lc->layer_collections, false);
- }
-}
-
-static void direct_link_view_layer(BlendDataReader *reader, ViewLayer *view_layer)
-{
- view_layer->stats = NULL;
- BLO_read_list(reader, &view_layer->object_bases);
- BLO_read_data_address(reader, &view_layer->basact);
-
- direct_link_layer_collections(reader, &view_layer->layer_collections, true);
- BLO_read_data_address(reader, &view_layer->active_collection);
-
- BLO_read_data_address(reader, &view_layer->id_properties);
- IDP_BlendDataRead(reader, &view_layer->id_properties);
-
- BLO_read_list(reader, &(view_layer->freestyle_config.modules));
- BLO_read_list(reader, &(view_layer->freestyle_config.linesets));
-
- BLI_listbase_clear(&view_layer->drawdata);
- view_layer->object_bases_array = NULL;
- view_layer->object_bases_hash = NULL;
-}
-
-static void lib_link_layer_collection(BlendLibReader *reader,
- Library *lib,
- LayerCollection *layer_collection,
- bool master)
-{
- /* Master collection is not a real data-lock. */
- if (!master) {
- BLO_read_id_address(reader, lib, &layer_collection->collection);
- }
-
- LISTBASE_FOREACH (
- LayerCollection *, layer_collection_nested, &layer_collection->layer_collections) {
- lib_link_layer_collection(reader, lib, layer_collection_nested, false);
- }
-}
-
-static void lib_link_view_layer(BlendLibReader *reader, Library *lib, ViewLayer *view_layer)
-{
- LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) {
- BLO_read_id_address(reader, lib, &fmc->script);
- }
-
- LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
- BLO_read_id_address(reader, lib, &fls->linestyle);
- BLO_read_id_address(reader, lib, &fls->group);
- }
-
- for (Base *base = view_layer->object_bases.first, *base_next = NULL; base; base = base_next) {
- base_next = base->next;
-
- /* we only bump the use count for the collection objects */
- BLO_read_id_address(reader, lib, &base->object);
-
- if (base->object == NULL) {
- /* Free in case linked object got lost. */
- BLI_freelinkN(&view_layer->object_bases, base);
- if (view_layer->basact == base) {
- view_layer->basact = NULL;
- }
- }
- }
-
- LISTBASE_FOREACH (LayerCollection *, layer_collection, &view_layer->layer_collections) {
- lib_link_layer_collection(reader, lib, layer_collection, true);
- }
-
- BLO_read_id_address(reader, lib, &view_layer->mat_override);
-
- IDP_BlendReadLib(reader, view_layer->id_properties);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Read ID: Collection
- * \{ */
-
-#ifdef USE_COLLECTION_COMPAT_28
-static void direct_link_scene_collection(BlendDataReader *reader, SceneCollection *sc)
-{
- BLO_read_list(reader, &sc->objects);
- BLO_read_list(reader, &sc->scene_collections);
-
- LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
- direct_link_scene_collection(reader, nsc);
- }
-}
-
-static void lib_link_scene_collection(BlendLibReader *reader, Library *lib, SceneCollection *sc)
-{
- LISTBASE_FOREACH (LinkData *, link, &sc->objects) {
- BLO_read_id_address(reader, lib, &link->data);
- BLI_assert(link->data);
- }
-
- LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
- lib_link_scene_collection(reader, lib, nsc);
- }
-}
-#endif
-
-static void direct_link_collection(BlendDataReader *reader, Collection *collection)
-{
- BLO_read_list(reader, &collection->gobject);
- BLO_read_list(reader, &collection->children);
-
- BLO_read_data_address(reader, &collection->preview);
- BKE_previewimg_blend_read(reader, collection->preview);
-
- collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
- collection->tag = 0;
- BLI_listbase_clear(&collection->object_cache);
- BLI_listbase_clear(&collection->parents);
-
-#ifdef USE_COLLECTION_COMPAT_28
- /* This runs before the very first doversion. */
- BLO_read_data_address(reader, &collection->collection);
- if (collection->collection != NULL) {
- direct_link_scene_collection(reader, collection->collection);
- }
-
- BLO_read_data_address(reader, &collection->view_layer);
- if (collection->view_layer != NULL) {
- direct_link_view_layer(reader, collection->view_layer);
- }
-#endif
-}
-
-static void lib_link_collection_data(BlendLibReader *reader, Library *lib, Collection *collection)
-{
- LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
- BLO_read_id_address(reader, lib, &cob->ob);
-
- if (cob->ob == NULL) {
- BLI_freelinkN(&collection->gobject, cob);
- }
- }
-
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- BLO_read_id_address(reader, lib, &child->collection);
- }
-}
-
-static void lib_link_collection(BlendLibReader *reader, Collection *collection)
-{
-#ifdef USE_COLLECTION_COMPAT_28
- if (collection->collection) {
- lib_link_scene_collection(reader, collection->id.lib, collection->collection);
- }
-
- if (collection->view_layer) {
- lib_link_view_layer(reader, collection->id.lib, collection->view_layer);
- }
-#endif
-
- lib_link_collection_data(reader, collection->id.lib, collection);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Read ID: Scene
* \{ */
@@ -4322,14 +3946,6 @@ static void direct_link_lightcache(BlendDataReader *reader, LightCache *cache)
BLO_read_data_address(reader, &cache->grid_data);
}
-static void direct_link_view3dshading(BlendDataReader *reader, View3DShading *shading)
-{
- if (shading->prop) {
- BLO_read_data_address(reader, &shading->prop);
- IDP_BlendDataRead(reader, &shading->prop);
- }
-}
-
/* check for cyclic set-scene,
* libs can cause this case which is normally prevented, see (T#####) */
#define USE_SETSCENE_CHECK
@@ -4527,12 +4143,12 @@ static void lib_link_scene(BlendLibReader *reader, Scene *sce)
#ifdef USE_COLLECTION_COMPAT_28
if (sce->collection) {
- lib_link_scene_collection(reader, sce->id.lib, sce->collection);
+ BKE_collection_compat_blend_read_lib(reader, sce->id.lib, sce->collection);
}
#endif
LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) {
- lib_link_view_layer(reader, sce->id.lib, view_layer);
+ BKE_view_layer_blend_read_lib(reader, sce->id.lib, view_layer);
}
if (sce->r.bake.cage_object) {
@@ -4916,14 +4532,14 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce)
/* this runs before the very first doversion */
if (sce->collection) {
BLO_read_data_address(reader, &sce->collection);
- direct_link_scene_collection(reader, sce->collection);
+ BKE_collection_compat_blend_read_data(reader, sce->collection);
}
#endif
/* insert into global old-new map for reading without UI (link_global accesses it again) */
link_glob_list(reader->fd, &sce->view_layers);
LISTBASE_FOREACH (ViewLayer *, view_layer, &sce->view_layers) {
- direct_link_view_layer(reader, view_layer);
+ BKE_view_layer_blend_read_data(reader, view_layer);
}
if (BLO_read_data_is_undo(reader)) {
@@ -4938,7 +4554,7 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce)
}
EEVEE_lightcache_info_update(&sce->eevee);
- direct_link_view3dshading(reader, &sce->display.shading);
+ BKE_screen_view3d_shading_blend_read_data(reader, &sce->display.shading);
BLO_read_data_address(reader, &sce->layer_properties);
IDP_BlendDataRead(reader, &sce->layer_properties);
@@ -4947,540 +4563,12 @@ static void direct_link_scene(BlendDataReader *reader, Scene *sce)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Read Screen Area/Region (Screen Data)
- * \{ */
-
-static void direct_link_panel_list(BlendDataReader *reader, ListBase *lb)
-{
- BLO_read_list(reader, lb);
-
- LISTBASE_FOREACH (Panel *, panel, lb) {
- panel->runtime_flag = 0;
- panel->activedata = NULL;
- panel->type = NULL;
- panel->runtime.custom_data_ptr = NULL;
- direct_link_panel_list(reader, &panel->children);
- }
-}
-
-static void direct_link_region(BlendDataReader *reader, ARegion *region, int spacetype)
-{
- direct_link_panel_list(reader, &region->panels);
-
- BLO_read_list(reader, &region->panels_category_active);
-
- BLO_read_list(reader, &region->ui_lists);
-
- /* The area's search filter is runtime only, so we need to clear the active flag on read. */
- region->flag &= ~RGN_FLAG_SEARCH_FILTER_ACTIVE;
-
- LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
- ui_list->type = NULL;
- ui_list->dyn_data = NULL;
- BLO_read_data_address(reader, &ui_list->properties);
- IDP_BlendDataRead(reader, &ui_list->properties);
- }
-
- BLO_read_list(reader, &region->ui_previews);
-
- if (spacetype == SPACE_EMPTY) {
- /* unknown space type, don't leak regiondata */
- region->regiondata = NULL;
- }
- else if (region->flag & RGN_FLAG_TEMP_REGIONDATA) {
- /* Runtime data, don't use. */
- region->regiondata = NULL;
- }
- else {
- BLO_read_data_address(reader, &region->regiondata);
- if (region->regiondata) {
- if (spacetype == SPACE_VIEW3D) {
- RegionView3D *rv3d = region->regiondata;
-
- BLO_read_data_address(reader, &rv3d->localvd);
- BLO_read_data_address(reader, &rv3d->clipbb);
-
- rv3d->depths = NULL;
- rv3d->render_engine = NULL;
- rv3d->sms = NULL;
- rv3d->smooth_timer = NULL;
-
- rv3d->rflag &= ~(RV3D_NAVIGATING | RV3D_PAINTING);
- rv3d->runtime_viewlock = 0;
- }
- }
- }
-
- region->v2d.sms = NULL;
- region->v2d.alpha_hor = region->v2d.alpha_vert = 255; /* visible by default */
- BLI_listbase_clear(&region->panels_category);
- BLI_listbase_clear(&region->handlers);
- BLI_listbase_clear(&region->uiblocks);
- region->headerstr = NULL;
- region->visible = 0;
- region->type = NULL;
- region->do_draw = 0;
- region->gizmo_map = NULL;
- region->regiontimer = NULL;
- region->draw_buffer = NULL;
- memset(&region->drawrct, 0, sizeof(region->drawrct));
-}
-
-static void direct_link_area(BlendDataReader *reader, ScrArea *area)
-{
- BLO_read_list(reader, &(area->spacedata));
- BLO_read_list(reader, &(area->regionbase));
-
- BLI_listbase_clear(&area->handlers);
- area->type = NULL; /* spacetype callbacks */
-
- /* Should always be unset so that rna_Area_type_get works correctly. */
- area->butspacetype = SPACE_EMPTY;
-
- area->region_active_win = -1;
-
- area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
-
- BLO_read_data_address(reader, &area->global);
-
- /* if we do not have the spacetype registered we cannot
- * free it, so don't allocate any new memory for such spacetypes. */
- if (!BKE_spacetype_exists(area->spacetype)) {
- /* Hint for versioning code to replace deprecated space types. */
- area->butspacetype = area->spacetype;
-
- area->spacetype = SPACE_EMPTY;
- }
-
- LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
- direct_link_region(reader, region, area->spacetype);
- }
-
- /* accident can happen when read/save new file with older version */
- /* 2.50: we now always add spacedata for info */
- if (area->spacedata.first == NULL) {
- SpaceInfo *sinfo = MEM_callocN(sizeof(SpaceInfo), "spaceinfo");
- area->spacetype = sinfo->spacetype = SPACE_INFO;
- BLI_addtail(&area->spacedata, sinfo);
- }
- /* add local view3d too */
- else if (area->spacetype == SPACE_VIEW3D) {
- blo_do_versions_view3d_split_250(area->spacedata.first, &area->regionbase);
- }
-
- LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
- BLO_read_list(reader, &(sl->regionbase));
-
- /* if we do not have the spacetype registered we cannot
- * free it, so don't allocate any new memory for such spacetypes. */
- if (!BKE_spacetype_exists(sl->spacetype)) {
- sl->spacetype = SPACE_EMPTY;
- }
-
- LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) {
- direct_link_region(reader, region, sl->spacetype);
- }
-
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
-
- v3d->flag |= V3D_INVALID_BACKBUF;
-
- if (v3d->gpd) {
- BLO_read_data_address(reader, &v3d->gpd);
- BKE_gpencil_blend_read_data(reader, v3d->gpd);
- }
- BLO_read_data_address(reader, &v3d->localvd);
-
- /* Runtime data */
- v3d->runtime.properties_storage = NULL;
- v3d->runtime.flag = 0;
-
- /* render can be quite heavy, set to solid on load */
- if (v3d->shading.type == OB_RENDER) {
- v3d->shading.type = OB_SOLID;
- }
- v3d->shading.prev_type = OB_SOLID;
-
- direct_link_view3dshading(reader, &v3d->shading);
-
- blo_do_versions_view3d_split_250(v3d, &sl->regionbase);
- }
- else if (sl->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)sl;
-
- BLO_read_data_address(reader, &sipo->ads);
- BLI_listbase_clear(&sipo->runtime.ghost_curves);
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)sl;
-
- BLO_read_data_address(reader, &snla->ads);
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
-
- /* use newdataadr_no_us and do not free old memory avoiding double
- * frees and use of freed memory. this could happen because of a
- * bug fixed in revision 58959 where the treestore memory address
- * was not unique */
- TreeStore *ts = newdataadr_no_us(reader->fd, space_outliner->treestore);
- space_outliner->treestore = NULL;
- if (ts) {
- TreeStoreElem *elems = newdataadr_no_us(reader->fd, ts->data);
-
- space_outliner->treestore = BLI_mempool_create(
- sizeof(TreeStoreElem), ts->usedelem, 512, BLI_MEMPOOL_ALLOW_ITER);
- if (ts->usedelem && elems) {
- for (int i = 0; i < ts->usedelem; i++) {
- TreeStoreElem *new_elem = BLI_mempool_alloc(space_outliner->treestore);
- *new_elem = elems[i];
- }
- }
- /* we only saved what was used */
- space_outliner->storeflag |= SO_TREESTORE_CLEANUP; /* at first draw */
- }
- space_outliner->treehash = NULL;
- space_outliner->tree.first = space_outliner->tree.last = NULL;
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- sima->iuser.scene = NULL;
- sima->iuser.ok = 1;
- sima->scopes.waveform_1 = NULL;
- sima->scopes.waveform_2 = NULL;
- sima->scopes.waveform_3 = NULL;
- sima->scopes.vecscope = NULL;
- sima->scopes.ok = 0;
-
- /* WARNING: gpencil data is no longer stored directly in sima after 2.5
- * so sacrifice a few old files for now to avoid crashes with new files!
- * committed: r28002 */
-#if 0
- sima->gpd = newdataadr(fd, sima->gpd);
- if (sima->gpd) {
- BKE_gpencil_blend_read_data(fd, sima->gpd);
- }
-#endif
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
-
- if (snode->gpd) {
- BLO_read_data_address(reader, &snode->gpd);
- BKE_gpencil_blend_read_data(reader, snode->gpd);
- }
-
- BLO_read_list(reader, &snode->treepath);
- snode->edittree = NULL;
- snode->iofsd = NULL;
- BLI_listbase_clear(&snode->linkdrag);
- }
- else if (sl->spacetype == SPACE_TEXT) {
- SpaceText *st = (SpaceText *)sl;
- memset(&st->runtime, 0, sizeof(st->runtime));
- }
- else if (sl->spacetype == SPACE_SEQ) {
- SpaceSeq *sseq = (SpaceSeq *)sl;
-
- /* grease pencil data is not a direct data and can't be linked from direct_link*
- * functions, it should be linked from lib_link* functions instead
- *
- * otherwise it'll lead to lost grease data on open because it'll likely be
- * read from file after all other users of grease pencil and newdataadr would
- * simple return NULL here (sergey)
- */
-#if 0
- if (sseq->gpd) {
- sseq->gpd = newdataadr(fd, sseq->gpd);
- BKE_gpencil_blend_read_data(fd, sseq->gpd);
- }
-#endif
- sseq->scopes.reference_ibuf = NULL;
- sseq->scopes.zebra_ibuf = NULL;
- sseq->scopes.waveform_ibuf = NULL;
- sseq->scopes.sep_waveform_ibuf = NULL;
- sseq->scopes.vector_ibuf = NULL;
- sseq->scopes.histogram_ibuf = NULL;
- }
- else if (sl->spacetype == SPACE_PROPERTIES) {
- SpaceProperties *sbuts = (SpaceProperties *)sl;
-
- sbuts->path = NULL;
- sbuts->texuser = NULL;
- sbuts->mainbo = sbuts->mainb;
- sbuts->mainbuser = sbuts->mainb;
- sbuts->runtime = NULL;
- }
- else if (sl->spacetype == SPACE_CONSOLE) {
- SpaceConsole *sconsole = (SpaceConsole *)sl;
-
- BLO_read_list(reader, &sconsole->scrollback);
- BLO_read_list(reader, &sconsole->history);
-
- /* comma expressions, (e.g. expr1, expr2, expr3) evaluate each expression,
- * from left to right. the right-most expression sets the result of the comma
- * expression as a whole*/
- LISTBASE_FOREACH_MUTABLE (ConsoleLine *, cl, &sconsole->history) {
- BLO_read_data_address(reader, &cl->line);
- if (cl->line) {
- /* the allocted length is not written, so reset here */
- cl->len_alloc = cl->len + 1;
- }
- else {
- BLI_remlink(&sconsole->history, cl);
- MEM_freeN(cl);
- }
- }
- }
- else if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
-
- /* this sort of info is probably irrelevant for reloading...
- * plus, it isn't saved to files yet!
- */
- sfile->folders_prev = sfile->folders_next = NULL;
- sfile->files = NULL;
- sfile->layout = NULL;
- sfile->op = NULL;
- sfile->previews_timer = NULL;
- BLO_read_data_address(reader, &sfile->params);
- }
- else if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
-
- sclip->scopes.track_search = NULL;
- sclip->scopes.track_preview = NULL;
- sclip->scopes.ok = 0;
- }
- }
-
- BLI_listbase_clear(&area->actionzones);
-
- BLO_read_data_address(reader, &area->v1);
- BLO_read_data_address(reader, &area->v2);
- BLO_read_data_address(reader, &area->v3);
- BLO_read_data_address(reader, &area->v4);
-}
-
-static void lib_link_area(BlendLibReader *reader, ID *parent_id, ScrArea *area)
-{
- BLO_read_id_address(reader, parent_id->lib, &area->full);
-
- memset(&area->runtime, 0x0, sizeof(area->runtime));
-
- LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
- switch (sl->spacetype) {
- case SPACE_VIEW3D: {
- View3D *v3d = (View3D *)sl;
-
- BLO_read_id_address(reader, parent_id->lib, &v3d->camera);
- BLO_read_id_address(reader, parent_id->lib, &v3d->ob_center);
-
- if (v3d->localvd) {
- BLO_read_id_address(reader, parent_id->lib, &v3d->localvd->camera);
- }
- break;
- }
- case SPACE_GRAPH: {
- SpaceGraph *sipo = (SpaceGraph *)sl;
- bDopeSheet *ads = sipo->ads;
-
- if (ads) {
- BLO_read_id_address(reader, parent_id->lib, &ads->source);
- BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
- }
- break;
- }
- case SPACE_PROPERTIES: {
- SpaceProperties *sbuts = (SpaceProperties *)sl;
- BLO_read_id_address(reader, parent_id->lib, &sbuts->pinid);
- if (sbuts->pinid == NULL) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
- }
- break;
- }
- case SPACE_FILE:
- break;
- case SPACE_ACTION: {
- SpaceAction *saction = (SpaceAction *)sl;
- bDopeSheet *ads = &saction->ads;
-
- if (ads) {
- BLO_read_id_address(reader, parent_id->lib, &ads->source);
- BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
- }
-
- BLO_read_id_address(reader, parent_id->lib, &saction->action);
- break;
- }
- case SPACE_IMAGE: {
- SpaceImage *sima = (SpaceImage *)sl;
-
- BLO_read_id_address(reader, parent_id->lib, &sima->image);
- BLO_read_id_address(reader, parent_id->lib, &sima->mask_info.mask);
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- BLO_read_id_address(reader, parent_id->lib, &sima->gpd);
- break;
- }
- case SPACE_SEQ: {
- SpaceSeq *sseq = (SpaceSeq *)sl;
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- BLO_read_id_address(reader, parent_id->lib, &sseq->gpd);
- break;
- }
- case SPACE_NLA: {
- SpaceNla *snla = (SpaceNla *)sl;
- bDopeSheet *ads = snla->ads;
-
- if (ads) {
- BLO_read_id_address(reader, parent_id->lib, &ads->source);
- BLO_read_id_address(reader, parent_id->lib, &ads->filter_grp);
- }
- break;
- }
- case SPACE_TEXT: {
- SpaceText *st = (SpaceText *)sl;
-
- BLO_read_id_address(reader, parent_id->lib, &st->text);
- break;
- }
- case SPACE_SCRIPT: {
- SpaceScript *scpt = (SpaceScript *)sl;
- /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
- if (scpt->script) {
- BLO_read_id_address(reader, parent_id->lib, &scpt->script);
- if (scpt->script) {
- SCRIPT_SET_NULL(scpt->script);
- }
- }
- break;
- }
- case SPACE_OUTLINER: {
- SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
- BLO_read_id_address(reader, NULL, &space_outliner->search_tse.id);
-
- if (space_outliner->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
-
- BLI_mempool_iternew(space_outliner->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- BLO_read_id_address(reader, NULL, &tselem->id);
- }
- if (space_outliner->treehash) {
- /* rebuild hash table, because it depends on ids too */
- space_outliner->storeflag |= SO_TREESTORE_REBUILD;
- }
- }
- break;
- }
- case SPACE_NODE: {
- SpaceNode *snode = (SpaceNode *)sl;
-
- /* node tree can be stored locally in id too, link this first */
- BLO_read_id_address(reader, parent_id->lib, &snode->id);
- BLO_read_id_address(reader, parent_id->lib, &snode->from);
-
- bNodeTree *ntree = snode->id ? ntreeFromID(snode->id) : NULL;
- if (ntree) {
- snode->nodetree = ntree;
- }
- else {
- BLO_read_id_address(reader, parent_id->lib, &snode->nodetree);
- }
-
- bNodeTreePath *path;
- for (path = snode->treepath.first; path; path = path->next) {
- if (path == snode->treepath.first) {
- /* first nodetree in path is same as snode->nodetree */
- path->nodetree = snode->nodetree;
- }
- else {
- BLO_read_id_address(reader, parent_id->lib, &path->nodetree);
- }
-
- if (!path->nodetree) {
- break;
- }
- }
-
- /* remaining path entries are invalid, remove */
- bNodeTreePath *path_next;
- for (; path; path = path_next) {
- path_next = path->next;
-
- BLI_remlink(&snode->treepath, path);
- MEM_freeN(path);
- }
-
- /* edittree is just the last in the path,
- * set this directly since the path may have been shortened above */
- if (snode->treepath.last) {
- path = snode->treepath.last;
- snode->edittree = path->nodetree;
- }
- else {
- snode->edittree = NULL;
- }
- break;
- }
- case SPACE_CLIP: {
- SpaceClip *sclip = (SpaceClip *)sl;
- BLO_read_id_address(reader, parent_id->lib, &sclip->clip);
- BLO_read_id_address(reader, parent_id->lib, &sclip->mask_info.mask);
- break;
- }
- default:
- break;
- }
- }
-}
-
-/**
- * \return false on error.
- */
-static bool direct_link_area_map(BlendDataReader *reader, ScrAreaMap *area_map)
-{
- BLO_read_list(reader, &area_map->vertbase);
- BLO_read_list(reader, &area_map->edgebase);
- BLO_read_list(reader, &area_map->areabase);
- LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) {
- direct_link_area(reader, area);
- }
-
- /* edges */
- LISTBASE_FOREACH (ScrEdge *, se, &area_map->edgebase) {
- BLO_read_data_address(reader, &se->v1);
- BLO_read_data_address(reader, &se->v2);
- BKE_screen_sort_scrvert(&se->v1, &se->v2);
-
- if (se->v1 == NULL) {
- BLI_remlink(&area_map->edgebase, se);
-
- return false;
- }
- }
-
- return true;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name XR-data
* \{ */
static void direct_link_wm_xr_data(BlendDataReader *reader, wmXrData *xr_data)
{
- direct_link_view3dshading(reader, &xr_data->session_settings.shading);
+ BKE_screen_view3d_shading_blend_read_data(reader, &xr_data->session_settings.shading);
}
static void lib_link_wm_xr_data(BlendLibReader *reader, ID *parent_id, wmXrData *xr_data)
@@ -5517,7 +4605,7 @@ static void direct_link_windowmanager(BlendDataReader *reader, wmWindowManager *
win->workspace_hook->temp_layout_store = NULL;
}
- direct_link_area_map(reader, &win->global_areas);
+ BKE_screen_area_map_blend_read_data(reader, &win->global_areas);
win->ghostwin = NULL;
win->gpuctx = NULL;
@@ -5588,7 +4676,7 @@ static void lib_link_windowmanager(BlendLibReader *reader, wmWindowManager *wm)
BLO_read_id_address(reader, NULL, &win->screen);
LISTBASE_FOREACH (ScrArea *, area, &win->global_areas.areabase) {
- lib_link_area(reader, &wm->id, area);
+ BKE_screen_area_blend_read_lib(reader, &wm->id, area);
}
lib_link_wm_xr_data(reader, &wm->id, &wm->xr);
@@ -5601,22 +4689,6 @@ static void lib_link_windowmanager(BlendLibReader *reader, wmWindowManager *wm)
/** \name Read ID: Screen
* \{ */
-/* note: file read without screens option G_FILE_NO_UI;
- * check lib pointers in call below */
-static void lib_link_screen(BlendLibReader *reader, bScreen *screen)
-{
- /* deprecated, but needed for versioning (will be NULL'ed then) */
- BLO_read_id_address(reader, screen->id.lib, &screen->scene);
-
- screen->animtimer = NULL; /* saved in rare cases */
- screen->tool_tip = NULL;
- screen->scrubbing = false;
-
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- lib_link_area(reader, &screen->id, area);
- }
-}
-
/* how to handle user count on pointer restore */
typedef enum ePointerUserMode {
USER_IGNORE = 0, /* ignore user count */
@@ -6093,29 +5165,6 @@ void blo_lib_link_restore(Main *oldmain,
BKE_main_idmap_destroy(id_map);
}
-/* for the saved 2.50 files without regiondata */
-/* and as patch for 2.48 and older */
-void blo_do_versions_view3d_split_250(View3D *v3d, ListBase *regions)
-{
- LISTBASE_FOREACH (ARegion *, region, regions) {
- if (region->regiontype == RGN_TYPE_WINDOW && region->regiondata == NULL) {
- RegionView3D *rv3d;
-
- rv3d = region->regiondata = MEM_callocN(sizeof(RegionView3D), "region v3d patch");
- rv3d->persp = (char)v3d->persp;
- rv3d->view = (char)v3d->view;
- rv3d->dist = v3d->dist;
- copy_v3_v3(rv3d->ofs, v3d->ofs);
- copy_qt_qt(rv3d->viewquat, v3d->viewquat);
- }
- }
-
- /* this was not initialized correct always */
- if (v3d->gridsubdiv == 0) {
- v3d->gridsubdiv = 10;
- }
-}
-
static bool direct_link_screen(BlendDataReader *reader, bScreen *screen)
{
bool success = true;
@@ -6127,7 +5176,7 @@ static bool direct_link_screen(BlendDataReader *reader, bScreen *screen)
BLO_read_data_address(reader, &screen->preview);
BKE_previewimg_blend_read(reader, screen->preview);
- if (!direct_link_area_map(reader, AREAMAP_FROM_SCREEN(screen))) {
+ if (!BKE_screen_area_map_blend_read_data(reader, AREAMAP_FROM_SCREEN(screen))) {
printf("Error reading Screen %s... removing it.\n", screen->id.name + 2);
success = false;
}
@@ -6396,15 +5445,9 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID *
case ID_LI:
direct_link_library(fd, (Library *)id, main);
break;
- case ID_GR:
- direct_link_collection(&reader, (Collection *)id);
- break;
- case ID_PA:
- direct_link_particlesettings(&reader, (ParticleSettings *)id);
- break;
case ID_WS:
- direct_link_workspace(&reader, (WorkSpace *)id);
- break;
+ case ID_PA:
+ case ID_GR:
case ID_ME:
case ID_LT:
case ID_AC:
@@ -7023,27 +6066,12 @@ static void lib_link_all(FileData *fd, Main *bmain)
case ID_WM:
lib_link_windowmanager(&reader, (wmWindowManager *)id);
break;
- case ID_WS:
- /* Could we skip WS in undo case? */
- lib_link_workspaces(&reader, (WorkSpace *)id);
- break;
case ID_SCE:
lib_link_scene(&reader, (Scene *)id);
break;
case ID_OB:
lib_link_object(&reader, (Object *)id);
break;
- case ID_SCR:
- /* DO NOT skip screens here, 3D viewport may contains pointers
- * to other ID data (like #View3D.ob_center)! See T41411. */
- lib_link_screen(&reader, (bScreen *)id);
- break;
- case ID_PA:
- lib_link_particlesettings(&reader, (ParticleSettings *)id);
- break;
- case ID_GR:
- lib_link_collection(&reader, (Collection *)id);
- break;
case ID_IP:
/* XXX deprecated... still needs to be maintained for version patches still. */
lib_link_ipo(&reader, (Ipo *)id);
@@ -7051,6 +6079,10 @@ static void lib_link_all(FileData *fd, Main *bmain)
case ID_LI:
lib_link_library(&reader, (Library *)id); /* Only init users. */
break;
+ case ID_WS:
+ case ID_SCR:
+ case ID_PA:
+ case ID_GR:
case ID_ME:
case ID_LT:
case ID_AC:
@@ -7665,7 +6697,6 @@ static void expand_constraint_channels(BlendExpander *expander, ListBase *chanba
}
static void expand_id(BlendExpander *expander, ID *id);
-static void expand_collection(BlendExpander *expander, Collection *collection);
static void expand_id_embedded_id(BlendExpander *expander, ID *id)
{
@@ -7680,7 +6711,7 @@ static void expand_id_embedded_id(BlendExpander *expander, ID *id)
Scene *scene = (Scene *)id;
if (scene->master_collection != NULL) {
expand_id(expander, &scene->master_collection->id);
- expand_collection(expander, scene->master_collection);
+ BKE_collection_blend_read_expand(expander, scene->master_collection);
}
}
}
@@ -7702,71 +6733,6 @@ static void expand_id(BlendExpander *expander, ID *id)
expand_id_embedded_id(expander, id);
}
-static void expand_particlesettings(BlendExpander *expander, ParticleSettings *part)
-{
- BLO_expand(expander, part->instance_object);
- BLO_expand(expander, part->instance_collection);
- BLO_expand(expander, part->force_group);
- BLO_expand(expander, part->bb_ob);
- BLO_expand(expander, part->collision_group);
-
- for (int a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- BLO_expand(expander, part->mtex[a]->tex);
- BLO_expand(expander, part->mtex[a]->object);
- }
- }
-
- if (part->effector_weights) {
- BLO_expand(expander, part->effector_weights->group);
- }
-
- if (part->pd) {
- BLO_expand(expander, part->pd->tex);
- BLO_expand(expander, part->pd->f_source);
- }
- if (part->pd2) {
- BLO_expand(expander, part->pd2->tex);
- BLO_expand(expander, part->pd2->f_source);
- }
-
- if (part->boids) {
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
- if (rule->type == eBoidRuleType_Avoid) {
- BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule;
- BLO_expand(expander, gabr->ob);
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule;
- BLO_expand(expander, flbr->ob);
- }
- }
- }
- }
-
- LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
- BLO_expand(expander, dw->ob);
- }
-}
-
-static void expand_collection(BlendExpander *expander, Collection *collection)
-{
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- BLO_expand(expander, cob->ob);
- }
-
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- BLO_expand(expander, child->collection);
- }
-
-#ifdef USE_COLLECTION_COMPAT_28
- if (collection->collection != NULL) {
- expand_scene_collection(expander, collection->collection);
- }
-#endif
-}
-
/* callback function used to expand constraint ID-links */
static void expand_constraint_cb(bConstraint *UNUSED(con),
ID **idpoin,
@@ -7892,19 +6858,6 @@ static void expand_object(BlendExpander *expander, Object *ob)
}
}
-#ifdef USE_COLLECTION_COMPAT_28
-static void expand_scene_collection(BlendExpander *expander, SceneCollection *sc)
-{
- LISTBASE_FOREACH (LinkData *, link, &sc->objects) {
- BLO_expand(expander, link->data);
- }
-
- LISTBASE_FOREACH (SceneCollection *, nsc, &sc->scene_collections) {
- expand_scene_collection(expander, nsc);
- }
-}
-#endif
-
static void expand_scene(BlendExpander *expander, Scene *sce)
{
LISTBASE_FOREACH (Base *, base_legacy, &sce->base) {
@@ -8002,7 +6955,7 @@ static void expand_scene(BlendExpander *expander, Scene *sce)
#ifdef USE_COLLECTION_COMPAT_28
if (sce->collection) {
- expand_scene_collection(expander, sce->collection);
+ BKE_collection_compat_blend_read_expand(expander, sce->collection);
}
#endif
@@ -8011,13 +6964,6 @@ static void expand_scene(BlendExpander *expander, Scene *sce)
}
}
-static void expand_workspace(BlendExpander *expander, WorkSpace *workspace)
-{
- LISTBASE_FOREACH (WorkSpaceLayout *, layout, &workspace->layouts) {
- BLO_expand(expander, BKE_workspace_layout_screen_get(layout));
- }
-}
-
/**
* Set the callback func used over all ID data found by \a BLO_expand_main func.
*
@@ -8067,18 +7013,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar)
case ID_SCE:
expand_scene(&expander, (Scene *)id);
break;
- case ID_GR:
- expand_collection(&expander, (Collection *)id);
- break;
case ID_IP:
expand_ipo(&expander, (Ipo *)id); /* XXX deprecated - old animation system */
break;
- case ID_PA:
- expand_particlesettings(&expander, (ParticleSettings *)id);
- break;
- case ID_WS:
- expand_workspace(&expander, (WorkSpace *)id);
- break;
default:
break;
}
@@ -9039,6 +7976,11 @@ void *BLO_read_get_new_data_address(BlendDataReader *reader, const void *old_add
return newdataadr(reader->fd, old_address);
}
+void *BLO_read_get_new_data_address_no_us(BlendDataReader *reader, const void *old_address)
+{
+ return newdataadr_no_us(reader->fd, old_address);
+}
+
void *BLO_read_get_new_packed_address(BlendDataReader *reader, const void *old_address)
{
return newpackedadr(reader->fd, old_address);
@@ -9209,6 +8151,11 @@ bool BLO_read_lib_is_undo(BlendLibReader *reader)
return reader->fd->memfile != NULL;
}
+Main *BLO_read_lib_get_main(BlendLibReader *reader)
+{
+ return reader->main;
+}
+
void BLO_expand_id(BlendExpander *expander, ID *id)
{
expand_doit(expander->fd, expander->main, id);
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 4fa41731454..57d6779d1cb 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -187,7 +187,6 @@ void *blo_do_versions_newlibadr_us(struct FileData *fd, const void *lib, const v
struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
void blo_do_version_old_trackto_to_constraints(struct Object *ob);
-void blo_do_versions_view3d_split_250(struct View3D *v3d, struct ListBase *regions);
void blo_do_versions_key_uidgen(struct Key *key);
void blo_do_versions_userdef(struct UserDef *userdef);
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index f7592308023..1988b2e1f33 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -266,7 +266,7 @@ static void area_add_window_regions(ScrArea *area, SpaceLink *sl, ListBase *lb)
/* and we split view3d */
switch (sl->spacetype) {
case SPACE_VIEW3D:
- blo_do_versions_view3d_split_250((View3D *)sl, lb);
+ BKE_screen_view3d_do_versions_250((View3D *)sl, lb);
break;
case SPACE_OUTLINER: {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index a37ec2d9f0a..835e2f92c7c 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -155,6 +155,7 @@
#include "BKE_packedFile.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
+#include "BKE_screen.h"
#include "BKE_sequencer.h"
#include "BKE_shader_fx.h"
#include "BKE_subsurf.h"
@@ -804,41 +805,6 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
}
}
-static void write_boid_state(BlendWriter *writer, BoidState *state)
-{
- BLO_write_struct(writer, BoidState, state);
-
- LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
- switch (rule->type) {
- case eBoidRuleType_Goal:
- case eBoidRuleType_Avoid:
- BLO_write_struct(writer, BoidRuleGoalAvoid, rule);
- break;
- case eBoidRuleType_AvoidCollision:
- BLO_write_struct(writer, BoidRuleAvoidCollision, rule);
- break;
- case eBoidRuleType_FollowLeader:
- BLO_write_struct(writer, BoidRuleFollowLeader, rule);
- break;
- case eBoidRuleType_AverageSpeed:
- BLO_write_struct(writer, BoidRuleAverageSpeed, rule);
- break;
- case eBoidRuleType_Fight:
- BLO_write_struct(writer, BoidRuleFight, rule);
- break;
- default:
- BLO_write_struct(writer, BoidRule, rule);
- break;
- }
- }
-#if 0
- BoidCondition *cond = state->conditions.first;
- for (; cond; cond = cond->next) {
- BLO_write_struct(writer, BoidCondition, cond);
- }
-#endif
-}
-
/* update this also to readfile.c */
static const char *ptcache_data_struct[] = {
"", // BPHYS_DATA_INDEX
@@ -889,68 +855,6 @@ static void write_pointcaches(BlendWriter *writer, ListBase *ptcaches)
}
}
-static void write_particlesettings(BlendWriter *writer,
- ParticleSettings *part,
- const void *id_address)
-{
- if (part->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
- BKE_id_blend_write(writer, &part->id);
-
- if (part->adt) {
- BKE_animdata_blend_write(writer, part->adt);
- }
- BLO_write_struct(writer, PartDeflect, part->pd);
- BLO_write_struct(writer, PartDeflect, part->pd2);
- BLO_write_struct(writer, EffectorWeights, part->effector_weights);
-
- if (part->clumpcurve) {
- BKE_curvemapping_blend_write(writer, part->clumpcurve);
- }
- if (part->roughcurve) {
- BKE_curvemapping_blend_write(writer, part->roughcurve);
- }
- if (part->twistcurve) {
- BKE_curvemapping_blend_write(writer, part->twistcurve);
- }
-
- LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
- /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
- if (dw->ob != NULL) {
- dw->index = 0;
- if (part->instance_collection) { /* can be NULL if lining fails or set to None */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
- if (object == dw->ob) {
- break;
- }
- dw->index++;
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- }
- BLO_write_struct(writer, ParticleDupliWeight, dw);
- }
-
- if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- BLO_write_struct(writer, BoidSettings, part->boids);
-
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- write_boid_state(writer, state);
- }
- }
- if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- BLO_write_struct(writer, SPHFluidSettings, part->fluid);
- }
-
- for (int a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- BLO_write_struct(writer, MTex, part->mtex[a]);
- }
- }
- }
-}
-
static void write_particlesystems(BlendWriter *writer, ListBase *particles)
{
LISTBASE_FOREACH (ParticleSystem *, psys, particles) {
@@ -1384,37 +1288,6 @@ static void write_object(BlendWriter *writer, Object *ob, const void *id_address
}
}
-static void write_collection_nolib(BlendWriter *writer, Collection *collection)
-{
- /* Shared function for collection data-blocks and scene master collection. */
- BKE_previewimg_blend_write(writer, collection->preview);
-
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- BLO_write_struct(writer, CollectionObject, cob);
- }
-
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- BLO_write_struct(writer, CollectionChild, child);
- }
-}
-
-static void write_collection(BlendWriter *writer, Collection *collection, const void *id_address)
-{
- if (collection->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
- collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
- collection->tag = 0;
- BLI_listbase_clear(&collection->object_cache);
- BLI_listbase_clear(&collection->parents);
-
- /* write LibData */
- BLO_write_id_struct(writer, Collection, id_address, &collection->id);
- BKE_id_blend_write(writer, &collection->id);
-
- write_collection_nolib(writer, collection);
- }
-}
-
static void write_sequence_modifiers(BlendWriter *writer, ListBase *modbase)
{
LISTBASE_FOREACH (SequenceModifierData *, smd, modbase) {
@@ -1447,13 +1320,6 @@ static void write_view_settings(BlendWriter *writer, ColorManagedViewSettings *v
}
}
-static void write_view3dshading(BlendWriter *writer, View3DShading *shading)
-{
- if (shading->prop) {
- IDP_BlendWrite(writer, shading->prop);
- }
-}
-
static void write_paint(BlendWriter *writer, Paint *p)
{
if (p->cavity_curve) {
@@ -1745,7 +1611,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address)
if (sce->master_collection) {
BLO_write_struct(writer, Collection, sce->master_collection);
- write_collection_nolib(writer, sce->master_collection);
+ BKE_collection_blend_write_nolib(writer, sce->master_collection);
}
/* Eevee Lightcache */
@@ -1754,7 +1620,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address)
write_lightcache(writer, sce->eevee.light_cache_data);
}
- write_view3dshading(writer, &sce->display.shading);
+ BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading);
/* Freed on doversion. */
BLI_assert(sce->layer_properties == NULL);
@@ -1762,245 +1628,7 @@ static void write_scene(BlendWriter *writer, Scene *sce, const void *id_address)
static void write_wm_xr_data(BlendWriter *writer, wmXrData *xr_data)
{
- write_view3dshading(writer, &xr_data->session_settings.shading);
-}
-
-static void write_region(BlendWriter *writer, ARegion *region, int spacetype)
-{
- BLO_write_struct(writer, ARegion, region);
-
- if (region->regiondata) {
- if (region->flag & RGN_FLAG_TEMP_REGIONDATA) {
- return;
- }
-
- switch (spacetype) {
- case SPACE_VIEW3D:
- if (region->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = region->regiondata;
- BLO_write_struct(writer, RegionView3D, rv3d);
-
- if (rv3d->localvd) {
- BLO_write_struct(writer, RegionView3D, rv3d->localvd);
- }
- if (rv3d->clipbb) {
- BLO_write_struct(writer, BoundBox, rv3d->clipbb);
- }
- }
- else {
- printf("regiondata write missing!\n");
- }
- break;
- default:
- printf("regiondata write missing!\n");
- }
- }
-}
-
-static void write_uilist(BlendWriter *writer, uiList *ui_list)
-{
- BLO_write_struct(writer, uiList, ui_list);
-
- if (ui_list->properties) {
- IDP_BlendWrite(writer, ui_list->properties);
- }
-}
-
-static void write_space_outliner(BlendWriter *writer, SpaceOutliner *space_outliner)
-{
- BLI_mempool *ts = space_outliner->treestore;
-
- if (ts) {
- SpaceOutliner space_outliner_flat = *space_outliner;
-
- int elems = BLI_mempool_len(ts);
- /* linearize mempool to array */
- TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
-
- if (data) {
- /* In this block we use the memory location of the treestore
- * but _not_ its data, the addresses in this case are UUID's,
- * since we can't rely on malloc giving us different values each time.
- */
- TreeStore ts_flat = {0};
-
- /* we know the treestore is at least as big as a pointer,
- * so offsetting works to give us a UUID. */
- void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *));
-
- ts_flat.usedelem = elems;
- ts_flat.totelem = elems;
- ts_flat.data = data_addr;
-
- BLO_write_struct(writer, SpaceOutliner, space_outliner);
-
- BLO_write_struct_at_address(writer, TreeStore, ts, &ts_flat);
- BLO_write_struct_array_at_address(writer, TreeStoreElem, elems, data_addr, data);
-
- MEM_freeN(data);
- }
- else {
- space_outliner_flat.treestore = NULL;
- BLO_write_struct_at_address(writer, SpaceOutliner, space_outliner, &space_outliner_flat);
- }
- }
- else {
- BLO_write_struct(writer, SpaceOutliner, space_outliner);
- }
-}
-
-static void write_panel_list(BlendWriter *writer, ListBase *lb)
-{
- LISTBASE_FOREACH (Panel *, panel, lb) {
- BLO_write_struct(writer, Panel, panel);
- write_panel_list(writer, &panel->children);
- }
-}
-
-static void write_area_regions(BlendWriter *writer, ScrArea *area)
-{
- LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
- write_region(writer, region, area->spacetype);
- write_panel_list(writer, &region->panels);
-
- LISTBASE_FOREACH (PanelCategoryStack *, pc_act, &region->panels_category_active) {
- BLO_write_struct(writer, PanelCategoryStack, pc_act);
- }
-
- LISTBASE_FOREACH (uiList *, ui_list, &region->ui_lists) {
- write_uilist(writer, ui_list);
- }
-
- LISTBASE_FOREACH (uiPreview *, ui_preview, &region->ui_previews) {
- BLO_write_struct(writer, uiPreview, ui_preview);
- }
- }
-
- LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
- LISTBASE_FOREACH (ARegion *, region, &sl->regionbase) {
- write_region(writer, region, sl->spacetype);
- }
-
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BLO_write_struct(writer, View3D, v3d);
-
- if (v3d->localvd) {
- BLO_write_struct(writer, View3D, v3d->localvd);
- }
-
- write_view3dshading(writer, &v3d->shading);
- }
- else if (sl->spacetype == SPACE_GRAPH) {
- SpaceGraph *sipo = (SpaceGraph *)sl;
- ListBase tmpGhosts = sipo->runtime.ghost_curves;
-
- /* temporarily disable ghost curves when saving */
- BLI_listbase_clear(&sipo->runtime.ghost_curves);
-
- BLO_write_struct(writer, SpaceGraph, sl);
- if (sipo->ads) {
- BLO_write_struct(writer, bDopeSheet, sipo->ads);
- }
-
- /* reenable ghost curves */
- sipo->runtime.ghost_curves = tmpGhosts;
- }
- else if (sl->spacetype == SPACE_PROPERTIES) {
- BLO_write_struct(writer, SpaceProperties, sl);
- }
- else if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
-
- BLO_write_struct(writer, SpaceFile, sl);
- if (sfile->params) {
- BLO_write_struct(writer, FileSelectParams, sfile->params);
- }
- }
- else if (sl->spacetype == SPACE_SEQ) {
- BLO_write_struct(writer, SpaceSeq, sl);
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
- write_space_outliner(writer, space_outliner);
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- BLO_write_struct(writer, SpaceImage, sl);
- }
- else if (sl->spacetype == SPACE_TEXT) {
- BLO_write_struct(writer, SpaceText, sl);
- }
- else if (sl->spacetype == SPACE_SCRIPT) {
- SpaceScript *scr = (SpaceScript *)sl;
- scr->but_refs = NULL;
- BLO_write_struct(writer, SpaceScript, sl);
- }
- else if (sl->spacetype == SPACE_ACTION) {
- BLO_write_struct(writer, SpaceAction, sl);
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)sl;
-
- BLO_write_struct(writer, SpaceNla, snla);
- if (snla->ads) {
- BLO_write_struct(writer, bDopeSheet, snla->ads);
- }
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- BLO_write_struct(writer, SpaceNode, snode);
-
- LISTBASE_FOREACH (bNodeTreePath *, path, &snode->treepath) {
- BLO_write_struct(writer, bNodeTreePath, path);
- }
- }
- else if (sl->spacetype == SPACE_CONSOLE) {
- SpaceConsole *con = (SpaceConsole *)sl;
-
- LISTBASE_FOREACH (ConsoleLine *, cl, &con->history) {
- /* 'len_alloc' is invalid on write, set from 'len' on read */
- BLO_write_struct(writer, ConsoleLine, cl);
- BLO_write_raw(writer, (size_t)cl->len + 1, cl->line);
- }
- BLO_write_struct(writer, SpaceConsole, sl);
- }
-#ifdef WITH_GLOBAL_AREA_WRITING
- else if (sl->spacetype == SPACE_TOPBAR) {
- BLO_write_struct(writer, SpaceTopBar, sl);
- }
- else if (sl->spacetype == SPACE_STATUSBAR) {
- BLO_write_struct(writer, SpaceStatusBar, sl);
- }
-#endif
- else if (sl->spacetype == SPACE_USERPREF) {
- BLO_write_struct(writer, SpaceUserPref, sl);
- }
- else if (sl->spacetype == SPACE_CLIP) {
- BLO_write_struct(writer, SpaceClip, sl);
- }
- else if (sl->spacetype == SPACE_INFO) {
- BLO_write_struct(writer, SpaceInfo, sl);
- }
- }
-}
-
-static void write_area_map(BlendWriter *writer, ScrAreaMap *area_map)
-{
- BLO_write_struct_list(writer, ScrVert, &area_map->vertbase);
- BLO_write_struct_list(writer, ScrEdge, &area_map->edgebase);
- LISTBASE_FOREACH (ScrArea *, area, &area_map->areabase) {
- area->butspacetype = area->spacetype; /* Just for compatibility, will be reset below. */
-
- BLO_write_struct(writer, ScrArea, area);
-
-#ifdef WITH_GLOBAL_AREA_WRITING
- BLO_write_struct(writer, ScrGlobalAreaData, area->global);
-#endif
-
- write_area_regions(writer, area);
-
- area->butspacetype = SPACE_EMPTY; /* Unset again, was changed above. */
- }
+ BKE_screen_view3d_shading_blend_write(writer, &xr_data->session_settings.shading);
}
static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const void *id_address)
@@ -2024,7 +1652,7 @@ static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const
BLO_write_struct(writer, Stereo3dFormat, win->stereo3d_format);
#ifdef WITH_GLOBAL_AREA_WRITING
- write_area_map(writer, &win->global_areas);
+ BKE_screen_area_map_blend_write(writer, &win->global_areas);
#else
win->global_areas = global_areas;
#endif
@@ -2034,37 +1662,6 @@ static void write_windowmanager(BlendWriter *writer, wmWindowManager *wm, const
}
}
-static void write_screen(BlendWriter *writer, bScreen *screen, const void *id_address)
-{
- /* Screens are reference counted, only saved if used by a workspace. */
- if (screen->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
- writestruct_at_address(writer->wd, ID_SCRN, bScreen, 1, id_address, screen);
- BKE_id_blend_write(writer, &screen->id);
-
- BKE_previewimg_blend_write(writer, screen->preview);
-
- /* direct data */
- write_area_map(writer, AREAMAP_FROM_SCREEN(screen));
- }
-}
-
-static void write_workspace(BlendWriter *writer, WorkSpace *workspace, const void *id_address)
-{
- BLO_write_id_struct(writer, WorkSpace, id_address, &workspace->id);
- BKE_id_blend_write(writer, &workspace->id);
- BLO_write_struct_list(writer, WorkSpaceLayout, &workspace->layouts);
- BLO_write_struct_list(writer, WorkSpaceDataRelation, &workspace->hook_layout_relations);
- BLO_write_struct_list(writer, wmOwnerID, &workspace->owner_ids);
- BLO_write_struct_list(writer, bToolRef, &workspace->tools);
- LISTBASE_FOREACH (bToolRef *, tref, &workspace->tools) {
- if (tref->properties) {
- IDP_BlendWrite(writer, tref->properties);
- }
- }
-}
-
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
@@ -2326,24 +1923,16 @@ static bool write_file_handle(Main *mainvar,
case ID_WM:
write_windowmanager(&writer, (wmWindowManager *)id_buffer, id);
break;
- case ID_WS:
- write_workspace(&writer, (WorkSpace *)id_buffer, id);
- break;
- case ID_SCR:
- write_screen(&writer, (bScreen *)id_buffer, id);
- break;
case ID_SCE:
write_scene(&writer, (Scene *)id_buffer, id);
break;
- case ID_GR:
- write_collection(&writer, (Collection *)id_buffer, id);
- break;
case ID_OB:
write_object(&writer, (Object *)id_buffer, id);
break;
+ case ID_WS:
+ case ID_SCR:
case ID_PA:
- write_particlesettings(&writer, (ParticleSettings *)id_buffer, id);
- break;
+ case ID_GR:
case ID_ME:
case ID_LT:
case ID_AC:
@@ -2678,7 +2267,13 @@ void BLO_write_struct_at_address_by_id(BlendWriter *writer,
const void *address,
const void *data_ptr)
{
- writestruct_at_address_nr(writer->wd, DATA, struct_id, 1, address, data_ptr);
+ BLO_write_struct_at_address_by_id_with_filecode(writer, DATA, struct_id, address, data_ptr);
+}
+
+void BLO_write_struct_at_address_by_id_with_filecode(
+ BlendWriter *writer, int filecode, int struct_id, const void *address, const void *data_ptr)
+{
+ writestruct_at_address_nr(writer->wd, filecode, struct_id, 1, address, data_ptr);
}
void BLO_write_struct_array_by_id(BlendWriter *writer,
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 52b41726276..4361f6f9b51 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -247,6 +247,10 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
gp_style = gpencil_viewport_material_overrides(pd, ob, color_type, gp_style);
+ /* Dots or Squares rotation. */
+ mat_data->alignment_rot_cos = cosf(gp_style->alignment_rotation);
+ mat_data->alignment_rot_sin = sinf(gp_style->alignment_rotation);
+
/* Stroke Style */
if ((gp_style->stroke_style == GP_MATERIAL_STROKE_STYLE_TEXTURE) && (gp_style->sima)) {
bool premul;
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 0922ab6552c..04128dc157e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -62,7 +62,7 @@ typedef struct gpMaterial {
float stroke_color[4];
float fill_color[4];
float fill_mix_color[4];
- float fill_uv_transform[3][2], _pad0[2];
+ float fill_uv_transform[3][2], alignment_rot_cos, alignment_rot_sin;
float stroke_texture_mix;
float stroke_u_scale;
float fill_texture_mix;
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 5e930af7bd7..94b066c12e5 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -461,6 +461,14 @@ void stroke_vertex()
float rot_cos = abs(uv_rot);
x_axis = mat2(rot_cos, -rot_sin, rot_sin, rot_cos) * x_axis;
+# ifdef GP_MATERIAL_BUFFER_LEN
+ if (is_dot) {
+ float alignment_cos = MATERIAL(m).fill_uv_offset.z;
+ float alignment_sin = MATERIAL(m).fill_uv_offset.w;
+ x_axis = mat2(alignment_cos, -alignment_sin, alignment_sin, alignment_cos) * x_axis;
+ }
+# endif
+
vec2 y_axis = rotate_90deg(x_axis);
strokeAspect = decode_aspect(aspect1);
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index fc622c7a52e..deebf1d1efc 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -21,13 +21,11 @@
* \ingroup edanimation
*/
-/* User-Interface Stuff for F-Modifiers:
- * This file defines the (C-Coded) templates + editing callbacks needed
- * by the interface stuff or F-Modifiers, as used by F-Curves in the Graph Editor,
- * and NLA-Strips in the NLA Editor.
+/**
+ * User Interface for F-Modifiers
*
- * Copy/Paste Buffer for F-Modifiers:
- * For now, this is also defined in this file so that it can be shared between the
+ * This file defines templates and some editing callbacks needed by the interface for
+ * F-Modifiers, as used by F-Curves in the Graph Editor and NLA-Strips in the NLA Editor.
*/
#include <string.h>
@@ -1047,8 +1045,12 @@ void ANIM_uiTemplate_fmodifier_draw(uiLayout *layout,
}
}
-/* ********************************************** */
-/* COPY/PASTE BUFFER STUFF */
+/* -------------------------------------------------------------------- */
+/** \name Copy / Paste Buffer Code
+ *
+ * For now, this is also defined in this file so that it can be shared between the graph editor
+ * and the NLA editor.
+ * \{ */
/* Copy/Paste Buffer itself (list of FModifier 's) */
static ListBase fmodifier_copypaste_buf = {NULL, NULL};
@@ -1139,4 +1141,4 @@ bool ANIM_fmodifiers_paste_from_buf(ListBase *modifiers, bool replace, FCurve *c
return ok;
}
-/* ********************************************** */
+/** \} */
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 15f3939b2f6..d39c7eb0d95 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -1131,7 +1131,7 @@ static int *init_index_map(Object *obedit, int *r_old_totvert)
}
int vertex_index = 0;
- LISTBASE_FOREACH (Nurb *, nu, &curve->nurb) {
+ LISTBASE_FOREACH (Nurb *, nu, &editnurb->nurbs) {
if (nu->bezt) {
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index 2a880c11afb..1e5984ee14c 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -635,7 +635,10 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
/** \name Text To Object
* \{ */
-static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3])
+static void txt_add_object(bContext *C,
+ const TextLine *firstline,
+ int totline,
+ const float offset[3])
{
Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
@@ -644,7 +647,7 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
Curve *cu;
Object *obedit;
Base *base;
- struct TextLine *tmp;
+ const struct TextLine *tmp;
int nchars = 0, nbytes = 0;
char *s;
int a;
@@ -709,10 +712,10 @@ static void txt_add_object(bContext *C, TextLine *firstline, int totline, const
WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, obedit);
}
-void ED_text_to_object(bContext *C, Text *text, const bool split_lines)
+void ED_text_to_object(bContext *C, const Text *text, const bool split_lines)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- TextLine *line;
+ const TextLine *line;
float offset[3];
int linenum = 0;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 98789706a13..aae92f5ed50 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3398,24 +3398,50 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
}
/* define start and end points of each stroke */
- float area[3], sb[3], ea[3], eb[3];
+ float start_a[3], start_b[3], end_a[3], end_b[3];
pt = &gps_a->points[0];
- copy_v3_v3(area, &pt->x);
+ copy_v3_v3(start_a, &pt->x);
pt = &gps_a->points[gps_a->totpoints - 1];
- copy_v3_v3(ea, &pt->x);
+ copy_v3_v3(end_a, &pt->x);
pt = &gps_b->points[0];
- copy_v3_v3(sb, &pt->x);
+ copy_v3_v3(start_b, &pt->x);
pt = &gps_b->points[gps_b->totpoints - 1];
- copy_v3_v3(eb, &pt->x);
+ copy_v3_v3(end_b, &pt->x);
- /* review if need flip stroke B */
- float ea_sb = len_squared_v3v3(ea, sb);
- float ea_eb = len_squared_v3v3(ea, eb);
- /* flip if distance to end point is shorter */
- if (ea_eb < ea_sb) {
+ /* Check if need flip strokes. */
+ float dist = len_squared_v3v3(end_a, start_b);
+ bool flip_a = false;
+ bool flip_b = false;
+ float lowest = dist;
+
+ dist = len_squared_v3v3(end_a, end_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = false;
+ flip_b = true;
+ }
+
+ dist = len_squared_v3v3(start_a, start_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = true;
+ flip_b = false;
+ }
+
+ dist = len_squared_v3v3(start_a, end_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = true;
+ flip_b = true;
+ }
+
+ if (flip_a) {
+ gpencil_flip_stroke(gps_a);
+ }
+ if (flip_b) {
gpencil_flip_stroke(gps_b);
}
@@ -3439,16 +3465,69 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a,
}
}
+typedef struct tJoinStrokes {
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ bool used;
+} tJoinStrokes;
+
+static int gpencil_get_nearest_stroke_index(tJoinStrokes *strokes_list,
+ const bGPDstroke *gps,
+ const int totstrokes)
+{
+ int index = -1;
+ float min_dist = FLT_MAX;
+ float dist, start_a[3], end_a[3], start_b[3], end_b[3];
+
+ bGPDspoint *pt = &gps->points[0];
+ copy_v3_v3(start_a, &pt->x);
+
+ pt = &gps->points[gps->totpoints - 1];
+ copy_v3_v3(end_a, &pt->x);
+
+ for (int i = 0; i < totstrokes; i++) {
+ tJoinStrokes *elem = &strokes_list[i];
+ if (elem->used) {
+ continue;
+ }
+ pt = &elem->gps->points[0];
+ copy_v3_v3(start_b, &pt->x);
+
+ pt = &elem->gps->points[elem->gps->totpoints - 1];
+ copy_v3_v3(end_b, &pt->x);
+
+ dist = len_squared_v3v3(start_a, start_b);
+ if (dist < min_dist) {
+ min_dist = dist;
+ index = i;
+ }
+ dist = len_squared_v3v3(start_a, end_b);
+ if (dist < min_dist) {
+ min_dist = dist;
+ index = i;
+ }
+ dist = len_squared_v3v3(end_a, start_b);
+ if (dist < min_dist) {
+ min_dist = dist;
+ index = i;
+ }
+ dist = len_squared_v3v3(end_a, end_b);
+ if (dist < min_dist) {
+ min_dist = dist;
+ index = i;
+ }
+ }
+
+ return index;
+}
+
static int gpencil_stroke_join_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
bGPDlayer *activegpl = BKE_gpencil_layer_active_get(gpd);
Object *ob = CTX_data_active_object(C);
-
- bGPDframe *gpf_a = NULL;
- bGPDstroke *stroke_a = NULL;
- bGPDstroke *stroke_b = NULL;
- bGPDstroke *new_stroke = NULL;
+ /* Limit the number of strokes to join. */
+ const int max_join_strokes = 64;
const int type = RNA_enum_get(op->ptr, "type");
const bool leave_gaps = RNA_boolean_get(op->ptr, "leave_gaps");
@@ -3464,87 +3543,89 @@ static int gpencil_stroke_join_exec(bContext *C, wmOperator *op)
BLI_assert(ELEM(type, GP_STROKE_JOIN, GP_STROKE_JOINCOPY));
- /* read all selected strokes */
- bool first = false;
+ int tot_strokes = 0;
+ /** Alloc memory */
+ tJoinStrokes *strokes_list = MEM_malloc_arrayN(sizeof(tJoinStrokes), max_join_strokes, __func__);
+ tJoinStrokes *elem = NULL;
+ /* Read all selected strokes to create a list. */
CTX_DATA_BEGIN (C, bGPDlayer *, gpl, editable_gpencil_layers) {
bGPDframe *gpf = gpl->actframe;
if (gpf == NULL) {
continue;
}
- LISTBASE_FOREACH_MUTABLE (bGPDstroke *, gps, &gpf->strokes) {
+ /* Add all stroke selected of the frame. */
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
if (gps->flag & GP_STROKE_SELECT) {
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
- /* check if the color is editable */
+ /* check if the color is editable. */
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
-
- /* to join strokes, cyclic must be disabled */
- gps->flag &= ~GP_STROKE_CYCLIC;
-
- /* saves first frame and stroke */
- if (!first) {
- first = true;
- gpf_a = gpf;
- stroke_a = gps;
+ elem = &strokes_list[tot_strokes];
+ elem->gpf = gpf;
+ elem->gps = gps;
+ elem->used = false;
+
+ tot_strokes++;
+ /* Limit the number of strokes. */
+ if (tot_strokes == max_join_strokes) {
+ BKE_reportf(op->reports,
+ RPT_WARNING,
+ "Too many strokes selected. Only joined first %d strokes.",
+ max_join_strokes);
+ break;
}
- else {
- stroke_b = gps;
-
- /* create a new stroke if was not created before (only created if something to join) */
- if (new_stroke == NULL) {
- new_stroke = BKE_gpencil_stroke_duplicate(stroke_a, true);
+ }
+ }
+ }
+ CTX_DATA_END;
- /* if new, set current color */
- if (type == GP_STROKE_JOINCOPY) {
- new_stroke->mat_nr = stroke_a->mat_nr;
- }
- }
+ /* Nothing to join. */
+ if (tot_strokes < 2) {
+ MEM_SAFE_FREE(strokes_list);
+ return OPERATOR_CANCELLED;
+ }
- /* join new_stroke and stroke B. New stroke will contain all the previous data */
- gpencil_stroke_join_strokes(new_stroke, stroke_b, leave_gaps);
+ /* Take first stroke. */
+ elem = &strokes_list[0];
+ elem->used = true;
- /* if join only, delete old strokes */
- if (type == GP_STROKE_JOIN) {
- if (stroke_a) {
- /* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(new_stroke);
+ /* Create a new stroke. */
+ bGPDstroke *gps_new = BKE_gpencil_stroke_duplicate(elem->gps, true);
+ gps_new->flag &= ~GP_STROKE_CYCLIC;
+ BLI_insertlinkbefore(&elem->gpf->strokes, elem->gps, gps_new);
- BLI_insertlinkbefore(&gpf_a->strokes, stroke_a, new_stroke);
- BLI_remlink(&gpf->strokes, stroke_a);
- BKE_gpencil_free_stroke(stroke_a);
- stroke_a = NULL;
- }
- if (stroke_b) {
- BLI_remlink(&gpf->strokes, stroke_b);
- BKE_gpencil_free_stroke(stroke_b);
- stroke_b = NULL;
- }
- }
- }
- }
+ /* Join all strokes until the list is completed. */
+ while (true) {
+ int i = gpencil_get_nearest_stroke_index(strokes_list, gps_new, tot_strokes);
+ if (i < 0) {
+ break;
}
+ elem = &strokes_list[i];
+ /* Join new_stroke and stroke B. */
+ gpencil_stroke_join_strokes(gps_new, elem->gps, leave_gaps);
+ elem->used = true;
}
- CTX_DATA_END;
- /* add new stroke if was not added before */
- if (type == GP_STROKE_JOINCOPY) {
- if (new_stroke) {
- /* Add a new frame if needed */
- if (activegpl->actframe == NULL) {
- activegpl->actframe = BKE_gpencil_frame_addnew(activegpl, gpf_a->framenum);
- }
- /* Calc geometry data. */
- BKE_gpencil_stroke_geometry_update(new_stroke);
+ /* Calc geometry data for new stroke. */
+ BKE_gpencil_stroke_geometry_update(gps_new);
- BLI_addtail(&activegpl->actframe->strokes, new_stroke);
+ /* If join only, delete old strokes. */
+ if (type == GP_STROKE_JOIN) {
+ for (int i = 0; i < tot_strokes; i++) {
+ elem = &strokes_list[i];
+ BLI_remlink(&elem->gpf->strokes, elem->gps);
+ BKE_gpencil_free_stroke(elem->gps);
}
}
+ /* Free memory. */
+ MEM_SAFE_FREE(strokes_list);
+
/* notifiers */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 380dfd1a7a2..320357dc678 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -220,7 +220,7 @@ static bool gpencil_interpolate_check_todo(bContext *C, bGPdata *gpd)
int fFrame;
/* only selected */
- if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
+ if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
((gps_from->flag & GP_STROKE_SELECT) == 0)) {
continue;
}
@@ -300,7 +300,7 @@ static void gpencil_interpolate_set_points(bContext *C, tGPDinterpolate *tgpi)
bool valid = true;
/* only selected */
- if ((tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
+ if ((GPENCIL_EDIT_MODE(gpd)) && (tgpi->flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
((gps_from->flag & GP_STROKE_SELECT) == 0)) {
valid = false;
}
@@ -1018,7 +1018,7 @@ static int gpencil_interpolate_seq_exec(bContext *C, wmOperator *op)
for (gps_from = prevFrame->strokes.first; gps_from; gps_from = gps_from->next) {
/* only selected */
- if ((flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
+ if ((GPENCIL_EDIT_MODE(gpd)) && (flag & GP_TOOLFLAG_INTERPOLATE_ONLY_SELECTED) &&
((gps_from->flag & GP_STROKE_SELECT) == 0)) {
continue;
}
diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h
index f9b1d9cdc64..8015a665970 100644
--- a/source/blender/editors/include/ED_curve.h
+++ b/source/blender/editors/include/ED_curve.h
@@ -84,7 +84,7 @@ void ED_curve_editfont_load(struct Object *obedit);
void ED_curve_editfont_make(struct Object *obedit);
void ED_curve_editfont_free(struct Object *obedit);
-void ED_text_to_object(struct bContext *C, struct Text *text, const bool split_lines);
+void ED_text_to_object(struct bContext *C, const struct Text *text, const bool split_lines);
void ED_curve_beztcpy(struct EditNurb *editnurb,
struct BezTriple *dst,
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index dbd374415b0..989854872f3 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -36,6 +36,9 @@ struct wmOperator;
struct wmOperatorType;
/* undo.c */
+bool ED_undo_is_state_valid(struct bContext *C);
+void ED_undo_group_begin(struct bContext *C);
+void ED_undo_group_end(struct bContext *C);
void ED_undo_push(struct bContext *C, const char *str);
void ED_undo_push_op(struct bContext *C, struct wmOperator *op);
void ED_undo_grouped_push(struct bContext *C, const char *str);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 4451199bb7c..ac31148340a 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4550,10 +4550,22 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
button_activate_state(C, but, BUTTON_STATE_EXIT);
return WM_UI_HANDLER_BREAK;
}
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- /* Support alt+wheel on expanded enum rows */
+ if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ /* Support ctrl-wheel to cycle values on expanded enum rows. */
if (but->type == UI_BTYPE_ROW) {
- const int direction = (event->type == WHEELDOWNMOUSE) ? -1 : 1;
+ int type = event->type;
+ int val = event->val;
+
+ /* Convert pan to scroll-wheel. */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ if (type == MOUSEPAN) {
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ const int direction = (type == WHEELDOWNMOUSE) ? -1 : 1;
uiBut *but_select = ui_but_find_select_in_enum(but, direction);
if (but_select) {
uiBut *but_other = (direction == -1) ? but_select->next : but_select->prev;
@@ -5648,8 +5660,20 @@ static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, co
return WM_UI_HANDLER_BREAK;
}
if (ui_but_supports_cycling(but)) {
- if (ELEM(event->type, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
- const int direction = (event->type == WHEELDOWNMOUSE) ? 1 : -1;
+ if (ELEM(event->type, MOUSEPAN, WHEELDOWNMOUSE, WHEELUPMOUSE) && event->ctrl) {
+ int type = event->type;
+ int val = event->val;
+
+ /* Convert pan to scroll-wheel. */
+ if (type == MOUSEPAN) {
+ ui_pan_to_scroll(event, &type, &val);
+
+ if (type == MOUSEPAN) {
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
+ const int direction = (type == WHEELDOWNMOUSE) ? 1 : -1;
data->value = ui_but_menu_step(but, direction);
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index cf589e43858..efb29fe75c3 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -964,7 +964,11 @@ static uiBut *ui_item_with_label(uiLayout *layout,
UI_block_layout_set_current(block, layout);
/* Only add new row if more than 1 item will be added. */
- if (name[0] || use_prop_decorate) {
+ if (name[0]
+#ifdef UI_PROP_DECORATE
+ || use_prop_decorate
+#endif
+ ) {
/* Also avoid setting 'align' if possible. Set the space to zero instead as aligning a large
* number of labels can end up aligning thousands of buttons when displaying key-map search (a
* heavy operation), see: T78636. */
@@ -972,8 +976,8 @@ static uiBut *ui_item_with_label(uiLayout *layout,
sub->space = 0;
}
-#ifdef UI_PROP_DECORATE
if (name[0]) {
+#ifdef UI_PROP_DECORATE
if (use_prop_sep) {
layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0);
}
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index 66194cf8783..258516a1c61 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1059,6 +1059,7 @@ static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* store initial mouse position (in view space) */
UI_view2d_region_to_view(
&region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
+ vzd->zoom_to_mouse_pos = true;
}
return view_zoomout_exec(C, op);
@@ -1232,6 +1233,11 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
v2d = vzd->v2d;
if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ ARegion *region = CTX_wm_region(C);
+
+ /* Store initial mouse position (in view space). */
+ UI_view2d_region_to_view(
+ &region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
vzd->zoom_to_mouse_pos = true;
}
@@ -1278,14 +1284,6 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* for modal exit test */
vzd->invoke_event = event->type;
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
- ARegion *region = CTX_wm_region(C);
-
- /* store initial mouse position (in view space) */
- UI_view2d_region_to_view(
- &region->v2d, event->mval[0], event->mval[1], &vzd->mx_2d, &vzd->my_2d);
- }
-
if (v2d->keepofs & V2D_LOCKOFS_X) {
WM_cursor_modal_set(window, WM_CURSOR_NS_SCROLL);
}
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index 089bd5567a7..9eaa8f3d31b 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -445,37 +445,41 @@ static int object_switch_object_invoke(bContext *C, wmOperator *op, const wmEven
return OPERATOR_CANCELLED;
}
- if (!ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
- return OPERATOR_CANCELLED;
- }
-
- Object *ob_dst_orig = DEG_get_original_object(ob_dst);
- Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig);
- BKE_view_layer_base_deselect_all(view_layer);
- BKE_view_layer_base_select_and_set_active(view_layer, base);
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
-
- /* FIXME: Do a single undo push. */
- ED_undo_push(C, "Change Active");
-
- ob_dst_orig = DEG_get_original_object(ob_dst);
- ED_object_mode_set_ex(C, last_mode, true, op->reports);
-
- /* Update the viewport rotation origin to the mouse cursor. */
- if (last_mode & OB_MODE_ALL_PAINT) {
- float global_loc[3];
- if (ED_view3d_autodist_simple(ar, event->mval, global_loc, 0, NULL)) {
- UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
- copy_v3_v3(ups->average_stroke_accum, global_loc);
- ups->average_stroke_counter = 1;
- ups->last_stroke_valid = true;
+ int retval = OPERATOR_CANCELLED;
+
+ ED_undo_group_begin(C);
+
+ if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
+ Object *ob_dst_orig = DEG_get_original_object(ob_dst);
+ Base *base = BKE_view_layer_base_find(view_layer, ob_dst_orig);
+ BKE_view_layer_base_deselect_all(view_layer);
+ BKE_view_layer_base_select_and_set_active(view_layer, base);
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+
+ ED_undo_push(C, "Change Active");
+
+ ob_dst_orig = DEG_get_original_object(ob_dst);
+ ED_object_mode_set_ex(C, last_mode, true, op->reports);
+
+ /* Update the viewport rotation origin to the mouse cursor. */
+ if (last_mode & OB_MODE_ALL_PAINT) {
+ float global_loc[3];
+ if (ED_view3d_autodist_simple(ar, event->mval, global_loc, 0, NULL)) {
+ UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
+ copy_v3_v3(ups->average_stroke_accum, global_loc);
+ ups->average_stroke_counter = 1;
+ ups->last_stroke_valid = true;
+ }
}
+
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ WM_toolsystem_update_from_context_view3d(C);
+ retval = OPERATOR_FINISHED;
}
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- WM_toolsystem_update_from_context_view3d(C);
+ ED_undo_group_end(C);
- return OPERATOR_FINISHED;
+ return retval;
}
void OBJECT_OT_switch_object(wmOperatorType *ot)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 3d65a9e5fcb..12c61b75ff7 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -696,7 +696,7 @@ bool ED_object_parent_set(ReportList *reports,
/* Preconditions. */
if (ob == par) {
/* Parenting an object to itself is impossible. */
- return true;
+ return false;
}
if (BKE_object_parent_loop_check(par, ob)) {
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index 5a789ee0b01..d961813d04a 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -2013,6 +2013,8 @@ static void outliner_draw_mode_column_toggle(uiBlock *block,
tip);
UI_but_func_set(but, outliner_mode_toggle_fn, tselem, NULL);
UI_but_flag_enable(but, UI_BUT_DRAG_LOCK);
+ /* Mode toggling handles it's own undo state because undo steps need to be grouped. */
+ UI_but_flag_disable(but, UI_BUT_UNDO);
if (ID_IS_LINKED(&ob->id)) {
UI_but_disable(but, TIP_("Can't edit external library data"));
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index c818aa8caa9..acdedf8a238 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -85,64 +85,107 @@
#include "outliner_intern.h"
+/**
+ * \note changes to selection are by convention and not essential.
+ *
+ * \note Handles own undo push.
+ */
static void do_outliner_item_editmode_toggle(bContext *C, Scene *scene, Base *base)
{
Main *bmain = CTX_data_main(C);
Object *ob = base->object;
+ bool changed = false;
if (BKE_object_is_in_editmode(ob)) {
- ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ changed = ED_object_editmode_exit_ex(bmain, scene, ob, EM_FREEDATA);
+ if (changed) {
+ ED_object_base_select(base, BA_DESELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
}
else {
- ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+ changed = ED_object_editmode_enter_ex(CTX_data_main(C), scene, ob, EM_NO_CONTEXT);
+ if (changed) {
+ ED_object_base_select(base, BA_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
+ }
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_object_tag(C);
+ ED_undo_push(C, "Outliner Edit Mode Toggle");
}
}
-static void do_outliner_item_posemode_toggle(bContext *C, Base *base)
+/**
+ * \note changes to selection are by convention and not essential.
+ *
+ * \note Handles own undo push.
+ */
+static void do_outliner_item_posemode_toggle(bContext *C, Scene *scene, Base *base)
{
Main *bmain = CTX_data_main(C);
Object *ob = base->object;
if (ID_IS_LINKED(ob)) {
BKE_report(CTX_wm_reports(C), RPT_WARNING, "Cannot pose libdata");
+ return;
}
- else if (ob->mode & OB_MODE_POSE) {
- ED_object_posemode_exit_ex(bmain, ob);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+
+ bool changed = false;
+ if (ob->mode & OB_MODE_POSE) {
+ changed = ED_object_posemode_exit_ex(bmain, ob);
+ if (changed) {
+ ED_object_base_select(base, BA_DESELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
+ }
}
else {
- ED_object_posemode_enter_ex(bmain, ob);
- WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
+ changed = ED_object_posemode_enter_ex(bmain, ob);
+ if (changed) {
+ ED_object_base_select(base, BA_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_POSE, NULL);
+ }
+ }
+
+ if (changed) {
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ ED_outliner_select_sync_from_object_tag(C);
+ ED_undo_push(C, "Outliner Pose Mode Toggle");
}
}
-/* Swap the current active object from the interaction mode with the given base. */
+/**
+ * Swap the current active object from the interaction mode with the given base.
+ *
+ * \note Changes to selection _are_ needed in this case,
+ * since entering the object mode uses the selection.
+ *
+ * If we didn't want to touch selection we could add an option to the operators
+ * not to do multi-object editing.
+ *
+ * \note Handles own undo push.
+ */
static void do_outliner_item_mode_toggle_generic(bContext *C, TreeViewContext *tvc, Base *base)
{
- Main *bmain = CTX_data_main(C);
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
const int active_mode = tvc->obact->mode;
+ ED_undo_group_begin(C);
- /* Return all objects to object mode. */
- FOREACH_OBJECT_BEGIN (tvc->view_layer, ob_iter) {
- ED_object_mode_generic_exit(bmain, depsgraph, tvc->scene, ob_iter);
- }
- FOREACH_OBJECT_END;
- WM_toolsystem_update_from_context_view3d(C);
-
- Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact);
- if (base_active != base) {
- ED_object_base_select(base_active, BA_DESELECT);
- ED_object_base_activate(C, base);
- ED_object_base_select(base, BA_SELECT);
+ if (ED_object_mode_set(C, OB_MODE_OBJECT)) {
+ Base *base_active = BKE_view_layer_base_find(tvc->view_layer, tvc->obact);
+ if (base_active != base) {
+ BKE_view_layer_base_deselect_all(tvc->view_layer);
+ BKE_view_layer_base_select_and_set_active(tvc->view_layer, base);
+ DEG_id_tag_update(&tvc->scene->id, ID_RECALC_SELECT);
+ ED_undo_push(C, "Change Active");
- /* XXX: Must add undo step between activation and setting mode to prevent an assert. */
- ED_undo_push(C, "outliner mode toggle");
- ED_object_mode_set(C, active_mode);
- ED_outliner_select_sync_from_object_tag(C);
+ /* Operator call does undo push. */
+ ED_object_mode_set(C, active_mode);
+ ED_outliner_select_sync_from_object_tag(C);
+ }
}
+ ED_undo_group_end(C);
}
/* Toggle the item's interaction mode if supported */
@@ -169,7 +212,7 @@ void outliner_item_mode_toggle(bContext *C,
do_outliner_item_editmode_toggle(C, tvc->scene, base);
}
else if (tvc->ob_pose && ob->type == OB_ARMATURE) {
- do_outliner_item_posemode_toggle(C, base);
+ do_outliner_item_posemode_toggle(C, tvc->scene, base);
}
}
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index 97d0db51de0..1ca7222e02d 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -159,6 +159,15 @@ static bool text_new_poll(bContext *UNUSED(C))
return 1;
}
+static bool text_data_poll(bContext *C)
+{
+ Text *text = CTX_data_edit_text(C);
+ if (!text) {
+ return false;
+ }
+ return true;
+}
+
static bool text_edit_poll(bContext *C)
{
Text *text = CTX_data_edit_text(C);
@@ -751,11 +760,6 @@ void TEXT_OT_save_as(wmOperatorType *ot)
/** \name Run Script Operator
* \{ */
-static bool text_run_script_poll(bContext *C)
-{
- return (CTX_data_edit_text(C) != NULL);
-}
-
static int text_run_script(bContext *C, ReportList *reports)
{
#ifdef WITH_PYTHON
@@ -817,7 +821,7 @@ void TEXT_OT_run_script(wmOperatorType *ot)
ot->description = "Run active script";
/* api callbacks */
- ot->poll = text_run_script_poll;
+ ot->poll = text_data_poll;
ot->exec = text_run_script_exec;
/* flags */
@@ -3911,7 +3915,7 @@ void TEXT_OT_resolve_conflict(wmOperatorType *ot)
static int text_to_3d_object_exec(bContext *C, wmOperator *op)
{
- Text *text = CTX_data_edit_text(C);
+ const Text *text = CTX_data_edit_text(C);
const bool split_lines = RNA_boolean_get(op->ptr, "split_lines");
ED_text_to_object(C, text, split_lines);
@@ -3928,7 +3932,7 @@ void TEXT_OT_to_3d_object(wmOperatorType *ot)
/* api callbacks */
ot->exec = text_to_3d_object_exec;
- ot->poll = text_edit_poll;
+ ot->poll = text_data_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
diff --git a/source/blender/editors/transform/transform_gizmo_2d.c b/source/blender/editors/transform/transform_gizmo_2d.c
index c40f3d3f140..09100bb50cc 100644
--- a/source/blender/editors/transform/transform_gizmo_2d.c
+++ b/source/blender/editors/transform/transform_gizmo_2d.c
@@ -53,7 +53,7 @@
/* -------------------------------------------------------------------- */
/** \name Shared Callback's
- */
+ * \{ */
static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt)
{
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 47d60cff0f9..2328f7d5256 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -76,6 +76,44 @@ static CLG_LogRef LOG = {"ed.undo"};
* Non-operator undo editor functions.
* \{ */
+/**
+ * Run from the main event loop, basic checks that undo is left in a correct state.
+ */
+bool ED_undo_is_state_valid(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ /* Currently only checks matching begin/end calls. */
+ if (wm->undo_stack == NULL) {
+ /* No undo stack is valid, nothing to do. */
+ return true;
+ }
+ if (wm->undo_stack->group_level != 0) {
+ /* If this fails #ED_undo_grouped_begin, #ED_undo_grouped_end calls don't match. */
+ return false;
+ }
+ if (wm->undo_stack->step_active != NULL) {
+ if (wm->undo_stack->step_active->skip == true) {
+ /* Skip is only allowed between begin/end calls,
+ * a state that should never happen in main event loop. */
+ return false;
+ }
+ }
+ return true;
+}
+
+void ED_undo_group_begin(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ BKE_undosys_stack_group_begin(wm->undo_stack);
+}
+
+void ED_undo_group_end(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ BKE_undosys_stack_group_end(wm->undo_stack);
+}
+
void ED_undo_push(bContext *C, const char *str)
{
CLOG_INFO(&LOG, 1, "name='%s'", str);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index dec6ef63ffb..628c5bc0476 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -86,7 +86,7 @@ static void initData(GpencilModifierData *md)
MEMCPY_STRUCT_AFTER(gpmd, DNA_struct_default_get(ArrayGpencilModifierData), modifier);
/* Open the first subpanel too, because it's activated by default. */
- md->ui_expand_flag = (1 << 0) | (1 << 1);
+ md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1;
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index c95e5376670..93a67602047 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -60,7 +60,7 @@ typedef struct bConstraint {
/** Constraint name, MAX_NAME. */
char name[64];
- /* Flag for panel and subpanel closed / open state in the UI. */
+ /* An "expand" bit for each of the constraint's (sub)panels (uiPanelDataExpansion). */
short ui_expand_flag;
/** Amount of influence exherted by constraint (0.0-1.0). */
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 1a83120cae9..7107e131eda 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -74,6 +74,7 @@ typedef struct GpencilModifierData {
int type, mode;
char _pad0[4];
short flag;
+ /* An "expand" bit for each of the modifier's (sub)panels (uiPanelDataExpansion). */
short ui_expand_flag;
/** MAX_NAME. */
char name[64];
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 355d3d6439b..1d31b876068 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -99,7 +99,8 @@ typedef struct MaterialGPencilStyle {
float mix_stroke_factor;
/** Mode used to align Dots and Boxes with stroke drawing path and object rotation */
int alignment_mode;
- char _pad[4];
+ /** Rotation for texture for Dots and Squares. */
+ float alignment_rotation;
} MaterialGPencilStyle;
/* MaterialGPencilStyle->flag */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 9dec5230c6c..d7ad1d59002 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -121,7 +121,7 @@ typedef struct ModifierData {
int type, mode;
char _pad0[4];
short flag;
- /* An "expand" bit for each of the modifier's (sub)panels. */
+ /* An "expand" bit for each of the modifier's (sub)panels (uiPanelDataExpansion). */
short ui_expand_flag;
/** MAX_NAME. */
char name[64];
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index f0ff02d3668..d2360d700d2 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -184,6 +184,34 @@ typedef struct Panel {
} Panel;
/**
+ * Used for passing expansion between instanced panel data and the panels themselves.
+ * There are 16 defines because the expansion data is typically stored in a short.
+ *
+ * \note Expansion for instanced panels is stored in depth first order. For example, the value of
+ * UI_SUBPANEL_DATA_EXPAND_2 correspond to mean the expansion of the second subpanel or the first
+ * subpanel's first subpanel.
+ */
+typedef enum uiPanelDataExpansion {
+ UI_PANEL_DATA_EXPAND_ROOT = (1 << 0),
+ UI_SUBPANEL_DATA_EXPAND_1 = (1 << 1),
+ UI_SUBPANEL_DATA_EXPAND_2 = (1 << 2),
+ UI_SUBPANEL_DATA_EXPAND_3 = (1 << 3),
+ UI_SUBPANEL_DATA_EXPAND_4 = (1 << 4),
+ UI_SUBPANEL_DATA_EXPAND_5 = (1 << 5),
+ UI_SUBPANEL_DATA_EXPAND_6 = (1 << 6),
+ UI_SUBPANEL_DATA_EXPAND_7 = (1 << 7),
+ UI_SUBPANEL_DATA_EXPAND_8 = (1 << 8),
+ UI_SUBPANEL_DATA_EXPAND_9 = (1 << 9),
+ UI_SUBPANEL_DATA_EXPAND_10 = (1 << 10),
+ UI_SUBPANEL_DATA_EXPAND_11 = (1 << 11),
+ UI_SUBPANEL_DATA_EXPAND_12 = (1 << 12),
+ UI_SUBPANEL_DATA_EXPAND_13 = (1 << 13),
+ UI_SUBPANEL_DATA_EXPAND_14 = (1 << 14),
+ UI_SUBPANEL_DATA_EXPAND_15 = (1 << 15),
+ UI_SUBPANEL_DATA_EXPAND_16 = (1 << 16),
+} uiPanelDataExpansion;
+
+/**
* Notes on Panel Categories:
*
* - #ARegion.panels_category (#PanelCategoryDyn)
diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h
index 5567d65b6db..07ccac5ba29 100644
--- a/source/blender/makesdna/DNA_shader_fx_types.h
+++ b/source/blender/makesdna/DNA_shader_fx_types.h
@@ -65,7 +65,7 @@ typedef struct ShaderFxData {
int type, mode;
char _pad0[4];
short flag;
- /* Expansion for shader effect panels and sub-panels. */
+ /* An "expand" bit for each of the constraint's (sub)panels (uiPanelDataExpansion). */
short ui_expand_flag;
/** MAX_NAME. */
char name[64];
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 4a02ac8f429..733b459495d 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -589,6 +589,7 @@ typedef struct WalkNavigation {
} WalkNavigation;
typedef struct UserDef_Runtime {
+ /** Mark as changed so the preferences are saved on exit. */
char is_dirty;
char _pad0[7];
} UserDef_Runtime;
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index 60eed60ace1..02ae71e3b3d 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -1456,8 +1456,16 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem simulation_methods[] = {
- {FLUID_DOMAIN_METHOD_FLIP, "FLIP", 0, "FLIP", "Use FLIP as the simulation method"},
- /*{FLUID_DOMAIN_METHOD_APIC, "APIC", 0, "APIC", "Use APIC as the simulation method"},*/
+ {FLUID_DOMAIN_METHOD_FLIP,
+ "FLIP",
+ 0,
+ "FLIP",
+ "Use FLIP as the simulation method (more splashy behavior)"},
+ {FLUID_DOMAIN_METHOD_APIC,
+ "APIC",
+ 0,
+ "APIC",
+ "Use APIC as the simulation method (more energetic and stable behavior)"},
{0, NULL, 0, NULL, NULL},
};
@@ -1820,6 +1828,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "simulation_method");
RNA_def_property_enum_items(prop, simulation_methods);
RNA_def_property_ui_text(prop, "Simulation Method", "Change the underlying simulation method");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_domain_data_reset");
prop = RNA_def_property(srna, "flip_ratio", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 5e16f1187fb..086a182e085 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -24,6 +24,8 @@
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
+#include "BLI_math.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -594,6 +596,16 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
prop, "Alignment", "Defines how align Dots and Boxes with drawing path and object rotation");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+ /* Rotation of texture for Dots or Strokes. */
+ prop = RNA_def_property(srna, "alignment_rotation", PROP_FLOAT, PROP_ANGLE);
+ RNA_def_property_float_sdna(prop, NULL, "alignment_rotation");
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f));
+ RNA_def_property_ui_range(prop, -DEG2RADF(90.0f), DEG2RADF(90.0f), 10, 3);
+ RNA_def_property_ui_text(
+ prop, "Rotation", "Additional rotation applied to dots and square strokes");
+ RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
+
/* pass index for future compositing and editing tools */
prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "index");
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 0ce56e66fab..349b6327ecb 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1527,12 +1527,7 @@ static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr,
static void rna_Modifier_show_expanded_set(PointerRNA *ptr, bool value)
{
ModifierData *md = ptr->data;
- if (value) {
- md->ui_expand_flag |= (1 << 0);
- }
- else {
- md->ui_expand_flag &= ~(1 << 0);
- }
+ SET_FLAG_FROM_TEST(md->ui_expand_flag, value, UI_PANEL_DATA_EXPAND_ROOT);
}
/**
@@ -1543,7 +1538,7 @@ static void rna_Modifier_show_expanded_set(PointerRNA *ptr, bool value)
static bool rna_Modifier_show_expanded_get(PointerRNA *ptr)
{
ModifierData *md = ptr->data;
- return md->ui_expand_flag & (1 << 0);
+ return md->ui_expand_flag & UI_PANEL_DATA_EXPAND_ROOT;
}
static int rna_MeshSequenceCacheModifier_has_velocity_get(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index eab48888d48..0f6136ef287 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3175,7 +3175,7 @@ static void rna_def_space_outliner(BlenderRNA *brna)
prop = RNA_def_property(srna, "filter_id_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "filter_id_type");
RNA_def_property_enum_items(prop, rna_enum_id_type_items);
- RNA_def_property_ui_text(prop, "Filter ID Type", "Data-block type to show");
+ RNA_def_property_ui_text(prop, "Filter by Type", "Data-block type to show");
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
}
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 17fe5d90eca..d4ba7e570c6 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -217,9 +217,10 @@ static void rna_userdef_version_get(PointerRNA *ptr, int *value)
value[2] = userdef->subversionfile;
}
+/** Mark the preferences as being changed so they are saved on exit. */
# define USERDEF_TAG_DIRTY rna_userdef_is_dirty_update_impl()
-/* Use single function so we can more easily breakpoint it. */
+/** Use single function so we can more easily break-point it. */
void rna_userdef_is_dirty_update_impl(void)
{
/* We can't use 'ptr->data' because this update function
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 6ca50a34ebf..12930a7e9b8 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -69,7 +69,7 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(amd, DNA_struct_default_get(ArrayModifierData), modifier);
/* Open the first subpanel by default, it corresspnds to Relative offset which is enabled too. */
- md->ui_expand_flag = (1 << 0) | (1 << 1);
+ md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1;
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index 131c02374a7..9f99e036601 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -74,7 +74,7 @@ static void initData(ModifierData *md)
MEMCPY_STRUCT_AFTER(mmd, DNA_struct_default_get(MultiresModifierData), modifier);
/* Open subdivision panels by default. */
- md->ui_expand_flag = (1 << 0) | (1 << 1);
+ md->ui_expand_flag = UI_PANEL_DATA_EXPAND_ROOT | UI_SUBPANEL_DATA_EXPAND_1;
}
static void requiredDataMask(Object *UNUSED(ob),
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 8eb9a3b0650..8f141a8e23b 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -3159,6 +3159,7 @@ static void wm_event_free_and_remove_from_queue_if_valid(wmEvent *event)
void wm_event_do_handlers(bContext *C)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ BLI_assert(ED_undo_is_state_valid(C));
/* Update key configuration before handling events. */
WM_keyconfig_update(wm);
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 4f5af4bf4ac..738b49dff84 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -415,6 +415,9 @@ int main(int argc,
* since they impact `BKE_appdir` behavior. */
BKE_appdir_init();
+ /* After parsing number of threads argument. */
+ BLI_task_scheduler_init();
+
/* Initialize sub-systems that use `BKE_appdir.h`. */
IMB_init();
@@ -425,9 +428,6 @@ int main(int argc,
main_signal_setup();
#endif
- /* After parsing number of threads argument. */
- BLI_task_scheduler_init();
-
#ifdef WITH_FFMPEG
/* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */
IMB_ffmpeg_init();
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index ef1c8e935c3..a36bdbf8a87 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -2071,6 +2071,8 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_argsAdd(ba, NULL, "--env-system-scripts", CB_EX(arg_handle_env_system_set, scripts), NULL);
BLI_argsAdd(ba, NULL, "--env-system-python", CB_EX(arg_handle_env_system_set, python), NULL);
+ BLI_argsAdd(ba, "-t", "--threads", CB(arg_handle_threads_set), NULL);
+
/* Pass: Background Mode & Settings
*
* Also and commands that exit after usage. */
@@ -2088,8 +2090,6 @@ void main_args_setup(bContext *C, bArgs *ba)
BLI_argsAdd(ba, NULL, "--disable-crash-handler", CB(arg_handle_crash_handler_disable), NULL);
BLI_argsAdd(ba, NULL, "--disable-abort-handler", CB(arg_handle_abort_handler_disable), NULL);
- BLI_argsAdd(ba, "-t", "--threads", CB(arg_handle_threads_set), NULL);
-
BLI_argsAdd(ba, "-b", "--background", CB(arg_handle_background_mode_set), NULL);
BLI_argsAdd(ba, "-a", NULL, CB(arg_handle_playback_mode), NULL);