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--extern/mantaflow/CMakeLists.txt62
-rw-r--r--extern/mantaflow/UPDATE.sh23
-rw-r--r--extern/mantaflow/dependencies/cnpy/LICENSE21
-rw-r--r--extern/mantaflow/dependencies/cnpy/cnpy.cpp385
-rw-r--r--extern/mantaflow/dependencies/cnpy/cnpy.h310
-rw-r--r--extern/mantaflow/preprocessed/fileio/iogrids.cpp43
-rw-r--r--extern/mantaflow/preprocessed/fileio/ioutil.cpp21
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--extern/mantaflow/preprocessed/mesh.cpp6
-rw-r--r--release/scripts/modules/addon_utils.py2
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py12
-rw-r--r--release/scripts/modules/bpy/utils/previews.py4
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py3
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py6
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py2
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--source/blender/blenkernel/BKE_node.h8
-rw-r--r--source/blender/blenkernel/BKE_simulation.h10
-rw-r--r--source/blender/blenkernel/CMakeLists.txt8
-rw-r--r--source/blender/blenkernel/intern/simulation.cc714
-rw-r--r--source/blender/blenlib/BLI_string_ref.hh12
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h3
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c9
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c159
-rw-r--r--source/blender/draw/intern/draw_cache_impl_pointcloud.c1
-rw-r--r--source/blender/editors/include/ED_uvedit.h30
-rw-r--r--source/blender/editors/interface/interface_templates.c27
-rw-r--r--source/blender/editors/object/object_constraint.c109
-rw-r--r--source/blender/editors/uvedit/uvedit_rip.c4
-rw-r--r--source/blender/editors/uvedit/uvedit_select.c115
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c2
-rw-r--r--source/blender/functions/CMakeLists.txt1
-rw-r--r--source/blender/functions/FN_cpp_type.hh11
-rw-r--r--source/blender/functions/intern/cpp_types.cc2
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c6
-rw-r--r--source/blender/io/common/CMakeLists.txt13
-rw-r--r--source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc (renamed from tests/gtests/usd/abstract_hierarchy_iterator_test.cc)29
-rw-r--r--source/blender/io/common/intern/hierarchy_context_order_test.cc (renamed from tests/gtests/usd/hierarchy_context_order_test.cc)14
-rw-r--r--source/blender/io/common/intern/object_identifier_test.cc (renamed from tests/gtests/usd/object_identifier_test.cc)6
-rw-r--r--source/blender/io/usd/CMakeLists.txt12
-rw-r--r--source/blender/io/usd/tests/usd_stage_creation_test.cc (renamed from tests/gtests/usd/usd_stage_creation_test.cc)16
-rw-r--r--source/blender/nodes/CMakeLists.txt6
-rw-r--r--source/blender/nodes/NOD_derived_node_tree.hh (renamed from source/blender/blenkernel/BKE_derived_node_tree.hh)16
-rw-r--r--source/blender/nodes/NOD_node_tree_multi_function.hh (renamed from source/blender/blenkernel/BKE_node_tree_multi_function.hh)20
-rw-r--r--source/blender/nodes/NOD_node_tree_ref.hh (renamed from source/blender/blenkernel/BKE_node_tree_ref.hh)14
-rw-r--r--source/blender/nodes/function/node_function_util.hh2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_boolean_math.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_combine_strings.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_float_compare.cc2
-rw-r--r--source/blender/nodes/function/nodes/node_fn_group_instance_id.cc6
-rw-r--r--source/blender/nodes/intern/derived_node_tree.cc (renamed from source/blender/blenkernel/intern/derived_node_tree.cc)6
-rw-r--r--source/blender/nodes/intern/node_socket.cc14
-rw-r--r--source/blender/nodes/intern/node_tree_multi_function.cc (renamed from source/blender/blenkernel/intern/node_tree_multi_function.cc)8
-rw-r--r--source/blender/nodes/intern/node_tree_ref.cc (renamed from source/blender/blenkernel/intern/node_tree_ref.cc)6
-rw-r--r--source/blender/nodes/shader/node_shader_util.h2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_map_range.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.cc6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc4
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_valToRgb.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_value.cc2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.cc4
-rw-r--r--source/blender/simulation/CMakeLists.txt11
-rw-r--r--source/blender/simulation/SIM_particle_function.hh89
-rw-r--r--source/blender/simulation/SIM_simulation_update.hh (renamed from source/blender/functions/FN_cpp_types.hh)38
-rw-r--r--source/blender/simulation/intern/particle_function.cc160
-rw-r--r--source/blender/simulation/intern/simulation_update.cc495
-rw-r--r--tests/gtests/CMakeLists.txt3
-rw-r--r--tests/gtests/blenloader/blendfile_loading_base_test.cc11
-rw-r--r--tests/gtests/functions/FN_array_spans_test.cc7
-rw-r--r--tests/gtests/functions/FN_attributes_ref_test.cc1
-rw-r--r--tests/gtests/functions/FN_cpp_type_test.cc5
-rw-r--r--tests/gtests/functions/FN_generic_vector_array_test.cc15
-rw-r--r--tests/gtests/functions/FN_multi_function_network_test.cc7
-rw-r--r--tests/gtests/functions/FN_multi_function_test.cc11
-rw-r--r--tests/gtests/functions/FN_spans_test.cc17
-rw-r--r--tests/gtests/runner/BlenderAddTests.cmake3
-rw-r--r--tests/gtests/runner/CMakeLists.txt12
-rw-r--r--tests/gtests/testing/testing.h9
-rw-r--r--tests/gtests/testing/testing_main.cc25
-rw-r--r--tests/gtests/usd/CMakeLists.txt109
82 files changed, 1445 insertions, 1940 deletions
diff --git a/extern/mantaflow/CMakeLists.txt b/extern/mantaflow/CMakeLists.txt
index bbf75039782..9f66b42c6bf 100644
--- a/extern/mantaflow/CMakeLists.txt
+++ b/extern/mantaflow/CMakeLists.txt
@@ -35,15 +35,28 @@ set(MANTAVERSION "0.13")
add_definitions(-DWITH_FLUID=1)
-set(MANTA_DEP
- dependencies
-)
+# Compile Mantaflow dependencies too (e.g. cnpy for numpy file IO).
+# Make sure that dependencies exist before enabling this option by updating the source files in extern/
+set(WITH_MANTA_DEPENDENCIES 0)
+
+# Enable Mantaflow numpy support
+set(WITH_MANTA_NUMPY 0)
+
+if(NOT WITH_MANTA_DEPENDENCIES)
+ add_definitions(-DNO_CNPY=1)
+endif()
+
set(MANTA_HLP
helper
)
set(MANTA_PP
preprocessed
)
+if(WITH_MANTA_DEPENDENCIES)
+ set(MANTA_DEP
+ dependencies
+ )
+endif()
if(WITH_TBB)
add_definitions(-DTBB=1)
@@ -62,6 +75,10 @@ if(WIN32)
add_definitions(-D_USE_MATH_DEFINES)
endif()
+if(WITH_MANTA_NUMPY AND WITH_PYTHON_INSTALL_NUMPY)
+ add_definitions(-DNUMPY=1)
+endif()
+
set(INC
${MANTA_PP}
${MANTA_PP}/fileio
@@ -69,14 +86,25 @@ set(INC
${MANTA_PP}/plugin
${MANTA_HLP}/pwrapper
${MANTA_HLP}/util
- ${MANTA_DEP}/cnpy
)
+if(WITH_MANTA_DEPENDENCIES)
+ list(APPEND INC
+ ${MANTA_DEP}/cnpy
+ )
+endif()
+
set(INC_SYS
${PYTHON_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
)
+if(WITH_MANTA_NUMPY AND WITH_PYTHON_INSTALL_NUMPY)
+ list(APPEND INC_SYS
+ ${PYTHON_NUMPY_INCLUDE_DIRS}
+ )
+endif()
+
if(WITH_TBB)
list(APPEND INC_SYS
${TBB_INCLUDE_DIRS}
@@ -96,9 +124,6 @@ if(WITH_OPENVDB)
endif()
set(SRC
- ${MANTA_DEP}/cnpy/cnpy.cpp
- ${MANTA_DEP}/cnpy/cnpy.h
-
${MANTA_PP}/commonkernels.h
${MANTA_PP}/commonkernels.h.reg.cpp
${MANTA_PP}/conjugategrad.cpp
@@ -161,14 +186,10 @@ set(SRC
${MANTA_PP}/plugin/initplugins.cpp
${MANTA_PP}/plugin/kepsilon.cpp
${MANTA_PP}/plugin/meshplugins.cpp
-# TODO (sebbas): add numpy to libraries
-# ${MANTA_PP}/plugin/numpyconvert.cpp
${MANTA_PP}/plugin/pressure.cpp
${MANTA_PP}/plugin/ptsplugins.cpp
${MANTA_PP}/plugin/secondaryparticles.cpp
${MANTA_PP}/plugin/surfaceturbulence.cpp
-# TODO (sebbas): add numpy to libraries
-# ${MANTA_PP}/plugin/tfplugins.cpp
${MANTA_PP}/plugin/vortexplugins.cpp
${MANTA_PP}/plugin/waveletturbulence.cpp
${MANTA_PP}/plugin/waves.cpp
@@ -193,9 +214,6 @@ set(SRC
${MANTA_PP}/vortexsheet.h.reg.cpp
${MANTA_HLP}/pwrapper/manta.h
-# TODO (sebbas): add numpy to libraries
-# ${MANTA_HLP}/pwrapper/numpyWrap.cpp
-# ${MANTA_HLP}/pwrapper/numpyWrap.h
${MANTA_HLP}/pwrapper/pclass.cpp
${MANTA_HLP}/pwrapper/pclass.h
${MANTA_HLP}/pwrapper/pconvert.cpp
@@ -221,6 +239,22 @@ set(SRC
${MANTA_HLP}/util/vectorbase.h
)
+if(WITH_MANTA_DEPENDENCIES)
+ list(APPEND SRC
+ ${MANTA_DEP}/cnpy/cnpy.cpp
+ ${MANTA_DEP}/cnpy/cnpy.h
+ )
+endif()
+
+if(WITH_MANTA_NUMPY AND WITH_PYTHON_INSTALL_NUMPY)
+ list(APPEND SRC
+ ${MANTA_PP}/plugin/numpyconvert.cpp
+ ${MANTA_PP}/plugin/tfplugins.cpp
+ ${MANTA_HLP}/pwrapper/numpyWrap.cpp
+ ${MANTA_HLP}/pwrapper/numpyWrap.h
+ )
+endif()
+
set(LIB
${PYTHON_LINKFLAGS}
${PYTHON_LIBRARIES}
diff --git a/extern/mantaflow/UPDATE.sh b/extern/mantaflow/UPDATE.sh
index 3feb1ba9226..aed4e2a9b71 100644
--- a/extern/mantaflow/UPDATE.sh
+++ b/extern/mantaflow/UPDATE.sh
@@ -13,6 +13,12 @@ BLENDER_INSTALLATION=/Users/sebbas/Developer/Blender/fluid-mantaflow
# Try to check out Mantaflow repository before building?
CLEAN_REPOSITORY=0
+# Skip copying dependency files?
+WITH_DEPENDENCIES=0
+
+# Build with numpy support?
+USE_NUMPY=0
+
# Choose which multithreading platform to use for Mantaflow preprocessing
USE_OMP=0
USE_TBB=1
@@ -50,17 +56,21 @@ fi
MANTA_BUILD_PATH=$MANTA_INSTALLATION/build_blender/
mkdir -p $MANTA_BUILD_PATH
cd $MANTA_BUILD_PATH
-cmake ../mantaflowgit -DGUI=OFF -DOPENMP=$USE_OMP -DTBB=$USE_TBB -DBLENDER=ON -DPREPDEBUG=ON && make -j8
+cmake ../mantaflowgit -DGUI=0 -DOPENMP=$USE_OMP -DTBB=$USE_TBB -DBLENDER=1 -DPREPDEBUG=1 -DNUMPY=$USE_NUMPY && make -j8
# ==================== 3) COPY MANTAFLOW FILES TO BLENDER ROOT ===========================
-mkdir -p $BLENDER_INSTALLATION/blender/tmp/dependencies/ && cp -Rf $MANTA_INSTALLATION/mantaflowgit/dependencies/cnpy "$_"
+if [[ "$WITH_DEPENDENCIES" -eq "1" ]]; then
+ mkdir -p $BLENDER_INSTALLATION/blender/tmp/dependencies/ && cp -Rf $MANTA_INSTALLATION/mantaflowgit/dependencies/cnpy "$_"
+fi
mkdir -p $BLENDER_INSTALLATION/blender/tmp/helper/ && cp -Rf $MANTA_INSTALLATION/mantaflowgit/source/util "$_"
mkdir -p $BLENDER_INSTALLATION/blender/tmp/helper/ && cp -Rf $MANTA_INSTALLATION/mantaflowgit/source/pwrapper "$_"
mkdir -p $BLENDER_INSTALLATION/blender/tmp/preprocessed/ && cp -Rf $MANTA_INSTALLATION/build_blender/pp/source/. "$_"
# Remove some files that are not need in Blender
-rm $BLENDER_INSTALLATION/blender/tmp/dependencies/cnpy/example1.cpp
+if [[ "$WITH_DEPENDENCIES" -eq "1" ]]; then
+ rm $BLENDER_INSTALLATION/blender/tmp/dependencies/cnpy/example1.cpp
+fi
rm $BLENDER_INSTALLATION/blender/tmp/helper/pwrapper/pymain.cpp
rm $BLENDER_INSTALLATION/blender/tmp/preprocessed/*.reg
rm $BLENDER_INSTALLATION/blender/tmp/preprocessed/python/*.reg
@@ -82,8 +92,13 @@ BLENDER_TMP_DEP=$BLENDER_TMP/dependencies
BLENDER_TMP_HLP=$BLENDER_TMP/helper
BLENDER_TMP_PP=$BLENDER_TMP/preprocessed
+# Before moving new files, delete all existing file in the Blender repository
+rm -Rf $BLENDER_MANTA_EXTERN/dependencies $BLENDER_MANTA_EXTERN/helper $BLENDER_MANTA_EXTERN/preprocessed
+
# Move files from tmp dir to extern/
-cp -Rf $BLENDER_TMP_DEP $BLENDER_MANTA_EXTERN
+if [[ "$WITH_DEPENDENCIES" -eq "1" ]]; then
+ cp -Rf $BLENDER_TMP_DEP $BLENDER_MANTA_EXTERN
+fi
cp -Rf $BLENDER_TMP_HLP $BLENDER_MANTA_EXTERN
cp -Rf $BLENDER_TMP_PP $BLENDER_MANTA_EXTERN
diff --git a/extern/mantaflow/dependencies/cnpy/LICENSE b/extern/mantaflow/dependencies/cnpy/LICENSE
deleted file mode 100644
index e60eadbccb3..00000000000
--- a/extern/mantaflow/dependencies/cnpy/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License
-
-Copyright (c) Carl Rogers, 2011
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/extern/mantaflow/dependencies/cnpy/cnpy.cpp b/extern/mantaflow/dependencies/cnpy/cnpy.cpp
deleted file mode 100644
index 7f0ce21ece8..00000000000
--- a/extern/mantaflow/dependencies/cnpy/cnpy.cpp
+++ /dev/null
@@ -1,385 +0,0 @@
-// Copyright (C) 2011 Carl Rogers
-// Released under MIT License
-// license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
-
-#include "cnpy.h"
-#include <complex>
-#include <cstdlib>
-#include <algorithm>
-#include <cstring>
-#include <iomanip>
-#include <stdint.h>
-#include <stdexcept>
-#include <regex>
-
-char cnpy::BigEndianTest()
-{
- int x = 1;
- return (((char *)&x)[0]) ? '<' : '>';
-}
-
-char cnpy::map_type(const std::type_info &t)
-{
- if (t == typeid(float))
- return 'f';
- if (t == typeid(double))
- return 'f';
- if (t == typeid(long double))
- return 'f';
-
- if (t == typeid(int))
- return 'i';
- if (t == typeid(char))
- return 'i';
- if (t == typeid(short))
- return 'i';
- if (t == typeid(long))
- return 'i';
- if (t == typeid(long long))
- return 'i';
-
- if (t == typeid(unsigned char))
- return 'u';
- if (t == typeid(unsigned short))
- return 'u';
- if (t == typeid(unsigned long))
- return 'u';
- if (t == typeid(unsigned long long))
- return 'u';
- if (t == typeid(unsigned int))
- return 'u';
-
- if (t == typeid(bool))
- return 'b';
-
- if (t == typeid(std::complex<float>))
- return 'c';
- if (t == typeid(std::complex<double>))
- return 'c';
- if (t == typeid(std::complex<long double>))
- return 'c';
-
- else
- return '?';
-}
-
-template<> std::vector<char> &cnpy::operator+=(std::vector<char> &lhs, const std::string rhs)
-{
- lhs.insert(lhs.end(), rhs.begin(), rhs.end());
- return lhs;
-}
-
-template<> std::vector<char> &cnpy::operator+=(std::vector<char> &lhs, const char *rhs)
-{
- // write in little endian
- size_t len = strlen(rhs);
- lhs.reserve(len);
- for (size_t byte = 0; byte < len; byte++) {
- lhs.push_back(rhs[byte]);
- }
- return lhs;
-}
-
-void cnpy::parse_npy_header(unsigned char *buffer,
- size_t &word_size,
- std::vector<size_t> &shape,
- bool &fortran_order)
-{
- // std::string magic_string(buffer,6);
- uint8_t major_version = *reinterpret_cast<uint8_t *>(buffer + 6);
- uint8_t minor_version = *reinterpret_cast<uint8_t *>(buffer + 7);
- uint16_t header_len = *reinterpret_cast<uint16_t *>(buffer + 8);
- std::string header(reinterpret_cast<char *>(buffer + 9), header_len);
-
- size_t loc1, loc2;
-
- // fortran order
- loc1 = header.find("fortran_order") + 16;
- fortran_order = (header.substr(loc1, 4) == "True" ? true : false);
-
- // shape
- loc1 = header.find("(");
- loc2 = header.find(")");
-
- std::regex num_regex("[0-9][0-9]*");
- std::smatch sm;
- shape.clear();
-
- std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1);
- while (std::regex_search(str_shape, sm, num_regex)) {
- shape.push_back(std::stoi(sm[0].str()));
- str_shape = sm.suffix().str();
- }
-
- // endian, word size, data type
- // byte order code | stands for not applicable.
- // not sure when this applies except for byte array
- loc1 = header.find("descr") + 9;
- bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
- assert(littleEndian);
-
- // char type = header[loc1+1];
- // assert(type == map_type(T));
-
- std::string str_ws = header.substr(loc1 + 2);
- loc2 = str_ws.find("'");
- word_size = atoi(str_ws.substr(0, loc2).c_str());
-}
-
-void cnpy::parse_npy_header(FILE *fp,
- size_t &word_size,
- std::vector<size_t> &shape,
- bool &fortran_order)
-{
- char buffer[256];
- size_t res = fread(buffer, sizeof(char), 11, fp);
- if (res != 11)
- throw std::runtime_error("parse_npy_header: failed fread");
- std::string header = fgets(buffer, 256, fp);
- assert(header[header.size() - 1] == '\n');
-
- size_t loc1, loc2;
-
- // fortran order
- loc1 = header.find("fortran_order");
- if (loc1 == std::string::npos)
- throw std::runtime_error("parse_npy_header: failed to find header keyword: 'fortran_order'");
- loc1 += 16;
- fortran_order = (header.substr(loc1, 4) == "True" ? true : false);
-
- // shape
- loc1 = header.find("(");
- loc2 = header.find(")");
- if (loc1 == std::string::npos || loc2 == std::string::npos)
- throw std::runtime_error("parse_npy_header: failed to find header keyword: '(' or ')'");
-
- std::regex num_regex("[0-9][0-9]*");
- std::smatch sm;
- shape.clear();
-
- std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1);
- while (std::regex_search(str_shape, sm, num_regex)) {
- shape.push_back(std::stoi(sm[0].str()));
- str_shape = sm.suffix().str();
- }
-
- // endian, word size, data type
- // byte order code | stands for not applicable.
- // not sure when this applies except for byte array
- loc1 = header.find("descr");
- if (loc1 == std::string::npos)
- throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'");
- loc1 += 9;
- bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
- assert(littleEndian);
-
- // char type = header[loc1+1];
- // assert(type == map_type(T));
-
- std::string str_ws = header.substr(loc1 + 2);
- loc2 = str_ws.find("'");
- word_size = atoi(str_ws.substr(0, loc2).c_str());
-}
-
-void cnpy::parse_zip_footer(FILE *fp,
- uint16_t &nrecs,
- size_t &global_header_size,
- size_t &global_header_offset)
-{
- std::vector<char> footer(22);
- fseek(fp, -22, SEEK_END);
- size_t res = fread(&footer[0], sizeof(char), 22, fp);
- if (res != 22)
- throw std::runtime_error("parse_zip_footer: failed fread");
-
- uint16_t disk_no, disk_start, nrecs_on_disk, comment_len;
- disk_no = *(uint16_t *)&footer[4];
- disk_start = *(uint16_t *)&footer[6];
- nrecs_on_disk = *(uint16_t *)&footer[8];
- nrecs = *(uint16_t *)&footer[10];
- global_header_size = *(uint32_t *)&footer[12];
- global_header_offset = *(uint32_t *)&footer[16];
- comment_len = *(uint16_t *)&footer[20];
-
- assert(disk_no == 0);
- assert(disk_start == 0);
- assert(nrecs_on_disk == nrecs);
- assert(comment_len == 0);
-}
-
-cnpy::NpyArray load_the_npy_file(FILE *fp)
-{
- std::vector<size_t> shape;
- size_t word_size;
- bool fortran_order;
- cnpy::parse_npy_header(fp, word_size, shape, fortran_order);
-
- cnpy::NpyArray arr(shape, word_size, fortran_order);
- size_t nread = fread(arr.data<char>(), 1, arr.num_bytes(), fp);
- if (nread != arr.num_bytes())
- throw std::runtime_error("load_the_npy_file: failed fread");
- return arr;
-}
-
-cnpy::NpyArray load_the_npz_array(FILE *fp, uint32_t compr_bytes, uint32_t uncompr_bytes)
-{
-
- std::vector<unsigned char> buffer_compr(compr_bytes);
- std::vector<unsigned char> buffer_uncompr(uncompr_bytes);
- size_t nread = fread(&buffer_compr[0], 1, compr_bytes, fp);
- if (nread != compr_bytes)
- throw std::runtime_error("load_the_npy_file: failed fread");
-
- int err;
- z_stream d_stream;
-
- d_stream.zalloc = Z_NULL;
- d_stream.zfree = Z_NULL;
- d_stream.opaque = Z_NULL;
- d_stream.avail_in = 0;
- d_stream.next_in = Z_NULL;
- err = inflateInit2(&d_stream, -MAX_WBITS);
-
- d_stream.avail_in = compr_bytes;
- d_stream.next_in = &buffer_compr[0];
- d_stream.avail_out = uncompr_bytes;
- d_stream.next_out = &buffer_uncompr[0];
-
- err = inflate(&d_stream, Z_FINISH);
- err = inflateEnd(&d_stream);
-
- std::vector<size_t> shape;
- size_t word_size;
- bool fortran_order;
- cnpy::parse_npy_header(&buffer_uncompr[0], word_size, shape, fortran_order);
-
- cnpy::NpyArray array(shape, word_size, fortran_order);
-
- size_t offset = uncompr_bytes - array.num_bytes();
- memcpy(array.data<unsigned char>(), &buffer_uncompr[0] + offset, array.num_bytes());
-
- return array;
-}
-
-cnpy::npz_t cnpy::npz_load(std::string fname)
-{
- FILE *fp = fopen(fname.c_str(), "rb");
-
- if (!fp) {
- throw std::runtime_error("npz_load: Error! Unable to open file " + fname + "!");
- }
-
- cnpy::npz_t arrays;
-
- while (1) {
- std::vector<char> local_header(30);
- size_t headerres = fread(&local_header[0], sizeof(char), 30, fp);
- if (headerres != 30)
- throw std::runtime_error("npz_load: failed fread");
-
- // if we've reached the global header, stop reading
- if (local_header[2] != 0x03 || local_header[3] != 0x04)
- break;
-
- // read in the variable name
- uint16_t name_len = *(uint16_t *)&local_header[26];
- std::string varname(name_len, ' ');
- size_t vname_res = fread(&varname[0], sizeof(char), name_len, fp);
- if (vname_res != name_len)
- throw std::runtime_error("npz_load: failed fread");
-
- // erase the lagging .npy
- varname.erase(varname.end() - 4, varname.end());
-
- // read in the extra field
- uint16_t extra_field_len = *(uint16_t *)&local_header[28];
- if (extra_field_len > 0) {
- std::vector<char> buff(extra_field_len);
- size_t efield_res = fread(&buff[0], sizeof(char), extra_field_len, fp);
- if (efield_res != extra_field_len)
- throw std::runtime_error("npz_load: failed fread");
- }
-
- uint16_t compr_method = *reinterpret_cast<uint16_t *>(&local_header[0] + 8);
- uint32_t compr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0] + 18);
- uint32_t uncompr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0] + 22);
-
- if (compr_method == 0) {
- arrays[varname] = load_the_npy_file(fp);
- }
- else {
- arrays[varname] = load_the_npz_array(fp, compr_bytes, uncompr_bytes);
- }
- }
-
- fclose(fp);
- return arrays;
-}
-
-cnpy::NpyArray cnpy::npz_load(std::string fname, std::string varname)
-{
- FILE *fp = fopen(fname.c_str(), "rb");
-
- if (!fp)
- throw std::runtime_error("npz_load: Unable to open file " + fname);
-
- while (1) {
- std::vector<char> local_header(30);
- size_t header_res = fread(&local_header[0], sizeof(char), 30, fp);
- if (header_res != 30)
- throw std::runtime_error("npz_load: failed fread");
-
- // if we've reached the global header, stop reading
- if (local_header[2] != 0x03 || local_header[3] != 0x04)
- break;
-
- // read in the variable name
- uint16_t name_len = *(uint16_t *)&local_header[26];
- std::string vname(name_len, ' ');
- size_t vname_res = fread(&vname[0], sizeof(char), name_len, fp);
- if (vname_res != name_len)
- throw std::runtime_error("npz_load: failed fread");
- vname.erase(vname.end() - 4, vname.end()); // erase the lagging .npy
-
- // read in the extra field
- uint16_t extra_field_len = *(uint16_t *)&local_header[28];
- fseek(fp, extra_field_len, SEEK_CUR); // skip past the extra field
-
- uint16_t compr_method = *reinterpret_cast<uint16_t *>(&local_header[0] + 8);
- uint32_t compr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0] + 18);
- uint32_t uncompr_bytes = *reinterpret_cast<uint32_t *>(&local_header[0] + 22);
-
- if (vname == varname) {
- NpyArray array = (compr_method == 0) ? load_the_npy_file(fp) :
- load_the_npz_array(fp, compr_bytes, uncompr_bytes);
- fclose(fp);
- return array;
- }
- else {
- // skip past the data
- // uint32_t size = *(uint32_t*) &local_header[22];
- uint32_t size = *(uint32_t *)&local_header[18]; // using index 18 instead of 22 enables
- // support for compressed data
- fseek(fp, size, SEEK_CUR);
- }
- }
-
- fclose(fp);
-
- // if we get here, we haven't found the variable in the file
- throw std::runtime_error("npz_load: Variable name " + varname + " not found in " + fname);
-}
-
-cnpy::NpyArray cnpy::npy_load(std::string fname)
-{
-
- FILE *fp = fopen(fname.c_str(), "rb");
-
- if (!fp)
- throw std::runtime_error("npy_load: Unable to open file " + fname);
-
- NpyArray arr = load_the_npy_file(fp);
-
- fclose(fp);
- return arr;
-}
diff --git a/extern/mantaflow/dependencies/cnpy/cnpy.h b/extern/mantaflow/dependencies/cnpy/cnpy.h
deleted file mode 100644
index e4b6365cb6f..00000000000
--- a/extern/mantaflow/dependencies/cnpy/cnpy.h
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright (C) 2011 Carl Rogers
-// Released under MIT License
-// license available in LICENSE file, or at http://www.opensource.org/licenses/mit-license.php
-
-#ifndef LIBCNPY_H_
-#define LIBCNPY_H_
-
-#include <string>
-#include <stdexcept>
-#include <sstream>
-#include <vector>
-#include <cstdio>
-#include <typeinfo>
-#include <iostream>
-#include <cassert>
-#include <zlib.h>
-#include <map>
-#include <memory>
-#include <stdint.h>
-#include <numeric>
-
-namespace cnpy {
-
-struct NpyArray {
- NpyArray(const std::vector<size_t> &_shape, size_t _word_size, bool _fortran_order)
- : shape(_shape), word_size(_word_size), fortran_order(_fortran_order)
- {
- num_vals = 1;
- for (size_t i = 0; i < shape.size(); i++)
- num_vals *= shape[i];
- data_holder = std::shared_ptr<std::vector<char>>(new std::vector<char>(num_vals * word_size));
- }
-
- NpyArray() : shape(0), word_size(0), fortran_order(0), num_vals(0)
- {
- }
-
- template<typename T> T *data()
- {
- return reinterpret_cast<T *>(&(*data_holder)[0]);
- }
-
- template<typename T> const T *data() const
- {
- return reinterpret_cast<T *>(&(*data_holder)[0]);
- }
-
- template<typename T> std::vector<T> as_vec() const
- {
- const T *p = data<T>();
- return std::vector<T>(p, p + num_vals);
- }
-
- size_t num_bytes() const
- {
- return data_holder->size();
- }
-
- std::shared_ptr<std::vector<char>> data_holder;
- std::vector<size_t> shape;
- size_t word_size;
- bool fortran_order;
- size_t num_vals;
-};
-
-using npz_t = std::map<std::string, NpyArray>;
-
-char BigEndianTest();
-char map_type(const std::type_info &t);
-template<typename T> std::vector<char> create_npy_header(const std::vector<size_t> &shape);
-void parse_npy_header(FILE *fp,
- size_t &word_size,
- std::vector<size_t> &shape,
- bool &fortran_order);
-void parse_npy_header(unsigned char *buffer,
- size_t &word_size,
- std::vector<size_t> &shape,
- bool &fortran_order);
-void parse_zip_footer(FILE *fp,
- uint16_t &nrecs,
- size_t &global_header_size,
- size_t &global_header_offset);
-npz_t npz_load(std::string fname);
-NpyArray npz_load(std::string fname, std::string varname);
-NpyArray npy_load(std::string fname);
-
-template<typename T> std::vector<char> &operator+=(std::vector<char> &lhs, const T rhs)
-{
- // write in little endian
- for (size_t byte = 0; byte < sizeof(T); byte++) {
- char val = *((char *)&rhs + byte);
- lhs.push_back(val);
- }
- return lhs;
-}
-
-template<> std::vector<char> &operator+=(std::vector<char> &lhs, const std::string rhs);
-template<> std::vector<char> &operator+=(std::vector<char> &lhs, const char *rhs);
-
-template<typename T>
-void npy_save(std::string fname,
- const T *data,
- const std::vector<size_t> shape,
- std::string mode = "w")
-{
- FILE *fp = NULL;
- std::vector<size_t> true_data_shape; // if appending, the shape of existing + new data
-
- if (mode == "a")
- fp = fopen(fname.c_str(), "r+b");
-
- if (fp) {
- // file exists. we need to append to it. read the header, modify the array size
- size_t word_size;
- bool fortran_order;
- parse_npy_header(fp, word_size, true_data_shape, fortran_order);
- assert(!fortran_order);
-
- if (word_size != sizeof(T)) {
- std::cout << "libnpy error: " << fname << " has word size " << word_size
- << " but npy_save appending data sized " << sizeof(T) << "\n";
- assert(word_size == sizeof(T));
- }
- if (true_data_shape.size() != shape.size()) {
- std::cout << "libnpy error: npy_save attempting to append misdimensioned data to " << fname
- << "\n";
- assert(true_data_shape.size() != shape.size());
- }
-
- for (size_t i = 1; i < shape.size(); i++) {
- if (shape[i] != true_data_shape[i]) {
- std::cout << "libnpy error: npy_save attempting to append misshaped data to " << fname
- << "\n";
- assert(shape[i] == true_data_shape[i]);
- }
- }
- true_data_shape[0] += shape[0];
- }
- else {
- fp = fopen(fname.c_str(), "wb");
- true_data_shape = shape;
- }
-
- std::vector<char> header = create_npy_header<T>(true_data_shape);
- size_t nels = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<size_t>());
-
- fseek(fp, 0, SEEK_SET);
- fwrite(&header[0], sizeof(char), header.size(), fp);
- fseek(fp, 0, SEEK_END);
- fwrite(data, sizeof(T), nels, fp);
- fclose(fp);
-}
-
-template<typename T>
-void npz_save(std::string zipname,
- std::string fname,
- const T *data,
- const std::vector<size_t> &shape,
- std::string mode = "w")
-{
- // first, append a .npy to the fname
- fname += ".npy";
-
- // now, on with the show
- FILE *fp = NULL;
- uint16_t nrecs = 0;
- size_t global_header_offset = 0;
- std::vector<char> global_header;
-
- if (mode == "a")
- fp = fopen(zipname.c_str(), "r+b");
-
- if (fp) {
- // zip file exists. we need to add a new npy file to it.
- // first read the footer. this gives us the offset and size of the global header
- // then read and store the global header.
- // below, we will write the the new data at the start of the global header then append the
- // global header and footer below it
- size_t global_header_size;
- parse_zip_footer(fp, nrecs, global_header_size, global_header_offset);
- fseek(fp, global_header_offset, SEEK_SET);
- global_header.resize(global_header_size);
- size_t res = fread(&global_header[0], sizeof(char), global_header_size, fp);
- if (res != global_header_size) {
- throw std::runtime_error("npz_save: header read error while adding to existing zip");
- }
- fseek(fp, global_header_offset, SEEK_SET);
- }
- else {
- fp = fopen(zipname.c_str(), "wb");
- }
-
- std::vector<char> npy_header = create_npy_header<T>(shape);
-
- size_t nels = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<size_t>());
- size_t nbytes = nels * sizeof(T) + npy_header.size();
-
- // get the CRC of the data to be added
- uint32_t crc = crc32(0L, (uint8_t *)&npy_header[0], npy_header.size());
- crc = crc32(crc, (uint8_t *)data, nels * sizeof(T));
-
- // build the local header
- std::vector<char> local_header;
- local_header += "PK"; // first part of sig
- local_header += (uint16_t)0x0403; // second part of sig
- local_header += (uint16_t)20; // min version to extract
- local_header += (uint16_t)0; // general purpose bit flag
- local_header += (uint16_t)0; // compression method
- local_header += (uint16_t)0; // file last mod time
- local_header += (uint16_t)0; // file last mod date
- local_header += (uint32_t)crc; // crc
- local_header += (uint32_t)nbytes; // compressed size
- local_header += (uint32_t)nbytes; // uncompressed size
- local_header += (uint16_t)fname.size(); // fname length
- local_header += (uint16_t)0; // extra field length
- local_header += fname;
-
- // build global header
- global_header += "PK"; // first part of sig
- global_header += (uint16_t)0x0201; // second part of sig
- global_header += (uint16_t)20; // version made by
- global_header.insert(global_header.end(), local_header.begin() + 4, local_header.begin() + 30);
- global_header += (uint16_t)0; // file comment length
- global_header += (uint16_t)0; // disk number where file starts
- global_header += (uint16_t)0; // internal file attributes
- global_header += (uint32_t)0; // external file attributes
- global_header += (uint32_t)
- global_header_offset; // relative offset of local file header, since it begins where the
- // global header used to begin
- global_header += fname;
-
- // build footer
- std::vector<char> footer;
- footer += "PK"; // first part of sig
- footer += (uint16_t)0x0605; // second part of sig
- footer += (uint16_t)0; // number of this disk
- footer += (uint16_t)0; // disk where footer starts
- footer += (uint16_t)(nrecs + 1); // number of records on this disk
- footer += (uint16_t)(nrecs + 1); // total number of records
- footer += (uint32_t)global_header.size(); // nbytes of global headers
- footer += (uint32_t)(global_header_offset + nbytes +
- local_header.size()); // offset of start of global headers, since global
- // header now starts after newly written array
- footer += (uint16_t)0; // zip file comment length
-
- // write everything
- fwrite(&local_header[0], sizeof(char), local_header.size(), fp);
- fwrite(&npy_header[0], sizeof(char), npy_header.size(), fp);
- fwrite(data, sizeof(T), nels, fp);
- fwrite(&global_header[0], sizeof(char), global_header.size(), fp);
- fwrite(&footer[0], sizeof(char), footer.size(), fp);
- fclose(fp);
-}
-
-template<typename T>
-void npy_save(std::string fname, const std::vector<T> data, std::string mode = "w")
-{
- std::vector<size_t> shape;
- shape.push_back(data.size());
- npy_save(fname, &data[0], shape, mode);
-}
-
-template<typename T>
-void npz_save(std::string zipname,
- std::string fname,
- const std::vector<T> data,
- std::string mode = "w")
-{
- std::vector<size_t> shape;
- shape.push_back(data.size());
- npz_save(zipname, fname, &data[0], shape, mode);
-}
-
-template<typename T> std::vector<char> create_npy_header(const std::vector<size_t> &shape)
-{
-
- std::vector<char> dict;
- dict += "{'descr': '";
- dict += BigEndianTest();
- dict += map_type(typeid(T));
- dict += std::to_string(sizeof(T));
- dict += "', 'fortran_order': False, 'shape': (";
- dict += std::to_string(shape[0]);
- for (size_t i = 1; i < shape.size(); i++) {
- dict += ", ";
- dict += std::to_string(shape[i]);
- }
- if (shape.size() == 1)
- dict += ",";
- dict += "), }";
- // pad with spaces so that preamble+dict is modulo 16 bytes. preamble is 10 bytes. dict needs to
- // end with \n
- int remainder = 16 - (10 + dict.size()) % 16;
- dict.insert(dict.end(), remainder, ' ');
- dict.back() = '\n';
-
- std::vector<char> header;
- header += (char)0x93;
- header += "NUMPY";
- header += (char)0x01; // major version of numpy format
- header += (char)0x00; // minor version of numpy format
- header += (uint16_t)dict.size();
- header.insert(header.end(), dict.begin(), dict.end());
-
- return header;
-}
-
-} // namespace cnpy
-
-#endif
diff --git a/extern/mantaflow/preprocessed/fileio/iogrids.cpp b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
index e2550d6db8b..825ce0ae8b5 100644
--- a/extern/mantaflow/preprocessed/fileio/iogrids.cpp
+++ b/extern/mantaflow/preprocessed/fileio/iogrids.cpp
@@ -27,7 +27,10 @@ extern "C" {
}
#endif
-#include "cnpy.h"
+#if NO_CNPY != 1
+# include "cnpy.h"
+#endif
+
#include "mantaio.h"
#include "grid.h"
#include "vector4d.h"
@@ -965,12 +968,16 @@ int readGrid4dUni(
};
void readGrid4dUniCleanup(void **fileHandle)
{
+#if NO_ZLIB != 1
gzFile gzf = NULL;
if (fileHandle) {
gzf = (gzFile)(*fileHandle);
gzclose(gzf);
*fileHandle = NULL;
}
+#else
+ debMsg("file format not supported without zlib", 1);
+#endif
}
template<class T> int writeGrid4dRaw(const string &name, Grid4d<T> *grid)
@@ -1021,15 +1028,13 @@ template<class T> int readGrid4dRaw(const string &name, Grid4d<T> *grid)
template<class T> int writeGridNumpy(const string &name, Grid<T> *grid)
{
-#if NO_ZLIB == 1
- debMsg("file format not supported without zlib", 1);
- return 0;
-#endif
+
#if FLOATINGPOINT_PRECISION != 1
errMsg("writeGridNumpy: Double precision not yet supported");
return 0;
#endif
+#if NO_CNPY != 1
// find suffix to differentiate between npy <-> npz , TODO: check for actual "npy" string
std::string::size_type idx;
bool bUseNpz = false;
@@ -1075,19 +1080,21 @@ template<class T> int writeGridNumpy(const string &name, Grid<T> *grid)
cnpy::npy_save(name, &grid[0], shape, "w");
}
return 1;
-};
+#else
+ debMsg("file format not supported without cnpy", 1);
+ return 0;
+#endif
+}
template<class T> int readGridNumpy(const string &name, Grid<T> *grid)
{
-#if NO_ZLIB == 1
- debMsg("file format not supported without zlib", 1);
- return 0;
-#endif
+
#if FLOATINGPOINT_PRECISION != 1
errMsg("readGridNumpy: Double precision not yet supported");
return 0;
#endif
+#if NO_CNPY != 1
// find suffix to differentiate between npy <-> npz
std::string::size_type idx;
bool bUseNpz = false;
@@ -1144,7 +1151,11 @@ template<class T> int readGridNumpy(const string &name, Grid<T> *grid)
gridArr.data<T>(),
sizeof(T) * grid->getSizeX() * grid->getSizeY() * grid->getSizeZ());
return 1;
-};
+#else
+ debMsg("file format not supported without cnpy", 1);
+ return 0;
+#endif
+}
int writeGridsNumpy(const string &name, std::vector<PbClass *> *grids)
{
@@ -1163,13 +1174,12 @@ void getNpzFileSize(
const string &name, int &x, int &y, int &z, int *t = NULL, std::string *info = NULL)
{
x = y = z = 0;
-#if NO_ZLIB != 1
- debMsg("file format not supported without zlib", 1);
- return;
-#endif
+
#if FLOATINGPOINT_PRECISION != 1
errMsg("getNpzFileSize: Double precision not yet supported");
#endif
+
+#if NO_CNPY != 1
// find suffix to differentiate between npy <-> npz
cnpy::NpyArray gridArr;
cnpy::npz_t fNpz = cnpy::npz_load(name);
@@ -1180,6 +1190,9 @@ void getNpzFileSize(
x = gridArr.shape[2];
if (t)
(*t) = 0; // unused for now
+#else
+ debMsg("file format not supported without cnpy", 1);
+#endif
}
Vec3 getNpzFileSize(const string &name)
{
diff --git a/extern/mantaflow/preprocessed/fileio/ioutil.cpp b/extern/mantaflow/preprocessed/fileio/ioutil.cpp
index cc63cf87ac1..cf40d71fcc4 100644
--- a/extern/mantaflow/preprocessed/fileio/ioutil.cpp
+++ b/extern/mantaflow/preprocessed/fileio/ioutil.cpp
@@ -26,17 +26,18 @@
extern "C" {
# include <zlib.h>
}
+#endif
-# if defined(WIN32) || defined(_WIN32)
-# include <windows.h>
-# include <string>
-# endif
+#if defined(WIN32) || defined(_WIN32)
+# include <windows.h>
+# include <string>
+#endif
using namespace std;
namespace Manta {
-# if defined(WIN32) || defined(_WIN32)
+#if defined(WIN32) || defined(_WIN32)
static wstring stringToWstring(const char *str)
{
const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), NULL, 0);
@@ -44,10 +45,11 @@ static wstring stringToWstring(const char *str)
MultiByteToWideChar(CP_UTF8, 0, str, strlen(str), &strWide[0], length_wc);
return strWide;
}
-# endif // WIN32==1
+#endif // WIN32==1
void *safeGzopen(const char *filename, const char *mode)
{
+#if NO_ZLIB != 1
gzFile gzfile;
# if defined(WIN32) || defined(_WIN32)
@@ -58,8 +60,11 @@ void *safeGzopen(const char *filename, const char *mode)
# endif
return gzfile;
-}
+#else
+ debMsg("safeGzopen not supported without zlib", 1);
+ return nullptr;
#endif // NO_ZLIB != 1
+}
#if defined(OPENVDB)
// Convert from OpenVDB value to Manta value.
@@ -109,4 +114,4 @@ template<> void convertTo(openvdb::Vec3s *out, Vec3 &in)
}
#endif // OPENVDB==1
-} // namespace
+} // namespace Manta
diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h
index 67cede606da..5763d31f7fb 100644
--- a/extern/mantaflow/preprocessed/gitinfo.h
+++ b/extern/mantaflow/preprocessed/gitinfo.h
@@ -1,3 +1,3 @@
-#define MANTA_GIT_VERSION "commit 1881a368ed10797e84b470645d7c738ef75ad6d8"
+#define MANTA_GIT_VERSION "commit 78ecf1940765e45d8fc15b3304a622785a84939e"
diff --git a/extern/mantaflow/preprocessed/mesh.cpp b/extern/mantaflow/preprocessed/mesh.cpp
index c99d621d2bd..7a27b88ece7 100644
--- a/extern/mantaflow/preprocessed/mesh.cpp
+++ b/extern/mantaflow/preprocessed/mesh.cpp
@@ -1371,11 +1371,11 @@ void Mesh::updateDataFields()
for (size_t i = 0; i < mNodes.size(); ++i) {
Vec3 pos = mNodes[i].pos;
for (IndexInt md = 0; md < (IndexInt)mMdataReal.size(); ++md)
- mMdataReal[md]->initNewValue(i, mNodes[i].pos);
+ mMdataReal[md]->initNewValue(i, pos);
for (IndexInt md = 0; md < (IndexInt)mMdataVec3.size(); ++md)
- mMdataVec3[md]->initNewValue(i, mNodes[i].pos);
+ mMdataVec3[md]->initNewValue(i, pos);
for (IndexInt md = 0; md < (IndexInt)mMdataInt.size(); ++md)
- mMdataInt[md]->initNewValue(i, mNodes[i].pos);
+ mMdataInt[md]->initNewValue(i, pos);
}
}
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 8a074d23db9..af6d4b1cd29 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -367,7 +367,7 @@ def enable(module_name, *, default_set=False, persistent=False, handle_error=Non
if mod.bl_info.get("blender", (0, 0, 0)) < (2, 80, 0):
if _bpy.app.debug:
- print(f"Warning: Add-on '{module_name:s}' was not upgraded for 2.80, ignoring")
+ print("Warning: Add-on '%s' was not upgraded for 2.80, ignoring" % module_name)
return None
# 2) Try register collected modules.
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 19450bb38ec..8a67a598ccd 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -789,7 +789,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False):
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
if cls is None:
- raise Exception(f"Space type {space_type!r} has no toolbar")
+ raise Exception("Space type %r has no toolbar" % space_type)
tools = cls._tools[context_mode]
# First sanity check
@@ -799,9 +799,9 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False):
if item is not None
}
if not issubclass(tool_cls, WorkSpaceTool):
- raise Exception(f"Expected WorkSpaceTool subclass, not {type(tool_cls)!r}")
+ raise Exception("Expected WorkSpaceTool subclass, not %r" % type(tool_cls))
if tool_cls.bl_idname in tools_id:
- raise Exception(f"Tool {tool_cls.bl_idname!r} already exists!")
+ raise Exception("Tool %r already exists!" % tool_cls.bl_idname)
del tools_id, WorkSpaceTool
# Convert the class into a ToolDef.
@@ -900,7 +900,7 @@ def unregister_tool(tool_cls):
from bl_ui.space_toolsystem_common import ToolSelectPanelHelper
cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type)
if cls is None:
- raise Exception(f"Space type {space_type!r} has no toolbar")
+ raise Exception("Space type %r has no toolbar" % space_type)
tools = cls._tools[context_mode]
tool_def = tool_cls._bl_tool
@@ -952,7 +952,7 @@ def unregister_tool(tool_cls):
break
if not changed:
- raise Exception(f"Unable to remove {tool_cls!r}")
+ raise Exception("Unable to remove %r" % tool_cls)
del tool_cls._bl_tool
keymap_data = tool_def.keymap
@@ -963,7 +963,7 @@ def unregister_tool(tool_cls):
for kc in (keyconfigs.default, keyconfigs.addon):
km = kc.keymaps.get(keymap_data[0])
if km is None:
- print(f"Warning keymap {keymap_data[0]!r} not found in {kc.name!r}!")
+ print("Warning keymap %r not found in %r!" % (keymap_data[0], kc.name))
else:
kc.keymaps.remove(km)
diff --git a/release/scripts/modules/bpy/utils/previews.py b/release/scripts/modules/bpy/utils/previews.py
index 7f337677635..511df853d66 100644
--- a/release/scripts/modules/bpy/utils/previews.py
+++ b/release/scripts/modules/bpy/utils/previews.py
@@ -85,7 +85,7 @@ class ImagePreviewCollection(dict):
def new(self, name):
if name in self:
- raise KeyError(f"key {name!r} already exists")
+ raise KeyError("key %r already exists" % name)
p = self[name] = _utils_previews.new(
self._gen_key(name))
return p
@@ -93,7 +93,7 @@ class ImagePreviewCollection(dict):
def load(self, name, path, path_type, force_reload=False):
if name in self:
- raise KeyError(f"key {name!r} already exists")
+ raise KeyError("key %r already exists" % name)
p = self[name] = _utils_previews.load(
self._gen_key(name), path, path_type, force_reload)
return p
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 8a9d3052a2e..b8f6ca0a5a0 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -749,6 +749,9 @@ def km_property_editor(_params):
# ShaderFX panels
("object.shaderfx_remove", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}),
("object.shaderfx_remove", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),
+ # Constraint panels
+ ("constraint.delete", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}),
+ ("constraint.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),
])
return keymap
diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
index 255852d3b26..6c29c07c62e 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -143,10 +143,10 @@ class PlayRenderedAnim(Operator):
]
cmd.extend(opts)
elif preset == 'FRAMECYCLER':
- opts = [file, f"{scene.frame_start:d}-{scene.frame_end:d}"]
+ opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)]
cmd.extend(opts)
elif preset == 'RV':
- opts = ["-fps", str(rd.fps), "-play", f"[ {file:s} ]"]
+ opts = ["-fps", str(rd.fps), "-play", "[ %s ]" % file]
cmd.extend(opts)
elif preset == 'MPLAYER':
opts = []
@@ -156,7 +156,7 @@ class PlayRenderedAnim(Operator):
opts += [
("mf://" + file.replace("#", "?")),
"-mf",
- f"fps={fps_final:4f}"
+ "fps=%.4f" % fps_final,
]
opts += ["-loop", "0", "-really-quiet", "-fs"]
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 032a4a612c8..43883ff0f3a 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1238,7 +1238,7 @@ class CLIP_MT_view_zoom(Menu):
layout.operator(
"clip.view_zoom_ratio",
- text=iface_(f"Zoom {a:d}:{b:d}"),
+ text=iface_("Zoom %d:%d") % (a, b),
translate=False,
).ratio = a / b
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 5392ed9cc25..66c98b81e0e 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -994,7 +994,7 @@ class USERPREF_PT_theme_bone_color_sets(ThemePanel, CenterAlignMixIn, Panel):
layout.use_property_split = True
for i, ui in enumerate(theme.bone_color_sets, 1):
- layout.label(text=iface_(f"Color Set {i:d}"), translate=False)
+ layout.label(text=iface_("Color Set %d") % i, translate=False)
flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index fe80a0c1c36..749e92bdcf7 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1100,7 +1100,7 @@ class VIEW3D_MT_mirror(Menu):
for (space_name, space_id) in (("Global", 'GLOBAL'), ("Local", 'LOCAL')):
for axis_index, axis_name in enumerate("XYZ"):
- props = layout.operator("transform.mirror", text=f"{axis_name!s} {space_name!s}")
+ props = layout.operator("transform.mirror", text="%s %s" % (axis_name, space_name))
props.constraint_axis[axis_index] = True
props.orient_type = space_id
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index acd4c75befd..1d01436c7e4 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -106,18 +106,18 @@ typedef struct bNodeSocketTemplate {
* However, achieving this requires quite a few changes currently. */
#ifdef __cplusplus
namespace blender {
-namespace bke {
+namespace nodes {
class SocketMFNetworkBuilder;
class NodeMFNetworkBuilder;
-} // namespace bke
+} // namespace nodes
namespace fn {
class MFDataType;
}
} // namespace blender
-using NodeExpandInMFNetworkFunction = void (*)(blender::bke::NodeMFNetworkBuilder &builder);
+using NodeExpandInMFNetworkFunction = void (*)(blender::nodes::NodeMFNetworkBuilder &builder);
using SocketGetMFDataTypeFunction = blender::fn::MFDataType (*)();
-using SocketExpandInMFNetworkFunction = void (*)(blender::bke::SocketMFNetworkBuilder &builder);
+using SocketExpandInMFNetworkFunction = void (*)(blender::nodes::SocketMFNetworkBuilder &builder);
#else
typedef void *NodeExpandInMFNetworkFunction;
diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h
index ff6aaa5e30e..36f4122f4dc 100644
--- a/source/blender/blenkernel/BKE_simulation.h
+++ b/source/blender/blenkernel/BKE_simulation.h
@@ -17,13 +17,15 @@
#ifndef __BKE_SIMULATION_H__
#define __BKE_SIMULATION_H__
+#include "DNA_simulation_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
struct Depsgraph;
struct Main;
-struct Simulation;
+struct Scene;
void *BKE_simulation_add(struct Main *bmain, const char *name);
@@ -31,6 +33,12 @@ void BKE_simulation_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Simulation *simulation);
+SimulationState *BKE_simulation_state_add(Simulation *simulation,
+ eSimulationStateType type,
+ const char *name);
+void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state);
+void BKE_simulation_state_remove_all(Simulation *simulation);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 30e6baf1a9d..800fa7d18ee 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -107,7 +107,6 @@ set(SRC
intern/customdata_file.c
intern/data_transfer.c
intern/deform.c
- intern/derived_node_tree.cc
intern/displist.c
intern/displist_tangent.c
intern/dynamicpaint.c
@@ -188,8 +187,6 @@ set(SRC
intern/multires_unsubdivide.c
intern/nla.c
intern/node.c
- intern/node_tree_multi_function.cc
- intern/node_tree_ref.cc
intern/object.c
intern/object_deform.c
intern/object_dupli.c
@@ -298,7 +295,6 @@ set(SRC
BKE_customdata_file.h
BKE_data_transfer.h
BKE_deform.h
- BKE_derived_node_tree.hh
BKE_displist.h
BKE_displist_tangent.h
BKE_duplilist.h
@@ -359,8 +355,6 @@ set(SRC
BKE_multires.h
BKE_nla.h
BKE_node.h
- BKE_node_tree_multi_function.hh
- BKE_node_tree_ref.hh
BKE_object.h
BKE_object_deform.h
BKE_object_facemap.h
@@ -443,7 +437,7 @@ set(LIB
bf_intern_opensubdiv # Uses stub when disabled.
bf_modifiers
bf_nodes
- bf_physics
+ bf_simulation
bf_rna
bf_shader_fx
)
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 831de084500..1ac987d130d 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -45,25 +45,22 @@
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
-#include "BKE_node_tree_multi_function.hh"
#include "BKE_pointcache.h"
#include "BKE_simulation.h"
+#include "NOD_node_tree_multi_function.hh"
#include "NOD_simulation.h"
#include "BLT_translation.h"
#include "FN_attributes_ref.hh"
-#include "FN_cpp_types.hh"
#include "FN_multi_function_network_evaluation.hh"
#include "FN_multi_function_network_optimization.hh"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-extern "C" {
-void WM_clipboard_text_set(const char *buf, bool selection);
-}
+#include "SIM_simulation_update.hh"
static void simulation_init_data(ID *id)
{
@@ -107,6 +104,58 @@ static void free_particle_simulation_state(ParticleSimulationState *state)
MEM_freeN(state);
}
+SimulationState *BKE_simulation_state_add(Simulation *simulation,
+ eSimulationStateType type,
+ const char *name)
+{
+ BLI_assert(simulation != nullptr);
+ BLI_assert(name != nullptr);
+
+ bool is_cow_simulation = DEG_is_evaluated_id(&simulation->id);
+
+ switch (type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN(sizeof(*state), AT);
+ state->head.type = SIM_STATE_TYPE_PARTICLES;
+ state->head.name = BLI_strdup(name);
+ CustomData_reset(&state->attributes);
+
+ if (!is_cow_simulation) {
+ state->point_cache = BKE_ptcache_add(&state->ptcaches);
+ }
+
+ BLI_addtail(&simulation->states, state);
+ return &state->head;
+ }
+ }
+
+ BLI_assert(false);
+ return nullptr;
+}
+
+void BKE_simulation_state_remove(Simulation *simulation, SimulationState *state)
+{
+ BLI_assert(simulation != nullptr);
+ BLI_assert(state != nullptr);
+ BLI_assert(BLI_findindex(&simulation->states, state) >= 0);
+
+ BLI_remlink(&simulation->states, state);
+ switch ((eSimulationStateType)state->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ free_particle_simulation_state((ParticleSimulationState *)state);
+ break;
+ }
+ }
+}
+
+void BKE_simulation_state_remove_all(Simulation *simulation)
+{
+ BLI_assert(simulation != nullptr);
+ while (!BLI_listbase_is_empty(&simulation->states)) {
+ BKE_simulation_state_remove(simulation, (SimulationState *)simulation->states.first);
+ }
+}
+
static void simulation_free_data(ID *id)
{
Simulation *simulation = (Simulation *)id;
@@ -119,14 +168,7 @@ static void simulation_free_data(ID *id)
simulation->nodetree = nullptr;
}
- LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- free_particle_simulation_state((ParticleSimulationState *)state);
- break;
- }
- }
- }
+ BKE_simulation_state_remove_all(simulation);
}
static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
@@ -164,651 +206,7 @@ void *BKE_simulation_add(Main *bmain, const char *name)
return simulation;
}
-namespace blender::bke {
-
-static void ensure_attributes_exist(ParticleSimulationState *state)
-{
- if (CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Position") == nullptr) {
- CustomData_add_layer_named(
- &state->attributes, CD_PROP_FLOAT3, CD_CALLOC, nullptr, state->tot_particles, "Position");
- }
- if (CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Velocity") == nullptr) {
- CustomData_add_layer_named(
- &state->attributes, CD_PROP_FLOAT3, CD_CALLOC, nullptr, state->tot_particles, "Velocity");
- }
- if (CustomData_get_layer_named(&state->attributes, CD_PROP_INT32, "ID") == nullptr) {
- CustomData_add_layer_named(
- &state->attributes, CD_PROP_INT32, CD_CALLOC, nullptr, state->tot_particles, "ID");
- }
-}
-
-static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow)
-{
- LISTBASE_FOREACH_MUTABLE (SimulationState *, state_cow, &simulation_cow->states) {
- switch ((eSimulationStateType)state_cow->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- BLI_remlink(&simulation_cow->states, state_cow);
- free_particle_simulation_state((ParticleSimulationState *)state_cow);
- break;
- }
- }
- }
- simulation_cow->current_frame = simulation_orig->current_frame;
-
- LISTBASE_FOREACH (SimulationState *, state_orig, &simulation_orig->states) {
- switch ((eSimulationStateType)state_orig->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state_orig = (ParticleSimulationState *)state_orig;
- ParticleSimulationState *particle_state_cow = (ParticleSimulationState *)MEM_callocN(
- sizeof(*particle_state_cow), AT);
- particle_state_cow->tot_particles = particle_state_orig->tot_particles;
- particle_state_cow->head.name = BLI_strdup(state_orig->name);
- CustomData_copy(&particle_state_orig->attributes,
- &particle_state_cow->attributes,
- CD_MASK_ALL,
- CD_DUPLICATE,
- particle_state_orig->tot_particles);
- BLI_addtail(&simulation_cow->states, particle_state_cow);
- break;
- }
- }
- }
-}
-
-static Map<const fn::MFOutputSocket *, std::string> deduplicate_attribute_nodes(
- fn::MFNetwork &network, MFNetworkTreeMap &network_map, const DerivedNodeTree &tree)
-{
- Span<const DNode *> attribute_dnodes = tree.nodes_by_type("SimulationNodeParticleAttribute");
- uint amount = attribute_dnodes.size();
- if (amount == 0) {
- return {};
- }
-
- Vector<fn::MFInputSocket *> name_sockets;
- for (const DNode *dnode : attribute_dnodes) {
- fn::MFInputSocket &name_socket = network_map.lookup_dummy(dnode->input(0));
- name_sockets.append(&name_socket);
- }
-
- fn::MFNetworkEvaluator network_fn{{}, name_sockets.as_span()};
-
- fn::MFParamsBuilder params{network_fn, 1};
-
- Array<std::string> attribute_names{amount, NoInitialization()};
- for (uint i : IndexRange(amount)) {
- params.add_uninitialized_single_output(
- fn::GMutableSpan(fn::CPPType_string, attribute_names.data() + i, 1));
- }
-
- fn::MFContextBuilder context;
- /* Todo: Check that the names don't depend on dummy nodes. */
- network_fn.call({0}, params, context);
-
- Map<std::pair<std::string, fn::MFDataType>, Vector<fn::MFNode *>>
- attribute_nodes_by_name_and_type;
- for (uint i : IndexRange(amount)) {
- attribute_nodes_by_name_and_type
- .lookup_or_add_default({attribute_names[i], name_sockets[i]->node().output(0).data_type()})
- .append(&name_sockets[i]->node());
- }
-
- Map<const fn::MFOutputSocket *, std::string> attribute_inputs;
- for (auto item : attribute_nodes_by_name_and_type.items()) {
- StringRef attribute_name = item.key.first;
- fn::MFDataType data_type = item.key.second;
- Span<fn::MFNode *> nodes = item.value;
-
- fn::MFOutputSocket &new_attribute_socket = network.add_input(
- "Attribute '" + attribute_name + "'", data_type);
- for (fn::MFNode *node : nodes) {
- network.relink(node->output(0), new_attribute_socket);
- }
- network.remove(nodes);
-
- attribute_inputs.add_new(&new_attribute_socket, attribute_name);
- }
-
- return attribute_inputs;
-}
-
-class CustomDataAttributesRef {
- private:
- Vector<void *> buffers_;
- uint size_;
- std::unique_ptr<fn::AttributesInfo> info_;
-
- public:
- CustomDataAttributesRef(CustomData &custom_data, uint size)
- {
- fn::AttributesInfoBuilder builder;
- for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) {
- buffers_.append(layer.data);
- switch (layer.type) {
- case CD_PROP_INT32: {
- builder.add<int32_t>(layer.name, 0);
- break;
- }
- case CD_PROP_FLOAT3: {
- builder.add<float3>(layer.name, {0, 0, 0});
- break;
- }
- }
- }
- info_ = std::make_unique<fn::AttributesInfo>(builder);
- size_ = size;
- }
-
- operator fn::MutableAttributesRef()
- {
- return fn::MutableAttributesRef(*info_, buffers_, size_);
- }
-
- operator fn::AttributesRef() const
- {
- return fn::AttributesRef(*info_, buffers_, size_);
- }
-};
-
-static std::string dnode_to_path(const DNode &dnode)
-{
- std::string path;
- for (const DParentNode *parent = dnode.parent(); parent; parent = parent->parent()) {
- path = parent->node_ref().name() + "/" + path;
- }
- path = path + dnode.name();
- return path;
-}
-
-static void remove_unused_states(Simulation *simulation, const VectorSet<std::string> &state_names)
-{
- LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
- if (!state_names.contains(state->name)) {
- BLI_remlink(&simulation->states, state);
- free_particle_simulation_state((ParticleSimulationState *)state);
- }
- }
-}
-
-static void reset_states(Simulation *simulation)
-{
- LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
- switch ((eSimulationStateType)state->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- CustomData_free(&particle_state->attributes, particle_state->tot_particles);
- particle_state->tot_particles = 0;
- break;
- }
- }
- }
-}
-
-static SimulationState *try_find_state_by_name(Simulation *simulation, StringRef name)
-{
- LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
- if (state->name == name) {
- return state;
- }
- }
- return nullptr;
-}
-
-static void add_missing_particle_states(Simulation *simulation, Span<std::string> state_names)
-{
- for (StringRefNull name : state_names) {
- SimulationState *state = try_find_state_by_name(simulation, name);
- if (state != nullptr) {
- BLI_assert(state->type == SIM_STATE_TYPE_PARTICLES);
- continue;
- }
-
- ParticleSimulationState *particle_state = (ParticleSimulationState *)MEM_callocN(
- sizeof(*particle_state), AT);
- particle_state->head.type = SIM_STATE_TYPE_PARTICLES;
- particle_state->head.name = BLI_strdup(name.data());
- CustomData_reset(&particle_state->attributes);
- particle_state->point_cache = BKE_ptcache_add(&particle_state->ptcaches);
- BLI_addtail(&simulation->states, particle_state);
- }
-}
-
-static void reinitialize_empty_simulation_states(Simulation *simulation,
- const DerivedNodeTree &tree)
-{
- VectorSet<std::string> state_names;
- for (const DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
- state_names.add(dnode_to_path(*dnode));
- }
-
- remove_unused_states(simulation, state_names);
- reset_states(simulation);
- add_missing_particle_states(simulation, state_names);
-}
-
-static void update_simulation_state_list(Simulation *simulation, const DerivedNodeTree &tree)
-{
- VectorSet<std::string> state_names;
- for (const DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
- state_names.add(dnode_to_path(*dnode));
- }
-
- remove_unused_states(simulation, state_names);
- add_missing_particle_states(simulation, state_names);
-}
-
-class ParticleFunctionInput {
- public:
- virtual ~ParticleFunctionInput() = default;
- virtual void add_input(fn::AttributesRef attributes,
- fn::MFParamsBuilder &params,
- ResourceCollector &resources) const = 0;
-};
-
-class ParticleFunction {
- private:
- const fn::MultiFunction *global_fn_;
- const fn::MultiFunction *per_particle_fn_;
- Array<const ParticleFunctionInput *> global_inputs_;
- Array<const ParticleFunctionInput *> per_particle_inputs_;
- Array<bool> output_is_global_;
- Vector<uint> global_output_indices_;
- Vector<uint> per_particle_output_indices_;
- Vector<fn::MFDataType> output_types_;
- Vector<StringRefNull> output_names_;
-
- friend class ParticleFunctionEvaluator;
-
- public:
- ParticleFunction(const fn::MultiFunction *global_fn,
- const fn::MultiFunction *per_particle_fn,
- Span<const ParticleFunctionInput *> global_inputs,
- Span<const ParticleFunctionInput *> per_particle_inputs,
- Span<bool> output_is_global)
- : global_fn_(global_fn),
- per_particle_fn_(per_particle_fn),
- global_inputs_(global_inputs),
- per_particle_inputs_(per_particle_inputs),
- output_is_global_(output_is_global)
- {
- for (uint i : output_is_global_.index_range()) {
- if (output_is_global_[i]) {
- uint param_index = global_inputs_.size() + global_output_indices_.size();
- fn::MFParamType param_type = global_fn_->param_type(param_index);
- BLI_assert(param_type.is_output());
- output_types_.append(param_type.data_type());
- output_names_.append(global_fn_->param_name(param_index));
- global_output_indices_.append(i);
- }
- else {
- uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size();
- fn::MFParamType param_type = per_particle_fn_->param_type(param_index);
- BLI_assert(param_type.is_output());
- output_types_.append(param_type.data_type());
- output_names_.append(per_particle_fn_->param_name(param_index));
- per_particle_output_indices_.append(i);
- }
- }
- }
-};
-
-class ParticleFunctionEvaluator {
- private:
- ResourceCollector resources_;
- const ParticleFunction &particle_fn_;
- IndexMask mask_;
- fn::MFContextBuilder global_context_;
- fn::MFContextBuilder per_particle_context_;
- fn::AttributesRef particle_attributes_;
- Vector<void *> outputs_;
- bool is_computed_ = false;
-
- public:
- ParticleFunctionEvaluator(const ParticleFunction &particle_fn,
- IndexMask mask,
- fn::AttributesRef particle_attributes)
- : particle_fn_(particle_fn),
- mask_(mask),
- particle_attributes_(particle_attributes),
- outputs_(particle_fn_.output_types_.size(), nullptr)
- {
- }
-
- ~ParticleFunctionEvaluator()
- {
- for (uint output_index : outputs_.index_range()) {
- void *buffer = outputs_[output_index];
- fn::MFDataType data_type = particle_fn_.output_types_[output_index];
- BLI_assert(data_type.is_single()); /* For now. */
- const fn::CPPType &type = data_type.single_type();
-
- if (particle_fn_.output_is_global_[output_index]) {
- type.destruct(buffer);
- }
- else {
- type.destruct_indices(outputs_[0], mask_);
- }
- }
- }
-
- void compute()
- {
- BLI_assert(!is_computed_);
- this->compute_globals();
- this->compute_per_particle();
- is_computed_ = true;
- }
-
- template<typename T> fn::VSpan<T> get(uint output_index, StringRef expected_name) const
- {
- return this->get(output_index, expected_name).typed<T>();
- }
-
- fn::GVSpan get(uint output_index, StringRef expected_name) const
- {
-#ifdef DEBUG
- StringRef real_name = particle_fn_.output_names_[output_index];
- BLI_assert(expected_name == real_name);
- BLI_assert(is_computed_);
-#endif
- UNUSED_VARS_NDEBUG(expected_name);
- const void *buffer = outputs_[output_index];
- const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type();
- if (particle_fn_.output_is_global_[output_index]) {
- return fn::GVSpan::FromSingleWithMaxSize(type, buffer);
- }
- else {
- return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size()));
- }
- }
-
- private:
- void compute_globals()
- {
- if (particle_fn_.global_fn_ == nullptr) {
- return;
- }
-
- fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size());
-
- /* Add input parameters. */
- for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) {
- input->add_input(particle_attributes_, params, resources_);
- }
-
- /* Add output parameters. */
- for (uint output_index : particle_fn_.global_output_indices_) {
- fn::MFDataType data_type = particle_fn_.output_types_[output_index];
- BLI_assert(data_type.is_single()); /* For now. */
-
- const fn::CPPType &type = data_type.single_type();
- void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment());
- params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1));
- outputs_[output_index] = buffer;
- }
-
- particle_fn_.global_fn_->call({0}, params, global_context_);
- }
-
- void compute_per_particle()
- {
- if (particle_fn_.per_particle_fn_ == nullptr) {
- return;
- }
-
- fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size());
-
- /* Add input parameters. */
- for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) {
- input->add_input(particle_attributes_, params, resources_);
- }
-
- /* Add output parameters. */
- for (uint output_index : particle_fn_.per_particle_output_indices_) {
- fn::MFDataType data_type = particle_fn_.output_types_[output_index];
- BLI_assert(data_type.is_single()); /* For now. */
-
- const fn::CPPType &type = data_type.single_type();
- void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(),
- type.alignment());
- params.add_uninitialized_single_output(
- fn::GMutableSpan(type, buffer, mask_.min_array_size()));
- outputs_[output_index] = buffer;
- }
-
- particle_fn_.per_particle_fn_->call(mask_, params, global_context_);
- }
-};
-
-class ParticleAttributeInput : public ParticleFunctionInput {
- private:
- std::string attribute_name_;
- const fn::CPPType &attribute_type_;
-
- public:
- ParticleAttributeInput(std::string attribute_name, const fn::CPPType &attribute_type)
- : attribute_name_(std::move(attribute_name)), attribute_type_(attribute_type)
- {
- }
-
- void add_input(fn::AttributesRef attributes,
- fn::MFParamsBuilder &params,
- ResourceCollector &UNUSED(resources)) const override
- {
- std::optional<fn::GSpan> span = attributes.try_get(attribute_name_, attribute_type_);
- if (span.has_value()) {
- params.add_readonly_single_input(*span);
- }
- else {
- params.add_readonly_single_input(fn::GVSpan::FromDefault(attribute_type_));
- }
- }
-};
-
-static const ParticleFunction *create_particle_function_for_inputs(
- Span<const fn::MFInputSocket *> sockets_to_compute,
- ResourceCollector &resources,
- const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
-{
- BLI_assert(sockets_to_compute.size() >= 1);
- const fn::MFNetwork &network = sockets_to_compute[0]->node().network();
-
- VectorSet<const fn::MFOutputSocket *> dummy_deps;
- VectorSet<const fn::MFInputSocket *> unlinked_input_deps;
- network.find_dependencies(sockets_to_compute, dummy_deps, unlinked_input_deps);
- BLI_assert(unlinked_input_deps.size() == 0);
-
- Vector<const ParticleFunctionInput *> per_particle_inputs;
- for (const fn::MFOutputSocket *socket : dummy_deps) {
- const std::string *attribute_name = attribute_inputs.lookup_ptr(socket);
- if (attribute_name == nullptr) {
- return nullptr;
- }
- per_particle_inputs.append(&resources.construct<ParticleAttributeInput>(
- AT, *attribute_name, socket->data_type().single_type()));
- }
-
- const fn::MultiFunction &per_particle_fn = resources.construct<fn::MFNetworkEvaluator>(
- AT, dummy_deps.as_span(), sockets_to_compute);
-
- Array<bool> output_is_global(sockets_to_compute.size(), false);
-
- const ParticleFunction &particle_fn = resources.construct<ParticleFunction>(
- AT,
- nullptr,
- &per_particle_fn,
- Span<const ParticleFunctionInput *>(),
- per_particle_inputs.as_span(),
- output_is_global.as_span());
-
- return &particle_fn;
-}
-
-class ParticleForce {
- public:
- virtual ~ParticleForce() = default;
- virtual void add_force(fn::AttributesRef attributes,
- MutableSpan<float3> r_combined_force) const = 0;
-};
-
-class ParticleFunctionForce : public ParticleForce {
- private:
- const ParticleFunction &particle_fn_;
-
- public:
- ParticleFunctionForce(const ParticleFunction &particle_fn) : particle_fn_(particle_fn)
- {
- }
-
- void add_force(fn::AttributesRef attributes, MutableSpan<float3> r_combined_force) const override
- {
- IndexMask mask = IndexRange(attributes.size());
- ParticleFunctionEvaluator evaluator{particle_fn_, mask, attributes};
- evaluator.compute();
- fn::VSpan<float3> forces = evaluator.get<float3>(0, "Force");
- for (uint i : mask) {
- r_combined_force[i] += forces[i];
- }
- }
-};
-
-static Vector<const ParticleForce *> create_forces_for_particle_simulation(
- const DNode &simulation_node,
- MFNetworkTreeMap &network_map,
- ResourceCollector &resources,
- const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
-{
- Vector<const ParticleForce *> forces;
- for (const DOutputSocket *origin_socket : simulation_node.input(2, "Forces").linked_sockets()) {
- const DNode &origin_node = origin_socket->node();
- if (origin_node.idname() != "SimulationNodeForce") {
- continue;
- }
-
- const fn::MFInputSocket &force_socket = network_map.lookup_dummy(
- origin_node.input(0, "Force"));
-
- const ParticleFunction *particle_fn = create_particle_function_for_inputs(
- {&force_socket}, resources, attribute_inputs);
-
- if (particle_fn == nullptr) {
- continue;
- }
-
- const ParticleForce &force = resources.construct<ParticleFunctionForce>(AT, *particle_fn);
- forces.append(&force);
- }
- return forces;
-}
-
-static Map<std::string, Vector<const ParticleForce *>> collect_forces(
- MFNetworkTreeMap &network_map,
- ResourceCollector &resources,
- const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
-{
- Map<std::string, Vector<const ParticleForce *>> forces_by_simulation;
- for (const DNode *dnode : network_map.tree().nodes_by_type("SimulationNodeParticleSimulation")) {
- std::string name = dnode_to_path(*dnode);
- Vector<const ParticleForce *> forces = create_forces_for_particle_simulation(
- *dnode, network_map, resources, attribute_inputs);
- forces_by_simulation.add_new(std::move(name), std::move(forces));
- }
- return forces_by_simulation;
-}
-
-static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation_cow)
-{
- int current_frame = scene->r.cfra;
- if (simulation_cow->current_frame == current_frame) {
- return;
- }
-
- /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */
- if (!DEG_is_active(depsgraph)) {
- return;
- }
-
- Simulation *simulation_orig = (Simulation *)DEG_get_original_id(&simulation_cow->id);
-
- NodeTreeRefMap tree_refs;
- /* TODO: Use simulation_cow, but need to add depsgraph relations before that. */
- const DerivedNodeTree tree{simulation_orig->nodetree, tree_refs};
- fn::MFNetwork network;
- ResourceCollector resources;
- MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, resources);
- Map<const fn::MFOutputSocket *, std::string> attribute_inputs = deduplicate_attribute_nodes(
- network, network_map, tree);
- fn::mf_network_optimization::constant_folding(network, resources);
- fn::mf_network_optimization::common_subnetwork_elimination(network);
- fn::mf_network_optimization::dead_node_removal(network);
- // WM_clipboard_text_set(network.to_dot().c_str(), false);
-
- Map<std::string, Vector<const ParticleForce *>> forces_by_simulation = collect_forces(
- network_map, resources, attribute_inputs);
-
- if (current_frame == 1) {
- reinitialize_empty_simulation_states(simulation_orig, tree);
-
- RNG *rng = BLI_rng_new(0);
-
- simulation_orig->current_frame = 1;
- LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
- state->tot_particles = 1000;
- CustomData_realloc(&state->attributes, state->tot_particles);
- ensure_attributes_exist(state);
-
- CustomDataAttributesRef custom_data_attributes{state->attributes,
- (uint)state->tot_particles};
-
- fn::MutableAttributesRef attributes = custom_data_attributes;
- MutableSpan<float3> positions = attributes.get<float3>("Position");
- MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
- MutableSpan<int32_t> ids = attributes.get<int32_t>("ID");
-
- for (uint i : positions.index_range()) {
- positions[i] = {i / 100.0f, 0, 0};
- velocities[i] = {0, BLI_rng_get_float(rng) - 0.5f, BLI_rng_get_float(rng) - 0.5f};
- ids[i] = i;
- }
- }
-
- BLI_rng_free(rng);
-
- copy_states_to_cow(simulation_orig, simulation_cow);
- }
- else if (current_frame == simulation_orig->current_frame + 1) {
- update_simulation_state_list(simulation_orig, tree);
- float time_step = 1.0f / 24.0f;
- simulation_orig->current_frame = current_frame;
-
- LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
- ensure_attributes_exist(state);
-
- CustomDataAttributesRef custom_data_attributes{state->attributes,
- (uint)state->tot_particles};
-
- fn::MutableAttributesRef attributes = custom_data_attributes;
- MutableSpan<float3> positions = attributes.get<float3>("Position");
- MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
-
- Array<float3> force_vectors{(uint)state->tot_particles, {0, 0, 0}};
- Span<const ParticleForce *> forces = forces_by_simulation.lookup_as(state->head.name);
- for (const ParticleForce *force : forces) {
- force->add_force(attributes, force_vectors);
- }
-
- for (uint i : positions.index_range()) {
- velocities[i] += force_vectors[i] * time_step;
- positions[i] += velocities[i] * time_step;
- }
- }
-
- copy_states_to_cow(simulation_orig, simulation_cow);
- }
-}
-
-} // namespace blender::bke
-
void BKE_simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation)
{
- blender::bke::simulation_data_update(depsgraph, scene, simulation);
+ blender::sim::update_simulation_in_depsgraph(depsgraph, scene, simulation);
}
diff --git a/source/blender/blenlib/BLI_string_ref.hh b/source/blender/blenlib/BLI_string_ref.hh
index bcf2d20338e..5b555b8cd1d 100644
--- a/source/blender/blenlib/BLI_string_ref.hh
+++ b/source/blender/blenlib/BLI_string_ref.hh
@@ -187,7 +187,7 @@ class StringRefNull : public StringRefBase {
* Reference a std::string. Remember that when the std::string is destructed, the StringRefNull
* will point to uninitialized memory.
*/
- StringRefNull(const std::string &str) : StringRefNull(str.data())
+ StringRefNull(const std::string &str) : StringRefNull(str.c_str())
{
}
@@ -200,6 +200,16 @@ class StringRefNull : public StringRefBase {
BLI_assert(index <= size_);
return data_[index];
}
+
+ /**
+ * Returns the beginning of a null-terminated char array.
+ *
+ * This is like ->data(), but can only be called on a StringRefNull.
+ */
+ const char *c_str() const
+ {
+ return data_;
+ }
};
/**
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index f05e8e2f9d6..4156e2e79d8 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -170,8 +170,7 @@ typedef enum DRWBatchFlag {
MBC_WIRE_EDGES = (1 << 23),
MBC_WIRE_LOOPS = (1 << 24),
MBC_WIRE_LOOPS_UVS = (1 << 25),
- MBC_SURF_PER_MAT = (1 << 26),
- MBC_SKIN_ROOTS = (1 << 27),
+ MBC_SKIN_ROOTS = (1 << 26),
} DRWBatchFlag;
#define MBC_EDITUV \
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index a27ee90b148..1737f8b2ff9 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -890,12 +890,13 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data
MeshExtract_Tri_Data *data = _data;
GPU_indexbuf_build_in_place(&data->elb, ibo);
/* HACK: Create ibo sub-ranges and assign them to each #GPUBatch. */
- if (mr->use_final_mesh && mr->cache->surface_per_mat && mr->cache->surface_per_mat[0]) {
- BLI_assert(mr->cache->surface_per_mat[0]->elem == ibo);
+ if (mr->use_final_mesh) {
for (int i = 0; i < mr->mat_len; i++) {
/* Multiply by 3 because these are triangle indices. */
- const int start = data->tri_mat_start[i] * 3;
- const int len = data->tri_mat_end[i] * 3 - data->tri_mat_start[i] * 3;
+ const int mat_start = data->tri_mat_start[i];
+ const int mat_end = data->tri_mat_end[i];
+ const int start = mat_start * 3;
+ const int len = (mat_end - mat_start) * 3;
GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len);
/* WARNING: We modify the #GPUBatch here! */
GPU_batch_elembuf_set(mr->cache->surface_per_mat[i], sub_ibo, true);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index e69fb795948..410d59b557b 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -527,14 +527,26 @@ static void mesh_batch_cache_check_vertex_group(MeshBatchCache *cache,
}
}
-static void mesh_batch_cache_discard_shaded_batches(MeshBatchCache *cache)
+static void mesh_batch_cache_request_surface_batches(MeshBatchCache *cache)
{
+ mesh_batch_cache_add_request(cache, MBC_SURFACE);
+ DRW_batch_request(&cache->batch.surface);
+ if (cache->surface_per_mat) {
+ for (int i = 0; i < cache->mat_len; i++) {
+ DRW_batch_request(&cache->surface_per_mat[i]);
+ }
+ }
+}
+
+static void mesh_batch_cache_discard_surface_batches(MeshBatchCache *cache)
+{
+ GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
if (cache->surface_per_mat) {
for (int i = 0; i < cache->mat_len; i++) {
GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
}
}
- cache->batch_ready &= ~MBC_SURF_PER_MAT;
+ cache->batch_ready &= ~MBC_SURFACE;
}
static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
@@ -546,7 +558,7 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache)
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.vcol);
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.orco);
}
- mesh_batch_cache_discard_shaded_batches(cache);
+ mesh_batch_cache_discard_surface_batches(cache);
mesh_cd_layers_type_clear(&cache->cd_used);
MEM_SAFE_FREE(cache->surface_per_mat);
@@ -586,10 +598,7 @@ static void mesh_batch_cache_discard_uvedit(MeshBatchCache *cache)
cache->cd_used.edit_uv = 0;
/* Discard other batches that uses vbo.uv */
- mesh_batch_cache_discard_shaded_batches(cache);
-
- GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
- cache->batch_ready &= ~MBC_SURFACE;
+ mesh_batch_cache_discard_surface_batches(cache);
}
static void mesh_batch_cache_discard_uvedit_select(MeshBatchCache *cache)
@@ -651,12 +660,8 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops);
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_edges);
- if (cache->surface_per_mat) {
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_DISCARD_SAFE(cache->surface_per_mat[i]);
- }
- }
- cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS | MBC_SURF_PER_MAT);
+ mesh_batch_cache_discard_surface_batches(cache);
+ cache->batch_ready &= ~(MBC_SURFACE | MBC_WIRE_EDGES | MBC_WIRE_LOOPS);
break;
case BKE_MESH_BATCH_DIRTY_ALL:
cache->is_dirty = true;
@@ -782,8 +787,8 @@ GPUBatch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
GPUBatch *DRW_mesh_batch_cache_get_surface(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- mesh_batch_cache_add_request(cache, MBC_SURFACE);
- return DRW_batch_request(&cache->batch.surface);
+ mesh_batch_cache_request_surface_batches(cache);
+ return cache->batch.surface;
}
GPUBatch *DRW_mesh_batch_cache_get_loose_edges(Mesh *me)
@@ -841,23 +846,15 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me,
BLI_assert(gpumat_array_len == cache->mat_len);
mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed);
-
- mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
-
- for (int i = 0; i < cache->mat_len; i++) {
- DRW_batch_request(&cache->surface_per_mat[i]);
- }
+ mesh_batch_cache_request_surface_batches(cache);
return cache->surface_per_mat;
}
GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- mesh_batch_cache_add_request(cache, MBC_SURF_PER_MAT);
texpaint_request_active_uv(cache, me);
- for (int i = 0; i < cache->mat_len; i++) {
- DRW_batch_request(&cache->surface_per_mat[i]);
- }
+ mesh_batch_cache_request_surface_batches(cache);
return cache->surface_per_mat;
}
@@ -865,24 +862,24 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
texpaint_request_active_uv(cache, me);
- mesh_batch_cache_add_request(cache, MBC_SURFACE);
- return DRW_batch_request(&cache->batch.surface);
+ mesh_batch_cache_request_surface_batches(cache);
+ return cache->batch.surface;
}
GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
texpaint_request_active_vcol(cache, me);
- mesh_batch_cache_add_request(cache, MBC_SURFACE);
- return DRW_batch_request(&cache->batch.surface);
+ mesh_batch_cache_request_surface_batches(cache);
+ return cache->batch.surface;
}
GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
sculpt_request_active_vcol(cache, me);
- mesh_batch_cache_add_request(cache, MBC_SURFACE);
- return DRW_batch_request(&cache->batch.surface);
+ mesh_batch_cache_request_surface_batches(cache);
+ return cache->batch.surface;
}
int DRW_mesh_material_count_get(Mesh *me)
@@ -900,8 +897,7 @@ GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
/* Request surface to trigger the vbo filling. Otherwise it may do nothing. */
- mesh_batch_cache_add_request(cache, MBC_SURFACE);
- DRW_batch_request(&cache->batch.surface);
+ mesh_batch_cache_request_surface_batches(cache);
DRW_vbo_request(NULL, &cache->final.vbo.pos_nor);
return cache->final.vbo.pos_nor;
@@ -1122,6 +1118,40 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
mesh_cd_layers_type_clear(&cache->cd_used_over_time);
}
+#ifdef DEBUG
+/* Sanity check function to test if all requested batches are available. */
+static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ /* Make sure all requested batches have been setup. */
+ /* Note: The next line creates a different scheduling than during release builds what can lead to
+ * some issues (See T77867 where we needed to disable this function in order to debug what was
+ * happening in release builds). */
+ BLI_task_graph_work_and_wait(task_graph);
+ for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
+ BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
+ }
+ for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i]));
+ }
+ for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i]));
+ }
+ for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i]));
+ }
+ for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i]));
+ }
+ for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i]));
+ }
+ for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) {
+ BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i]));
+ }
+}
+#endif
+
/* Can be called for any surface type. Mesh *me is the final mesh. */
void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
Object *ob,
@@ -1142,10 +1172,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
/* Early out */
if (cache->batch_requested == 0) {
#ifdef DEBUG
- goto check;
-#else
- return;
+ drw_mesh_batch_cache_check_available(task_graph, me);
#endif
+ return;
}
/* Sanity check. */
@@ -1170,30 +1199,8 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
}
}
- /* HACK: if MBC_SURF_PER_MAT is requested and ibo.tris is already available, it won't have it's
- * index ranges initialized. So discard ibo.tris in order to recreate it.
- * This needs to happen before saved_elem_ranges is populated. */
- if ((batch_requested & MBC_SURF_PER_MAT) != 0 && (cache->batch_ready & MBC_SURF_PER_MAT) == 0) {
- FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) {
- GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris);
- }
- /* Clear all batches that reference ibo.tris. */
- GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
- GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edit_mesh_analysis);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edit_triangles);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edit_lnor);
- GPU_BATCH_CLEAR_SAFE(cache->batch.edit_selection_faces);
- for (int i = 0; i < cache->mat_len; i++) {
- GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]);
- }
-
- cache->batch_ready &= ~(MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_MESH_ANALYSIS |
- MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR | MBC_EDIT_SELECTION_FACES);
- }
-
if (batch_requested &
- (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA |
+ (MBC_SURFACE | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA |
MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) {
/* Modifiers will only generate an orco layer if the mesh is deformed. */
if (cache->cd_needed.orco != 0) {
@@ -1246,7 +1253,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]);
}
GPU_BATCH_CLEAR_SAFE(cache->batch.surface);
- cache->batch_ready &= ~(MBC_SURFACE | MBC_SURF_PER_MAT);
+ cache->batch_ready &= ~(MBC_SURFACE);
mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed);
}
@@ -1282,10 +1289,9 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
/* Second chance to early out */
if ((batch_requested & ~cache->batch_ready) == 0) {
#ifdef DEBUG
- goto check;
-#else
- return;
+ drw_mesh_batch_cache_check_available(task_graph, me);
#endif
+ return;
}
cache->batch_ready |= batch_requested;
@@ -1537,32 +1543,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
ts,
use_hide);
#ifdef DEBUG
-check:
- /* Make sure all requested batches have been setup. */
- /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and
- * additional looping.*/
- BLI_task_graph_work_and_wait(task_graph);
- for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
- BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
- }
- for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i]));
- }
- for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i]));
- }
- for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i]));
- }
- for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i]));
- }
- for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) {
- BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i]));
- }
- for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) {
- BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i]));
- }
+ drw_mesh_batch_cache_check_available(task_graph, me);
#endif
}
diff --git a/source/blender/draw/intern/draw_cache_impl_pointcloud.c b/source/blender/draw/intern/draw_cache_impl_pointcloud.c
index 5977c60335f..17902f27513 100644
--- a/source/blender/draw/intern/draw_cache_impl_pointcloud.c
+++ b/source/blender/draw/intern/draw_cache_impl_pointcloud.c
@@ -270,6 +270,7 @@ GPUBatch **DRW_cache_pointcloud_surface_shaded_get(Object *ob,
PointCloud *pointcloud = ob->data;
PointCloudBatchCache *cache = pointcloud_batch_cache_get(pointcloud);
BLI_assert(cache->mat_len == gpumat_array_len);
+ UNUSED_VARS(gpumat_array_len);
if (cache->surface_per_mat[0] == NULL) {
pointcloud_batch_cache_ensure_pos(ob, cache);
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index ec41e785714..1b87fae1bb4 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -115,51 +115,51 @@ bool uvedit_uv_select_test(const struct Scene *scene,
struct BMLoop *l,
const int cd_loop_uv_offset);
/* uv face */
-bool uvedit_face_select_set(const struct Scene *scene,
+void uvedit_face_select_set(const struct Scene *scene,
struct BMEditMesh *em,
struct BMFace *efa,
const bool select,
const bool do_history,
const int cd_loop_uv_offset);
-bool uvedit_face_select_enable(const struct Scene *scene,
+void uvedit_face_select_enable(const struct Scene *scene,
struct BMEditMesh *em,
struct BMFace *efa,
const bool do_history,
const int cd_loop_uv_offset);
-bool uvedit_face_select_disable(const struct Scene *scene,
+void uvedit_face_select_disable(const struct Scene *scene,
struct BMEditMesh *em,
struct BMFace *efa,
const int cd_loop_uv_offset);
/* uv edge */
-void uvedit_edge_select_set(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_edge_select_set(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const bool select,
const bool do_history,
const int cd_loop_uv_offset);
-void uvedit_edge_select_enable(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_edge_select_enable(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const bool do_history,
const int cd_loop_uv_offset);
-void uvedit_edge_select_disable(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_edge_select_disable(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const int cd_loop_uv_offset);
/* uv vert */
-void uvedit_uv_select_set(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_uv_select_set(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const bool select,
const bool do_history,
const int cd_loop_uv_offset);
-void uvedit_uv_select_enable(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_uv_select_enable(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const bool do_history,
const int cd_loop_uv_offset);
-void uvedit_uv_select_disable(struct BMEditMesh *em,
- const struct Scene *scene,
+void uvedit_uv_select_disable(const struct Scene *scene,
+ struct BMEditMesh *em,
struct BMLoop *l,
const int cd_loop_uv_offset);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 3c0b5bd3027..21696b9c1ab 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -2027,6 +2027,7 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_
ScrArea *sa = CTX_wm_area(C);
ARegion *region = CTX_wm_region(C);
+ Object *ob = ED_object_active_context(C);
ListBase *constraints = get_constraints(C, use_bone_constraints);
/* Switch between the bone panel ID function and the object panel ID function. */
@@ -2042,11 +2043,15 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_
char panel_idname[MAX_NAME];
panel_id_func(con, panel_idname);
+ /* Create custom data RNA pointer. */
+ PointerRNA *con_ptr = MEM_mallocN(sizeof(PointerRNA), "panel customdata");
+ RNA_pointer_create(&ob->id, &RNA_Constraint, con, con_ptr);
+
Panel *new_panel = UI_panel_add_instanced(
- sa, region, &region->panels, panel_idname, i, NULL);
+ sa, region, &region->panels, panel_idname, i, con_ptr);
+
if (new_panel) {
- /* Set the list panel functionality function pointers since we don't do it with
- * python. */
+ /* Set the list panel functionality function pointers since we don't do it with python. */
new_panel->type->set_list_data_expand_flag = set_constraint_expand_flag;
new_panel->type->get_list_data_expand_flag = get_constraint_expand_flag;
new_panel->type->reorder = constraint_reorder;
@@ -2062,6 +2067,22 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_
UI_panel_set_expand_from_list_data(C, panel);
}
}
+
+ /* Assuming there's only one group of instanced panels, update the custom data pointers. */
+ Panel *panel = region->panels.first;
+ LISTBASE_FOREACH (bConstraint *, con, constraints) {
+ /* Move to the next instanced panel corresponding to the next constraint. */
+ while ((panel->type == NULL) || !(panel->type->flag & PNL_INSTANCED)) {
+ panel = panel->next;
+ BLI_assert(panel != NULL); /* There shouldn't be fewer panels than constraint panels. */
+ }
+
+ PointerRNA *con_ptr = MEM_mallocN(sizeof(PointerRNA), "constraint panel customdata");
+ RNA_pointer_create(&ob->id, &RNA_Constraint, con, con_ptr);
+ UI_panel_custom_data_set(panel, con_ptr);
+
+ panel = panel->next;
+ }
}
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 90ea71ae5c5..bcb1b8afbdd 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -702,7 +702,17 @@ static void edit_constraint_properties(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
-static bool edit_constraint_invoke_properties(bContext *C, wmOperator *op)
+static void edit_constraint_report_property(wmOperatorType *ot)
+{
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "report", false, "Report", "Create a notification after the operation");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+}
+
+static bool edit_constraint_invoke_properties(bContext *C,
+ wmOperator *op,
+ const wmEvent *event,
+ int *r_retval)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
@@ -730,6 +740,31 @@ static bool edit_constraint_invoke_properties(bContext *C, wmOperator *op)
return true;
}
+ /* Check the custom data of panels under the mouse for a modifier. */
+ if (event != NULL) {
+ PointerRNA *panel_ptr = UI_region_panel_custom_data_under_cursor(C, event);
+
+ if (!(panel_ptr == NULL || RNA_pointer_is_null(panel_ptr))) {
+ if (RNA_struct_is_a(panel_ptr->type, &RNA_Constraint)) {
+ con = panel_ptr->data;
+ RNA_string_set(op->ptr, "constraint", con->name);
+ list = ED_object_constraint_list_from_constraint(ob, con, NULL);
+ RNA_enum_set(op->ptr,
+ "owner",
+ (&ob->constraints == list) ? EDIT_CONSTRAINT_OWNER_OBJECT :
+ EDIT_CONSTRAINT_OWNER_BONE);
+
+ return true;
+ }
+
+ BLI_assert(r_retval != NULL); /* We need the return value in this case. */
+ if (r_retval != NULL) {
+ *r_retval = (OPERATOR_PASS_THROUGH | OPERATOR_CANCELLED);
+ }
+ return false;
+ }
+ }
+
return false;
}
@@ -813,7 +848,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op)
static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return stretchto_reset_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -868,7 +903,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op)
static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return limitdistance_reset_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -946,7 +981,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return childof_set_inverse_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -995,7 +1030,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return childof_clear_inverse_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -1120,7 +1155,7 @@ static int followpath_path_animate_invoke(bContext *C,
const wmEvent *UNUSED(event))
{
/* hook up invoke properties for figuring out which constraint we're dealing with */
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return followpath_path_animate_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -1201,7 +1236,7 @@ static int objectsolver_set_inverse_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return objectsolver_set_inverse_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -1257,7 +1292,7 @@ static int objectsolver_clear_inverse_invoke(bContext *C,
wmOperator *op,
const wmEvent *UNUSED(event))
{
- if (edit_constraint_invoke_properties(C, op)) {
+ if (edit_constraint_invoke_properties(C, op, NULL, NULL)) {
return objectsolver_clear_inverse_exec(C, op);
}
return OPERATOR_CANCELLED;
@@ -1374,26 +1409,23 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr
DEG_relations_tag_update(bmain);
}
-static bool constraint_poll(bContext *C)
-{
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- return (ptr.owner_id && ptr.data);
-}
-
/** \} */
/* ------------------------------------------------------------------- */
/** \name Delete Constraint Operator
* \{ */
-static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
+static int constraint_delete_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = (Object *)ptr.owner_id;
- bConstraint *con = ptr.data;
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, 0);
ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL);
+ /* Store name temporarily for report. */
+ char name[MAX_NAME];
+ strcpy(name, con->name);
+
/* free the constraint */
if (BKE_constraint_remove_ex(lb, ob, con, true)) {
/* there's no active constraint now, so make sure this is the case */
@@ -1407,12 +1439,25 @@ static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* notifiers */
WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT | NA_REMOVED, ob);
+ if (RNA_boolean_get(op->ptr, "report")) {
+ BKE_reportf(op->reports, RPT_INFO, "Removed constraint: %s", name);
+ }
+
return OPERATOR_FINISHED;
}
/* couldn't remove due to some invalid data */
return OPERATOR_CANCELLED;
}
+static int constraint_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int retval;
+ if (edit_constraint_invoke_properties(C, op, event, &retval)) {
+ return constraint_delete_exec(C, op);
+ }
+ return OPERATOR_CANCELLED;
+}
+
void CONSTRAINT_OT_delete(wmOperatorType *ot)
{
/* identifiers */
@@ -1421,11 +1466,14 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
ot->description = "Remove constraint from constraint stack";
/* callbacks */
+ ot->invoke = constraint_delete_invoke;
ot->exec = constraint_delete_exec;
- ot->poll = constraint_poll;
+ ot->poll = edit_constraint_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ edit_constraint_properties(ot);
+ edit_constraint_report_property(ot);
}
/** \} */
@@ -1455,12 +1503,13 @@ static int constraint_move_down_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_constraint_invoke_properties(C, op)) {
+ int retval;
+ if (edit_constraint_invoke_properties(C, op, event, &retval)) {
return constraint_move_down_exec(C, op);
}
- return OPERATOR_CANCELLED;
+ return retval;
}
void CONSTRAINT_OT_move_down(wmOperatorType *ot)
@@ -1509,12 +1558,13 @@ static int constraint_move_up_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_constraint_invoke_properties(C, op)) {
+ int retval;
+ if (edit_constraint_invoke_properties(C, op, event, &retval)) {
return constraint_move_up_exec(C, op);
}
- return OPERATOR_CANCELLED;
+ return retval;
}
void CONSTRAINT_OT_move_up(wmOperatorType *ot)
@@ -1565,14 +1615,13 @@ static int constraint_move_to_index_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int constraint_move_to_index_invoke(bContext *C,
- wmOperator *op,
- const wmEvent *UNUSED(event))
+static int constraint_move_to_index_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- if (edit_constraint_invoke_properties(C, op)) {
+ int retval;
+ if (edit_constraint_invoke_properties(C, op, event, &retval)) {
return constraint_move_to_index_exec(C, op);
}
- return OPERATOR_CANCELLED;
+ return retval;
}
void CONSTRAINT_OT_move_to_index(wmOperatorType *ot)
diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c
index 562f0ce84c1..07bec2da1ae 100644
--- a/source/blender/editors/uvedit/uvedit_rip.c
+++ b/source/blender/editors/uvedit/uvedit_rip.c
@@ -857,7 +857,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter);
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
- uvedit_uv_select_disable(em, scene, l_iter, cd_loop_uv_offset);
+ uvedit_uv_select_disable(scene, em, l_iter, cd_loop_uv_offset);
changed = true;
}
/* Ensure we don't operate on these again. */
@@ -875,7 +875,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter);
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
- uvedit_uv_select_disable(em, scene, l_iter, cd_loop_uv_offset);
+ uvedit_uv_select_disable(scene, em, l_iter, cd_loop_uv_offset);
changed = true;
}
/* Ensure we don't operate on these again. */
diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c
index ddb276a663a..12b2207b62b 100644
--- a/source/blender/editors/uvedit/uvedit_select.c
+++ b/source/blender/editors/uvedit/uvedit_select.c
@@ -161,7 +161,7 @@ static void uvedit_vertex_select_tagged(BMEditMesh *em,
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -202,7 +202,7 @@ bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_
return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset);
}
-bool uvedit_face_select_set(const struct Scene *scene,
+void uvedit_face_select_set(const struct Scene *scene,
struct BMEditMesh *em,
struct BMFace *efa,
const bool select,
@@ -210,12 +210,14 @@ bool uvedit_face_select_set(const struct Scene *scene,
const int cd_loop_uv_offset)
{
if (select) {
- return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset);
+ uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset);
+ }
+ else {
+ uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
}
- return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset);
}
-bool uvedit_face_select_enable(const Scene *scene,
+void uvedit_face_select_enable(const Scene *scene,
BMEditMesh *em,
BMFace *efa,
const bool do_history,
@@ -238,14 +240,10 @@ bool uvedit_face_select_enable(const Scene *scene,
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= MLOOPUV_VERTSEL;
}
-
- return true;
}
-
- return false;
}
-bool uvedit_face_select_disable(const Scene *scene,
+void uvedit_face_select_disable(const Scene *scene,
BMEditMesh *em,
BMFace *efa,
const int cd_loop_uv_offset)
@@ -264,11 +262,7 @@ bool uvedit_face_select_disable(const Scene *scene,
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag &= ~MLOOPUV_VERTSEL;
}
-
- return true;
}
-
- return false;
}
bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset)
@@ -296,8 +290,8 @@ bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv
return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
}
-void uvedit_edge_select_set(BMEditMesh *em,
- const Scene *scene,
+void uvedit_edge_select_set(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const bool select,
const bool do_history,
@@ -305,15 +299,15 @@ void uvedit_edge_select_set(BMEditMesh *em,
{
if (select) {
- uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
+ uvedit_edge_select_enable(scene, em, l, do_history, cd_loop_uv_offset);
}
else {
- uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset);
+ uvedit_edge_select_disable(scene, em, l, cd_loop_uv_offset);
}
}
-void uvedit_edge_select_enable(BMEditMesh *em,
- const Scene *scene,
+void uvedit_edge_select_enable(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const bool do_history,
const int cd_loop_uv_offset)
@@ -348,8 +342,8 @@ void uvedit_edge_select_enable(BMEditMesh *em,
}
}
-void uvedit_edge_select_disable(BMEditMesh *em,
- const Scene *scene,
+void uvedit_edge_select_disable(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const int cd_loop_uv_offset)
@@ -396,23 +390,23 @@ bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_o
return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset);
}
-void uvedit_uv_select_set(BMEditMesh *em,
- const Scene *scene,
+void uvedit_uv_select_set(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const bool select,
const bool do_history,
const int cd_loop_uv_offset)
{
if (select) {
- uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset);
+ uvedit_uv_select_enable(scene, em, l, do_history, cd_loop_uv_offset);
}
else {
- uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset);
+ uvedit_uv_select_disable(scene, em, l, cd_loop_uv_offset);
}
}
-void uvedit_uv_select_enable(BMEditMesh *em,
- const Scene *scene,
+void uvedit_uv_select_enable(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const bool do_history,
const int cd_loop_uv_offset)
@@ -437,8 +431,8 @@ void uvedit_uv_select_enable(BMEditMesh *em,
}
}
-void uvedit_uv_select_disable(BMEditMesh *em,
- const Scene *scene,
+void uvedit_uv_select_disable(const Scene *scene,
+ BMEditMesh *em,
BMLoop *l,
const int cd_loop_uv_offset)
{
@@ -921,7 +915,7 @@ static int uv_select_edgeloop(
iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l);
if (iterv_curr->flag) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -1476,18 +1470,21 @@ void UV_OT_select_all(wmOperatorType *ot)
/** \name Mouse Select Operator
* \{ */
-static bool uv_sticky_select(
- const float *limit, const int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen)
+static bool uv_sticky_select(const float limit[2],
+ const int hitv[],
+ int v,
+ float *hituv[],
+ const float uv[2],
+ int sticky,
+ int hitlen)
{
- int i;
-
- /* this function test if some vertex needs to selected
+ /* This function test if some vertex needs to selected
* in addition to the existing ones due to sticky select */
if (sticky == SI_STICKY_DISABLE) {
return false;
}
- for (i = 0; i < hitlen; i++) {
+ for (int i = 0; i < hitlen; i++) {
if (hitv[i] == v) {
if (sticky == SI_STICKY_LOC) {
if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) {
@@ -1684,13 +1681,13 @@ static int uv_mouse_select_multi(bContext *C,
if (selectmode == UV_SELECT_VERTEX) {
/* (de)select uv vertex */
select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset);
- uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_EDGE) {
/* (de)select edge */
select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset));
- uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset);
+ uvedit_edge_select_set(scene, em, hit.l, select, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_FACE) {
@@ -1721,7 +1718,7 @@ static int uv_mouse_select_multi(bContext *C,
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uv_sticky_select(
limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -1735,12 +1732,12 @@ static int uv_mouse_select_multi(bContext *C,
if (selectmode == UV_SELECT_VERTEX) {
/* select vertex */
- uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
+ uvedit_uv_select_enable(scene, em, hit.l, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_EDGE) {
/* select edge */
- uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset);
+ uvedit_edge_select_enable(scene, em, hit.l, true, cd_loop_uv_offset);
flush = 1;
}
else if (selectmode == UV_SELECT_FACE) {
@@ -1763,7 +1760,7 @@ static int uv_mouse_select_multi(bContext *C,
if (uv_sticky_select(
limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) {
- uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
+ uvedit_uv_select_enable(scene, em, l, false, cd_loop_uv_offset);
}
flush = 1;
@@ -2269,7 +2266,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
UvMapVert *start_vlist = NULL, *vlist_iter;
BMFace *efa_vlist;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v));
@@ -2300,7 +2297,7 @@ static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene,
l_other = BM_iter_at_index(
em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index);
- uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l_other, select, false, cd_loop_uv_offset);
}
vlist_iter = vlist_iter->next;
}
@@ -2353,7 +2350,7 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima,
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -2440,7 +2437,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima,
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -2474,7 +2471,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima,
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
}
}
}
@@ -2582,8 +2579,8 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
if ((select != luv_select) || (select != luv_select_prev)) {
if (BLI_rctf_isect_pt_v(&rectf, luv->uv) &&
BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
}
@@ -2614,14 +2611,14 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) {
/* UV_SYNC_SELECTION - can't do pinned selection */
if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
}
}
else if (pinned) {
if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
@@ -2815,8 +2812,8 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
if ((select != luv_select) || (select != luv_select_prev)) {
if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
changed = true;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
}
@@ -2844,7 +2841,7 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) {
changed = true;
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
}
@@ -3012,8 +3009,8 @@ static bool do_lasso_select_mesh_uv(bContext *C,
region, &rect, mcoords, mcoords_len, luv->uv) &&
do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
changed = true;
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
@@ -3042,7 +3039,7 @@ static bool do_lasso_select_mesh_uv(bContext *C,
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv->uv)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
changed = true;
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
@@ -3149,7 +3146,7 @@ static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op))
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_PINNED) {
- uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset);
+ uvedit_uv_select_enable(scene, em, l, false, cd_loop_uv_offset);
changed = true;
}
}
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 29e10f03e3c..f649ee528d4 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -981,7 +981,7 @@ static void stitch_propagate_uv_final_position(Scene *scene,
if (final) {
copy_v2_v2(luv->uv, final_position[index].uv);
- uvedit_uv_select_enable(state->em, scene, l, false, cd_loop_uv_offset);
+ uvedit_uv_select_enable(scene, state->em, l, false, cd_loop_uv_offset);
}
else {
int face_preview_pos =
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index 0ec531dea0d..2686275e898 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -38,7 +38,6 @@ set(SRC
FN_array_spans.hh
FN_attributes_ref.hh
FN_cpp_type.hh
- FN_cpp_types.hh
FN_generic_vector_array.hh
FN_multi_function.hh
FN_multi_function_builder.hh
diff --git a/source/blender/functions/FN_cpp_type.hh b/source/blender/functions/FN_cpp_type.hh
index 7ec60809194..ce02bfd05be 100644
--- a/source/blender/functions/FN_cpp_type.hh
+++ b/source/blender/functions/FN_cpp_type.hh
@@ -788,15 +788,12 @@ inline std::unique_ptr<const CPPType> create_cpp_type(StringRef name, const T &d
} // namespace blender::fn
#define MAKE_CPP_TYPE(IDENTIFIER, TYPE_NAME) \
- static TYPE_NAME default_value_##IDENTIFIER; \
- static std::unique_ptr<const blender::fn::CPPType> CPPTYPE_##IDENTIFIER##_owner = \
- blender::fn::create_cpp_type<TYPE_NAME>(STRINGIFY(IDENTIFIER), default_value_##IDENTIFIER); \
- const blender::fn::CPPType &CPPType_##IDENTIFIER = *CPPTYPE_##IDENTIFIER##_owner; \
template<> const blender::fn::CPPType &blender::fn::CPPType::get<TYPE_NAME>() \
{ \
- /* This can happen when trying to access a CPPType during static storage initialization. */ \
- BLI_assert(CPPTYPE_##IDENTIFIER##_owner.get() != nullptr); \
- return CPPType_##IDENTIFIER; \
+ static TYPE_NAME default_value; \
+ static std::unique_ptr<const CPPType> cpp_type = blender::fn::create_cpp_type<TYPE_NAME>( \
+ STRINGIFY(IDENTIFIER), default_value); \
+ return *cpp_type; \
}
#endif /* __FN_CPP_TYPE_HH__ */
diff --git a/source/blender/functions/intern/cpp_types.cc b/source/blender/functions/intern/cpp_types.cc
index 052278afd65..3bf4683d815 100644
--- a/source/blender/functions/intern/cpp_types.cc
+++ b/source/blender/functions/intern/cpp_types.cc
@@ -14,7 +14,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "FN_cpp_types.hh"
+#include "FN_cpp_type.hh"
#include "BLI_color.hh"
#include "BLI_float2.hh"
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 366a1d17d69..40c1e6f59b2 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -683,6 +683,10 @@ static void gpu_framebuffer_read_color_ex(
{
GLenum type = gpu_get_gl_channel_type(channels);
GLenum gl_format = gpu_get_gl_datatype(format);
+ /* TODO: needed for selection buffers to work properly, this should be handled better. */
+ if (type == GL_RED && gl_format == GL_UNSIGNED_INT) {
+ type = GL_RED_INTEGER;
+ }
glReadBuffer(readfb);
glReadPixels(x, y, w, h, type, gl_format, data);
}
@@ -1075,4 +1079,4 @@ void GPU_frontbuffer_read_pixels(
{
glReadBuffer(GL_FRONT);
gpu_framebuffer_read_color_ex(x, y, w, h, channels, GL_FRONT, format, data);
-} \ No newline at end of file
+}
diff --git a/source/blender/io/common/CMakeLists.txt b/source/blender/io/common/CMakeLists.txt
index 708f24ca0e2..a6975863413 100644
--- a/source/blender/io/common/CMakeLists.txt
+++ b/source/blender/io/common/CMakeLists.txt
@@ -48,3 +48,16 @@ set(LIB
blender_add_lib(bf_io_common "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
target_link_libraries(bf_io_common INTERFACE)
+
+if(WITH_GTESTS)
+ set(TEST_SRC
+ intern/abstract_hierarchy_iterator_test.cc
+ intern/hierarchy_context_order_test.cc
+ intern/object_identifier_test.cc
+ )
+ set(TEST_LIB
+ bf_blenloader_test
+ )
+ include(GTestTesting)
+ blender_add_test_lib(bf_io_common_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}")
+endif()
diff --git a/tests/gtests/usd/abstract_hierarchy_iterator_test.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc
index d9148a7b289..266c865ee52 100644
--- a/tests/gtests/usd/abstract_hierarchy_iterator_test.cc
+++ b/source/blender/io/common/intern/abstract_hierarchy_iterator_test.cc
@@ -19,21 +19,21 @@
#include "IO_abstract_hierarchy_iterator.h"
#include "blenloader/blendfile_loading_base_test.h"
-extern "C" {
#include "BLI_math.h"
#include "DEG_depsgraph.h"
#include "DNA_object_types.h"
-}
#include <map>
#include <set>
+namespace blender::io {
+
+namespace {
+
/* Mapping from ID.name to set of export hierarchy path. Duplicated objects can be exported
* multiple times with different export paths, hence the set. */
typedef std::map<std::string, std::set<std::string>> used_writers;
-using namespace blender::io;
-
class TestHierarchyWriter : public AbstractHierarchyWriter {
public:
std::string writer_type;
@@ -57,16 +57,7 @@ class TestHierarchyWriter : public AbstractHierarchyWriter {
}
};
-void debug_print_writers(const char *label, const used_writers &writers_map)
-{
- printf("%s:\n", label);
- for (auto idname_writers : writers_map) {
- printf(" %s:\n", idname_writers.first.c_str());
- for (const std::string &export_path : idname_writers.second) {
- printf(" - %s\n", export_path.c_str());
- }
- }
-}
+} // namespace
class TestingHierarchyIterator : public AbstractHierarchyIterator {
public: /* Public so that the test cases can directly inspect the created writers. */
@@ -75,7 +66,6 @@ class TestingHierarchyIterator : public AbstractHierarchyIterator {
used_writers hair_writers;
used_writers particle_writers;
- public:
explicit TestingHierarchyIterator(Depsgraph *depsgraph) : AbstractHierarchyIterator(depsgraph)
{
}
@@ -84,19 +74,19 @@ class TestingHierarchyIterator : public AbstractHierarchyIterator {
}
protected:
- AbstractHierarchyWriter *create_transform_writer(const HierarchyContext *context) override
+ AbstractHierarchyWriter *create_transform_writer(const HierarchyContext * /*context*/) override
{
return new TestHierarchyWriter("transform", transform_writers);
}
- AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) override
+ AbstractHierarchyWriter *create_data_writer(const HierarchyContext * /*context*/) override
{
return new TestHierarchyWriter("data", data_writers);
}
- AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) override
+ AbstractHierarchyWriter *create_hair_writer(const HierarchyContext * /*context*/) override
{
return new TestHierarchyWriter("hair", hair_writers);
}
- AbstractHierarchyWriter *create_particle_writer(const HierarchyContext *context) override
+ AbstractHierarchyWriter *create_particle_writer(const HierarchyContext * /*context*/) override
{
return new TestHierarchyWriter("particle", particle_writers);
}
@@ -325,3 +315,4 @@ TEST_F(USDHierarchyIteratorTest, ExportSubsetTest)
EXPECT_EQ(expected_transforms, iterator->transform_writers);
EXPECT_EQ(expected_data, iterator->data_writers);
}
+} // namespace blender::io
diff --git a/tests/gtests/usd/hierarchy_context_order_test.cc b/source/blender/io/common/intern/hierarchy_context_order_test.cc
index 25cda6d8670..7273b92c479 100644
--- a/tests/gtests/usd/hierarchy_context_order_test.cc
+++ b/source/blender/io/common/intern/hierarchy_context_order_test.cc
@@ -24,16 +24,20 @@ extern "C" {
#include "BLI_utildefines.h"
}
-using namespace blender::io;
+namespace blender::io {
-class HierarchyContextOrderTest : public testing::Test {
-};
+namespace {
-static Object *fake_pointer(int value)
+Object *fake_pointer(int value)
{
return static_cast<Object *>(POINTER_FROM_INT(value));
}
+} // namespace
+
+class HierarchyContextOrderTest : public testing::Test {
+};
+
TEST_F(HierarchyContextOrderTest, ObjectPointerTest)
{
HierarchyContext ctx_a = {0};
@@ -121,3 +125,5 @@ TEST_F(HierarchyContextOrderTest, TransitiveTest)
EXPECT_FALSE(ctx_d < ctx_b);
EXPECT_FALSE(ctx_d < ctx_c);
}
+
+} // namespace blender::io
diff --git a/tests/gtests/usd/object_identifier_test.cc b/source/blender/io/common/intern/object_identifier_test.cc
index 810d4470260..2b565876f22 100644
--- a/tests/gtests/usd/object_identifier_test.cc
+++ b/source/blender/io/common/intern/object_identifier_test.cc
@@ -24,8 +24,7 @@
#include <climits>
-namespace blender {
-namespace io {
+namespace blender::io {
namespace {
@@ -232,5 +231,4 @@ TEST_F(PersistentIDTest, as_object_name_suffix)
EXPECT_EQ("-3--2--1", TestPersistentID(-1, -2, -3).as_object_name_suffix());
}
-} // namespace io
-} // namespace blender
+} // namespace blender::io
diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt
index 19e16a5b328..79b15c60b94 100644
--- a/source/blender/io/usd/CMakeLists.txt
+++ b/source/blender/io/usd/CMakeLists.txt
@@ -109,3 +109,15 @@ else()
endif()
target_link_libraries(bf_usd INTERFACE ${TBB_LIBRARIES})
+
+if(WITH_GTESTS)
+ set(TEST_SRC
+ tests/usd_stage_creation_test.cc
+ )
+ set(TEST_INC
+ )
+ set(TEST_LIB
+ )
+ include(GTestTesting)
+ blender_add_test_lib(bf_io_usd_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}")
+endif()
diff --git a/tests/gtests/usd/usd_stage_creation_test.cc b/source/blender/io/usd/tests/usd_stage_creation_test.cc
index b262e21f053..d41ae6c4f26 100644
--- a/tests/gtests/usd/usd_stage_creation_test.cc
+++ b/source/blender/io/usd/tests/usd_stage_creation_test.cc
@@ -21,28 +21,32 @@
#include <string>
-extern "C" {
#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "BKE_appdir.h"
+extern "C" {
/* Workaround to make it possible to pass a path at runtime to USD. See creator.c. */
void usd_initialise_plugin_path(const char *datafiles_usd_path);
}
-DEFINE_string(test_usd_datafiles_dir, "", "The bin/{BLENDER_VERSION}/datafiles/usd directory.");
+namespace blender::io::usd {
class USDStageCreationTest : public testing::Test {
};
TEST_F(USDStageCreationTest, JSONFileLoadingTest)
{
- if (FLAGS_test_usd_datafiles_dir.empty()) {
- FAIL() << "Pass the --test-usd-datafiles-dir flag";
+ const std::string &release_dir = blender::tests::flags_test_release_dir();
+ if (release_dir.empty()) {
+ FAIL();
}
- usd_initialise_plugin_path(FLAGS_test_usd_datafiles_dir.c_str());
+ char usd_datafiles_dir[FILE_MAX];
+ BLI_path_join(usd_datafiles_dir, FILE_MAX, release_dir.c_str(), "datafiles", "usd", nullptr);
+
+ usd_initialise_plugin_path(usd_datafiles_dir);
/* Simply the ability to create a USD Stage for a specific filename means that the extension
* has been recognised by the USD library, and that a USD plugin has been loaded to write such
@@ -60,3 +64,5 @@ TEST_F(USDStageCreationTest, JSONFileLoadingTest)
FAIL() << "unable to find suitable USD plugin to write " << filename;
}
}
+
+} // namespace blender::io::usd
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 9106eacb31a..b3cb8163f2a 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -273,9 +273,12 @@ set(SRC
texture/node_texture_tree.c
texture/node_texture_util.c
+ intern/derived_node_tree.cc
intern/node_common.c
intern/node_exec.c
intern/node_socket.cc
+ intern/node_tree_multi_function.cc
+ intern/node_tree_ref.cc
intern/node_util.c
composite/node_composite_util.h
@@ -286,7 +289,10 @@ set(SRC
NOD_common.h
NOD_composite.h
+ NOD_derived_node_tree.hh
NOD_function.h
+ NOD_node_tree_multi_function.hh
+ NOD_node_tree_ref.hh
NOD_shader.h
NOD_simulation.h
NOD_socket.h
diff --git a/source/blender/blenkernel/BKE_derived_node_tree.hh b/source/blender/nodes/NOD_derived_node_tree.hh
index 083057835a5..84370dcd399 100644
--- a/source/blender/blenkernel/BKE_derived_node_tree.hh
+++ b/source/blender/nodes/NOD_derived_node_tree.hh
@@ -14,11 +14,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BKE_DERIVED_NODE_TREE_HH__
-#define __BKE_DERIVED_NODE_TREE_HH__
+#ifndef __NOD_DERIVED_NODE_TREE_HH__
+#define __NOD_DERIVED_NODE_TREE_HH__
/** \file
- * \ingroup bke
+ * \ingroup nodes
*
* DerivedNodeTree provides a flattened view on a bNodeTree, i.e. node groups are inlined. It
* builds on top of NodeTreeRef and supports similar queries efficiently.
@@ -30,9 +30,9 @@
* There is a dot graph exporter for debugging purposes.
*/
-#include "BKE_node_tree_ref.hh"
+#include "NOD_node_tree_ref.hh"
-namespace blender::bke {
+namespace blender::nodes {
class DSocket;
class DInputSocket;
@@ -477,7 +477,7 @@ inline Span<const DNode *> DerivedNodeTree::nodes() const
inline Span<const DNode *> DerivedNodeTree::nodes_by_type(StringRefNull idname) const
{
- const bNodeType *nodetype = nodeTypeFind(idname.data());
+ const bNodeType *nodetype = nodeTypeFind(idname.c_str());
return this->nodes_by_type(nodetype);
}
@@ -512,6 +512,6 @@ inline Span<const DGroupInput *> DerivedNodeTree::group_inputs() const
return group_inputs_;
}
-} // namespace blender::bke
+} // namespace blender::nodes
-#endif /* __BKE_DERIVED_NODE_TREE_HH__ */
+#endif /* __NOD_DERIVED_NODE_TREE_HH__ */
diff --git a/source/blender/blenkernel/BKE_node_tree_multi_function.hh b/source/blender/nodes/NOD_node_tree_multi_function.hh
index 7219eb1726a..f7a1fbb114d 100644
--- a/source/blender/blenkernel/BKE_node_tree_multi_function.hh
+++ b/source/blender/nodes/NOD_node_tree_multi_function.hh
@@ -14,11 +14,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BKE_NODE_TREE_FUNCTION_HH__
-#define __BKE_NODE_TREE_FUNCTION_HH__
+#ifndef __NOD_NODE_TREE_FUNCTION_HH__
+#define __NOD_NODE_TREE_FUNCTION_HH__
/** \file
- * \ingroup bke
+ * \ingroup nodes
*
* This file allows you to generate a multi-function network from a user-generated node tree.
*/
@@ -26,12 +26,11 @@
#include "FN_multi_function_builder.hh"
#include "FN_multi_function_network.hh"
-#include "BKE_derived_node_tree.hh"
+#include "NOD_derived_node_tree.hh"
#include "BLI_resource_collector.hh"
-namespace blender {
-namespace bke {
+namespace blender::nodes {
/* Maybe this should be moved to BKE_node.h. */
inline bool is_multi_function_data_socket(const bNodeSocket *bsocket)
@@ -44,7 +43,7 @@ inline bool is_multi_function_data_socket(const bNodeSocket *bsocket)
}
/**
- * A MFNetworkTreeMap maps various components of a bke::DerivedNodeTree to components of a
+ * A MFNetworkTreeMap maps various components of a DerivedNodeTree to components of a
* fn::MFNetwork. This is necessary for further processing of a multi-function network that has
* been generated from a node tree.
*/
@@ -241,7 +240,7 @@ class MFNetworkBuilderBase {
BLI_STATIC_ASSERT((std::is_base_of_v<fn::MultiFunction, T>), "");
void *buffer = common_.resources.linear_allocator().allocate(sizeof(T), alignof(T));
T *fn = new (buffer) T(std::forward<Args>(args)...);
- common_.resources.add(destruct_ptr<T>(fn), fn->name().data());
+ common_.resources.add(destruct_ptr<T>(fn), fn->name().c_str());
return *fn;
}
};
@@ -384,7 +383,6 @@ MFNetworkTreeMap insert_node_tree_into_mf_network(fn::MFNetwork &network,
const DerivedNodeTree &tree,
ResourceCollector &resources);
-} // namespace bke
-} // namespace blender
+} // namespace blender::nodes
-#endif /* __BKE_NODE_TREE_FUNCTION_HH__ */
+#endif /* __NOD_NODE_TREE_FUNCTION_HH__ */
diff --git a/source/blender/blenkernel/BKE_node_tree_ref.hh b/source/blender/nodes/NOD_node_tree_ref.hh
index b1e8904d718..907184125b8 100644
--- a/source/blender/blenkernel/BKE_node_tree_ref.hh
+++ b/source/blender/nodes/NOD_node_tree_ref.hh
@@ -14,11 +14,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __BKE_NODE_TREE_REF_HH__
-#define __BKE_NODE_TREE_REF_HH__
+#ifndef __NOD_NODE_TREE_REF_HH__
+#define __NOD_NODE_TREE_REF_HH__
/** \file
- * \ingroup bke
+ * \ingroup nodes
*
* NodeTreeRef makes querying information about a bNodeTree more efficient. It is an immutable data
* structure. It should not be used after anymore, after the underlying node tree changed.
@@ -58,7 +58,7 @@
#include "RNA_access.h"
-namespace blender::bke {
+namespace blender::nodes {
class SocketRef;
class InputSocketRef;
@@ -405,7 +405,7 @@ inline Span<const NodeRef *> NodeTreeRef::nodes() const
inline Span<const NodeRef *> NodeTreeRef::nodes_by_type(StringRefNull idname) const
{
- const bNodeType *nodetype = nodeTypeFind(idname.data());
+ const bNodeType *nodetype = nodeTypeFind(idname.c_str());
return this->nodes_by_type(nodetype);
}
@@ -440,6 +440,6 @@ inline bNodeTree *NodeTreeRef::btree() const
return btree_;
}
-} // namespace blender::bke
+} // namespace blender::nodes
-#endif /* __BKE_NODE_TREE_REF_HH__ */
+#endif /* __NOD_NODE_TREE_REF_HH__ */
diff --git a/source/blender/nodes/function/node_function_util.hh b/source/blender/nodes/function/node_function_util.hh
index 938cb5dd593..8e09ab0f24f 100644
--- a/source/blender/nodes/function/node_function_util.hh
+++ b/source/blender/nodes/function/node_function_util.hh
@@ -27,11 +27,11 @@
#include "DNA_node_types.h"
#include "BKE_node.h"
-#include "BKE_node_tree_multi_function.hh"
#include "BLT_translation.h"
#include "NOD_function.h"
+#include "NOD_node_tree_multi_function.hh"
#include "node_util.h"
diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
index 3a145311a08..231771abbfa 100644
--- a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
+++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc
@@ -71,7 +71,7 @@ static const blender::fn::MultiFunction &get_multi_function(bNode &bnode)
return blender::fn::dummy_multi_function;
}
-static void node_boolean_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void node_boolean_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode());
builder.set_matching_fn(fn);
diff --git a/source/blender/nodes/function/nodes/node_fn_combine_strings.cc b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc
index a880933bc12..a545c4f0749 100644
--- a/source/blender/nodes/function/nodes/node_fn_combine_strings.cc
+++ b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc
@@ -28,7 +28,7 @@ static bNodeSocketTemplate fn_node_combine_strings_out[] = {
};
static void fn_node_combine_strings_expand_in_mf_network(
- blender::bke::NodeMFNetworkBuilder &builder)
+ blender::nodes::NodeMFNetworkBuilder &builder)
{
static blender::fn::CustomMF_SI_SI_SO<std::string, std::string, std::string> combine_fn{
"Combine Strings", [](const std::string &a, const std::string &b) { return a + b; }};
diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
index fb2c4d88caf..f8bd9a30940 100644
--- a/source/blender/nodes/function/nodes/node_fn_float_compare.cc
+++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc
@@ -90,7 +90,7 @@ static const blender::fn::MultiFunction &get_multi_function(bNode &node)
return blender::fn::dummy_multi_function;
}
-static void node_float_compare_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void node_float_compare_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
const blender::fn::MultiFunction &fn = get_multi_function(builder.bnode());
builder.set_matching_fn(fn);
diff --git a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
index c61c941ee0d..1e22cde721d 100644
--- a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
+++ b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc
@@ -22,11 +22,11 @@ static bNodeSocketTemplate fn_node_group_instance_id_out[] = {
};
static void fn_node_group_instance_id_expand_in_mf_network(
- blender::bke::NodeMFNetworkBuilder &builder)
+ blender::nodes::NodeMFNetworkBuilder &builder)
{
- const blender::bke::DNode &node = builder.dnode();
+ const blender::nodes::DNode &node = builder.dnode();
std::string id = "/";
- for (const blender::bke::DParentNode *parent = node.parent(); parent;
+ for (const blender::nodes::DParentNode *parent = node.parent(); parent;
parent = parent->parent()) {
id = "/" + parent->node_ref().name() + id;
}
diff --git a/source/blender/blenkernel/intern/derived_node_tree.cc b/source/blender/nodes/intern/derived_node_tree.cc
index 01317eeb5ce..daec67b53a9 100644
--- a/source/blender/blenkernel/intern/derived_node_tree.cc
+++ b/source/blender/nodes/intern/derived_node_tree.cc
@@ -14,13 +14,13 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "BKE_derived_node_tree.hh"
+#include "NOD_derived_node_tree.hh"
#include "BLI_dot_export.hh"
#define UNINITIALIZED_ID UINT32_MAX
-namespace blender::bke {
+namespace blender::nodes {
static const NodeTreeRef &get_tree_ref(NodeTreeRefMap &node_tree_refs, bNodeTree *btree)
{
@@ -438,4 +438,4 @@ std::string DerivedNodeTree::to_dot() const
return digraph.to_dot_string();
}
-} // namespace blender::bke
+} // namespace blender::nodes
diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc
index 02124465dda..3a82438a211 100644
--- a/source/blender/nodes/intern/node_socket.cc
+++ b/source/blender/nodes/intern/node_socket.cc
@@ -34,13 +34,13 @@
#include "BKE_lib_id.h"
#include "BKE_node.h"
-#include "BKE_node_tree_multi_function.hh"
#include "RNA_access.h"
#include "RNA_types.h"
#include "MEM_guardedalloc.h"
+#include "NOD_node_tree_multi_function.hh"
#include "NOD_socket.h"
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
@@ -517,7 +517,7 @@ static bNodeSocketType *make_socket_type_bool()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_BOOLEAN, PROP_NONE);
socktype->get_mf_data_type = []() { return blender::fn::MFDataType::ForSingle<bool>(); };
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
bool value = builder.socket_default_value<bNodeSocketValueBoolean>()->value;
builder.set_constant_value(value);
};
@@ -528,7 +528,7 @@ static bNodeSocketType *make_socket_type_float(PropertySubType subtype)
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_FLOAT, subtype);
socktype->get_mf_data_type = []() { return blender::fn::MFDataType::ForSingle<float>(); };
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
float value = builder.socket_default_value<bNodeSocketValueFloat>()->value;
builder.set_constant_value(value);
};
@@ -539,7 +539,7 @@ static bNodeSocketType *make_socket_type_int(PropertySubType subtype)
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_INT, subtype);
socktype->get_mf_data_type = []() { return blender::fn::MFDataType::ForSingle<int>(); };
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
int value = builder.socket_default_value<bNodeSocketValueInt>()->value;
builder.set_constant_value(value);
};
@@ -552,7 +552,7 @@ static bNodeSocketType *make_socket_type_vector(PropertySubType subtype)
socktype->get_mf_data_type = []() {
return blender::fn::MFDataType::ForSingle<blender::float3>();
};
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
blender::float3 value = builder.socket_default_value<bNodeSocketValueVector>()->value;
builder.set_constant_value(value);
};
@@ -565,7 +565,7 @@ static bNodeSocketType *make_socket_type_rgba()
socktype->get_mf_data_type = []() {
return blender::fn::MFDataType::ForSingle<blender::Color4f>();
};
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
blender::Color4f value = builder.socket_default_value<bNodeSocketValueRGBA>()->value;
builder.set_constant_value(value);
};
@@ -576,7 +576,7 @@ static bNodeSocketType *make_socket_type_string()
{
bNodeSocketType *socktype = make_standard_socket_type(SOCK_STRING, PROP_NONE);
socktype->get_mf_data_type = []() { return blender::fn::MFDataType::ForSingle<std::string>(); };
- socktype->expand_in_mf_network = [](blender::bke::SocketMFNetworkBuilder &builder) {
+ socktype->expand_in_mf_network = [](blender::nodes::SocketMFNetworkBuilder &builder) {
std::string value = builder.socket_default_value<bNodeSocketValueString>()->value;
builder.set_constant_value(value);
};
diff --git a/source/blender/blenkernel/intern/node_tree_multi_function.cc b/source/blender/nodes/intern/node_tree_multi_function.cc
index 537ec056126..f77b19354a4 100644
--- a/source/blender/blenkernel/intern/node_tree_multi_function.cc
+++ b/source/blender/nodes/intern/node_tree_multi_function.cc
@@ -14,13 +14,12 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "BKE_node_tree_multi_function.hh"
+#include "NOD_node_tree_multi_function.hh"
#include "BLI_color.hh"
#include "BLI_float3.hh"
-namespace blender {
-namespace bke {
+namespace blender::nodes {
/* Maybe this should be moved to BKE_node.h. */
static std::optional<fn::MFDataType> try_get_multi_function_data_type_of_socket(
@@ -342,5 +341,4 @@ MFNetworkTreeMap insert_node_tree_into_mf_network(fn::MFNetwork &network,
return network_map;
}
-} // namespace bke
-} // namespace blender
+} // namespace blender::nodes
diff --git a/source/blender/blenkernel/intern/node_tree_ref.cc b/source/blender/nodes/intern/node_tree_ref.cc
index 5c998a06cb5..186ca750f10 100644
--- a/source/blender/blenkernel/intern/node_tree_ref.cc
+++ b/source/blender/nodes/intern/node_tree_ref.cc
@@ -14,11 +14,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#include "BKE_node_tree_ref.hh"
+#include "NOD_node_tree_ref.hh"
#include "BLI_dot_export.hh"
-namespace blender::bke {
+namespace blender::nodes {
NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
{
@@ -174,4 +174,4 @@ std::string NodeTreeRef::to_dot() const
return digraph.to_dot_string();
}
-} // namespace blender::bke
+} // namespace blender::nodes
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 2aed485c8bc..b0ba1ea194f 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -73,7 +73,7 @@
#ifdef __cplusplus
# include "FN_multi_function_builder.hh"
-# include "BKE_node_tree_multi_function.hh"
+# include "NOD_node_tree_multi_function.hh"
# include "BLI_color.hh"
# include "BLI_float3.hh"
diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.cc b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
index 3f8a516c175..b026499ec4b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_map_range.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_map_range.cc
@@ -128,7 +128,7 @@ class MapRangeFunction : public blender::fn::MultiFunction {
}
};
-static void sh_node_map_range_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_map_range_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
bNode &bnode = builder.bnode();
bool clamp = bnode.custom1 != 0;
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.cc b/source/blender/nodes/shader/nodes/node_shader_math.cc
index c6762f17919..c7035da8c70 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_math.cc
@@ -147,7 +147,7 @@ static int gpu_shader_math(GPUMaterial *mat,
}
static const blender::fn::MultiFunction &get_base_multi_function(
- blender::bke::NodeMFNetworkBuilder &builder)
+ blender::nodes::NodeMFNetworkBuilder &builder)
{
const int mode = builder.bnode().custom1;
switch (mode) {
@@ -347,11 +347,11 @@ static const blender::fn::MultiFunction &get_base_multi_function(
}
}
-static void sh_node_math_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
const blender::fn::MultiFunction &base_function = get_base_multi_function(builder);
- const blender::bke::DNode &dnode = builder.dnode();
+ const blender::nodes::DNode &dnode = builder.dnode();
blender::fn::MFNetwork &network = builder.network();
blender::fn::MFFunctionNode &base_node = network.add_function(base_function);
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
index 8cab115c0b5..4b4b80ea1ad 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.cc
@@ -89,7 +89,7 @@ class SeparateRGBFunction : public blender::fn::MultiFunction {
}
};
-static void sh_node_seprgb_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_seprgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
static SeparateRGBFunction fn;
builder.set_matching_fn(fn);
@@ -146,7 +146,7 @@ static int gpu_shader_combrgb(GPUMaterial *mat,
return GPU_stack_link(mat, node, "combine_rgb", in, out);
}
-static void sh_node_combrgb_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_combrgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, blender::Color4f> fn{
"Combine RGB", [](float r, float g, float b) { return blender::Color4f(r, g, b, 1.0f); }};
diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
index d9af37ab46b..03e18acc245 100644
--- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.cc
@@ -74,7 +74,7 @@ class MF_SeparateXYZ : public blender::fn::MultiFunction {
}
};
-static void sh_node_sepxyz_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_sepxyz_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
static MF_SeparateXYZ separate_fn;
builder.set_matching_fn(separate_fn);
@@ -113,7 +113,7 @@ static int gpu_shader_combxyz(GPUMaterial *mat,
return GPU_stack_link(mat, node, "combine_xyz", in, out);
}
-static void sh_node_combxyz_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_combxyz_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
static blender::fn::CustomMF_SI_SI_SI_SO<float, float, float, blender::float3> fn{
"Combine Vector", [](float x, float y, float z) { return blender::float3(x, y, z); }};
diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
index 76409c836d8..21f15bcf6f4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.cc
@@ -157,7 +157,7 @@ class ColorBandFunction : public blender::fn::MultiFunction {
}
};
-static void sh_node_valtorgb_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_valtorgb_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
bNode &bnode = builder.bnode();
const ColorBand *color_band = (const ColorBand *)bnode.storage;
diff --git a/source/blender/nodes/shader/nodes/node_shader_value.cc b/source/blender/nodes/shader/nodes/node_shader_value.cc
index 64701018d63..1d7c3f47233 100644
--- a/source/blender/nodes/shader/nodes/node_shader_value.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_value.cc
@@ -39,7 +39,7 @@ static int gpu_shader_value(GPUMaterial *mat,
return GPU_stack_link(mat, node, "set_value", in, out, link);
}
-static void sh_node_value_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_value_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
const bNodeSocket *bsocket = builder.dnode().output(0).bsocket();
const bNodeSocketValueFloat *value = (const bNodeSocketValueFloat *)bsocket->default_value;
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
index 8301ab4d855..c18ad8bb244 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.cc
@@ -161,7 +161,7 @@ static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node
}
static const blender::fn::MultiFunction &get_multi_function(
- blender::bke::NodeMFNetworkBuilder &builder)
+ blender::nodes::NodeMFNetworkBuilder &builder)
{
using blender::float3;
@@ -271,7 +271,7 @@ static const blender::fn::MultiFunction &get_multi_function(
};
}
-static void sh_node_vector_math_expand_in_mf_network(blender::bke::NodeMFNetworkBuilder &builder)
+static void sh_node_vector_math_expand_in_mf_network(blender::nodes::NodeMFNetworkBuilder &builder)
{
const blender::fn::MultiFunction &fn = get_multi_function(builder);
builder.set_matching_fn(fn);
diff --git a/source/blender/simulation/CMakeLists.txt b/source/blender/simulation/CMakeLists.txt
index aced9664f51..fa4838b0875 100644
--- a/source/blender/simulation/CMakeLists.txt
+++ b/source/blender/simulation/CMakeLists.txt
@@ -24,8 +24,11 @@ set(INC
../blenkernel
../blenlib
../depsgraph
+ ../functions
../imbuf
../makesdna
+ ../makesrna
+ ../nodes
../../../intern/guardedalloc
)
@@ -41,11 +44,17 @@ set(SRC
intern/implicit.h
intern/implicit_blender.c
intern/implicit_eigen.cpp
+ intern/particle_function.cc
+ intern/simulation_update.cc
SIM_mass_spring.h
+ SIM_particle_function.hh
+ SIM_simulation_update.hh
)
set(LIB
+ bf_blenkernel
+ bf_nodes
)
if(WITH_OPENMP_STATIC)
@@ -54,4 +63,4 @@ if(WITH_OPENMP_STATIC)
)
endif()
-blender_add_lib(bf_physics "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
+blender_add_lib(bf_simulation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
diff --git a/source/blender/simulation/SIM_particle_function.hh b/source/blender/simulation/SIM_particle_function.hh
new file mode 100644
index 00000000000..eae61b1ae11
--- /dev/null
+++ b/source/blender/simulation/SIM_particle_function.hh
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#ifndef __SIM_PARTICLE_FUNCTION_HH__
+#define __SIM_PARTICLE_FUNCTION_HH__
+
+#include "FN_attributes_ref.hh"
+#include "FN_multi_function.hh"
+
+#include "BLI_resource_collector.hh"
+
+namespace blender::sim {
+
+class ParticleFunctionInput {
+ public:
+ virtual ~ParticleFunctionInput() = default;
+ virtual void add_input(fn::AttributesRef attributes,
+ fn::MFParamsBuilder &params,
+ ResourceCollector &resources) const = 0;
+};
+
+class ParticleFunction {
+ private:
+ const fn::MultiFunction *global_fn_;
+ const fn::MultiFunction *per_particle_fn_;
+ Array<const ParticleFunctionInput *> global_inputs_;
+ Array<const ParticleFunctionInput *> per_particle_inputs_;
+ Array<bool> output_is_global_;
+ Vector<uint> global_output_indices_;
+ Vector<uint> per_particle_output_indices_;
+ Vector<fn::MFDataType> output_types_;
+ Vector<StringRefNull> output_names_;
+
+ friend class ParticleFunctionEvaluator;
+
+ public:
+ ParticleFunction(const fn::MultiFunction *global_fn,
+ const fn::MultiFunction *per_particle_fn,
+ Span<const ParticleFunctionInput *> global_inputs,
+ Span<const ParticleFunctionInput *> per_particle_inputs,
+ Span<bool> output_is_global);
+};
+
+class ParticleFunctionEvaluator {
+ private:
+ ResourceCollector resources_;
+ const ParticleFunction &particle_fn_;
+ IndexMask mask_;
+ fn::MFContextBuilder global_context_;
+ fn::MFContextBuilder per_particle_context_;
+ fn::AttributesRef particle_attributes_;
+ Vector<void *> outputs_;
+ bool is_computed_ = false;
+
+ public:
+ ParticleFunctionEvaluator(const ParticleFunction &particle_fn,
+ IndexMask mask,
+ fn::AttributesRef particle_attributes);
+ ~ParticleFunctionEvaluator();
+
+ void compute();
+ fn::GVSpan get(uint output_index, StringRef expected_name) const;
+
+ template<typename T> fn::VSpan<T> get(uint output_index, StringRef expected_name) const
+ {
+ return this->get(output_index, expected_name).typed<T>();
+ }
+
+ private:
+ void compute_globals();
+ void compute_per_particle();
+};
+
+} // namespace blender::sim
+
+#endif /* __SIM_PARTICLE_FUNCTION_HH__ */
diff --git a/source/blender/functions/FN_cpp_types.hh b/source/blender/simulation/SIM_simulation_update.hh
index 63f6b49885f..40b62bfb58a 100644
--- a/source/blender/functions/FN_cpp_types.hh
+++ b/source/blender/simulation/SIM_simulation_update.hh
@@ -14,35 +14,19 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-#ifndef __FN_CPP_TYPES_HH__
-#define __FN_CPP_TYPES_HH__
+#ifndef __SIM_SIMULATION_UPDATE_HH__
+#define __SIM_SIMULATION_UPDATE_HH__
-/** \file
- * \ingroup fn
- *
- * This header provides convenient access to CPPType instances for some core types like integer
- * types.
- */
-
-#include "FN_cpp_type.hh"
-
-namespace blender::fn {
-
-extern const CPPType &CPPType_bool;
-
-extern const CPPType &CPPType_float;
-extern const CPPType &CPPType_float3;
-extern const CPPType &CPPType_float4x4;
-
-extern const CPPType &CPPType_int32;
-extern const CPPType &CPPType_uint32;
-extern const CPPType &CPPType_uint8;
+struct Depsgraph;
+struct Scene;
+struct Simulation;
-extern const CPPType &CPPType_Color4f;
-extern const CPPType &CPPType_Color4b;
+namespace blender::sim {
-extern const CPPType &CPPType_string;
+void update_simulation_in_depsgraph(Depsgraph *depsgraph,
+ Scene *scene_cow,
+ Simulation *simulation_cow);
-} // namespace blender::fn
+}
-#endif /* __FN_CPP_TYPES_HH__ */
+#endif /* __SIM_SIMULATION_UPDATE_HH__ */
diff --git a/source/blender/simulation/intern/particle_function.cc b/source/blender/simulation/intern/particle_function.cc
new file mode 100644
index 00000000000..7a0c9ccdb13
--- /dev/null
+++ b/source/blender/simulation/intern/particle_function.cc
@@ -0,0 +1,160 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "SIM_particle_function.hh"
+
+namespace blender::sim {
+
+ParticleFunction::ParticleFunction(const fn::MultiFunction *global_fn,
+ const fn::MultiFunction *per_particle_fn,
+ Span<const ParticleFunctionInput *> global_inputs,
+ Span<const ParticleFunctionInput *> per_particle_inputs,
+ Span<bool> output_is_global)
+ : global_fn_(global_fn),
+ per_particle_fn_(per_particle_fn),
+ global_inputs_(global_inputs),
+ per_particle_inputs_(per_particle_inputs),
+ output_is_global_(output_is_global)
+{
+ for (uint i : output_is_global_.index_range()) {
+ if (output_is_global_[i]) {
+ uint param_index = global_inputs_.size() + global_output_indices_.size();
+ fn::MFParamType param_type = global_fn_->param_type(param_index);
+ BLI_assert(param_type.is_output());
+ output_types_.append(param_type.data_type());
+ output_names_.append(global_fn_->param_name(param_index));
+ global_output_indices_.append(i);
+ }
+ else {
+ uint param_index = per_particle_inputs_.size() + per_particle_output_indices_.size();
+ fn::MFParamType param_type = per_particle_fn_->param_type(param_index);
+ BLI_assert(param_type.is_output());
+ output_types_.append(param_type.data_type());
+ output_names_.append(per_particle_fn_->param_name(param_index));
+ per_particle_output_indices_.append(i);
+ }
+ }
+}
+
+ParticleFunctionEvaluator::ParticleFunctionEvaluator(const ParticleFunction &particle_fn,
+ IndexMask mask,
+ fn::AttributesRef particle_attributes)
+ : particle_fn_(particle_fn),
+ mask_(mask),
+ particle_attributes_(particle_attributes),
+ outputs_(particle_fn_.output_types_.size(), nullptr)
+{
+}
+
+ParticleFunctionEvaluator::~ParticleFunctionEvaluator()
+{
+ for (uint output_index : outputs_.index_range()) {
+ void *buffer = outputs_[output_index];
+ fn::MFDataType data_type = particle_fn_.output_types_[output_index];
+ BLI_assert(data_type.is_single()); /* For now. */
+ const fn::CPPType &type = data_type.single_type();
+
+ if (particle_fn_.output_is_global_[output_index]) {
+ type.destruct(buffer);
+ }
+ else {
+ type.destruct_indices(outputs_[0], mask_);
+ }
+ }
+}
+
+void ParticleFunctionEvaluator::compute()
+{
+ BLI_assert(!is_computed_);
+ this->compute_globals();
+ this->compute_per_particle();
+ is_computed_ = true;
+}
+
+fn::GVSpan ParticleFunctionEvaluator::get(uint output_index, StringRef expected_name) const
+{
+#ifdef DEBUG
+ StringRef real_name = particle_fn_.output_names_[output_index];
+ BLI_assert(expected_name == real_name);
+ BLI_assert(is_computed_);
+#endif
+ UNUSED_VARS_NDEBUG(expected_name);
+ const void *buffer = outputs_[output_index];
+ const fn::CPPType &type = particle_fn_.output_types_[output_index].single_type();
+ if (particle_fn_.output_is_global_[output_index]) {
+ return fn::GVSpan::FromSingleWithMaxSize(type, buffer);
+ }
+ else {
+ return fn::GVSpan(fn::GSpan(type, buffer, mask_.min_array_size()));
+ }
+}
+
+void ParticleFunctionEvaluator::compute_globals()
+{
+ if (particle_fn_.global_fn_ == nullptr) {
+ return;
+ }
+
+ fn::MFParamsBuilder params(*particle_fn_.global_fn_, mask_.min_array_size());
+
+ /* Add input parameters. */
+ for (const ParticleFunctionInput *input : particle_fn_.global_inputs_) {
+ input->add_input(particle_attributes_, params, resources_);
+ }
+
+ /* Add output parameters. */
+ for (uint output_index : particle_fn_.global_output_indices_) {
+ fn::MFDataType data_type = particle_fn_.output_types_[output_index];
+ BLI_assert(data_type.is_single()); /* For now. */
+
+ const fn::CPPType &type = data_type.single_type();
+ void *buffer = resources_.linear_allocator().allocate(type.size(), type.alignment());
+ params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, 1));
+ outputs_[output_index] = buffer;
+ }
+
+ particle_fn_.global_fn_->call({0}, params, global_context_);
+}
+
+void ParticleFunctionEvaluator::compute_per_particle()
+{
+ if (particle_fn_.per_particle_fn_ == nullptr) {
+ return;
+ }
+
+ fn::MFParamsBuilder params(*particle_fn_.per_particle_fn_, mask_.min_array_size());
+
+ /* Add input parameters. */
+ for (const ParticleFunctionInput *input : particle_fn_.per_particle_inputs_) {
+ input->add_input(particle_attributes_, params, resources_);
+ }
+
+ /* Add output parameters. */
+ for (uint output_index : particle_fn_.per_particle_output_indices_) {
+ fn::MFDataType data_type = particle_fn_.output_types_[output_index];
+ BLI_assert(data_type.is_single()); /* For now. */
+
+ const fn::CPPType &type = data_type.single_type();
+ void *buffer = resources_.linear_allocator().allocate(type.size() * mask_.min_array_size(),
+ type.alignment());
+ params.add_uninitialized_single_output(fn::GMutableSpan(type, buffer, mask_.min_array_size()));
+ outputs_[output_index] = buffer;
+ }
+
+ particle_fn_.per_particle_fn_->call(mask_, params, global_context_);
+}
+
+} // namespace blender::sim
diff --git a/source/blender/simulation/intern/simulation_update.cc b/source/blender/simulation/intern/simulation_update.cc
new file mode 100644
index 00000000000..d682b018b11
--- /dev/null
+++ b/source/blender/simulation/intern/simulation_update.cc
@@ -0,0 +1,495 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "SIM_particle_function.hh"
+#include "SIM_simulation_update.hh"
+
+#include "BKE_customdata.h"
+#include "BKE_simulation.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_simulation_types.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "BLI_array.hh"
+#include "BLI_float3.hh"
+#include "BLI_listbase.h"
+#include "BLI_map.hh"
+#include "BLI_rand.h"
+#include "BLI_vector.hh"
+
+#include "NOD_node_tree_multi_function.hh"
+
+#include "FN_attributes_ref.hh"
+#include "FN_multi_function_network_evaluation.hh"
+#include "FN_multi_function_network_optimization.hh"
+
+extern "C" {
+void WM_clipboard_text_set(const char *buf, bool selection);
+}
+
+namespace blender::sim {
+
+static void ensure_attributes_exist(ParticleSimulationState *state)
+{
+ if (CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Position") == nullptr) {
+ CustomData_add_layer_named(
+ &state->attributes, CD_PROP_FLOAT3, CD_CALLOC, nullptr, state->tot_particles, "Position");
+ }
+ if (CustomData_get_layer_named(&state->attributes, CD_PROP_FLOAT3, "Velocity") == nullptr) {
+ CustomData_add_layer_named(
+ &state->attributes, CD_PROP_FLOAT3, CD_CALLOC, nullptr, state->tot_particles, "Velocity");
+ }
+ if (CustomData_get_layer_named(&state->attributes, CD_PROP_INT32, "ID") == nullptr) {
+ CustomData_add_layer_named(
+ &state->attributes, CD_PROP_INT32, CD_CALLOC, nullptr, state->tot_particles, "ID");
+ }
+}
+
+static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow)
+{
+ BKE_simulation_state_remove_all(simulation_cow);
+ simulation_cow->current_frame = simulation_orig->current_frame;
+
+ LISTBASE_FOREACH (SimulationState *, state_orig, &simulation_orig->states) {
+ switch ((eSimulationStateType)state_orig->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ ParticleSimulationState *particle_state_orig = (ParticleSimulationState *)state_orig;
+ ParticleSimulationState *particle_state_cow = (ParticleSimulationState *)
+ BKE_simulation_state_add(simulation_cow, SIM_STATE_TYPE_PARTICLES, state_orig->name);
+ particle_state_cow->tot_particles = particle_state_orig->tot_particles;
+ CustomData_copy(&particle_state_orig->attributes,
+ &particle_state_cow->attributes,
+ CD_MASK_ALL,
+ CD_DUPLICATE,
+ particle_state_orig->tot_particles);
+ break;
+ }
+ }
+ }
+}
+
+static Map<const fn::MFOutputSocket *, std::string> deduplicate_attribute_nodes(
+ fn::MFNetwork &network,
+ nodes::MFNetworkTreeMap &network_map,
+ const nodes::DerivedNodeTree &tree)
+{
+ Span<const nodes::DNode *> attribute_dnodes = tree.nodes_by_type(
+ "SimulationNodeParticleAttribute");
+ uint amount = attribute_dnodes.size();
+ if (amount == 0) {
+ return {};
+ }
+
+ Vector<fn::MFInputSocket *> name_sockets;
+ for (const nodes::DNode *dnode : attribute_dnodes) {
+ fn::MFInputSocket &name_socket = network_map.lookup_dummy(dnode->input(0));
+ name_sockets.append(&name_socket);
+ }
+
+ fn::MFNetworkEvaluator network_fn{{}, name_sockets.as_span()};
+
+ fn::MFParamsBuilder params{network_fn, 1};
+
+ Array<std::string> attribute_names{amount, NoInitialization()};
+ for (uint i : IndexRange(amount)) {
+ params.add_uninitialized_single_output(
+ fn::GMutableSpan(fn::CPPType::get<std::string>(), attribute_names.data() + i, 1));
+ }
+
+ fn::MFContextBuilder context;
+ /* Todo: Check that the names don't depend on dummy nodes. */
+ network_fn.call({0}, params, context);
+
+ Map<std::pair<std::string, fn::MFDataType>, Vector<fn::MFNode *>>
+ attribute_nodes_by_name_and_type;
+ for (uint i : IndexRange(amount)) {
+ attribute_nodes_by_name_and_type
+ .lookup_or_add_default({attribute_names[i], name_sockets[i]->node().output(0).data_type()})
+ .append(&name_sockets[i]->node());
+ }
+
+ Map<const fn::MFOutputSocket *, std::string> attribute_inputs;
+ for (auto item : attribute_nodes_by_name_and_type.items()) {
+ StringRef attribute_name = item.key.first;
+ fn::MFDataType data_type = item.key.second;
+ Span<fn::MFNode *> nodes = item.value;
+
+ fn::MFOutputSocket &new_attribute_socket = network.add_input(
+ "Attribute '" + attribute_name + "'", data_type);
+ for (fn::MFNode *node : nodes) {
+ network.relink(node->output(0), new_attribute_socket);
+ }
+ network.remove(nodes);
+
+ attribute_inputs.add_new(&new_attribute_socket, attribute_name);
+ }
+
+ return attribute_inputs;
+}
+
+class CustomDataAttributesRef {
+ private:
+ Vector<void *> buffers_;
+ uint size_;
+ std::unique_ptr<fn::AttributesInfo> info_;
+
+ public:
+ CustomDataAttributesRef(CustomData &custom_data, uint size)
+ {
+ fn::AttributesInfoBuilder builder;
+ for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) {
+ buffers_.append(layer.data);
+ switch (layer.type) {
+ case CD_PROP_INT32: {
+ builder.add<int32_t>(layer.name, 0);
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ builder.add<float3>(layer.name, {0, 0, 0});
+ break;
+ }
+ }
+ }
+ info_ = std::make_unique<fn::AttributesInfo>(builder);
+ size_ = size;
+ }
+
+ operator fn::MutableAttributesRef()
+ {
+ return fn::MutableAttributesRef(*info_, buffers_, size_);
+ }
+
+ operator fn::AttributesRef() const
+ {
+ return fn::AttributesRef(*info_, buffers_, size_);
+ }
+};
+
+static std::string dnode_to_path(const nodes::DNode &dnode)
+{
+ std::string path;
+ for (const nodes::DParentNode *parent = dnode.parent(); parent; parent = parent->parent()) {
+ path = parent->node_ref().name() + "/" + path;
+ }
+ path = path + dnode.name();
+ return path;
+}
+
+static void remove_unused_states(Simulation *simulation, const VectorSet<std::string> &state_names)
+{
+ LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
+ if (!state_names.contains(state->name)) {
+ BKE_simulation_state_remove(simulation, state);
+ }
+ }
+}
+
+static void reset_states(Simulation *simulation)
+{
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ switch ((eSimulationStateType)state->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
+ CustomData_free(&particle_state->attributes, particle_state->tot_particles);
+ particle_state->tot_particles = 0;
+ break;
+ }
+ }
+ }
+}
+
+static SimulationState *try_find_state_by_name(Simulation *simulation, StringRef name)
+{
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ if (state->name == name) {
+ return state;
+ }
+ }
+ return nullptr;
+}
+
+static void add_missing_particle_states(Simulation *simulation, Span<std::string> state_names)
+{
+ for (StringRefNull name : state_names) {
+ SimulationState *state = try_find_state_by_name(simulation, name);
+ if (state != nullptr) {
+ BLI_assert(state->type == SIM_STATE_TYPE_PARTICLES);
+ continue;
+ }
+
+ BKE_simulation_state_add(simulation, SIM_STATE_TYPE_PARTICLES, name.c_str());
+ }
+}
+
+static void reinitialize_empty_simulation_states(Simulation *simulation,
+ const nodes::DerivedNodeTree &tree)
+{
+ VectorSet<std::string> state_names;
+ for (const nodes::DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
+ state_names.add(dnode_to_path(*dnode));
+ }
+
+ remove_unused_states(simulation, state_names);
+ reset_states(simulation);
+ add_missing_particle_states(simulation, state_names);
+}
+
+static void update_simulation_state_list(Simulation *simulation,
+ const nodes::DerivedNodeTree &tree)
+{
+ VectorSet<std::string> state_names;
+ for (const nodes::DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
+ state_names.add(dnode_to_path(*dnode));
+ }
+
+ remove_unused_states(simulation, state_names);
+ add_missing_particle_states(simulation, state_names);
+}
+
+class ParticleAttributeInput : public ParticleFunctionInput {
+ private:
+ std::string attribute_name_;
+ const fn::CPPType &attribute_type_;
+
+ public:
+ ParticleAttributeInput(std::string attribute_name, const fn::CPPType &attribute_type)
+ : attribute_name_(std::move(attribute_name)), attribute_type_(attribute_type)
+ {
+ }
+
+ void add_input(fn::AttributesRef attributes,
+ fn::MFParamsBuilder &params,
+ ResourceCollector &UNUSED(resources)) const override
+ {
+ std::optional<fn::GSpan> span = attributes.try_get(attribute_name_, attribute_type_);
+ if (span.has_value()) {
+ params.add_readonly_single_input(*span);
+ }
+ else {
+ params.add_readonly_single_input(fn::GVSpan::FromDefault(attribute_type_));
+ }
+ }
+};
+
+static const ParticleFunction *create_particle_function_for_inputs(
+ Span<const fn::MFInputSocket *> sockets_to_compute,
+ ResourceCollector &resources,
+ const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
+{
+ BLI_assert(sockets_to_compute.size() >= 1);
+ const fn::MFNetwork &network = sockets_to_compute[0]->node().network();
+
+ VectorSet<const fn::MFOutputSocket *> dummy_deps;
+ VectorSet<const fn::MFInputSocket *> unlinked_input_deps;
+ network.find_dependencies(sockets_to_compute, dummy_deps, unlinked_input_deps);
+ BLI_assert(unlinked_input_deps.size() == 0);
+
+ Vector<const ParticleFunctionInput *> per_particle_inputs;
+ for (const fn::MFOutputSocket *socket : dummy_deps) {
+ const std::string *attribute_name = attribute_inputs.lookup_ptr(socket);
+ if (attribute_name == nullptr) {
+ return nullptr;
+ }
+ per_particle_inputs.append(&resources.construct<ParticleAttributeInput>(
+ AT, *attribute_name, socket->data_type().single_type()));
+ }
+
+ const fn::MultiFunction &per_particle_fn = resources.construct<fn::MFNetworkEvaluator>(
+ AT, dummy_deps.as_span(), sockets_to_compute);
+
+ Array<bool> output_is_global(sockets_to_compute.size(), false);
+
+ const ParticleFunction &particle_fn = resources.construct<ParticleFunction>(
+ AT,
+ nullptr,
+ &per_particle_fn,
+ Span<const ParticleFunctionInput *>(),
+ per_particle_inputs.as_span(),
+ output_is_global.as_span());
+
+ return &particle_fn;
+}
+
+class ParticleForce {
+ public:
+ virtual ~ParticleForce() = default;
+ virtual void add_force(fn::AttributesRef attributes,
+ MutableSpan<float3> r_combined_force) const = 0;
+};
+
+class ParticleFunctionForce : public ParticleForce {
+ private:
+ const ParticleFunction &particle_fn_;
+
+ public:
+ ParticleFunctionForce(const ParticleFunction &particle_fn) : particle_fn_(particle_fn)
+ {
+ }
+
+ void add_force(fn::AttributesRef attributes, MutableSpan<float3> r_combined_force) const override
+ {
+ IndexMask mask = IndexRange(attributes.size());
+ ParticleFunctionEvaluator evaluator{particle_fn_, mask, attributes};
+ evaluator.compute();
+ fn::VSpan<float3> forces = evaluator.get<float3>(0, "Force");
+ for (uint i : mask) {
+ r_combined_force[i] += forces[i];
+ }
+ }
+};
+
+static Vector<const ParticleForce *> create_forces_for_particle_simulation(
+ const nodes::DNode &simulation_node,
+ nodes::MFNetworkTreeMap &network_map,
+ ResourceCollector &resources,
+ const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
+{
+ Vector<const ParticleForce *> forces;
+ for (const nodes::DOutputSocket *origin_socket :
+ simulation_node.input(2, "Forces").linked_sockets()) {
+ const nodes::DNode &origin_node = origin_socket->node();
+ if (origin_node.idname() != "SimulationNodeForce") {
+ continue;
+ }
+
+ const fn::MFInputSocket &force_socket = network_map.lookup_dummy(
+ origin_node.input(0, "Force"));
+
+ const ParticleFunction *particle_fn = create_particle_function_for_inputs(
+ {&force_socket}, resources, attribute_inputs);
+
+ if (particle_fn == nullptr) {
+ continue;
+ }
+
+ const ParticleForce &force = resources.construct<ParticleFunctionForce>(AT, *particle_fn);
+ forces.append(&force);
+ }
+ return forces;
+}
+
+static Map<std::string, Vector<const ParticleForce *>> collect_forces(
+ nodes::MFNetworkTreeMap &network_map,
+ ResourceCollector &resources,
+ const Map<const fn::MFOutputSocket *, std::string> &attribute_inputs)
+{
+ Map<std::string, Vector<const ParticleForce *>> forces_by_simulation;
+ for (const nodes::DNode *dnode :
+ network_map.tree().nodes_by_type("SimulationNodeParticleSimulation")) {
+ std::string name = dnode_to_path(*dnode);
+ Vector<const ParticleForce *> forces = create_forces_for_particle_simulation(
+ *dnode, network_map, resources, attribute_inputs);
+ forces_by_simulation.add_new(std::move(name), std::move(forces));
+ }
+ return forces_by_simulation;
+}
+
+void update_simulation_in_depsgraph(Depsgraph *depsgraph,
+ Scene *scene_cow,
+ Simulation *simulation_cow)
+{
+ int current_frame = scene_cow->r.cfra;
+ if (simulation_cow->current_frame == current_frame) {
+ return;
+ }
+
+ /* Below we modify the original state/cache. Only the active depsgraph is allowed to do that. */
+ if (!DEG_is_active(depsgraph)) {
+ return;
+ }
+
+ Simulation *simulation_orig = (Simulation *)DEG_get_original_id(&simulation_cow->id);
+
+ nodes::NodeTreeRefMap tree_refs;
+ /* TODO: Use simulation_cow, but need to add depsgraph relations before that. */
+ const nodes::DerivedNodeTree tree{simulation_orig->nodetree, tree_refs};
+ fn::MFNetwork network;
+ ResourceCollector resources;
+ nodes::MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, resources);
+ Map<const fn::MFOutputSocket *, std::string> attribute_inputs = deduplicate_attribute_nodes(
+ network, network_map, tree);
+ fn::mf_network_optimization::constant_folding(network, resources);
+ fn::mf_network_optimization::common_subnetwork_elimination(network);
+ fn::mf_network_optimization::dead_node_removal(network);
+ // WM_clipboard_text_set(network.to_dot().c_str(), false);
+
+ Map<std::string, Vector<const ParticleForce *>> forces_by_simulation = collect_forces(
+ network_map, resources, attribute_inputs);
+
+ if (current_frame == 1) {
+ reinitialize_empty_simulation_states(simulation_orig, tree);
+
+ RNG *rng = BLI_rng_new(0);
+
+ simulation_orig->current_frame = 1;
+ LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
+ state->tot_particles = 1000;
+ CustomData_realloc(&state->attributes, state->tot_particles);
+ ensure_attributes_exist(state);
+
+ CustomDataAttributesRef custom_data_attributes{state->attributes,
+ (uint)state->tot_particles};
+
+ fn::MutableAttributesRef attributes = custom_data_attributes;
+ MutableSpan<float3> positions = attributes.get<float3>("Position");
+ MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
+ MutableSpan<int32_t> ids = attributes.get<int32_t>("ID");
+
+ for (uint i : positions.index_range()) {
+ positions[i] = {i / 100.0f, 0, 0};
+ velocities[i] = {0, BLI_rng_get_float(rng) - 0.5f, BLI_rng_get_float(rng) - 0.5f};
+ ids[i] = i;
+ }
+ }
+
+ BLI_rng_free(rng);
+
+ copy_states_to_cow(simulation_orig, simulation_cow);
+ }
+ else if (current_frame == simulation_orig->current_frame + 1) {
+ update_simulation_state_list(simulation_orig, tree);
+ float time_step = 1.0f / 24.0f;
+ simulation_orig->current_frame = current_frame;
+
+ LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
+ ensure_attributes_exist(state);
+
+ CustomDataAttributesRef custom_data_attributes{state->attributes,
+ (uint)state->tot_particles};
+
+ fn::MutableAttributesRef attributes = custom_data_attributes;
+ MutableSpan<float3> positions = attributes.get<float3>("Position");
+ MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
+
+ Array<float3> force_vectors{(uint)state->tot_particles, {0, 0, 0}};
+ Span<const ParticleForce *> forces = forces_by_simulation.lookup_as(state->head.name);
+ for (const ParticleForce *force : forces) {
+ force->add_force(attributes, force_vectors);
+ }
+
+ for (uint i : positions.index_range()) {
+ velocities[i] += force_vectors[i] * time_step;
+ positions[i] += velocities[i] * time_step;
+ }
+ }
+
+ copy_states_to_cow(simulation_orig, simulation_cow);
+ }
+}
+
+} // namespace blender::sim
diff --git a/tests/gtests/CMakeLists.txt b/tests/gtests/CMakeLists.txt
index 4ce68a6f4c0..282eb9080f5 100644
--- a/tests/gtests/CMakeLists.txt
+++ b/tests/gtests/CMakeLists.txt
@@ -19,7 +19,4 @@ if(WITH_GTESTS)
if(WITH_ALEMBIC)
add_subdirectory(alembic)
endif()
- if(WITH_USD)
- add_subdirectory(usd)
- endif()
endif()
diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.cc b/tests/gtests/blenloader/blendfile_loading_base_test.cc
index 62befae90cd..f15ae615e8a 100644
--- a/tests/gtests/blenloader/blendfile_loading_base_test.cc
+++ b/tests/gtests/blenloader/blendfile_loading_base_test.cc
@@ -50,8 +50,6 @@ extern "C" {
#include "wm.h"
}
-DEFINE_string(test_assets_dir, "", "lib/tests directory from SVN containing the test assets.");
-
BlendfileLoadingBaseTest::~BlendfileLoadingBaseTest()
{
}
@@ -125,19 +123,18 @@ void BlendfileLoadingBaseTest::TearDown()
bool BlendfileLoadingBaseTest::blendfile_load(const char *filepath)
{
- if (FLAGS_test_assets_dir.empty()) {
- ADD_FAILURE()
- << "Pass the flag --test-assets-dir and point to the lib/tests directory from SVN.";
+ const std::string &test_assets_dir = blender::tests::flags_test_asset_dir();
+ if (test_assets_dir.empty()) {
return false;
}
char abspath[FILENAME_MAX];
- BLI_path_join(abspath, sizeof(abspath), FLAGS_test_assets_dir.c_str(), filepath, NULL);
+ BLI_path_join(abspath, sizeof(abspath), test_assets_dir.c_str(), filepath, NULL);
bfile = BLO_read_from_file(abspath, BLO_READ_SKIP_NONE, NULL /* reports */);
if (bfile == nullptr) {
ADD_FAILURE() << "Unable to load file '" << filepath << "' from test assets dir '"
- << FLAGS_test_assets_dir << "'";
+ << test_assets_dir << "'";
return false;
}
return true;
diff --git a/tests/gtests/functions/FN_array_spans_test.cc b/tests/gtests/functions/FN_array_spans_test.cc
index 988d48fa452..6912a62ff17 100644
--- a/tests/gtests/functions/FN_array_spans_test.cc
+++ b/tests/gtests/functions/FN_array_spans_test.cc
@@ -3,7 +3,6 @@
#include "testing/testing.h"
#include "FN_array_spans.hh"
-#include "FN_cpp_types.hh"
#include "FN_generic_vector_array.hh"
#include "BLI_array.hh"
@@ -77,7 +76,7 @@ TEST(virtual_array_span, MultipleArrayConstructor)
TEST(generic_virtual_array_span, TypeConstructor)
{
- GVArraySpan span{CPPType_int32};
+ GVArraySpan span{CPPType::get<int32_t>()};
EXPECT_EQ(span.size(), 0);
EXPECT_TRUE(span.is_empty());
@@ -88,7 +87,7 @@ TEST(generic_virtual_array_span, TypeConstructor)
TEST(generic_virtual_array_span, GSpanConstructor)
{
std::array<std::string, 3> values = {"hello", "world", "test"};
- GVArraySpan span{GSpan(CPPType_string, values.data(), 3), 5};
+ GVArraySpan span{GSpan(CPPType::get<std::string>(), values.data(), 3), 5};
EXPECT_EQ(span.size(), 5);
EXPECT_FALSE(span.is_empty());
EXPECT_EQ(span[0][0], values.data());
@@ -119,7 +118,7 @@ TEST(generic_virtual_array_span, IsSingleArray1)
TEST(generic_virtual_array_span, IsSingleArray2)
{
- GVectorArray vectors{CPPType_int32, 3};
+ GVectorArray vectors{CPPType::get<int32_t>(), 3};
GVectorArrayRef<int> vectors_ref = vectors;
vectors_ref.append(1, 4);
diff --git a/tests/gtests/functions/FN_attributes_ref_test.cc b/tests/gtests/functions/FN_attributes_ref_test.cc
index 1c05bb930db..0b0afdc210f 100644
--- a/tests/gtests/functions/FN_attributes_ref_test.cc
+++ b/tests/gtests/functions/FN_attributes_ref_test.cc
@@ -2,7 +2,6 @@
#include "BLI_float3.hh"
#include "FN_attributes_ref.hh"
-#include "FN_cpp_types.hh"
#include "testing/testing.h"
diff --git a/tests/gtests/functions/FN_cpp_type_test.cc b/tests/gtests/functions/FN_cpp_type_test.cc
index da5ce3416ce..78731f9c987 100644
--- a/tests/gtests/functions/FN_cpp_type_test.cc
+++ b/tests/gtests/functions/FN_cpp_type_test.cc
@@ -3,7 +3,6 @@
#include "testing/testing.h"
#include "FN_cpp_type.hh"
-#include "FN_cpp_types.hh"
namespace blender::fn {
@@ -76,6 +75,8 @@ struct TestType {
MAKE_CPP_TYPE(TestType, TestType)
+const CPPType &CPPType_TestType = CPPType::get<TestType>();
+
TEST(cpp_type, Size)
{
EXPECT_EQ(CPPType_TestType.size(), sizeof(TestType));
@@ -312,7 +313,7 @@ TEST(cpp_type, DebugPrint)
{
int value = 42;
std::stringstream ss;
- CPPType_int32.debug_print((void *)&value, ss);
+ CPPType::get<int32_t>().debug_print((void *)&value, ss);
std::string text = ss.str();
EXPECT_EQ(text, "42");
}
diff --git a/tests/gtests/functions/FN_generic_vector_array_test.cc b/tests/gtests/functions/FN_generic_vector_array_test.cc
index 7ce7b543218..cfca678ad27 100644
--- a/tests/gtests/functions/FN_generic_vector_array_test.cc
+++ b/tests/gtests/functions/FN_generic_vector_array_test.cc
@@ -1,6 +1,5 @@
/* Apache License, Version 2.0 */
-#include "FN_cpp_types.hh"
#include "FN_generic_vector_array.hh"
#include "testing/testing.h"
@@ -9,19 +8,19 @@ namespace blender::fn {
TEST(generic_vector_array, Constructor)
{
- GVectorArray vectors{CPPType_int32, 3};
+ GVectorArray vectors{CPPType::get<int32_t>(), 3};
EXPECT_EQ(vectors.size(), 3);
EXPECT_EQ(vectors.lengths().size(), 3);
EXPECT_EQ(vectors.starts().size(), 3);
EXPECT_EQ(vectors.lengths()[0], 0);
EXPECT_EQ(vectors.lengths()[1], 0);
EXPECT_EQ(vectors.lengths()[2], 0);
- EXPECT_EQ(vectors.type(), CPPType_int32);
+ EXPECT_EQ(vectors.type(), CPPType::get<int32_t>());
}
TEST(generic_vector_array, Append)
{
- GVectorArray vectors{CPPType_string, 3};
+ GVectorArray vectors{CPPType::get<std::string>(), 3};
std::string value = "hello";
vectors.append(0, &value);
value = "world";
@@ -39,7 +38,7 @@ TEST(generic_vector_array, Append)
TEST(generic_vector_array, AsArraySpan)
{
- GVectorArray vectors{CPPType_int32, 3};
+ GVectorArray vectors{CPPType::get<int32_t>(), 3};
int value = 3;
vectors.append(0, &value);
vectors.append(0, &value);
@@ -49,7 +48,7 @@ TEST(generic_vector_array, AsArraySpan)
vectors.append(2, &value);
GVArraySpan span = vectors;
- EXPECT_EQ(span.type(), CPPType_int32);
+ EXPECT_EQ(span.type(), CPPType::get<int32_t>());
EXPECT_EQ(span.size(), 3);
EXPECT_EQ(span[0].size(), 2);
EXPECT_EQ(span[1].size(), 0);
@@ -60,7 +59,7 @@ TEST(generic_vector_array, AsArraySpan)
TEST(generic_vector_array, TypedRef)
{
- GVectorArray vectors{CPPType_int32, 4};
+ GVectorArray vectors{CPPType::get<int32_t>(), 4};
GVectorArrayRef<int> ref = vectors.typed<int>();
ref.append(0, 2);
ref.append(0, 6);
@@ -84,7 +83,7 @@ TEST(generic_vector_array, TypedRef)
TEST(generic_vector_array, Extend)
{
- GVectorArray vectors{CPPType_int32, 3};
+ GVectorArray vectors{CPPType::get<int32_t>(), 3};
GVectorArrayRef<int> ref = vectors;
ref.extend(1, {5, 6, 7});
diff --git a/tests/gtests/functions/FN_multi_function_network_test.cc b/tests/gtests/functions/FN_multi_function_network_test.cc
index 5507733c8be..35af8300cfa 100644
--- a/tests/gtests/functions/FN_multi_function_network_test.cc
+++ b/tests/gtests/functions/FN_multi_function_network_test.cc
@@ -2,7 +2,6 @@
#include "testing/testing.h"
-#include "FN_cpp_types.hh"
#include "FN_multi_function_builder.hh"
#include "FN_multi_function_network.hh"
#include "FN_multi_function_network_evaluation.hh"
@@ -195,7 +194,7 @@ TEST(multi_function_network, Test2)
Array<int> input_value_1 = {3, 6};
int input_value_2 = 4;
- GVectorArray output_value_1(CPPType_int32, 5);
+ GVectorArray output_value_1(CPPType::get<int32_t>(), 5);
Array<int> output_value_2(5, -1);
MFParamsBuilder params(network_fn, 5);
@@ -221,14 +220,14 @@ TEST(multi_function_network, Test2)
EXPECT_EQ(output_value_2[4], 39);
}
{
- GVectorArray input_value_1(CPPType_int32, 3);
+ GVectorArray input_value_1(CPPType::get<int32_t>(), 3);
GVectorArrayRef<int> input_value_ref_1 = input_value_1;
input_value_ref_1.extend(0, {3, 4, 5});
input_value_ref_1.extend(1, {1, 2});
Array<int> input_value_2 = {4, 2, 3};
- GVectorArray output_value_1(CPPType_int32, 3);
+ GVectorArray output_value_1(CPPType::get<int32_t>(), 3);
Array<int> output_value_2(3, -1);
MFParamsBuilder params(network_fn, 3);
diff --git a/tests/gtests/functions/FN_multi_function_test.cc b/tests/gtests/functions/FN_multi_function_test.cc
index 8cc8f91a300..66039e463ed 100644
--- a/tests/gtests/functions/FN_multi_function_test.cc
+++ b/tests/gtests/functions/FN_multi_function_test.cc
@@ -2,7 +2,6 @@
#include "testing/testing.h"
-#include "FN_cpp_types.hh"
#include "FN_multi_function.hh"
#include "FN_multi_function_builder.hh"
@@ -126,7 +125,7 @@ TEST(multi_function, CreateRangeFunction)
{
CreateRangeFunction fn;
- GVectorArray ranges(CPPType_uint32, 5);
+ GVectorArray ranges(CPPType::get<int32_t>(), 5);
GVectorArrayRef<uint> ranges_ref(ranges);
Array<uint> sizes = {3, 0, 6, 1, 4};
@@ -173,9 +172,9 @@ class GenericAppendFunction : public MultiFunction {
TEST(multi_function, GenericAppendFunction)
{
- GenericAppendFunction fn(CPPType_int32);
+ GenericAppendFunction fn(CPPType::get<int32_t>());
- GVectorArray vectors(CPPType_int32, 4);
+ GVectorArray vectors(CPPType::get<int32_t>(), 4);
GVectorArrayRef<int> vectors_ref(vectors);
vectors_ref.append(0, 1);
vectors_ref.append(0, 2);
@@ -318,7 +317,7 @@ TEST(multi_function, CustomMF_Constant)
TEST(multi_function, CustomMF_GenericConstant)
{
int value = 42;
- CustomMF_GenericConstant fn{CPPType_int32, (const void *)&value};
+ CustomMF_GenericConstant fn{CPPType::get<int32_t>(), (const void *)&value};
EXPECT_EQ(fn.param_name(0), "42");
Array<int> outputs(4, 0);
@@ -342,7 +341,7 @@ TEST(multi_function, CustomMF_GenericConstantArray)
CustomMF_GenericConstantArray fn{GSpan(Span(values))};
EXPECT_EQ(fn.param_name(0), "[3, 4, 5, 6, ]");
- GVectorArray g_vector_array{CPPType_int32, 4};
+ GVectorArray g_vector_array{CPPType::get<int32_t>(), 4};
GVectorArrayRef<int> vector_array = g_vector_array;
MFParamsBuilder params(fn, g_vector_array.size());
diff --git a/tests/gtests/functions/FN_spans_test.cc b/tests/gtests/functions/FN_spans_test.cc
index 8968d49c082..3172cdc7170 100644
--- a/tests/gtests/functions/FN_spans_test.cc
+++ b/tests/gtests/functions/FN_spans_test.cc
@@ -2,14 +2,13 @@
#include "testing/testing.h"
-#include "FN_cpp_types.hh"
#include "FN_spans.hh"
namespace blender::fn {
TEST(generic_span, TypeConstructor)
{
- GSpan span(CPPType_float);
+ GSpan span(CPPType::get<float>());
EXPECT_EQ(span.size(), 0);
EXPECT_EQ(span.typed<float>().size(), 0);
EXPECT_TRUE(span.is_empty());
@@ -19,7 +18,7 @@ TEST(generic_span, BufferAndSizeConstructor)
{
int values[4] = {6, 7, 3, 2};
void *buffer = (void *)values;
- GSpan span(CPPType_int32, buffer, 4);
+ GSpan span(CPPType::get<int32_t>(), buffer, 4);
EXPECT_EQ(span.size(), 4);
EXPECT_FALSE(span.is_empty());
EXPECT_EQ(span.typed<int>().size(), 4);
@@ -31,7 +30,7 @@ TEST(generic_span, BufferAndSizeConstructor)
TEST(generic_mutable_span, TypeConstructor)
{
- GMutableSpan span(CPPType_int32);
+ GMutableSpan span(CPPType::get<int32_t>());
EXPECT_EQ(span.size(), 0);
EXPECT_TRUE(span.is_empty());
}
@@ -40,7 +39,7 @@ TEST(generic_mutable_span, BufferAndSizeConstructor)
{
int values[4] = {4, 7, 3, 5};
void *buffer = (void *)values;
- GMutableSpan span(CPPType_int32, buffer, 4);
+ GMutableSpan span(CPPType::get<int32_t>(), buffer, 4);
EXPECT_EQ(span.size(), 4);
EXPECT_FALSE(span.is_empty());
EXPECT_EQ(span.typed<int>().size(), 4);
@@ -127,7 +126,7 @@ TEST(virtual_span, SingleConstructor)
TEST(generic_virtual_span, TypeConstructor)
{
- GVSpan span(CPPType_int32);
+ GVSpan span(CPPType::get<int32_t>());
EXPECT_EQ(span.size(), 0);
EXPECT_TRUE(span.is_empty());
EXPECT_FALSE(span.is_single_element());
@@ -139,7 +138,7 @@ TEST(generic_virtual_span, TypeConstructor)
TEST(generic_virtual_span, GenericSpanConstructor)
{
int values[4] = {3, 4, 5, 6};
- GVSpan span{GSpan(CPPType_int32, values, 4)};
+ GVSpan span{GSpan(CPPType::get<int32_t>(), values, 4)};
EXPECT_EQ(span.size(), 4);
EXPECT_FALSE(span.is_empty());
EXPECT_EQ(span[0], &values[0]);
@@ -167,7 +166,7 @@ TEST(generic_virtual_span, SpanConstructor)
{
std::array<int, 3> values = {6, 7, 8};
GVSpan span{Span<int>(values)};
- EXPECT_EQ(span.type(), CPPType_int32);
+ EXPECT_EQ(span.type(), CPPType::get<int32_t>());
EXPECT_EQ(span.size(), 3);
EXPECT_EQ(span[0], &values[0]);
EXPECT_EQ(span[1], &values[1]);
@@ -190,7 +189,7 @@ TEST(generic_virtual_span, SpanConstructor)
TEST(generic_virtual_span, SingleConstructor)
{
int value = 5;
- GVSpan span = GVSpan::FromSingle(CPPType_int32, &value, 3);
+ GVSpan span = GVSpan::FromSingle(CPPType::get<int32_t>(), &value, 3);
EXPECT_EQ(span.size(), 3);
EXPECT_FALSE(span.is_empty());
EXPECT_EQ(span[0], &value);
diff --git a/tests/gtests/runner/BlenderAddTests.cmake b/tests/gtests/runner/BlenderAddTests.cmake
new file mode 100644
index 00000000000..c4f5c8aba8a
--- /dev/null
+++ b/tests/gtests/runner/BlenderAddTests.cmake
@@ -0,0 +1,3 @@
+# Disable ASAN leak detection when trying to discover tests.
+set(ENV{ASAN_OPTIONS} "detect_leaks=0")
+include(GoogleTestAddTests)
diff --git a/tests/gtests/runner/CMakeLists.txt b/tests/gtests/runner/CMakeLists.txt
index e7cbabfe7c6..4da0bce09a4 100644
--- a/tests/gtests/runner/CMakeLists.txt
+++ b/tests/gtests/runner/CMakeLists.txt
@@ -60,4 +60,14 @@ setup_liblinks(blender_test)
# exposes those tests individually to the ctest runner.
# See https://cmake.org/cmake/help/v3.18/module/GoogleTest.html
include(GoogleTest)
-gtest_discover_tests(blender_test)
+
+set(_GOOGLETEST_DISCOVER_TESTS_SCRIPT
+ ${CMAKE_CURRENT_LIST_DIR}/BlenderAddTests.cmake
+)
+
+gtest_discover_tests(blender_test
+ # So that unit tests know where to find files:
+ EXTRA_ARGS
+ --test-assets-dir "${CMAKE_SOURCE_DIR}/../lib/tests"
+ --test-release-dir "$<TARGET_FILE_DIR:blender>/${BLENDER_VERSION}"
+)
diff --git a/tests/gtests/testing/testing.h b/tests/gtests/testing/testing.h
index 32cb6e7f18a..34928035b7d 100644
--- a/tests/gtests/testing/testing.h
+++ b/tests/gtests/testing/testing.h
@@ -7,6 +7,15 @@
#include "glog/logging.h"
#include "gtest/gtest.h"
+namespace blender::tests {
+
+/* These strings are passed on the CLI with the --test-asset-dir and --test-release-dir arguments.
+ * The arguments are added automatically when invoking tests via `ctest`. */
+const std::string &flags_test_asset_dir(); /* ../lib/tests in the SVN directory. */
+const std::string &flags_test_release_dir(); /* bin/{blender version} in the build directory. */
+
+} // namespace blender::tests
+
#define EXPECT_V3_NEAR(a, b, eps) \
{ \
EXPECT_NEAR(a[0], b[0], eps); \
diff --git a/tests/gtests/testing/testing_main.cc b/tests/gtests/testing/testing_main.cc
index 6b3a8e5515d..0acdcf3a8a5 100644
--- a/tests/gtests/testing/testing_main.cc
+++ b/tests/gtests/testing/testing_main.cc
@@ -19,6 +19,31 @@
#include "testing/testing.h"
+DEFINE_string(test_assets_dir, "", "lib/tests directory from SVN containing the test assets.");
+DEFINE_string(test_release_dir, "", "bin/{blender version} directory of the current build.");
+
+namespace blender::tests {
+
+const std::string &flags_test_asset_dir()
+{
+ if (FLAGS_test_assets_dir.empty()) {
+ ADD_FAILURE()
+ << "Pass the flag --test-assets-dir and point to the lib/tests directory from SVN.";
+ }
+ return FLAGS_test_assets_dir;
+}
+
+const std::string &flags_test_release_dir()
+{
+ if (FLAGS_test_release_dir.empty()) {
+ ADD_FAILURE()
+ << "Pass the flag --test-release-dir and point to the bin/{blender version} directory.";
+ }
+ return FLAGS_test_release_dir;
+}
+
+} // namespace blender::tests
+
int main(int argc, char **argv)
{
testing::InitGoogleTest(&argc, argv);
diff --git a/tests/gtests/usd/CMakeLists.txt b/tests/gtests/usd/CMakeLists.txt
deleted file mode 100644
index 0caa2fac155..00000000000
--- a/tests/gtests/usd/CMakeLists.txt
+++ /dev/null
@@ -1,109 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# The Original Code is Copyright (C) 2019, Blender Foundation
-# All rights reserved.
-# ***** END GPL LICENSE BLOCK *****
-
-# This suppresses the warning "This file includes at least one deprecated or antiquated
-# header which may be removed without further notice at a future date", which is caused
-# by the USD library including <ext/hash_set> on Linux. This has been reported at:
-# https://github.com/PixarAnimationStudios/USD/issues/1057.
-if(UNIX AND NOT APPLE)
- add_definitions(-D_GLIBCXX_PERMIT_BACKWARD_HASH)
-endif()
-if(WIN32)
- add_definitions(-DNOMINMAX)
-endif()
-add_definitions(-DPXR_STATIC)
-
-set(INC
- .
- ..
- ../../../source/blender/blenlib
- ../../../source/blender/blenkernel
- ../../../source/blender/io/common
- ../../../source/blender/io/usd
- ../../../source/blender/makesdna
- ../../../source/blender/depsgraph
- ${USD_INCLUDE_DIRS}
- ${BOOST_INCLUDE_DIR}
- ${TBB_INCLUDE_DIR}
-)
-
-set(LIB
- bf_blenloader_test
- bf_blenloader
-
- # Should not be needed but gives windows linker errors if the ocio libs are linked before this:
- bf_intern_opencolorio
- bf_gpu
-
- bf_usd
- bf_io_common
-
- ${BOOST_LIBRARIES}
- ${TBB_LIBRARIES}
-)
-
-include_directories(${INC})
-
-setup_libdirs()
-get_property(BLENDER_SORTED_LIBS GLOBAL PROPERTY BLENDER_SORTED_LIBS_PROP)
-
-set(SRC
- abstract_hierarchy_iterator_test.cc
- hierarchy_context_order_test.cc
- object_identifier_test.cc
-)
-
-# TODO(Sybren): re-enable this unit test.
-# if(NOT APPLE)
-# # TODO(Sybren): This unit test has only been tested on Linux, and should possibly be
-# # restructured to support other platforms as well.
-# list(APPEND SRC usd_stage_creation_test.cc)
-# endif()
-
-
-if(WITH_BUILDINFO)
- list(APPEND SRC
- "$<TARGET_OBJECTS:buildinfoobj>"
- )
-endif()
-
-# get_cmake_property(_variableNames VARIABLES)
-# list(SORT _variableNames)
-# foreach(_variableName ${_variableNames})
-# message(STATUS "${_variableName}=${${_variableName}}")
-# endforeach()
-
-# Works on Linux, not on Windows:
-# set(_usd_DATAFILES_DIR "${CMAKE_INSTALL_PREFIX}/${BLENDER_VERSION}/datafiles/usd")
-set(_usd_DATAFILES_DIR "$<TARGET_FILE_DIR:blender>/${BLENDER_VERSION}/datafiles/usd")
-
-BLENDER_SRC_GTEST_EX(
- NAME usd
- SRC "${SRC}"
- EXTRA_LIBS "${LIB}"
- COMMAND_ARGS
- --test-assets-dir "${CMAKE_SOURCE_DIR}/../lib/tests"
-)
-# TODO(Sybren): add the below CLI argument to the test when the usd_stage_creation_test.cc
-# test is reenabled.
-# --test-usd-datafiles-dir "${_usd_DATAFILES_DIR}"
-unset(_usd_DATAFILES_DIR)
-
-setup_liblinks(usd_test)