diff options
author | Antonio Vazquez <blendergit@gmail.com> | 2020-08-04 17:44:16 +0300 |
---|---|---|
committer | Antonio Vazquez <blendergit@gmail.com> | 2020-08-04 17:44:16 +0300 |
commit | 6197d4dafa8ee623f3779c883babb20a7555c992 (patch) | |
tree | 082750b7cb6f6c2612fa55597858f17310e83993 | |
parent | f0ed70eb12b81ed3fc97d7eeb88c2d7131aacb81 (diff) | |
parent | 21c31885eda9a2c041d975428cff0ec23faeffc6 (diff) |
Merge branch 'master' into greasepencil-edit-curve
131 files changed, 2156 insertions, 1177 deletions
diff --git a/build_files/buildbot/buildbot_utils.py b/build_files/buildbot/buildbot_utils.py index e8adf5ba810..287c3854377 100644 --- a/build_files/buildbot/buildbot_utils.py +++ b/build_files/buildbot/buildbot_utils.py @@ -67,6 +67,7 @@ def create_builder_from_arguments(): parser = argparse.ArgumentParser() parser.add_argument('builder_name') parser.add_argument('branch', default='master', nargs='?') + parser.add_argument("--codesign", action="store_true") args = parser.parse_args() return Builder(args.builder_name, args.branch) diff --git a/build_files/buildbot/worker_bundle_dmg.py b/build_files/buildbot/worker_bundle_dmg.py index cd3da85e12a..31e10d51610 100755 --- a/build_files/buildbot/worker_bundle_dmg.py +++ b/build_files/buildbot/worker_bundle_dmg.py @@ -82,6 +82,10 @@ def create_argument_parser(): type=Path, help="Optional path to applescript to set up folder looks of DMG." "If not provided default Blender's one is used.") + parser.add_argument( + '--codesign', + action="store_true" + help="Code sign and notarize DMG contents.") return parser @@ -395,7 +399,8 @@ def create_final_dmg(app_bundles: List[Path], dmg_filepath: Path, background_image_filepath: Path, volume_name: str, - applescript: Path) -> None: + applescript: Path, + codesign: bool) -> None: """ Create DMG with all app bundles @@ -421,7 +426,8 @@ def create_final_dmg(app_bundles: List[Path], # # This allows to recurs into the content of bundles without worrying about # possible interfereice of Application symlink. - codesign_app_bundles_in_dmg(mount_directory) + if codesign: + codesign_app_bundles_in_dmg(mount_directory) copy_background_if_needed(background_image_filepath, mount_directory) create_applications_link(mount_directory) @@ -434,7 +440,8 @@ def create_final_dmg(app_bundles: List[Path], compress_dmg(writable_dmg_filepath, dmg_filepath) writable_dmg_filepath.unlink() - codesign_and_notarize_dmg(dmg_filepath) + if codesign: + codesign_and_notarize_dmg(dmg_filepath) def ensure_dmg_extension(filepath: Path) -> Path: @@ -521,6 +528,7 @@ def main(): source_dir = args.source_dir.absolute() background_image_filepath = get_background_image(args.background_image) applescript = get_applescript(args.applescript) + codesign = args.codesign app_bundles = collect_and_log_app_bundles(source_dir) if not app_bundles: @@ -535,7 +543,8 @@ def main(): dmg_filepath, background_image_filepath, volume_name, - applescript) + applescript, + codesign) if __name__ == "__main__": diff --git a/build_files/buildbot/worker_compile.py b/build_files/buildbot/worker_compile.py index f1357e1864f..8e19c9436f8 100644 --- a/build_files/buildbot/worker_compile.py +++ b/build_files/buildbot/worker_compile.py @@ -24,7 +24,7 @@ import shutil import buildbot_utils def get_cmake_options(builder): - post_install_script = os.path.join( + codesign_script = os.path.join( builder.blender_dir, 'build_files', 'buildbot', 'worker_codesign.cmake') config_file = "build_files/cmake/config/blender_release.cmake" @@ -36,7 +36,8 @@ def get_cmake_options(builder): options.append('-DCMAKE_OSX_DEPLOYMENT_TARGET=10.9') elif builder.platform == 'win': options.extend(['-G', 'Visual Studio 16 2019', '-A', 'x64']) - options.extend(['-DPOSTINSTALL_SCRIPT:PATH=' + post_install_script]) + if builder.codesign: + options.extend(['-DPOSTINSTALL_SCRIPT:PATH=' + codesign_script]) elif builder.platform == 'linux': config_file = "build_files/buildbot/config/blender_linux.cmake" diff --git a/build_files/buildbot/worker_pack.py b/build_files/buildbot/worker_pack.py index 87ee49c87d8..96c8db8e6c8 100644 --- a/build_files/buildbot/worker_pack.py +++ b/build_files/buildbot/worker_pack.py @@ -117,6 +117,8 @@ def pack_mac(builder): if info.is_development_build: background_image = os.path.join(release_dir, 'buildbot', 'background.tif') command += ['--background-image', background_image] + if builder.codesign: + command += ['--codesign'] command += [builder.install_dir] buildbot_utils.call(command) @@ -150,7 +152,8 @@ def pack_win(builder): package_filename = package_name + '.msi' package_filepath = os.path.join(builder.build_dir, package_filename) - sign_file_or_directory(package_filepath) + if builder.codesign: + sign_file_or_directory(package_filepath) package_files += [(package_filepath, package_filename)] diff --git a/extern/audaspace/bindings/python/PySound.cpp b/extern/audaspace/bindings/python/PySound.cpp index 62ee3435e82..f2debccfd33 100644 --- a/extern/audaspace/bindings/python/PySound.cpp +++ b/extern/audaspace/bindings/python/PySound.cpp @@ -1395,9 +1395,9 @@ PyDoc_STRVAR(M_aud_Sound_threshold_doc, " all between to 0.\n\n" " :arg threshold: Threshold value over which an amplitude counts\n" " non-zero.\n\n" - ":type threshold: float\n" - ":return: The created :class:`Sound` object.\n" - ":rtype: :class:`Sound`"); + " :type threshold: float\n" + " :return: The created :class:`Sound` object.\n" + " :rtype: :class:`Sound`"); static PyObject * Sound_threshold(Sound* self, PyObject* args) diff --git a/extern/audaspace/src/respec/JOSResampleReader.cpp b/extern/audaspace/src/respec/JOSResampleReader.cpp index 6753a2e8b6b..378986fee28 100644 --- a/extern/audaspace/src/respec/JOSResampleReader.cpp +++ b/extern/audaspace/src/respec/JOSResampleReader.cpp @@ -119,8 +119,8 @@ void JOSResampleReader::updateBuffer(int size, double factor, int samplesize) P = int_to_fp(m_L) - P;\ \ end = std::floor((m_len - 1) / double(m_L) + m_P) - 1;\ - if(m_cache_valid - m_n - 2 < end)\ - end = m_cache_valid - m_n - 2;\ + if(m_cache_valid - int(m_n) - 2 < end)\ + end = m_cache_valid - int(m_n) - 2;\ \ data = buf + (m_n + 2 + end) * m_channels - 1;\ l = fp_to_int(P);\ @@ -166,8 +166,8 @@ void JOSResampleReader::updateBuffer(int size, double factor, int samplesize) P = 0 - P;\ \ end = (int_to_fp(m_len) - P) / P_increment - 1;\ - if(m_cache_valid - m_n - 2 < end)\ - end = m_cache_valid - m_n - 2;\ + if(m_cache_valid - int(m_n) - 2 < end)\ + end = m_cache_valid - int(m_n) - 2;\ \ P += P_increment * end;\ data = buf + (m_n + 2 + end) * m_channels - 1;\ diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 9043cd81293..f4354d5166e 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -923,7 +923,8 @@ static void create_subd_mesh(Scene *scene, /* Sync */ -static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob, BL::Scene b_scene) +static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob, + BL::Scene /*b_scene*/) { BL::Object::modifiers_iterator b_mod; diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index 6dcc7f7b3dd..07b345baff8 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -112,3 +112,4 @@ set_source_files_properties(util_avxf_avx_test.cpp PROPERTIES COMPILE_FLAGS "${C CYCLES_TEST(util_avxf_avx "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") set_source_files_properties(util_avxf_avx2_test.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}") CYCLES_TEST(util_avxf_avx2 "cycles_util;bf_intern_numaapi;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") +CYCLES_TEST(util_transform "cycles_util;${OPENIMAGEIO_LIBRARIES};${BOOST_LIBRARIES}") diff --git a/intern/cycles/test/util_transform_test.cpp b/intern/cycles/test/util_transform_test.cpp new file mode 100644 index 00000000000..58ce0fdfee4 --- /dev/null +++ b/intern/cycles/test/util_transform_test.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2011-2020 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testing/testing.h" + +#include "util/util_transform.h" +#include "util/util_vector.h" + +CCL_NAMESPACE_BEGIN + +TEST(transform_motion_decompose, Degenerated) +{ + // Simple case: single degenerated matrix. + { + vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f)}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_TRUE(transform_decomposed_isfinite_safe(&decomp[0])); + } + + // Copy from previous to current. + { + vector<Transform> motion = {transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f)), + transform_scale(0.0f, 0.0f, 0.0f)}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_NEAR(len(decomp[1].x - decomp[0].x), 0.0f, 1e-6f); + } + + // Copy from next to current. + { + vector<Transform> motion = {transform_scale(0.0f, 0.0f, 0.0f), + transform_rotate(M_PI_4_F, make_float3(1.0f, 1.0f, 1.0f))}; + vector<DecomposedTransform> decomp(motion.size()); + transform_motion_decompose(decomp.data(), motion.data(), motion.size()); + EXPECT_NEAR(len(decomp[0].x - decomp[1].x), 0.0f, 1e-6f); + } +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_math_fast.h b/intern/cycles/util/util_math_fast.h index e979bd9e0c0..4f92d2f10d3 100644 --- a/intern/cycles/util/util_math_fast.h +++ b/intern/cycles/util/util_math_fast.h @@ -87,7 +87,7 @@ ccl_device_inline int fast_rint(float x) /* Single roundps instruction on SSE4.1+ (for gcc/clang at least). */ return float_to_int(rintf(x)); #else - /* emulate rounding by adding/substracting 0.5. */ + /* emulate rounding by adding/subtracting 0.5. */ return float_to_int(x + copysignf(0.5f, x)); #endif } diff --git a/intern/cycles/util/util_math_float4.h b/intern/cycles/util/util_math_float4.h index cd4b3e3b74c..ec5328adb31 100644 --- a/intern/cycles/util/util_math_float4.h +++ b/intern/cycles/util/util_math_float4.h @@ -477,6 +477,24 @@ ccl_device_inline float4 safe_divide_float4_float(const float4 a, const float b) return (b != 0.0f) ? a / b : make_float4(0.0f, 0.0f, 0.0f, 0.0f); } +ccl_device_inline bool isfinite4_safe(float4 v) +{ + return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z) && isfinite_safe(v.w); +} + +ccl_device_inline float4 ensure_finite4(float4 v) +{ + if (!isfinite_safe(v.x)) + v.x = 0.0f; + if (!isfinite_safe(v.y)) + v.y = 0.0f; + if (!isfinite_safe(v.z)) + v.z = 0.0f; + if (!isfinite_safe(v.w)) + v.w = 0.0f; + return v; +} + CCL_NAMESPACE_END #endif /* __UTIL_MATH_FLOAT4_H__ */ diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 101122740d7..6417752f704 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -269,17 +269,17 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf /* extract scale and shear first */ float3 scale, shear; scale.x = len(colx); - colx /= scale.x; + colx = safe_divide_float3_float(colx, scale.x); shear.z = dot(colx, coly); coly -= shear.z * colx; scale.y = len(coly); - coly /= scale.y; + coly = safe_divide_float3_float(coly, scale.y); shear.y = dot(colx, colz); colz -= shear.y * colx; shear.x = dot(coly, colz); colz -= shear.x * coly; scale.z = len(colz); - colz /= scale.z; + colz = safe_divide_float3_float(colz, scale.z); transform_set_column(&M, 0, colx); transform_set_column(&M, 1, coly); @@ -300,6 +300,7 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size) { + /* Decompose and correct rotation. */ for (size_t i = 0; i < size; i++) { transform_decompose(decomp + i, motion + i); @@ -310,6 +311,27 @@ void transform_motion_decompose(DecomposedTransform *decomp, const Transform *mo decomp[i].x = -decomp[i].x; } } + + /* Copy rotation to decomposed transform where scale is degenerate. This avoids weird object + * rotation interpolation when the scale goes to 0 for a time step. + * + * Note that this is very simple and naive implementation, which only deals with degenerated + * scale happening only on one frame. It is possible to improve it further by interpolating + * rotation into s degenerated range using rotation from timesteps from adjacent non-degenerated + * time steps. */ + for (size_t i = 0; i < size; i++) { + const float3 scale = make_float3(decomp[i].y.w, decomp[i].z.w, decomp[i].w.w); + if (!is_zero(scale)) { + continue; + } + + if (i > 0) { + decomp[i].x = decomp[i - 1].x; + } + else if (i < size - 1) { + decomp[i].x = decomp[i + 1].x; + } + } } Transform transform_from_viewplane(BoundBox2D &viewplane) diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index d0a6264d5cf..d8bbd389aa6 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -466,6 +466,17 @@ ccl_device void transform_motion_array_interpolate(Transform *tfm, transform_compose(tfm, &decomp); } +ccl_device_inline bool transform_isfinite_safe(Transform *tfm) +{ + return isfinite4_safe(tfm->x) && isfinite4_safe(tfm->y) && isfinite4_safe(tfm->z); +} + +ccl_device_inline bool transform_decomposed_isfinite_safe(DecomposedTransform *decomp) +{ + return isfinite4_safe(decomp->x) && isfinite4_safe(decomp->y) && isfinite4_safe(decomp->z) && + isfinite4_safe(decomp->w); +} + #ifndef __KERNEL_GPU__ class BoundBox2D; diff --git a/intern/itasc/Scene.cpp b/intern/itasc/Scene.cpp index 5438a005d7c..0d2486ceac7 100644 --- a/intern/itasc/Scene.cpp +++ b/intern/itasc/Scene.cpp @@ -16,532 +16,623 @@ namespace iTaSC { class SceneLock : public ControlledObject::JointLockCallback { -private: - Scene* m_scene; - Range m_qrange; - -public: - SceneLock(Scene* scene) : - m_scene(scene), m_qrange(0,0) {} - virtual ~SceneLock() {} - - void setRange(Range& range) - { - m_qrange = range; - } - // lock a joint, no need to update output - virtual void lockJoint(unsigned int q_nr, unsigned int ndof) - { - q_nr += m_qrange.start; - project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - } - // lock a joint and update output in view of reiteration - virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double* qdot) - { - q_nr += m_qrange.start; - project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); - // update the output vector so that the movement of this joint will be - // taken into account and we can put the joint back in its initial position - // which means that the jacobian doesn't need to be changed - for (unsigned int i=0 ;i<ndof ; ++i, ++q_nr) { - m_scene->m_ydot -= m_scene->m_A.col(q_nr)*qdot[i]; - } - } + private: + Scene *m_scene; + Range m_qrange; + + public: + SceneLock(Scene *scene) : m_scene(scene), m_qrange(0, 0) + { + } + virtual ~SceneLock() + { + } + + void setRange(Range &range) + { + m_qrange = range; + } + // lock a joint, no need to update output + virtual void lockJoint(unsigned int q_nr, unsigned int ndof) + { + q_nr += m_qrange.start; + project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); + } + // lock a joint and update output in view of reiteration + virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double *qdot) + { + q_nr += m_qrange.start; + project(m_scene->m_Wq, Range(q_nr, ndof), m_qrange).setZero(); + // update the output vector so that the movement of this joint will be + // taken into account and we can put the joint back in its initial position + // which means that the jacobian doesn't need to be changed + for (unsigned int i = 0; i < ndof; ++i, ++q_nr) { + m_scene->m_ydot -= m_scene->m_A.col(q_nr) * qdot[i]; + } + } }; -Scene::Scene(): - m_A(), m_B(), m_Atemp(), m_Wq(), m_Jf(), m_Jq(), m_Ju(), m_Cf(), m_Cq(), m_Jf_inv(), - m_Vf(),m_Uf(), m_Wy(), m_ydot(), m_qdot(), m_xdot(), m_Sf(),m_tempf(), - m_ncTotal(0),m_nqTotal(0),m_nuTotal(0),m_nsets(0), - m_solver(NULL),m_cache(NULL) +Scene::Scene() + : m_A(), + m_B(), + m_Atemp(), + m_Wq(), + m_Jf(), + m_Jq(), + m_Ju(), + m_Cf(), + m_Cq(), + m_Jf_inv(), + m_Vf(), + m_Uf(), + m_Wy(), + m_ydot(), + m_qdot(), + m_xdot(), + m_Sf(), + m_tempf(), + m_ncTotal(0), + m_nqTotal(0), + m_nuTotal(0), + m_nsets(0), + m_solver(NULL), + m_cache(NULL) { - m_minstep = 0.01; - m_maxstep = 0.06; + m_minstep = 0.01; + m_maxstep = 0.06; } -Scene::~Scene() +Scene::~Scene() { - ConstraintMap::iterator constraint_it; - while ((constraint_it = constraints.begin()) != constraints.end()) { - delete constraint_it->second; - constraints.erase(constraint_it); - } - ObjectMap::iterator object_it; - while ((object_it = objects.begin()) != objects.end()) { - delete object_it->second; - objects.erase(object_it); - } + ConstraintMap::iterator constraint_it; + while ((constraint_it = constraints.begin()) != constraints.end()) { + delete constraint_it->second; + constraints.erase(constraint_it); + } + ObjectMap::iterator object_it; + while ((object_it = objects.begin()) != objects.end()) { + delete object_it->second; + objects.erase(object_it); + } } bool Scene::setParam(SceneParam paramId, double value) { - switch (paramId) { - case MIN_TIMESTEP: - m_minstep = value; - break; - case MAX_TIMESTEP: - m_maxstep = value; - break; - default: - return false; - } - return true; + switch (paramId) { + case MIN_TIMESTEP: + m_minstep = value; + break; + case MAX_TIMESTEP: + m_maxstep = value; + break; + default: + return false; + } + return true; } -bool Scene::addObject(const std::string& name, Object* object, UncontrolledObject* base, const std::string& baseFrame) +bool Scene::addObject(const std::string &name, + Object *object, + UncontrolledObject *base, + const std::string &baseFrame) { - // finalize the object before adding - if (!object->finalize()) - return false; - //Check if Object is controlled or uncontrolled. - if(object->getType()==Object::Controlled){ - int baseFrameIndex = base->addEndEffector(baseFrame); - if (baseFrameIndex < 0) - return false; - std::pair<ObjectMap::iterator, bool> result; - if (base->getNrOfCoordinates() == 0) { - // base is fixed object, no coordinate range - result = objects.insert(ObjectMap::value_type( - name, new Object_struct(object,base,baseFrameIndex, - Range(m_nqTotal,object->getNrOfCoordinates()), - Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()), - Range(0,0)))); - } else { - // base is a moving object, must be in list already - ObjectMap::iterator base_it; - for (base_it=objects.begin(); base_it != objects.end(); base_it++) { - if (base_it->second->object == base) - break; - } - if (base_it == objects.end()) - return false; - result = objects.insert(ObjectMap::value_type( - name, new Object_struct(object,base,baseFrameIndex, - Range(m_nqTotal,object->getNrOfCoordinates()), - Range(m_ncTotal,((ControlledObject*)object)->getNrOfConstraints()), - base_it->second->coordinaterange))); - } - if (!result.second) { - return false; - } - m_nqTotal+=object->getNrOfCoordinates(); - m_ncTotal+=((ControlledObject*)object)->getNrOfConstraints(); - return true; + // finalize the object before adding + if (!object->finalize()) + return false; + // Check if Object is controlled or uncontrolled. + if (object->getType() == Object::Controlled) { + int baseFrameIndex = base->addEndEffector(baseFrame); + if (baseFrameIndex < 0) + return false; + std::pair<ObjectMap::iterator, bool> result; + if (base->getNrOfCoordinates() == 0) { + // base is fixed object, no coordinate range + result = objects.insert(ObjectMap::value_type( + name, + new Object_struct(object, + base, + baseFrameIndex, + Range(m_nqTotal, object->getNrOfCoordinates()), + Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()), + Range(0, 0)))); + } + else { + // base is a moving object, must be in list already + ObjectMap::iterator base_it; + for (base_it = objects.begin(); base_it != objects.end(); base_it++) { + if (base_it->second->object == base) + break; + } + if (base_it == objects.end()) + return false; + result = objects.insert(ObjectMap::value_type( + name, + new Object_struct(object, + base, + baseFrameIndex, + Range(m_nqTotal, object->getNrOfCoordinates()), + Range(m_ncTotal, ((ControlledObject *)object)->getNrOfConstraints()), + base_it->second->coordinaterange))); } - if(object->getType()==Object::UnControlled){ - if ((WorldObject*)base != &Object::world) - return false; - std::pair<ObjectMap::iterator,bool> result = objects.insert(ObjectMap::value_type( - name,new Object_struct(object,base,0, - Range(0,0), - Range(0,0), - Range(m_nuTotal,object->getNrOfCoordinates())))); - if(!result.second) - return false; - m_nuTotal+=object->getNrOfCoordinates(); - return true; + if (!result.second) { + return false; } - return false; + m_nqTotal += object->getNrOfCoordinates(); + m_ncTotal += ((ControlledObject *)object)->getNrOfConstraints(); + return true; + } + if (object->getType() == Object::UnControlled) { + if ((WorldObject *)base != &Object::world) + return false; + std::pair<ObjectMap::iterator, bool> result = objects.insert( + ObjectMap::value_type(name, + new Object_struct(object, + base, + 0, + Range(0, 0), + Range(0, 0), + Range(m_nuTotal, object->getNrOfCoordinates())))); + if (!result.second) + return false; + m_nuTotal += object->getNrOfCoordinates(); + return true; + } + return false; } -bool Scene::addConstraintSet(const std::string& name,ConstraintSet* task,const std::string& object1,const std::string& object2, const std::string& ee1, const std::string& ee2) +bool Scene::addConstraintSet(const std::string &name, + ConstraintSet *task, + const std::string &object1, + const std::string &object2, + const std::string &ee1, + const std::string &ee2) { - //Check if objects exist: - ObjectMap::iterator object1_it = objects.find(object1); - ObjectMap::iterator object2_it = objects.find(object2); - if(object1_it==objects.end()||object2_it==objects.end()) - return false; - int ee1_index = object1_it->second->object->addEndEffector(ee1); - int ee2_index = object2_it->second->object->addEndEffector(ee2); - if (ee1_index < 0 || ee2_index < 0) - return false; - std::pair<ConstraintMap::iterator,bool> result = - constraints.insert(ConstraintMap::value_type(name,new ConstraintSet_struct( - task,object1_it,ee1_index,object2_it,ee2_index, - Range(m_ncTotal,task->getNrOfConstraints()),Range(6*m_nsets,6)))); - if(!result.second) - return false; - m_ncTotal+=task->getNrOfConstraints(); - m_nsets+=1; - return true; + // Check if objects exist: + ObjectMap::iterator object1_it = objects.find(object1); + ObjectMap::iterator object2_it = objects.find(object2); + if (object1_it == objects.end() || object2_it == objects.end()) + return false; + int ee1_index = object1_it->second->object->addEndEffector(ee1); + int ee2_index = object2_it->second->object->addEndEffector(ee2); + if (ee1_index < 0 || ee2_index < 0) + return false; + std::pair<ConstraintMap::iterator, bool> result = constraints.insert(ConstraintMap::value_type( + name, + new ConstraintSet_struct(task, + object1_it, + ee1_index, + object2_it, + ee2_index, + Range(m_ncTotal, task->getNrOfConstraints()), + Range(6 * m_nsets, 6)))); + if (!result.second) + return false; + m_ncTotal += task->getNrOfConstraints(); + m_nsets += 1; + return true; } -bool Scene::addSolver(Solver* _solver){ - if(m_solver==NULL){ - m_solver=_solver; - return true; - } - else - return false; +bool Scene::addSolver(Solver *_solver) +{ + if (m_solver == NULL) { + m_solver = _solver; + return true; + } + else + return false; } -bool Scene::addCache(Cache* _cache){ - if(m_cache==NULL){ - m_cache=_cache; - return true; - } - else - return false; +bool Scene::addCache(Cache *_cache) +{ + if (m_cache == NULL) { + m_cache = _cache; + return true; + } + else + return false; } -bool Scene::initialize(){ - - //prepare all matrices: - if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0) - return false; - - m_A = e_zero_matrix(m_ncTotal,m_nqTotal); - if (m_nuTotal > 0) { - m_B = e_zero_matrix(m_ncTotal,m_nuTotal); - m_xdot = e_zero_vector(m_nuTotal); - m_Ju = e_zero_matrix(6*m_nsets,m_nuTotal); - } - m_Atemp = e_zero_matrix(m_ncTotal,6*m_nsets); - m_ydot = e_zero_vector(m_ncTotal); - m_qdot = e_zero_vector(m_nqTotal); - m_Wq = e_zero_matrix(m_nqTotal,m_nqTotal); - m_Wy = e_zero_vector(m_ncTotal); - m_Jq = e_zero_matrix(6*m_nsets,m_nqTotal); - m_Jf = e_zero_matrix(6*m_nsets,6*m_nsets); - m_Jf_inv = m_Jf; - m_Cf = e_zero_matrix(m_ncTotal,m_Jf.rows()); - m_Cq = e_zero_matrix(m_ncTotal,m_nqTotal); - - bool result=true; - // finalize all objects - for (ObjectMap::iterator it=objects.begin(); it!=objects.end(); ++it) { - Object_struct* os = it->second; - - os->object->initCache(m_cache); - if (os->constraintrange.count > 0) - project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq()); - } - - m_ytask.resize(m_ncTotal); - bool toggle=true; - int cnt = 0; - //Initialize all ConstraintSets: - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - //Calculate the external pose: - ConstraintSet_struct* cs = it->second; - Frame external_pose; - getConstraintPose(cs->task, cs, external_pose); - result&=cs->task->initialise(external_pose); - cs->task->initCache(m_cache); - for (int i=0; i<cs->constraintrange.count; i++, cnt++) { - m_ytask[cnt] = toggle; - } - toggle = !toggle; - project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); - } +bool Scene::initialize() +{ - if(m_solver!=NULL) - m_solver->init(m_nqTotal,m_ncTotal,m_ytask); - else - return false; + // prepare all matrices: + if (m_ncTotal == 0 || m_nqTotal == 0 || m_nsets == 0) + return false; + m_A = e_zero_matrix(m_ncTotal, m_nqTotal); + if (m_nuTotal > 0) { + m_B = e_zero_matrix(m_ncTotal, m_nuTotal); + m_xdot = e_zero_vector(m_nuTotal); + m_Ju = e_zero_matrix(6 * m_nsets, m_nuTotal); + } + m_Atemp = e_zero_matrix(m_ncTotal, 6 * m_nsets); + m_ydot = e_zero_vector(m_ncTotal); + m_qdot = e_zero_vector(m_nqTotal); + m_Wq = e_zero_matrix(m_nqTotal, m_nqTotal); + m_Wy = e_zero_vector(m_ncTotal); + m_Jq = e_zero_matrix(6 * m_nsets, m_nqTotal); + m_Jf = e_zero_matrix(6 * m_nsets, 6 * m_nsets); + m_Jf_inv = m_Jf; + m_Cf = e_zero_matrix(m_ncTotal, m_Jf.rows()); + m_Cq = e_zero_matrix(m_ncTotal, m_nqTotal); + + bool result = true; + // finalize all objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + + os->object->initCache(m_cache); + if (os->constraintrange.count > 0) + project(m_Cq, + os->constraintrange, + os->jointrange) = (((ControlledObject *)(os->object))->getCq()); + } + + m_ytask.resize(m_ncTotal); + bool toggle = true; + int cnt = 0; + // Initialize all ConstraintSets: + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + // Calculate the external pose: + ConstraintSet_struct *cs = it->second; + Frame external_pose; + getConstraintPose(cs->task, cs, external_pose); + result &= cs->task->initialise(external_pose); + cs->task->initCache(m_cache); + for (int i = 0; i < cs->constraintrange.count; i++, cnt++) { + m_ytask[cnt] = toggle; + } + toggle = !toggle; + project(m_Cf, cs->constraintrange, cs->featurerange) = cs->task->getCf(); + } - return result; + if (m_solver != NULL) + m_solver->init(m_nqTotal, m_ncTotal, m_ytask); + else + return false; + + return result; } -bool Scene::getConstraintPose(ConstraintSet* constraint, void *_param, KDL::Frame& _pose) +bool Scene::getConstraintPose(ConstraintSet *constraint, void *_param, KDL::Frame &_pose) { - // function called from constraint when they need to get the external pose - ConstraintSet_struct* cs = (ConstraintSet_struct*)_param; - // verification, the pointer MUST match - assert (constraint == cs->task); - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - //Calculate the external pose: - _pose=(ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index)).Inverse()*(ob2->base->getPose(ob2->baseFrameIndex)*ob2->object->getPose(cs->ee2index)); - return true; + // function called from constraint when they need to get the external pose + ConstraintSet_struct *cs = (ConstraintSet_struct *)_param; + // verification, the pointer MUST match + assert(constraint == cs->task); + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + // Calculate the external pose: + _pose = + (ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index)).Inverse() * + (ob2->base->getPose(ob2->baseFrameIndex) * ob2->object->getPose(cs->ee2index)); + return true; } -bool Scene::update(double timestamp, double timestep, unsigned int numsubstep, bool reiterate, bool cache, bool interpolate) +bool Scene::update(double timestamp, + double timestep, + unsigned int numsubstep, + bool reiterate, + bool cache, + bool interpolate) { - // we must have valid timestep and timestamp - if (timestamp < KDL::epsilon || timestep < 0.0) - return false; - Timestamp ts; - ts.realTimestamp = timestamp; - // initially we start with the full timestep to allow velocity estimation over the full interval - ts.realTimestep = timestep; - setCacheTimestamp(ts); - ts.substep = 0; - // for reiteration don't load cache - // reiteration=additional iteration with same timestamp if application finds the convergence not good enough - ts.reiterate = (reiterate) ? 1 : 0; - ts.interpolate = (interpolate) ? 1 : 0; - ts.cache = (cache) ? 1 : 0; - ts.update = 1; - ts.numstep = (numsubstep & 0xFF); - bool autosubstep = (numsubstep == 0) ? true : false; - if (numsubstep < 1) - numsubstep = 1; - double timesubstep = timestep/numsubstep; - double timeleft = timestep; - - if (timeleft == 0.0) { - // this special case correspond to a request to cache data - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - it->second->object->pushCache(ts); - } - //Update the Constraints - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - it->second->task->pushCache(ts); - } - return true; - } - - // double maxqdot; // UNUSED - e_scalar nlcoef; - SceneLock lockCallback(this); - Frame external_pose; - bool locked; - - // initially we keep timestep unchanged so that update function compute the velocity over - while (numsubstep > 0) { - // get objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) { - Object_struct* os = it->second; - if (os->object->getType()==Object::Controlled) { - ((ControlledObject*)(os->object))->updateControlOutput(ts); - if (os->constraintrange.count > 0) { - project(m_ydot, os->constraintrange) = ((ControlledObject*)(os->object))->getControlOutput(); - project(m_Wy, os->constraintrange) = ((ControlledObject*)(os->object))->getWy(); - // project(m_Cq,os->constraintrange,os->jointrange) = (((ControlledObject*)(os->object))->getCq()); - } - if (os->jointrange.count > 0) { - project(m_Wq,os->jointrange,os->jointrange) = ((ControlledObject*)(os->object))->getWq(); - } - } - if (os->object->getType()==Object::UnControlled && ((UncontrolledObject*)os->object)->getNrOfCoordinates() != 0) { - ((UncontrolledObject*)(os->object))->updateCoordinates(ts); - if (!ts.substep) { - // velocity of uncontrolled object remains constant during substepping - project(m_xdot,os->coordinaterange) = ((UncontrolledObject*)(os->object))->getXudot(); - } - } - } - - //get new Constraints values - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it) { - ConstraintSet_struct* cs = it->second; - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - - if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() || ob2->object->updated()) { - // the object from which the constraint depends have changed position - // recompute the constraint pose - getConstraintPose(cs->task, cs, external_pose); - cs->task->initialise(external_pose); - } - cs->task->updateControlOutput(ts); - project(m_ydot,cs->constraintrange)=cs->task->getControlOutput(); - if (!ts.substep || cs->task->substep()) { - project(m_Wy,cs->constraintrange)=(cs->task)->getWy(); - //project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); - } - - project(m_Jf,cs->featurerange,cs->featurerange)=cs->task->getJf(); - //std::cout << "Jf = " << Jf << std::endl; - //Transform the reference frame of this jacobian to the world reference frame - Eigen::Block<e_matrix> Jf_part = project(m_Jf,cs->featurerange,cs->featurerange); - changeBase(Jf_part,ob1->base->getPose(ob1->baseFrameIndex)*ob1->object->getPose(cs->ee1index)); - //std::cout << "Jf_w = " << Jf << std::endl; - - //calculate the inverse of Jf - KDL::svd_eigen_HH(project(m_Jf,cs->featurerange,cs->featurerange),m_Uf,m_Sf,m_Vf,m_tempf); - for(unsigned int i=0;i<6;++i) - if(m_Sf(i)<KDL::epsilon) - m_Uf.col(i).setConstant(0.0); - else - m_Uf.col(i)*=(1/m_Sf(i)); - project(m_Jf_inv,cs->featurerange,cs->featurerange).noalias()=m_Vf*m_Uf.transpose(); - - //Get the robotjacobian associated with this constraintset - //Each jacobian is expressed in robot base frame => convert to world reference - //and negate second robot because it is taken reversed when closing the loop: - if(ob1->object->getType()==Object::Controlled){ - project(m_Jq,cs->featurerange,ob1->jointrange) = (((ControlledObject*)(ob1->object))->getJq(cs->ee1index)); - //Transform the reference frame of this jacobian to the world reference frame: - Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob1->jointrange); - changeBase(Jq_part,ob1->base->getPose(ob1->baseFrameIndex)); - // if the base of this object is moving, get the Ju part - if (ob1->base->getNrOfCoordinates() != 0) { - // Ju is already computed for world reference frame - project(m_Ju,cs->featurerange,ob1->coordinaterange)=ob1->base->getJu(ob1->baseFrameIndex); - } - } else if (ob1->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob1->object)->getNrOfCoordinates() != 0) { - // object1 is uncontrolled moving object - project(m_Ju,cs->featurerange,ob1->coordinaterange)=((UncontrolledObject*)ob1->object)->getJu(cs->ee1index); - } - if(ob2->object->getType()==Object::Controlled){ - //Get the robotjacobian associated with this constraintset - // process a special case where object2 and object1 are equal but using different end effector - if (ob1->object == ob2->object) { - // we must create a temporary matrix - e_matrix JqTemp(((ControlledObject*)(ob2->object))->getJq(cs->ee2index)); - //Transform the reference frame of this jacobian to the world reference frame: - changeBase(JqTemp,ob2->base->getPose(ob2->baseFrameIndex)); - // substract in place - project(m_Jq,cs->featurerange,ob2->jointrange) -= JqTemp; - } else { - project(m_Jq,cs->featurerange,ob2->jointrange) = -(((ControlledObject*)(ob2->object))->getJq(cs->ee2index)); - //Transform the reference frame of this jacobian to the world reference frame: - Eigen::Block<e_matrix> Jq_part = project(m_Jq,cs->featurerange,ob2->jointrange); - changeBase(Jq_part,ob2->base->getPose(ob2->baseFrameIndex)); - } - if (ob2->base->getNrOfCoordinates() != 0) { - // if base is the same as first object or first object base, - // that portion of m_Ju has been set already => substract inplace - if (ob2->base == ob1->base || ob2->base == ob1->object) { - project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ob2->base->getJu(ob2->baseFrameIndex); - } else { - project(m_Ju,cs->featurerange,ob2->coordinaterange) = -ob2->base->getJu(ob2->baseFrameIndex); - } - } - } else if (ob2->object->getType() == Object::UnControlled && ((UncontrolledObject*)ob2->object)->getNrOfCoordinates() != 0) { - if (ob2->object == ob1->base || ob2->object == ob1->object) { - project(m_Ju,cs->featurerange,ob2->coordinaterange) -= ((UncontrolledObject*)ob2->object)->getJu(cs->ee2index); - } else { - project(m_Ju,cs->featurerange,ob2->coordinaterange) = -((UncontrolledObject*)ob2->object)->getJu(cs->ee2index); - } - } - } - - //Calculate A - m_Atemp.noalias()=m_Cf*m_Jf_inv; - m_A.noalias() = m_Cq-(m_Atemp*m_Jq); - if (m_nuTotal > 0) { - m_B.noalias()=m_Atemp*m_Ju; - m_ydot.noalias() += m_B*m_xdot; - } - - //Call the solver with A, Wq, Wy, ydot to solver qdot: - if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef)) - // this should never happen - return false; - //send result to the objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it) { - Object_struct* os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange)); - } - // compute the constraint velocity - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - Object_struct* ob1 = cs->object1->second; - Object_struct* ob2 = cs->object2->second; - //Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot): - e_vector6 external_vel = e_zero_vector(6); - if (ob1->jointrange.count > 0) - external_vel.noalias() += (project(m_Jq,cs->featurerange,ob1->jointrange)*project(m_qdot,ob1->jointrange)); - if (ob2->jointrange.count > 0) - external_vel.noalias() += (project(m_Jq,cs->featurerange,ob2->jointrange)*project(m_qdot,ob2->jointrange)); - if (ob1->coordinaterange.count > 0) - external_vel.noalias() += (project(m_Ju,cs->featurerange,ob1->coordinaterange)*project(m_xdot,ob1->coordinaterange)); - if (ob2->coordinaterange.count > 0) - external_vel.noalias() += (project(m_Ju,cs->featurerange,ob2->coordinaterange)*project(m_xdot,ob2->coordinaterange)); - //the twist caused by the constraint must be opposite because of the closed loop - //estimate the velocity of the joints using the inverse jacobian - e_vector6 estimated_chidot = project(m_Jf_inv,cs->featurerange,cs->featurerange)*(-external_vel); - cs->task->setJointVelocity(estimated_chidot); - } - - if (autosubstep) { - // automatic computing of substep based on maximum joint change - // and joint limit gain variation - // We will pass the joint velocity to each object and they will recommend a maximum timestep - timesubstep = timeleft; - // get armature max joint velocity to estimate the maximum duration of integration - // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED - double maxsubstep = nlcoef*m_maxstep; - if (maxsubstep < m_minstep) - maxsubstep = m_minstep; - if (timesubstep > maxsubstep) - timesubstep = maxsubstep; - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - Object_struct* os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->getMaxTimestep(timesubstep); - } - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - cs->task->getMaxTimestep(timesubstep); - } - // use substep that are even dividers of timestep for more regularity - maxsubstep = 2.0*floor(timestep/2.0/timesubstep-0.66666); - timesubstep = (maxsubstep < 0.0) ? timestep : timestep/(2.0+maxsubstep); - if (timesubstep >= timeleft-(m_minstep/2.0)) { - timesubstep = timeleft; - numsubstep = 1; - timeleft = 0.; - } else { - numsubstep = 2; - timeleft -= timesubstep; - } - } - if (numsubstep > 1) { - ts.substep = 1; - } else { - // set substep to false for last iteration so that controlled output - // can be updated in updateKinematics() and model_update)() before next call to Secne::update() - ts.substep = 0; - } - // change timestep so that integration is done correctly - ts.realTimestep = timesubstep; - - do { - ObjectMap::iterator it; - Object_struct* os; - locked = false; - for(it=objects.begin();it!=objects.end();++it){ - os = it->second; - if (os->object->getType()==Object::Controlled) { - lockCallback.setRange(os->jointrange); - if (((ControlledObject*)os->object)->updateJoint(ts, lockCallback)) { - // this means one of the joint was locked and we must rerun - // the solver to update the remaining joints - locked = true; - break; - } - } - } - if (locked) { - // Some rows of m_Wq have been cleared so that the corresponding joint will not move - if(!m_solver->solve(m_A,m_Wy,m_ydot,m_Wq,m_qdot,nlcoef)) - // this should never happen - return false; - - //send result to the objects - for(it=objects.begin();it!=objects.end();++it) { - os = it->second; - if(os->object->getType()==Object::Controlled) - ((ControlledObject*)(os->object))->setJointVelocity(project(m_qdot,os->jointrange)); - } - } - } while (locked); - - //Update the Objects - for(ObjectMap::iterator it=objects.begin();it!=objects.end();++it){ - it->second->object->updateKinematics(ts); - // mark this object not updated since the constraint will be updated anyway - // this flag is only useful to detect external updates - it->second->object->updated(false); - } - //Update the Constraints - for(ConstraintMap::iterator it=constraints.begin();it!=constraints.end();++it){ - ConstraintSet_struct* cs = it->second; - //Calculate the external pose: - getConstraintPose(cs->task, cs, external_pose); - cs->task->modelUpdate(external_pose,ts); - // update the constraint output and cache - cs->task->updateKinematics(ts); - } - numsubstep--; - } - return true; -} + // we must have valid timestep and timestamp + if (timestamp < KDL::epsilon || timestep < 0.0) + return false; + Timestamp ts; + ts.realTimestamp = timestamp; + // initially we start with the full timestep to allow velocity estimation over the full interval + ts.realTimestep = timestep; + setCacheTimestamp(ts); + ts.substep = 0; + // for reiteration don't load cache + // reiteration=additional iteration with same timestamp if application finds the convergence not + // good enough + ts.reiterate = (reiterate) ? 1 : 0; + ts.interpolate = (interpolate) ? 1 : 0; + ts.cache = (cache) ? 1 : 0; + ts.update = 1; + ts.numstep = (numsubstep & 0xFF); + bool autosubstep = (numsubstep == 0) ? true : false; + if (numsubstep < 1) + numsubstep = 1; + double timesubstep = timestep / numsubstep; + double timeleft = timestep; + + if (timeleft == 0.0) { + // this special case correspond to a request to cache data + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + it->second->object->pushCache(ts); + } + // Update the Constraints + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + it->second->task->pushCache(ts); + } + return true; + } + + // double maxqdot; // UNUSED + e_scalar nlcoef; + SceneLock lockCallback(this); + Frame external_pose; + bool locked; + + // initially we keep timestep unchanged so that update function compute the velocity over + while (numsubstep > 0) { + // get objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) { + ((ControlledObject *)(os->object))->updateControlOutput(ts); + if (os->constraintrange.count > 0) { + project(m_ydot, + os->constraintrange) = ((ControlledObject *)(os->object))->getControlOutput(); + project(m_Wy, os->constraintrange) = ((ControlledObject *)(os->object))->getWy(); + // project(m_Cq,os->constraintrange,os->jointrange) = + // (((ControlledObject*)(os->object))->getCq()); + } + if (os->jointrange.count > 0) { + project( + m_Wq, os->jointrange, os->jointrange) = ((ControlledObject *)(os->object))->getWq(); + } + } + if (os->object->getType() == Object::UnControlled && + ((UncontrolledObject *)os->object)->getNrOfCoordinates() != 0) { + ((UncontrolledObject *)(os->object))->updateCoordinates(ts); + if (!ts.substep) { + // velocity of uncontrolled object remains constant during substepping + project(m_xdot, os->coordinaterange) = ((UncontrolledObject *)(os->object))->getXudot(); + } + } + } + + // get new Constraints values + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + + if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() || + ob2->object->updated()) { + // the object from which the constraint depends have changed position + // recompute the constraint pose + getConstraintPose(cs->task, cs, external_pose); + cs->task->initialise(external_pose); + } + cs->task->updateControlOutput(ts); + project(m_ydot, cs->constraintrange) = cs->task->getControlOutput(); + if (!ts.substep || cs->task->substep()) { + project(m_Wy, cs->constraintrange) = (cs->task)->getWy(); + // project(m_Cf,cs->constraintrange,cs->featurerange)=cs->task->getCf(); + } + + project(m_Jf, cs->featurerange, cs->featurerange) = cs->task->getJf(); + // std::cout << "Jf = " << Jf << std::endl; + // Transform the reference frame of this jacobian to the world reference frame + Eigen::Block<e_matrix> Jf_part = project(m_Jf, cs->featurerange, cs->featurerange); + changeBase(Jf_part, + ob1->base->getPose(ob1->baseFrameIndex) * ob1->object->getPose(cs->ee1index)); + // std::cout << "Jf_w = " << Jf << std::endl; + + // calculate the inverse of Jf + KDL::svd_eigen_HH( + project(m_Jf, cs->featurerange, cs->featurerange), m_Uf, m_Sf, m_Vf, m_tempf); + for (unsigned int i = 0; i < 6; ++i) + if (m_Sf(i) < KDL::epsilon) + m_Uf.col(i).setConstant(0.0); + else + m_Uf.col(i) *= (1 / m_Sf(i)); + project(m_Jf_inv, cs->featurerange, cs->featurerange).noalias() = m_Vf * m_Uf.transpose(); + + // Get the robotjacobian associated with this constraintset + // Each jacobian is expressed in robot base frame => convert to world reference + // and negate second robot because it is taken reversed when closing the loop: + if (ob1->object->getType() == Object::Controlled) { + project(m_Jq, + cs->featurerange, + ob1->jointrange) = (((ControlledObject *)(ob1->object))->getJq(cs->ee1index)); + // Transform the reference frame of this jacobian to the world reference frame: + Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob1->jointrange); + changeBase(Jq_part, ob1->base->getPose(ob1->baseFrameIndex)); + // if the base of this object is moving, get the Ju part + if (ob1->base->getNrOfCoordinates() != 0) { + // Ju is already computed for world reference frame + project(m_Ju, cs->featurerange, ob1->coordinaterange) = ob1->base->getJu( + ob1->baseFrameIndex); + } + } + else if (ob1->object->getType() == Object::UnControlled && + ((UncontrolledObject *)ob1->object)->getNrOfCoordinates() != 0) { + // object1 is uncontrolled moving object + project(m_Ju, + cs->featurerange, + ob1->coordinaterange) = ((UncontrolledObject *)ob1->object)->getJu(cs->ee1index); + } + if (ob2->object->getType() == Object::Controlled) { + // Get the robotjacobian associated with this constraintset + // process a special case where object2 and object1 are equal but using different end + // effector + if (ob1->object == ob2->object) { + // we must create a temporary matrix + e_matrix JqTemp(((ControlledObject *)(ob2->object))->getJq(cs->ee2index)); + // Transform the reference frame of this jacobian to the world reference frame: + changeBase(JqTemp, ob2->base->getPose(ob2->baseFrameIndex)); + // subtract in place + project(m_Jq, cs->featurerange, ob2->jointrange) -= JqTemp; + } + else { + project(m_Jq, cs->featurerange, ob2->jointrange) = -( + ((ControlledObject *)(ob2->object))->getJq(cs->ee2index)); + // Transform the reference frame of this jacobian to the world reference frame: + Eigen::Block<e_matrix> Jq_part = project(m_Jq, cs->featurerange, ob2->jointrange); + changeBase(Jq_part, ob2->base->getPose(ob2->baseFrameIndex)); + } + if (ob2->base->getNrOfCoordinates() != 0) { + // if base is the same as first object or first object base, + // that portion of m_Ju has been set already => subtract inplace + if (ob2->base == ob1->base || ob2->base == ob1->object) { + project(m_Ju, cs->featurerange, ob2->coordinaterange) -= ob2->base->getJu( + ob2->baseFrameIndex); + } + else { + project(m_Ju, cs->featurerange, ob2->coordinaterange) = -ob2->base->getJu( + ob2->baseFrameIndex); + } + } + } + else if (ob2->object->getType() == Object::UnControlled && + ((UncontrolledObject *)ob2->object)->getNrOfCoordinates() != 0) { + if (ob2->object == ob1->base || ob2->object == ob1->object) { + project(m_Ju, cs->featurerange, ob2->coordinaterange) -= + ((UncontrolledObject *)ob2->object)->getJu(cs->ee2index); + } + else { + project(m_Ju, cs->featurerange, ob2->coordinaterange) = + -((UncontrolledObject *)ob2->object)->getJu(cs->ee2index); + } + } + } + + // Calculate A + m_Atemp.noalias() = m_Cf * m_Jf_inv; + m_A.noalias() = m_Cq - (m_Atemp * m_Jq); + if (m_nuTotal > 0) { + m_B.noalias() = m_Atemp * m_Ju; + m_ydot.noalias() += m_B * m_xdot; + } + // Call the solver with A, Wq, Wy, ydot to solver qdot: + if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef)) + // this should never happen + return false; + // send result to the objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange)); + } + // compute the constraint velocity + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + Object_struct *ob1 = cs->object1->second; + Object_struct *ob2 = cs->object2->second; + // Calculate the twist of the world reference frame due to the robots (Jq*qdot+Ju*chiudot): + e_vector6 external_vel = e_zero_vector(6); + if (ob1->jointrange.count > 0) + external_vel.noalias() += (project(m_Jq, cs->featurerange, ob1->jointrange) * + project(m_qdot, ob1->jointrange)); + if (ob2->jointrange.count > 0) + external_vel.noalias() += (project(m_Jq, cs->featurerange, ob2->jointrange) * + project(m_qdot, ob2->jointrange)); + if (ob1->coordinaterange.count > 0) + external_vel.noalias() += (project(m_Ju, cs->featurerange, ob1->coordinaterange) * + project(m_xdot, ob1->coordinaterange)); + if (ob2->coordinaterange.count > 0) + external_vel.noalias() += (project(m_Ju, cs->featurerange, ob2->coordinaterange) * + project(m_xdot, ob2->coordinaterange)); + // the twist caused by the constraint must be opposite because of the closed loop + // estimate the velocity of the joints using the inverse jacobian + e_vector6 estimated_chidot = project(m_Jf_inv, cs->featurerange, cs->featurerange) * + (-external_vel); + cs->task->setJointVelocity(estimated_chidot); + } + + if (autosubstep) { + // automatic computing of substep based on maximum joint change + // and joint limit gain variation + // We will pass the joint velocity to each object and they will recommend a maximum timestep + timesubstep = timeleft; + // get armature max joint velocity to estimate the maximum duration of integration + // maxqdot = m_qdot.cwise().abs().maxCoeff(); // UNUSED + double maxsubstep = nlcoef * m_maxstep; + if (maxsubstep < m_minstep) + maxsubstep = m_minstep; + if (timesubstep > maxsubstep) + timesubstep = maxsubstep; + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + Object_struct *os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->getMaxTimestep(timesubstep); + } + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + cs->task->getMaxTimestep(timesubstep); + } + // use substep that are even dividers of timestep for more regularity + maxsubstep = 2.0 * floor(timestep / 2.0 / timesubstep - 0.66666); + timesubstep = (maxsubstep < 0.0) ? timestep : timestep / (2.0 + maxsubstep); + if (timesubstep >= timeleft - (m_minstep / 2.0)) { + timesubstep = timeleft; + numsubstep = 1; + timeleft = 0.; + } + else { + numsubstep = 2; + timeleft -= timesubstep; + } + } + if (numsubstep > 1) { + ts.substep = 1; + } + else { + // set substep to false for last iteration so that controlled output + // can be updated in updateKinematics() and model_update)() before next call to + // Secne::update() + ts.substep = 0; + } + // change timestep so that integration is done correctly + ts.realTimestep = timesubstep; + + do { + ObjectMap::iterator it; + Object_struct *os; + locked = false; + for (it = objects.begin(); it != objects.end(); ++it) { + os = it->second; + if (os->object->getType() == Object::Controlled) { + lockCallback.setRange(os->jointrange); + if (((ControlledObject *)os->object)->updateJoint(ts, lockCallback)) { + // this means one of the joint was locked and we must rerun + // the solver to update the remaining joints + locked = true; + break; + } + } + } + if (locked) { + // Some rows of m_Wq have been cleared so that the corresponding joint will not move + if (!m_solver->solve(m_A, m_Wy, m_ydot, m_Wq, m_qdot, nlcoef)) + // this should never happen + return false; + + // send result to the objects + for (it = objects.begin(); it != objects.end(); ++it) { + os = it->second; + if (os->object->getType() == Object::Controlled) + ((ControlledObject *)(os->object))->setJointVelocity(project(m_qdot, os->jointrange)); + } + } + } while (locked); + + // Update the Objects + for (ObjectMap::iterator it = objects.begin(); it != objects.end(); ++it) { + it->second->object->updateKinematics(ts); + // mark this object not updated since the constraint will be updated anyway + // this flag is only useful to detect external updates + it->second->object->updated(false); + } + // Update the Constraints + for (ConstraintMap::iterator it = constraints.begin(); it != constraints.end(); ++it) { + ConstraintSet_struct *cs = it->second; + // Calculate the external pose: + getConstraintPose(cs->task, cs, external_pose); + cs->task->modelUpdate(external_pose, ts); + // update the constraint output and cache + cs->task->updateKinematics(ts); + } + numsubstep--; + } + return true; } + +} // namespace iTaSC diff --git a/intern/mantaflow/extern/manta_fluid_API.h b/intern/mantaflow/extern/manta_fluid_API.h index dd5eab34ee0..124671467f7 100644 --- a/intern/mantaflow/extern/manta_fluid_API.h +++ b/intern/mantaflow/extern/manta_fluid_API.h @@ -77,7 +77,7 @@ int manta_get_frame(struct MANTA *fluid); float manta_get_timestep(struct MANTA *fluid); void manta_adapt_timestep(struct MANTA *fluid); bool manta_needs_realloc(struct MANTA *fluid, struct FluidModifierData *fmd); -void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd); +void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush); /* Fluid accessors */ size_t manta_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */); diff --git a/intern/mantaflow/intern/MANTA_main.cpp b/intern/mantaflow/intern/MANTA_main.cpp index 7de1aca6e87..586c413b044 100644 --- a/intern/mantaflow/intern/MANTA_main.cpp +++ b/intern/mantaflow/intern/MANTA_main.cpp @@ -1969,30 +1969,30 @@ void MANTA::adaptTimestep() runPythonString(pythonCommands); } -void MANTA::updatePointers(FluidModifierData *fmd) +void MANTA::updatePointers(FluidModifierData *fmd, bool flush) { if (with_debug) cout << "MANTA::updatePointers()" << endl; FluidDomainSettings *fds = fmd->domain; - bool liquid = (fds->type == FLUID_DOMAIN_TYPE_LIQUID); - bool smoke = (fds->type == FLUID_DOMAIN_TYPE_GAS); - bool noise = smoke && fds->flags & FLUID_DOMAIN_USE_NOISE; - bool heat = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; - bool colors = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; - bool fire = smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; - bool obstacle = fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; - bool guiding = fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; - bool invel = fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; - bool outflow = fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; - bool drops = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; - bool bubble = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; - bool floater = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; - bool tracer = liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; - bool parts = liquid && (drops | bubble | floater | tracer); - bool mesh = liquid && fds->flags & FLUID_DOMAIN_USE_MESH; - bool meshvel = liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS; + bool liquid = !flush && (fds->type == FLUID_DOMAIN_TYPE_LIQUID); + bool smoke = !flush && (fds->type == FLUID_DOMAIN_TYPE_GAS); + bool noise = !flush && smoke && fds->flags & FLUID_DOMAIN_USE_NOISE; + bool heat = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_HEAT; + bool colors = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_COLORS; + bool fire = !flush && smoke && fds->active_fields & FLUID_DOMAIN_ACTIVE_FIRE; + bool obstacle = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OBSTACLE; + bool guiding = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE; + bool invel = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_INVEL; + bool outflow = !flush && fds->active_fields & FLUID_DOMAIN_ACTIVE_OUTFLOW; + bool drops = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_SPRAY; + bool bubble = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_BUBBLE; + bool floater = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_FOAM; + bool tracer = !flush && liquid && fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER; + bool parts = !flush && liquid && (drops | bubble | floater | tracer); + bool mesh = !flush && liquid && fds->flags & FLUID_DOMAIN_USE_MESH; + bool meshvel = !flush && liquid && mesh && fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS; string func = "getDataPointer"; string funcNodes = "getNodesDataPointer"; @@ -2006,15 +2006,15 @@ void MANTA::updatePointers(FluidModifierData *fmd) string mesh_ext = "_mesh" + id; string sn_ext = "_sn" + id; - mFlags = getPointer<int>("flags" + s_ext, func); - mPhiIn = getPointer<float>("phiIn" + s_ext, func); - mPhiStaticIn = getPointer<float>("phiSIn" + s_ext, func); - mVelocityX = getPointer<float>("x_vel" + s_ext, func); - mVelocityY = getPointer<float>("y_vel" + s_ext, func); - mVelocityZ = getPointer<float>("z_vel" + s_ext, func); - mForceX = getPointer<float>("x_force" + s_ext, func); - mForceY = getPointer<float>("y_force" + s_ext, func); - mForceZ = getPointer<float>("z_force" + s_ext, func); + mFlags = (smoke || liquid) ? getPointer<int>("flags" + s_ext, func) : nullptr; + mPhiIn = (smoke || liquid) ? getPointer<float>("phiIn" + s_ext, func) : nullptr; + mPhiStaticIn = (smoke || liquid) ? getPointer<float>("phiSIn" + s_ext, func) : nullptr; + mVelocityX = (smoke || liquid) ? getPointer<float>("x_vel" + s_ext, func) : nullptr; + mVelocityY = (smoke || liquid) ? getPointer<float>("y_vel" + s_ext, func) : nullptr; + mVelocityZ = (smoke || liquid) ? getPointer<float>("z_vel" + s_ext, func) : nullptr; + mForceX = (smoke || liquid) ? getPointer<float>("x_force" + s_ext, func) : nullptr; + mForceY = (smoke || liquid) ? getPointer<float>("y_force" + s_ext, func) : nullptr; + mForceZ = (smoke || liquid) ? getPointer<float>("z_force" + s_ext, func) : nullptr; /* Outflow. */ mPhiOutIn = (outflow) ? getPointer<float>("phiOutIn" + s_ext, func) : nullptr; diff --git a/intern/mantaflow/intern/MANTA_main.h b/intern/mantaflow/intern/MANTA_main.h index 2de484db59d..5fd94ca01bc 100644 --- a/intern/mantaflow/intern/MANTA_main.h +++ b/intern/mantaflow/intern/MANTA_main.h @@ -77,14 +77,14 @@ struct MANTA { bool initSndParts(FluidModifierData *fmd = nullptr); bool initLiquidSndParts(FluidModifierData *fmd = nullptr); - /* Pointer transfer: Mantaflow -> Blender. */ - void updatePointers(FluidModifierData *fmd); + /* Pointer transfer: Mantaflow -> Blender. Use flush to reset all pointers to nullptr. */ + void updatePointers(FluidModifierData *fmd, bool flush = false); /* Write cache. */ bool writeConfiguration(FluidModifierData *fmd, int framenr); bool writeData(FluidModifierData *fmd, int framenr); bool writeNoise(FluidModifierData *fmd, int framenr); - // write calls for mesh and particles were left in bake calls for now + /* Write calls for mesh and particles were left in bake calls for now. */ /* Read cache (via Python). */ bool readConfiguration(FluidModifierData *fmd, int framenr); diff --git a/intern/mantaflow/intern/manta_fluid_API.cpp b/intern/mantaflow/intern/manta_fluid_API.cpp index f58ac186ff1..530dbd49b7c 100644 --- a/intern/mantaflow/intern/manta_fluid_API.cpp +++ b/intern/mantaflow/intern/manta_fluid_API.cpp @@ -230,11 +230,11 @@ bool manta_needs_realloc(MANTA *fluid, FluidModifierData *fmd) return fluid->needsRealloc(fmd); } -void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd) +void manta_update_pointers(struct MANTA *fluid, struct FluidModifierData *fmd, bool flush) { if (!fluid || !fmd) return; - fluid->updatePointers(fmd); + fluid->updatePointers(fmd, flush); } /* Fluid accessors */ diff --git a/intern/mantaflow/intern/strings/fluid_script.h b/intern/mantaflow/intern/strings/fluid_script.h index 0045d839be4..a01e333ab5e 100644 --- a/intern/mantaflow/intern/strings/fluid_script.h +++ b/intern/mantaflow/intern/strings/fluid_script.h @@ -418,19 +418,6 @@ const std::string fluid_post_step = "\n\ def fluid_post_step_$ID$():\n\ mantaMsg('Fluid post step')\n\ - forces_s$ID$.clear()\n\ - x_force_s$ID$.clear()\n\ - y_force_s$ID$.clear()\n\ - z_force_s$ID$.clear()\n\ - \n\ - if using_guiding_s$ID$:\n\ - weightGuide_s$ID$.clear()\n\ - if using_invel_s$ID$:\n\ - x_invel_s$ID$.clear()\n\ - y_invel_s$ID$.clear()\n\ - z_invel_s$ID$.clear()\n\ - invel_s$ID$.clear()\n\ - invelC_s$ID$.clear()\n\ \n\ # Copy vel grid to reals grids (which Blender internal will in turn use for vel access)\n\ copyVec3ToReal(source=vel_s$ID$, targetX=x_vel_s$ID$, targetY=y_vel_s$ID$, targetZ=z_vel_s$ID$)\n"; diff --git a/release/datafiles/locale b/release/datafiles/locale -Subproject 4af22e0492f401c609a0203cad1a9bc7fa00b86 +Subproject 2b3c19f5f61fc72dba56a7edfdc4e55e2327dc1 diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 25b00a0a52c81408b9dc15ea320a79ee956b3c0 +Subproject 49c39f59fbc464dd34388990123f271c39eacbf diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject f2f4a8b3bfa36ee49f7bdb3a1acb40ef4b39ee3 +Subproject a52733b58d95ce60ecde95a9eca242e7319c285 diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index aa80611ac6b..0ec3a322173 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -72,7 +72,7 @@ class SpellChecker: "wasn", # wasn't # Merged words - "antialiasing", + "antialiasing", "antialias", "arcsine", "arccosine", "arctangent", "autoclip", "autocomplete", @@ -241,7 +241,7 @@ class SpellChecker: "unsets", "unshadowed", "unspill", - "unstitchable", + "unstitchable", "unstitch", "unsubdivided", "unsubdivide", "untrusted", "vectorscope", @@ -421,6 +421,7 @@ class SpellChecker: "searchable", "spacebar", "subtractive", + "superellipse", "tooltip", "tooltips", "trackpad", "tuple", @@ -618,6 +619,7 @@ class SpellChecker: "musgrave", "nayar", "netravali", + "nishita", "ogawa", "oren", "peucker", # Ramer-Douglas-Peucker diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index c251d55714f..078b1c9ff38 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -293,7 +293,7 @@ class GRAPH_MT_key(Menu): # Using the modal operation doesn't make sense for this variant # as we do not have a modal mode for it, so just execute it. - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("graph.decimate", text="Decimate (Allowed Change)").mode = 'ERROR' layout.operator_context = operator_context diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index b5926692324..f2b0ba28d99 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -433,7 +433,7 @@ class NODE_MT_context_menu(Menu): layout.operator("node.delete") layout.operator("node.clipboard_copy", text="Copy") layout.operator("node.clipboard_paste", text="Paste") - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("node.delete_reconnect") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b501af5b203..f632e03438f 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1002,7 +1002,7 @@ class VIEW3D_MT_transform_base(Menu): if context.mode != 'OBJECT': layout.operator("transform.vertex_warp", text="Warp") - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("transform.vertex_random", text="Randomize").offset = 0.1 layout.operator_context = 'INVOKE_REGION_WIN' @@ -2074,7 +2074,7 @@ class VIEW3D_MT_edit_metaball_context_menu(Menu): layout.separator() # Remove - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("mball.delete_metaelems", text="Delete") @@ -2349,7 +2349,7 @@ class VIEW3D_MT_object(Menu): layout.separator() - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("object.delete", text="Delete").use_global = False layout.operator("object.delete", text="Delete Global").use_global = True @@ -2613,7 +2613,7 @@ class VIEW3D_MT_object_context_menu(Menu): layout.separator() - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("object.delete", text="Delete").use_global = False @@ -2699,7 +2699,7 @@ class VIEW3D_MT_object_parent(Menu): layout.separator() - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("object.parent_no_inverse_set") layout.operator_context = operator_context_default @@ -2790,7 +2790,7 @@ class VIEW3D_MT_make_single_user(Menu): def draw(self, _context): layout = self.layout - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' props = layout.operator("object.make_single_user", text="Object") props.object = True @@ -3730,7 +3730,7 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu): col.operator("transform.shrink_fatten", text="Shrink/Fatten") col.operator("transform.shear", text="Shear") col.operator("transform.vert_slide", text="Slide Vertices") - col.operator_context = 'EXEC_DEFAULT' + col.operator_context = 'EXEC_REGION_WIN' col.operator("transform.vertex_random", text="Randomize Vertices").offset = 0.1 col.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5 col.operator_context = 'INVOKE_REGION_WIN' @@ -3957,7 +3957,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.separator() layout.operator("transform.vert_slide", text="Slide Vertices") - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5 layout.operator("mesh.vertices_smooth_laplacian", text="Smooth Vertices (Laplacian)") layout.operator_context = 'INVOKE_REGION_WIN' @@ -4211,7 +4211,7 @@ class VIEW3D_MT_edit_mesh_normals(Menu): layout.operator_context = 'INVOKE_REGION_WIN' layout.operator("transform.rotate_normal", text="Rotate...") layout.operator("mesh.point_normals", text="Point to Target...") - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("mesh.merge_normals", text="Merge") layout.operator("mesh.split_normals", text="Split") @@ -4678,7 +4678,7 @@ class VIEW3D_MT_edit_meta(Menu): layout.menu("VIEW3D_MT_edit_meta_showhide") - layout.operator_context = 'EXEC_DEFAULT' + layout.operator_context = 'EXEC_REGION_WIN' layout.operator("mball.delete_metaelems", text="Delete") diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index b7904ce1879..c3cfd4b33ea 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -129,6 +129,8 @@ void BKE_pose_channel_free(struct bPoseChannel *pchan); void BKE_pose_channel_free_ex(struct bPoseChannel *pchan, bool do_id_user); void BKE_pose_channel_runtime_reset(struct bPoseChannel_Runtime *runtime); +void BKE_pose_channel_runtime_reset_on_copy(struct bPoseChannel_Runtime *runtime); + void BKE_pose_channel_runtime_free(struct bPoseChannel_Runtime *runtime); void BKE_pose_channel_free_bbone_cache(struct bPoseChannel_Runtime *runtime); @@ -153,12 +155,15 @@ void BKE_pose_copy_data_ex(struct bPose **dst, const bool copy_constraints); void BKE_pose_copy_data(struct bPose **dst, const struct bPose *src, const bool copy_constraints); void BKE_pose_channel_copy_data(struct bPoseChannel *pchan, const struct bPoseChannel *pchan_from); +void BKE_pose_channel_session_uuid_generate(struct bPoseChannel *pchan); struct bPoseChannel *BKE_pose_channel_find_name(const struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_active(struct Object *ob); struct bPoseChannel *BKE_pose_channel_active_or_first_selected(struct Object *ob); struct bPoseChannel *BKE_pose_channel_verify(struct bPose *pose, const char *name); struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name); +void BKE_pose_check_uuids_unique_and_report(const struct bPose *pose); + #ifndef NDEBUG bool BKE_pose_channels_is_valid(const struct bPose *pose); #endif diff --git a/source/blender/blenkernel/BKE_ocean.h b/source/blender/blenkernel/BKE_ocean.h index 6ce2e13cf18..2472e3dbad3 100644 --- a/source/blender/blenkernel/BKE_ocean.h +++ b/source/blender/blenkernel/BKE_ocean.h @@ -70,8 +70,10 @@ typedef struct OceanCache { struct Ocean *BKE_ocean_add(void); void BKE_ocean_free_data(struct Ocean *oc); void BKE_ocean_free(struct Ocean *oc); -bool BKE_ocean_ensure(struct OceanModifierData *omd); -void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd); +bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution); +void BKE_ocean_init_from_modifier(struct Ocean *ocean, + struct OceanModifierData const *omd, + const int resolution); void BKE_ocean_init(struct Ocean *o, int M, diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 3c0ec8147fe..02495496ee2 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -217,7 +217,7 @@ typedef struct ParticleCollision { /** Collision modifier for current object. */ struct CollisionModifierData *md; - /** Time factor of previous collision, needed for substracting face velocity. */ + /** Time factor of previous collision, needed for subtracting face velocity. */ float f; float fac1, fac2; diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 13716ddb5c6..98f52a29b5c 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -73,7 +73,7 @@ typedef struct SpaceType { /* Initial allocation, after this WM will call init() too. Some editors need * area and scene data (e.g. frame range) to set their initial scrolling. */ - struct SpaceLink *(*new)(const struct ScrArea *area, const struct Scene *scene); + struct SpaceLink *(*create)(const struct ScrArea *area, const struct Scene *scene); /* not free spacelink itself */ void (*free)(struct SpaceLink *sl); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index fa7eee83a68..85ac2c693cb 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_math.h" +#include "BLI_session_uuid.h" #include "BLI_string_utils.h" #include "BLI_utildefines.h" @@ -482,6 +483,11 @@ void action_groups_clear_tempflags(bAction *act) /* *************** Pose channels *************** */ +void BKE_pose_channel_session_uuid_generate(bPoseChannel *pchan) +{ + pchan->runtime.session_uuid = BLI_session_uuid_generate(); +} + /** * Return a pointer to the pose channel of the given name * from this pose. @@ -524,6 +530,8 @@ bPoseChannel *BKE_pose_channel_verify(bPose *pose, const char *name) /* If not, create it and add it */ chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); + BKE_pose_channel_session_uuid_generate(chan); + BLI_strncpy(chan->name, name, sizeof(chan->name)); chan->custom_scale = 1.0f; @@ -698,6 +706,10 @@ void BKE_pose_copy_data_ex(bPose **dst, id_us_plus((ID *)pchan->custom); } + if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { + BKE_pose_channel_session_uuid_generate(pchan); + } + /* warning, O(n2) here, if done without the hash, but these are rarely used features. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); @@ -726,7 +738,7 @@ void BKE_pose_copy_data_ex(bPose **dst, pchan->draw_data = NULL; /* Drawing cache, no need to copy. */ /* Runtime data, no need to copy. */ - memset(&pchan->runtime, 0, sizeof(pchan->runtime)); + BKE_pose_channel_runtime_reset_on_copy(&pchan->runtime); } /* for now, duplicate Bone Groups too when doing this */ @@ -956,6 +968,14 @@ void BKE_pose_channel_runtime_reset(bPoseChannel_Runtime *runtime) memset(runtime, 0, sizeof(*runtime)); } +/* Reset all non-persistent fields. */ +void BKE_pose_channel_runtime_reset_on_copy(bPoseChannel_Runtime *runtime) +{ + const SessionUUID uuid = runtime->session_uuid; + memset(runtime, 0, sizeof(*runtime)); + runtime->session_uuid = uuid; +} + /** Deallocates runtime cache of a pose channel */ void BKE_pose_channel_runtime_free(bPoseChannel_Runtime *runtime) { @@ -1692,3 +1712,30 @@ void what_does_obaction(Object *ob, BKE_animsys_evaluate_animdata(&workob->id, &adt, anim_eval_context, ADT_RECALC_ANIM, false); } } + +void BKE_pose_check_uuids_unique_and_report(const bPose *pose) +{ + if (pose == NULL) { + return; + } + + struct GSet *used_uuids = BLI_gset_new( + BLI_session_uuid_ghash_hash, BLI_session_uuid_ghash_compare, "sequencer used uuids"); + + LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { + const SessionUUID *session_uuid = &pchan->runtime.session_uuid; + if (!BLI_session_uuid_is_generated(session_uuid)) { + printf("Pose channel %s does not have UUID generated.\n", pchan->name); + continue; + } + + if (BLI_gset_lookup(used_uuids, session_uuid) != NULL) { + printf("Pose channel %s has duplicate UUID generated.\n", pchan->name); + continue; + } + + BLI_gset_insert(used_uuids, (void *)session_uuid); + } + + BLI_gset_free(used_uuids, NULL); +} diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c977ebe4ae2..631ce4edd20 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2205,7 +2205,7 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected) pchan->mpath = NULL; /* Reset runtime data, we don't want to share that with the proxy. */ - BKE_pose_channel_runtime_reset(&pchanw.runtime); + BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime); /* this is freed so copy a copy, else undo crashes */ if (pchanw.prop) { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 8178415a8f6..39fbea66637 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -503,7 +503,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.4f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -686,7 +686,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag &= ~GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 1.0f; - brush->gpencil_settings->flag &= ~GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag &= ~GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -717,7 +717,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.4f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -760,7 +760,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.6f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->input_samples = 10; brush->gpencil_settings->active_smooth = ACTIVE_SMOOTH; @@ -812,7 +812,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->draw_strength = 0.5f; brush->gpencil_settings->flag |= GP_BRUSH_DEFAULT_ERASER; brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->icon_id = GP_BRUSH_ICON_ERASE_SOFT; brush->gpencil_tool = GPAINT_TOOL_ERASE; brush->gpencil_settings->eraser_mode = GP_BRUSH_ERASER_SOFT; @@ -859,7 +859,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -872,7 +872,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -885,7 +885,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -898,7 +898,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -911,7 +911,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -924,7 +924,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; zero_v3(brush->secondary_rgb); break; @@ -937,7 +937,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; @@ -951,7 +951,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_flag = GP_SCULPT_FLAG_SMOOTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; @@ -965,7 +965,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -978,7 +978,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->size = 25.0f; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -991,7 +991,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1004,7 +1004,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.3f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1017,7 +1017,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1030,7 +1030,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.5f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1043,7 +1043,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->size = 25.0f; brush->gpencil_settings->draw_strength = 1.0f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; @@ -1056,7 +1056,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type) brush->gpencil_settings->flag |= GP_BRUSH_USE_PRESSURE; brush->gpencil_settings->draw_strength = 0.8f; - brush->gpencil_settings->flag |= GP_BRUSH_USE_STENGTH_PRESSURE; + brush->gpencil_settings->flag |= GP_BRUSH_USE_STRENGTH_PRESSURE; brush->gpencil_settings->sculpt_mode_flag |= GP_SCULPT_FLAGMODE_APPLY_POSITION; break; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index b9279ace39f..7b7b7ceb84b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -4203,7 +4203,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( brushVelocity[v3].v, weights); - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3v3(velocity, brushPointVelocity, bData->velocity[index].v); } @@ -4548,7 +4548,7 @@ static void dynamic_paint_paint_particle_cell_point_cb_ex( ParticleData *pa = psys->particles + part_index; mul_v3_v3fl(velocity, pa->state.vel, particle_timestep); - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3(velocity, bData->velocity[index].v); } @@ -4739,7 +4739,7 @@ static void dynamic_paint_paint_single_point_cb_ex(void *__restrict userdata, if (brush->flags & MOD_DPAINT_USES_VELOCITY) { float velocity[3]; - /* substract canvas point velocity */ + /* subtract canvas point velocity */ if (bData->velocity) { sub_v3_v3v3(velocity, brushVelocity->v, bData->velocity[index].v); } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index ad517fe1c23..019230572ef 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1119,7 +1119,7 @@ static void ensure_obstaclefields(FluidDomainSettings *fds) if (fds->active_fields & FLUID_DOMAIN_ACTIVE_GUIDE) { manta_ensure_guiding(fds->fluid, fds->fmd); } - manta_update_pointers(fds->fluid, fds->fmd); + manta_update_pointers(fds->fluid, fds->fmd, false); } static void update_obstacleflags(FluidDomainSettings *fds, @@ -2606,7 +2606,7 @@ static void ensure_flowsfields(FluidDomainSettings *fds) fds->particle_type & FLUID_DOMAIN_PARTICLE_TRACER)) { manta_liquid_ensure_sndparts(fds->fluid, fds->fmd); } - manta_update_pointers(fds->fluid, fds->fmd); + manta_update_pointers(fds->fluid, fds->fmd, false); } static void update_flowsflags(FluidDomainSettings *fds, Object **flowobjs, int numflowobj) @@ -2927,8 +2927,21 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, float *velx_initial = manta_get_in_velocity_x(fds->fluid); float *vely_initial = manta_get_in_velocity_y(fds->fluid); float *velz_initial = manta_get_in_velocity_z(fds->fluid); - uint z; + float *forcex = manta_get_force_x(fds->fluid); + float *forcey = manta_get_force_y(fds->fluid); + float *forcez = manta_get_force_z(fds->fluid); + + BLI_assert(forcex && forcey && forcez); + + /* Either all or no components have to exist. */ + BLI_assert((color_r && color_g && color_b) || (!color_r && !color_g && !color_b)); + BLI_assert((color_r_in && color_g_in && color_b_in) || + (!color_r_in && !color_g_in && !color_b_in)); + BLI_assert((velx_initial && vely_initial && velz_initial) || + (!velx_initial && !vely_initial && !velz_initial)); + + uint z; /* Grid reset before writing again. */ for (z = 0; z < fds->res[0] * fds->res[1] * fds->res[2]; z++) { /* Only reset static phi on first frame, dynamic phi gets reset every time. */ @@ -2952,7 +2965,7 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, if (heat_in) { heat_in[z] = heat[z]; } - if (color_r_in) { + if (color_r_in && color_g_in && color_b_in) { color_r_in[z] = color_r[z]; color_g_in[z] = color_b[z]; color_b_in[z] = color_g[z]; @@ -2964,11 +2977,15 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, if (emission_in) { emission_in[z] = 0.0f; } - if (velx_initial) { + if (velx_initial && vely_initial && velz_initial) { velx_initial[z] = 0.0f; vely_initial[z] = 0.0f; velz_initial[z] = 0.0f; } + /* Reset forces here as update_effectors() is skipped when no external forces are present. */ + forcex[z] = 0.0f; + forcey[z] = 0.0f; + forcez[z] = 0.0f; } /* Apply emission data for every flow object. */ @@ -3152,13 +3169,13 @@ static void update_effectors_task_cb(void *__restrict userdata, continue; } - /* get velocities from manta grid space and convert to blender units */ + /* Get velocities from manta grid space and convert to blender units. */ vel[0] = data->velocity_x[index]; vel[1] = data->velocity_y[index]; vel[2] = data->velocity_z[index]; mul_v3_fl(vel, fds->dx); - /* convert vel to global space */ + /* Convert vel to global space. */ mag = len_v3(vel); mul_mat3_m4_v3(fds->obmat, vel); normalize_v3(vel); @@ -3169,18 +3186,18 @@ static void update_effectors_task_cb(void *__restrict userdata, voxel_center[2] = fds->p0[2] + fds->cell_size[2] * ((float)(z + fds->res_min[2]) + 0.5f); mul_m4_v3(fds->obmat, voxel_center); - /* do effectors */ + /* Do effectors. */ pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint); BKE_effectors_apply( data->effectors, NULL, fds->effector_weights, &epoint, retvel, NULL, NULL); - /* convert retvel to local space */ + /* Convert retvel to local space. */ mag = len_v3(retvel); mul_mat3_m4_v3(fds->imat, retvel); normalize_v3(retvel); mul_v3_fl(retvel, mag); - /* constrain forces to interval -1 to 1 */ + /* Constrain forces to interval -1 to 1. */ data->force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f); data->force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f); data->force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f); @@ -3721,29 +3738,35 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, int mode = fds->cache_type; /* Do not process modifier if current frame is out of cache range. */ + bool escape = false; switch (mode) { case FLUID_DOMAIN_CACHE_ALL: case FLUID_DOMAIN_CACHE_MODULAR: if (fds->cache_frame_offset > 0) { if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->cache_frame_end + fds->cache_frame_offset) { - return; + escape = true; } } else { if (scene_framenr < fds->cache_frame_start + fds->cache_frame_offset || scene_framenr > fds->cache_frame_end) { - return; + escape = true; } } break; case FLUID_DOMAIN_CACHE_REPLAY: default: if (scene_framenr < fds->cache_frame_start || scene_framenr > fds->cache_frame_end) { - return; + escape = true; } break; } + /* If modifier will not be processed, update/flush pointers from (old) fluid object once more. */ + if (escape && fds->fluid) { + manta_update_pointers(fds->fluid, fmd, true); + return; + } /* Reset fluid if no fluid present. Also resets active fields. */ if (!fds->fluid) { @@ -4079,7 +4102,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, } /* Ensure that fluid pointers are always up to date at the end of modifier processing. */ - manta_update_pointers(fds->fluid, fmd); + manta_update_pointers(fds->fluid, fmd, false); fds->flags &= ~FLUID_DOMAIN_FILE_LOAD; fmd->time = scene_framenr; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index f94ef946851..198ff5a0540 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -753,18 +753,26 @@ struct Ocean *BKE_ocean_add(void) return oc; } -bool BKE_ocean_ensure(struct OceanModifierData *omd) +bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution) { if (omd->ocean) { - return false; + /* Check that the ocean has the same resolution than we want now. */ + if (omd->ocean->_M == resolution * resolution) { + return false; + } + else { + BKE_ocean_free(omd->ocean); + } } omd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(omd->ocean, omd); + BKE_ocean_init_from_modifier(omd->ocean, omd, resolution); return true; } -void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd) +void BKE_ocean_init_from_modifier(struct Ocean *ocean, + struct OceanModifierData const *omd, + const int resolution) { short do_heightfield, do_chop, do_normals, do_jacobian; @@ -774,9 +782,10 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM); BKE_ocean_free_data(ocean); + BKE_ocean_init(ocean, - omd->resolution * omd->resolution, - omd->resolution * omd->resolution, + resolution * resolution, + resolution * resolution, omd->spatial_size, omd->spatial_size, omd->wind_velocity, @@ -1607,7 +1616,8 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o), } void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean), - struct OceanModifierData const *UNUSED(omd)) + struct OceanModifierData const *UNUSED(omd), + int UNUSED(resolution)) { } diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index f37feab4b85..efe10b02940 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -1005,7 +1005,6 @@ bool bUnit_ReplaceString( /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */ changed |= unit_distribute_negatives(str, len_max); - printf("%s\n", str); /* Try to find a default unit from current or previous string. */ default_unit = unit_detect_from_str(usys, str, str_prev); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 937bf8b1ae6..7c187679ad1 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -3000,7 +3000,7 @@ int isect_line_line_epsilon_v3(const float v1[3], mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab)); add_v3_v3v3(r_i1, v1, a); - /* for the second line, just substract the offset from the first intersection point */ + /* for the second line, just subtract the offset from the first intersection point */ sub_v3_v3v3(r_i2, r_i1, t); return 2; /* two nearest points */ diff --git a/source/blender/blenlib/intern/session_uuid.c b/source/blender/blenlib/intern/session_uuid.c index d3446fae5cb..8ed96f02149 100644 --- a/source/blender/blenlib/intern/session_uuid.c +++ b/source/blender/blenlib/intern/session_uuid.c @@ -40,7 +40,7 @@ SessionUUID BLI_session_uuid_generate(void) if (!BLI_session_uuid_is_generated(&result)) { /* Happens when the UUID overflows. * - * Just request the UUID once again, hoping that there are no a lot of high-priority threads + * Just request the UUID once again, hoping that there are not a lot of high-priority threads * which will overflow the counter once again between the previous call and this one. * * NOTE: It is possible to have collisions after such overflow. */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e6d54550aa4..c24b4545e22 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5145,6 +5145,9 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose) pose->chan_array = NULL; for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + BKE_pose_channel_runtime_reset(&pchan->runtime); + BKE_pose_channel_session_uuid_generate(pchan); + pchan->bone = NULL; BLO_read_data_address(reader, &pchan->parent); BLO_read_data_address(reader, &pchan->child); @@ -5170,7 +5173,6 @@ static void direct_link_pose(BlendDataReader *reader, bPose *pose) CLAMP(pchan->rotmode, ROT_MODE_MIN, ROT_MODE_MAX); pchan->draw_data = NULL; - BKE_pose_channel_runtime_reset(&pchan->runtime); } pose->ikdata = NULL; if (pose->ikparam != NULL) { diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 74a07050d7d..4e3f701bacc 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -190,7 +190,7 @@ static void do_version_workspaces_create_from_screens(Main *bmain) static void do_version_area_change_space_to_space_action(ScrArea *area, const Scene *scene) { SpaceType *stype = BKE_spacetype_from_id(SPACE_ACTION); - SpaceAction *saction = (SpaceAction *)stype->new (area, scene); + SpaceAction *saction = (SpaceAction *)stype->create(area, scene); ARegion *region_channels; /* Properly free current regions */ diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index d2f45900325..94c9b125706 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -467,5 +467,16 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND; } } + + if (!DNA_struct_elem_find(fd->filesdna, "OceanModifierData", "int", "viewport_resolution")) { + for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_Ocean) { + OceanModifierData *omd = (OceanModifierData *)md; + omd->viewport_resolution = omd->resolution; + } + } + } + } } } diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c index 36122e06e9b..de26ca5ebd2 100644 --- a/source/blender/bmesh/operators/bmo_beautify.c +++ b/source/blender/bmesh/operators/bmo_beautify.c @@ -39,7 +39,10 @@ void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op) BMFace *f; BMEdge *e; const bool use_restrict_tag = BMO_slot_bool_get(op->slots_in, "use_restrict_tag"); - const short flag = (use_restrict_tag ? VERT_RESTRICT_TAG : 0); + const short flag = + ((use_restrict_tag ? VERT_RESTRICT_TAG : 0) | + /* Enable to avoid iterative edge rotation to cause the direction of faces to flip. */ + EDGE_RESTRICT_DEGENERATE); const short method = (short)BMO_slot_int_get(op->slots_in, "method"); BMEdge **edge_array; diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c index c877c534376..a25e4666a22 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.c +++ b/source/blender/bmesh/tools/bmesh_beautify.c @@ -141,7 +141,8 @@ static void erot_state_alternate(const BMEdge *e, EdRotState *e_state) static float bm_edge_calc_rotate_beauty__area(const float v1[3], const float v2[3], const float v3[3], - const float v4[3]) + const float v4[3], + const bool lock_degenerate) { /* not a loop (only to be able to break out) */ do { @@ -199,7 +200,8 @@ static float bm_edge_calc_rotate_beauty__area(const float v1[3], * Allowing to rotate out of a degenerate state can flip the faces * (when performed iteratively). */ - return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true, NULL); + return BLI_polyfill_beautify_quad_rotate_calc_ex( + v1_xy, v2_xy, v3_xy, v4_xy, lock_degenerate, NULL); } while (false); return FLT_MAX; @@ -262,7 +264,8 @@ float BM_verts_calc_rotate_beauty(const BMVert *v1, switch (method) { case 0: - return bm_edge_calc_rotate_beauty__area(v1->co, v2->co, v3->co, v4->co); + return bm_edge_calc_rotate_beauty__area( + v1->co, v2->co, v3->co, v4->co, flag & EDGE_RESTRICT_DEGENERATE); default: return bm_edge_calc_rotate_beauty__angle(v1->co, v2->co, v3->co, v4->co); } diff --git a/source/blender/bmesh/tools/bmesh_beautify.h b/source/blender/bmesh/tools/bmesh_beautify.h index f957f0d3560..d2c67693f73 100644 --- a/source/blender/bmesh/tools/bmesh_beautify.h +++ b/source/blender/bmesh/tools/bmesh_beautify.h @@ -22,7 +22,10 @@ */ enum { + /** Vertices tags must match (special case). */ VERT_RESTRICT_TAG = (1 << 0), + /** Don't rotate out of degenerate state (needed for iterative rotation). */ + EDGE_RESTRICT_DEGENERATE = (1 << 1), }; void BM_mesh_beautify_fill(BMesh *bm, diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index cc7aef65bbb..1d3dd8b0c1c 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -7143,68 +7143,64 @@ static float find_profile_fullness(BevelParams *bp) */ static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bool custom) { - int seg, seg_2; - - seg = bp->seg; - seg_2 = power_of_2_max_i(bp->seg); - if (seg > 1) { - /* Sample the input number of segments. */ - pro_spacing->xvals = (double *)BLI_memarena_alloc(bp->mem_arena, - (size_t)(seg + 1) * sizeof(double)); - pro_spacing->yvals = (double *)BLI_memarena_alloc(bp->mem_arena, - (size_t)(seg + 1) * sizeof(double)); + int seg = bp->seg; + + if (seg <= 1) { + /* Only 1 segment, we don't need any profile information. */ + pro_spacing->xvals = NULL; + pro_spacing->yvals = NULL; + pro_spacing->xvals_2 = NULL; + pro_spacing->yvals_2 = NULL; + pro_spacing->seg_2 = 0; + return; + } + + int seg_2 = max_ii(power_of_2_max_i(bp->seg), 4); + + /* Sample the seg_2 segments used during vertex mesh subdivision. */ + bp->pro_spacing.seg_2 = seg_2; + if (seg_2 == seg) { + pro_spacing->xvals_2 = pro_spacing->xvals; + pro_spacing->yvals_2 = pro_spacing->yvals; + } + else { + pro_spacing->xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, + sizeof(double) * (seg_2 + 1)); + pro_spacing->yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, + sizeof(double) * (seg_2 + 1)); if (custom) { - /* Make sure the curve profile's sample table is full. */ - if (bp->custom_profile->segments_len != seg || !bp->custom_profile->segments) { - BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg); - } + /* Make sure the curve profile widget's sample table is full of the seg_2 samples. */ + BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg_2); /* Copy segment locations into the profile spacing struct. */ - for (int i = 0; i < seg + 1; i++) { - pro_spacing->xvals[i] = (double)bp->custom_profile->segments[i].y; - pro_spacing->yvals[i] = (double)bp->custom_profile->segments[i].x; + for (int i = 0; i < seg_2 + 1; i++) { + pro_spacing->xvals_2[i] = (double)bp->custom_profile->segments[i].y; + pro_spacing->yvals_2[i] = (double)bp->custom_profile->segments[i].x; } } else { - find_even_superellipse_chords(seg, bp->pro_super_r, pro_spacing->xvals, pro_spacing->yvals); + find_even_superellipse_chords( + seg_2, bp->pro_super_r, pro_spacing->xvals_2, pro_spacing->yvals_2); } + } - /* Sample the seg_2 segments used for subdividing the vertex meshes. */ - if (seg_2 == 2) { - seg_2 = 4; + /* Sample the input number of segments. */ + pro_spacing->xvals = (double *)BLI_memarena_alloc(bp->mem_arena, sizeof(double) * (seg + 1)); + pro_spacing->yvals = (double *)BLI_memarena_alloc(bp->mem_arena, sizeof(double) * (seg + 1)); + if (custom) { + /* Make sure the curve profile's sample table is full. */ + if (bp->custom_profile->segments_len != seg || !bp->custom_profile->segments) { + BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg); } - bp->pro_spacing.seg_2 = seg_2; - if (seg_2 == seg) { - pro_spacing->xvals_2 = pro_spacing->xvals; - pro_spacing->yvals_2 = pro_spacing->yvals; - } - else { - pro_spacing->xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, - (size_t)(seg_2 + 1) * sizeof(double)); - pro_spacing->yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena, - (size_t)(seg_2 + 1) * sizeof(double)); - if (custom) { - /* Make sure the curve profile widget's sample table is full of the seg_2 samples. */ - BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg_2); - - /* Copy segment locations into the profile spacing struct. */ - for (int i = 0; i < seg_2 + 1; i++) { - pro_spacing->xvals_2[i] = (double)bp->custom_profile->segments[i].y; - pro_spacing->yvals_2[i] = (double)bp->custom_profile->segments[i].x; - } - } - else { - find_even_superellipse_chords( - seg_2, bp->pro_super_r, pro_spacing->xvals_2, pro_spacing->yvals_2); - } + + /* Copy segment locations into the profile spacing struct. */ + for (int i = 0; i < seg + 1; i++) { + pro_spacing->xvals[i] = (double)bp->custom_profile->segments[i].y; + pro_spacing->yvals[i] = (double)bp->custom_profile->segments[i].x; } } - else { /* Only 1 segment, we don't need any profile information. */ - pro_spacing->xvals = NULL; - pro_spacing->yvals = NULL; - pro_spacing->xvals_2 = NULL; - pro_spacing->yvals_2 = NULL; - pro_spacing->seg_2 = 0; + else { + find_even_superellipse_chords(seg, bp->pro_super_r, pro_spacing->xvals, pro_spacing->yvals); } } diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt index 51fce738700..417aaa2c4c0 100644 --- a/source/blender/depsgraph/CMakeLists.txt +++ b/source/blender/depsgraph/CMakeLists.txt @@ -54,6 +54,11 @@ set(SRC intern/builder/deg_builder_remove_noop.cc intern/builder/deg_builder_rna.cc intern/builder/deg_builder_transitive.cc + intern/builder/pipeline.cc + intern/builder/pipeline_compositor.cc + intern/builder/pipeline_from_ids.cc + intern/builder/pipeline_render.cc + intern/builder/pipeline_view_layer.cc intern/debug/deg_debug.cc intern/debug/deg_debug_relations_graphviz.cc intern/debug/deg_debug_stats_gnuplot.cc @@ -110,6 +115,11 @@ set(SRC intern/builder/deg_builder_remove_noop.h intern/builder/deg_builder_rna.h intern/builder/deg_builder_transitive.h + intern/builder/pipeline.h + intern/builder/pipeline_compositor.h + intern/builder/pipeline_from_ids.h + intern/builder/pipeline_render.h + intern/builder/pipeline_view_layer.h intern/debug/deg_debug.h intern/debug/deg_time_average.h intern/eval/deg_eval.h diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 390e996b63f..e262c880421 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -1817,6 +1817,9 @@ void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) if (scene->ed == nullptr) { return; } + if (built_map_.checkIsBuiltAndTag(scene, BuilderMap::TAG_SCENE_SEQUENCER)) { + return; + } build_scene_audio(scene); Scene *scene_cow = get_cow_datablock(scene); add_operation_node(&scene->id, diff --git a/source/blender/depsgraph/intern/builder/pipeline.cc b/source/blender/depsgraph/intern/builder/pipeline.cc new file mode 100644 index 00000000000..d6893ba11d8 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline.cc @@ -0,0 +1,132 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline.h" + +#include "PIL_time.h" + +#include "BKE_global.h" + +#include "DNA_scene_types.h" + +#include "deg_builder_cycle.h" +#include "deg_builder_nodes.h" +#include "deg_builder_relations.h" +#include "deg_builder_transitive.h" + +namespace blender { +namespace deg { + +AbstractBuilderPipeline::AbstractBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : deg_graph_(reinterpret_cast<Depsgraph *>(graph)), + bmain_(bmain), + scene_(scene), + view_layer_(view_layer), + builder_cache_() +{ +} + +AbstractBuilderPipeline::~AbstractBuilderPipeline() +{ +} + +void AbstractBuilderPipeline::build() +{ + double start_time = 0.0; + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + start_time = PIL_check_seconds_timer(); + } + + build_step_sanity_check(); + build_step_nodes(); + build_step_relations(); + build_step_finalize(); + + if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { + printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); + } +} + +void AbstractBuilderPipeline::build_step_sanity_check() +{ + BLI_assert(BLI_findindex(&scene_->view_layers, view_layer_) != -1); + BLI_assert(deg_graph_->scene == scene_); + BLI_assert(deg_graph_->view_layer == view_layer_); +} + +void AbstractBuilderPipeline::build_step_nodes() +{ + /* Generate all the nodes in the graph first */ + unique_ptr<DepsgraphNodeBuilder> node_builder = construct_node_builder(); + node_builder->begin_build(); + build_nodes(*node_builder); + node_builder->end_build(); +} + +void AbstractBuilderPipeline::build_step_relations() +{ + /* Hook up relationships between operations - to determine evaluation order. */ + unique_ptr<DepsgraphRelationBuilder> relation_builder = construct_relation_builder(); + relation_builder->begin_build(); + build_relations(*relation_builder); + relation_builder->build_copy_on_write_relations(); + relation_builder->build_driver_relations(); +} + +void AbstractBuilderPipeline::build_step_finalize() +{ + /* Detect and solve cycles. */ + deg_graph_detect_cycles(deg_graph_); + /* Simplify the graph by removing redundant relations (to optimize + * traversal later). */ + /* TODO: it would be useful to have an option to disable this in cases where + * it is causing trouble. */ + if (G.debug_value == 799) { + deg_graph_transitive_reduction(deg_graph_); + } + /* Store pointers to commonly used valuated datablocks. */ + deg_graph_->scene_cow = (Scene *)deg_graph_->get_cow_id(°_graph_->scene->id); + /* Flush visibility layer and re-schedule nodes for update. */ + deg_graph_build_finalize(bmain_, deg_graph_); + DEG_graph_on_visible_update(bmain_, reinterpret_cast<::Depsgraph *>(deg_graph_), false); +#if 0 + if (!DEG_debug_consistency_check(deg_graph_)) { + printf("Consistency validation failed, ABORTING!\n"); + abort(); + } +#endif + /* Relations are up to date. */ + deg_graph_->need_update = false; +} + +unique_ptr<DepsgraphNodeBuilder> AbstractBuilderPipeline::construct_node_builder() +{ + return std::make_unique<DepsgraphNodeBuilder>(bmain_, deg_graph_, &builder_cache_); +} + +unique_ptr<DepsgraphRelationBuilder> AbstractBuilderPipeline::construct_relation_builder() +{ + return std::make_unique<DepsgraphRelationBuilder>(bmain_, deg_graph_, &builder_cache_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline.h b/source/blender/depsgraph/intern/builder/pipeline.h new file mode 100644 index 00000000000..2c9c78bb2cb --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline.h @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "deg_builder_cache.h" + +#include "intern/depsgraph_type.h" + +struct Main; +struct Scene; +struct ViewLayer; +struct Depsgraph; + +namespace blender { +namespace deg { + +struct Depsgraph; +class DepsgraphNodeBuilder; +class DepsgraphRelationBuilder; + +/* Base class for Depsgraph Builder pipelines. + * + * Basically it runs through the following steps: + * - sanity check + * - build nodes + * - build relations + * - finalize + */ +class AbstractBuilderPipeline { + public: + AbstractBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + virtual ~AbstractBuilderPipeline(); + + void build(); + + protected: + Depsgraph *deg_graph_; + Main *bmain_; + Scene *scene_; + ViewLayer *view_layer_; + DepsgraphBuilderCache builder_cache_; + + virtual unique_ptr<DepsgraphNodeBuilder> construct_node_builder(); + virtual unique_ptr<DepsgraphRelationBuilder> construct_relation_builder(); + + virtual void build_step_sanity_check(); + void build_step_nodes(); + void build_step_relations(); + void build_step_finalize(); + + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) = 0; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) = 0; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_compositor.cc b/source/blender/depsgraph/intern/builder/pipeline_compositor.cc new file mode 100644 index 00000000000..3e56f17fc7e --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_compositor.cc @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_compositor.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +CompositorBuilderPipeline::CompositorBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, bNodeTree *nodetree) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer), nodetree_(nodetree) +{ + deg_graph_->is_render_pipeline_depsgraph = true; +} + +void CompositorBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_scene_render(scene_, view_layer_); + node_builder.build_nodetree(nodetree_); +} + +void CompositorBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_scene_render(scene_, view_layer_); + relation_builder.build_nodetree(nodetree_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_compositor.h b/source/blender/depsgraph/intern/builder/pipeline_compositor.h new file mode 100644 index 00000000000..892ece7c2a4 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_compositor.h @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +struct bNodeTree; + +namespace blender { +namespace deg { + +class CompositorBuilderPipeline : public AbstractBuilderPipeline { + public: + CompositorBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, bNodeTree *nodetree); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; + + private: + bNodeTree *nodetree_; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc new file mode 100644 index 00000000000..e44f554f197 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.cc @@ -0,0 +1,154 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_from_ids.h" + +#include "DNA_layer_types.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +namespace { + +class DepsgraphFromIDsFilter { + public: + DepsgraphFromIDsFilter(ID **ids, const int num_ids) + { + for (int i = 0; i < num_ids; ++i) { + ids_.add(ids[i]); + } + } + + bool contains(ID *id) + { + return ids_.contains(id); + } + + protected: + Set<ID *> ids_; +}; + +class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { + public: + DepsgraphFromIDsNodeBuilder( + Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) + : DepsgraphNodeBuilder(bmain, graph, cache), filter_(ids, num_ids) + { + } + + virtual bool need_pull_base_into_graph(Base *base) override + { + if (!filter_.contains(&base->object->id)) { + return false; + } + return DepsgraphNodeBuilder::need_pull_base_into_graph(base); + } + + virtual void build_object_proxy_group(Object *object, bool is_visible) override + { + if (object->proxy_group == nullptr) { + return; + } + if (!filter_.contains(&object->proxy_group->id)) { + return; + } + DepsgraphNodeBuilder::build_object_proxy_group(object, is_visible); + } + + protected: + DepsgraphFromIDsFilter filter_; +}; + +class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { + public: + DepsgraphFromIDsRelationBuilder( + Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) + : DepsgraphRelationBuilder(bmain, graph, cache), filter_(ids, num_ids) + { + } + + virtual bool need_pull_base_into_graph(Base *base) override + { + if (!filter_.contains(&base->object->id)) { + return false; + } + return DepsgraphRelationBuilder::need_pull_base_into_graph(base); + } + + virtual void build_object_proxy_group(Object *object) override + { + if (object->proxy_group == nullptr) { + return; + } + if (!filter_.contains(&object->proxy_group->id)) { + return; + } + DepsgraphRelationBuilder::build_object_proxy_group(object); + } + + protected: + DepsgraphFromIDsFilter filter_; +}; + +} // namespace + +FromIDsBuilderPipeline::FromIDsBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer, + ID **ids, + const int num_ids) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer), ids_(ids), num_ids_(num_ids) +{ +} + +unique_ptr<DepsgraphNodeBuilder> FromIDsBuilderPipeline::construct_node_builder() +{ + return std::make_unique<DepsgraphFromIDsNodeBuilder>( + bmain_, deg_graph_, &builder_cache_, ids_, num_ids_); +} + +unique_ptr<DepsgraphRelationBuilder> FromIDsBuilderPipeline::construct_relation_builder() +{ + return std::make_unique<DepsgraphFromIDsRelationBuilder>( + bmain_, deg_graph_, &builder_cache_, ids_, num_ids_); +} + +void FromIDsBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); + for (int i = 0; i < num_ids_; ++i) { + node_builder.build_id(ids_[i]); + } +} + +void FromIDsBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); + for (int i = 0; i < num_ids_; ++i) { + relation_builder.build_id(ids_[i]); + } +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_from_ids.h b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h new file mode 100644 index 00000000000..4a507f2c728 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_from_ids.h @@ -0,0 +1,62 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +/* Optimized builders for dependency graph built from a given set of IDs. + * + * General notes: + * + * - We pull in all bases if their objects are in the set of IDs. This allows to have proper + * visibility and other flags assigned to the objects. + * All other bases (the ones which points to object which is outside of the set of IDs) are + * completely ignored. + * + * - Proxy groups pointing to objects which are outside of the IDs set are also ignored. + * This way we avoid high-poly character body pulled into the dependency graph when it's coming + * from a library into an animation file and the dependency graph constructed for a proxy rig. */ + +class FromIDsBuilderPipeline : public AbstractBuilderPipeline { + public: + FromIDsBuilderPipeline( + ::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer, ID **ids, int num_ids); + + protected: + virtual unique_ptr<DepsgraphNodeBuilder> construct_node_builder() override; + virtual unique_ptr<DepsgraphRelationBuilder> construct_relation_builder() override; + + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; + + private: + ID **ids_; + const int num_ids_; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_render.cc b/source/blender/depsgraph/intern/builder/pipeline_render.cc new file mode 100644 index 00000000000..50a37d0d3e4 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_render.cc @@ -0,0 +1,49 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_render.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +RenderBuilderPipeline::RenderBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer) +{ + deg_graph_->is_render_pipeline_depsgraph = true; +} + +void RenderBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_scene_render(scene_, view_layer_); +} + +void RenderBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_scene_render(scene_, view_layer_); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_render.h b/source/blender/depsgraph/intern/builder/pipeline_render.h new file mode 100644 index 00000000000..df7f9e0de68 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_render.h @@ -0,0 +1,41 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +class RenderBuilderPipeline : public AbstractBuilderPipeline { + public: + RenderBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc b/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc new file mode 100644 index 00000000000..3223f17f349 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_view_layer.cc @@ -0,0 +1,48 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +#include "pipeline_view_layer.h" + +#include "intern/builder/deg_builder_nodes.h" +#include "intern/builder/deg_builder_relations.h" +#include "intern/depsgraph.h" + +namespace blender { +namespace deg { + +ViewLayerBuilderPipeline::ViewLayerBuilderPipeline(::Depsgraph *graph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) + : AbstractBuilderPipeline(graph, bmain, scene, view_layer) +{ +} + +void ViewLayerBuilderPipeline::build_nodes(DepsgraphNodeBuilder &node_builder) +{ + node_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); +} + +void ViewLayerBuilderPipeline::build_relations(DepsgraphRelationBuilder &relation_builder) +{ + relation_builder.build_view_layer(scene_, view_layer_, DEG_ID_LINKED_DIRECTLY); +} + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/builder/pipeline_view_layer.h b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h new file mode 100644 index 00000000000..fbd7b98acad --- /dev/null +++ b/source/blender/depsgraph/intern/builder/pipeline_view_layer.h @@ -0,0 +1,41 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup depsgraph + */ + +#pragma once + +#include "pipeline.h" + +namespace blender { +namespace deg { + +class ViewLayerBuilderPipeline : public AbstractBuilderPipeline { + public: + ViewLayerBuilderPipeline(::Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer); + + protected: + virtual void build_nodes(DepsgraphNodeBuilder &node_builder) override; + virtual void build_relations(DepsgraphRelationBuilder &relation_builder) override; +}; + +} // namespace deg +} // namespace blender diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index c11d051e663..fb933cb38f3 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -43,12 +43,11 @@ #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_debug.h" -#include "builder/deg_builder.h" -#include "builder/deg_builder_cache.h" -#include "builder/deg_builder_cycle.h" -#include "builder/deg_builder_nodes.h" #include "builder/deg_builder_relations.h" -#include "builder/deg_builder_transitive.h" +#include "builder/pipeline_compositor.h" +#include "builder/pipeline_from_ids.h" +#include "builder/pipeline_render.h" +#include "builder/pipeline_view_layer.h" #include "intern/debug/deg_debug.h" @@ -209,65 +208,14 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle) /* ******************** */ /* Graph Building API's */ -static void graph_build_finalize_common(deg::Depsgraph *deg_graph, Main *bmain) -{ - /* Detect and solve cycles. */ - deg::deg_graph_detect_cycles(deg_graph); - /* Simplify the graph by removing redundant relations (to optimize - * traversal later). */ - /* TODO: it would be useful to have an option to disable this in cases where - * it is causing trouble. */ - if (G.debug_value == 799) { - deg::deg_graph_transitive_reduction(deg_graph); - } - /* Store pointers to commonly used valuated datablocks. */ - deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(°_graph->scene->id); - /* Flush visibility layer and re-schedule nodes for update. */ - deg::deg_graph_build_finalize(bmain, deg_graph); - DEG_graph_on_visible_update(bmain, reinterpret_cast<::Depsgraph *>(deg_graph), false); -#if 0 - if (!DEG_debug_consistency_check(deg_graph)) { - printf("Consistency validation failed, ABORTING!\n"); - abort(); - } -#endif - /* Relations are up to date. */ - deg_graph->need_update = false; -} - /* Build depsgraph for the given scene layer, and dump results in given graph container. */ void DEG_graph_build_from_view_layer(Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1); - BLI_assert(deg_graph->scene == scene); - BLI_assert(deg_graph->view_layer == view_layer); - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); - node_builder.begin_build(); - node_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation order. */ - deg::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::ViewLayerBuilderPipeline builder(graph, bmain, scene, view_layer); + builder.build(); } void DEG_graph_build_for_render_pipeline(Depsgraph *graph, @@ -275,170 +223,17 @@ void DEG_graph_build_for_render_pipeline(Depsgraph *graph, Scene *scene, ViewLayer *view_layer) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(deg_graph->scene == scene); - deg_graph->is_render_pipeline_depsgraph = true; - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); - node_builder.begin_build(); - node_builder.build_scene_render(scene, view_layer); - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation - * order. */ - deg::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_scene_render(scene, view_layer); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::RenderBuilderPipeline builder(graph, bmain, scene, view_layer); + builder.build(); } void DEG_graph_build_for_compositor_preview( Depsgraph *graph, Main *bmain, Scene *scene, struct ViewLayer *view_layer, bNodeTree *nodetree) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(deg_graph->scene == scene); - deg_graph->is_render_pipeline_depsgraph = true; - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphNodeBuilder node_builder(bmain, deg_graph, &builder_cache); - node_builder.begin_build(); - node_builder.build_scene_render(scene, view_layer); - node_builder.build_nodetree(nodetree); - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation - * order. */ - deg::DepsgraphRelationBuilder relation_builder(bmain, deg_graph, &builder_cache); - relation_builder.begin_build(); - relation_builder.build_scene_render(scene, view_layer); - relation_builder.build_nodetree(nodetree); - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::CompositorBuilderPipeline builder(graph, bmain, scene, view_layer, nodetree); + builder.build(); } -/* Optimized builders for dependency graph built from a given set of IDs. - * - * General notes: - * - * - We pull in all bases if their objects are in the set of IDs. This allows to have proper - * visibility and other flags assigned to the objects. - * All other bases (the ones which points to object which is outside of the set of IDs) are - * completely ignored. - * - * - Proxy groups pointing to objects which are outside of the IDs set are also ignored. - * This way we avoid high-poly character body pulled into the dependency graph when it's coming - * from a library into an animation file and the dependency graph constructed for a proxy rig. */ - -namespace blender { -namespace deg { -namespace { - -class DepsgraphFromIDsFilter { - public: - DepsgraphFromIDsFilter(ID **ids, const int num_ids) - { - for (int i = 0; i < num_ids; ++i) { - ids_.add(ids[i]); - } - } - - bool contains(ID *id) - { - return ids_.contains(id); - } - - protected: - Set<ID *> ids_; -}; - -class DepsgraphFromIDsNodeBuilder : public DepsgraphNodeBuilder { - public: - DepsgraphFromIDsNodeBuilder( - Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) - : DepsgraphNodeBuilder(bmain, graph, cache), filter_(ids, num_ids) - { - } - - virtual bool need_pull_base_into_graph(Base *base) override - { - if (!filter_.contains(&base->object->id)) { - return false; - } - return DepsgraphNodeBuilder::need_pull_base_into_graph(base); - } - - virtual void build_object_proxy_group(Object *object, bool is_visible) override - { - if (object->proxy_group == nullptr) { - return; - } - if (!filter_.contains(&object->proxy_group->id)) { - return; - } - DepsgraphNodeBuilder::build_object_proxy_group(object, is_visible); - } - - protected: - DepsgraphFromIDsFilter filter_; -}; - -class DepsgraphFromIDsRelationBuilder : public DepsgraphRelationBuilder { - public: - DepsgraphFromIDsRelationBuilder( - Main *bmain, Depsgraph *graph, DepsgraphBuilderCache *cache, ID **ids, const int num_ids) - : DepsgraphRelationBuilder(bmain, graph, cache), filter_(ids, num_ids) - { - } - - virtual bool need_pull_base_into_graph(Base *base) override - { - if (!filter_.contains(&base->object->id)) { - return false; - } - return DepsgraphRelationBuilder::need_pull_base_into_graph(base); - } - - virtual void build_object_proxy_group(Object *object) override - { - if (object->proxy_group == nullptr) { - return; - } - if (!filter_.contains(&object->proxy_group->id)) { - return; - } - DepsgraphRelationBuilder::build_object_proxy_group(object); - } - - protected: - DepsgraphFromIDsFilter filter_; -}; - -} // namespace -} // namespace deg -} // namespace blender - void DEG_graph_build_from_ids(Depsgraph *graph, Main *bmain, Scene *scene, @@ -446,40 +241,8 @@ void DEG_graph_build_from_ids(Depsgraph *graph, ID **ids, const int num_ids) { - double start_time = 0.0; - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - start_time = PIL_check_seconds_timer(); - } - deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph); - /* Perform sanity checks. */ - BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1); - BLI_assert(deg_graph->scene == scene); - BLI_assert(deg_graph->view_layer == view_layer); - deg::DepsgraphBuilderCache builder_cache; - /* Generate all the nodes in the graph first */ - deg::DepsgraphFromIDsNodeBuilder node_builder(bmain, deg_graph, &builder_cache, ids, num_ids); - node_builder.begin_build(); - node_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - for (int i = 0; i < num_ids; ++i) { - node_builder.build_id(ids[i]); - } - node_builder.end_build(); - /* Hook up relationships between operations - to determine evaluation order. */ - deg::DepsgraphFromIDsRelationBuilder relation_builder( - bmain, deg_graph, &builder_cache, ids, num_ids); - relation_builder.begin_build(); - relation_builder.build_view_layer(scene, view_layer, deg::DEG_ID_LINKED_DIRECTLY); - for (int i = 0; i < num_ids; ++i) { - relation_builder.build_id(ids[i]); - } - relation_builder.build_copy_on_write_relations(); - relation_builder.build_driver_relations(); - /* Finalize building. */ - graph_build_finalize_common(deg_graph, bmain); - /* Finish statistics. */ - if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) { - printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time); - } + deg::FromIDsBuilderPipeline builder(graph, bmain, scene, view_layer, ids, num_ids); + builder.build(); } /* Tag graph relations for update. */ diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 1863a333930..1d8fba21857 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -48,11 +48,8 @@ #include "BKE_idtype.h" #include "BKE_node.h" #include "BKE_scene.h" -#include "BKE_workspace.h" - -#define new new_ #include "BKE_screen.h" -#undef new +#include "BKE_workspace.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index 9956391a2d7..89df41944e5 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -288,6 +288,14 @@ bool id_copy_inplace_no_main(const ID *id, ID *newid) { const ID *id_for_copy = id; + if (G.debug & G_DEBUG_DEPSGRAPH_UUID) { + const ID_Type id_type = GS(id_for_copy->name); + if (id_type == ID_OB) { + const Object *object = reinterpret_cast<const Object *>(id_for_copy); + BKE_pose_check_uuids_unique_and_report(object->pose); + } + } + #ifdef NESTED_ID_NASTY_WORKAROUND NestedIDHackTempStorage id_hack_storage; id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index e0957a10cb1..88334e41192 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -85,11 +85,11 @@ void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object) { if (object->pose != nullptr) { LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is nullptr in Edit mode. */ - if (pchan->orig_pchan != nullptr) { - pose_channel_runtime_data.add(pchan->orig_pchan, pchan->runtime); - BKE_pose_channel_runtime_reset(&pchan->runtime); - } + const SessionUUID &session_uuid = pchan->runtime.session_uuid; + BLI_assert(BLI_session_uuid_is_generated(&session_uuid)); + + pose_channel_runtime_data.add(session_uuid, pchan->runtime); + BKE_pose_channel_runtime_reset(&pchan->runtime); } } } @@ -171,13 +171,10 @@ void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object) { if (object->pose != nullptr) { LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - /* This is nullptr in Edit mode. */ - if (pchan->orig_pchan != nullptr) { - optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try( - pchan->orig_pchan); - if (runtime.has_value()) { - pchan->runtime = *runtime; - } + const SessionUUID &session_uuid = pchan->runtime.session_uuid; + optional<bPoseChannel_Runtime> runtime = pose_channel_runtime_data.pop_try(session_uuid); + if (runtime.has_value()) { + pchan->runtime = *runtime; } } } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h index 04d7fb1bc22..a10f15634ce 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.h @@ -24,6 +24,9 @@ #pragma once #include "DNA_object_types.h" +#include "DNA_session_uuid_types.h" + +#include "BLI_session_uuid.h" #include "intern/eval/deg_eval_runtime_backup_modifier.h" #include "intern/eval/deg_eval_runtime_backup_pose.h" @@ -54,7 +57,7 @@ class ObjectRuntimeBackup { short base_flag; unsigned short base_local_view_bits; ModifierRuntimeDataBackup modifier_runtime_data; - Map<bPoseChannel *, bPoseChannel_Runtime> pose_channel_runtime_data; + Map<SessionUUID, bPoseChannel_Runtime> pose_channel_runtime_data; }; } // namespace deg diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl index a12069dc57b..b0da4274a13 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl @@ -1,6 +1,6 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) -#pragma BLENDER_REQUIRE(cubemap_lib.glsl) +#pragma BLENDER_REQUIRE(lightprobe_lib.glsl) flat in int pid; in vec2 quadCoord; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl index f9bcc718a1e..dc5ec1e40f5 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_grid_display_frag.glsl @@ -1,3 +1,5 @@ +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(irradiance_lib.glsl) flat in int cellOffset; in vec2 quadCoord; diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl index 36fe9df9e5a..c19bf1e7b50 100644 --- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl +++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl @@ -487,7 +487,7 @@ void stroke_vertex() vec2 screen_ofs = miter * y; - /* Reminder: we packed the cap flag into the sign of stength and thickness sign. */ + /* Reminder: we packed the cap flag into the sign of strength and thickness sign. */ if ((is_stroke_start && strength1 > 0.0) || (is_stroke_end && thickness1 > 0.0) || (miter_break && !is_stroke_start && !is_stroke_end)) { screen_ofs += line * x; diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index b9d18972b9e..b6ce15b7ab9 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -302,7 +302,7 @@ static void gpencil_buffer_add_point(gpStrokeVert *verts, int v, bool is_endpoint) { - /* Note: we use the sign of stength and thickness to pass cap flag. */ + /* Note: we use the sign of strength and thickness to pass cap flag. */ const bool round_cap0 = (gps->caps[0] == GP_STROKE_CAP_ROUND); const bool round_cap1 = (gps->caps[1] == GP_STROKE_CAP_ROUND); gpStrokeVert *vert = &verts[v]; diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 712a93e8880..61c9bf65507 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1960,7 +1960,7 @@ void DRW_render_instance_buffer_finish(void) void DRW_draw_select_loop(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, - bool UNUSED(use_obedit_skip), + bool use_obedit_skip, bool draw_surface, bool UNUSED(use_nearest), const rcti *rect, @@ -1973,7 +1973,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); Object *obact = OBACT(view_layer); - Object *obedit = OBEDIT_FROM_OBACT(obact); + Object *obedit = use_obedit_skip ? NULL : OBEDIT_FROM_OBACT(obact); #ifndef USE_GPU_SELECT UNUSED_VARS(scene, view_layer, v3d, region, rect); #else @@ -2716,7 +2716,7 @@ void DRW_engines_free(void) void DRW_render_context_enable(Render *render) { if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); + WM_init_opengl(); } void *re_gl_context = RE_gl_context_get(render); @@ -2835,7 +2835,7 @@ void DRW_opengl_context_disable_ex(bool restore) void DRW_opengl_context_enable(void) { if (G.background && DST.gl_context == NULL) { - WM_init_opengl(G_MAIN); + WM_init_opengl(); } DRW_opengl_context_enable_ex(true); } diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index 0dd35fb9fdc..a737916e9a2 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -384,6 +384,7 @@ int ED_armature_join_objects_exec(bContext *C, wmOperator *op) BLI_remlink(curarm->edbo, curbone); BLI_addtail(arm->edbo, curbone); + /* Pose channel is moved from one storage to another, its UUID is still unique. */ BLI_remlink(&opose->chanbase, pchan); BLI_addtail(&pose->chanbase, pchan); BKE_pose_channels_hash_free(opose); diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 52c12392082..b8a8d0ba284 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -836,7 +836,7 @@ static short gpencil_stroke_addpoint(tGPsdata *p, } /* color strength */ - if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) { pt->strength *= BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, pressure); CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 35a6fabdce4..55430800106 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -745,7 +745,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { BKE_curvemapping_init(brush_settings->curve_jitter); } - if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) { BKE_curvemapping_init(brush_settings->curve_strength); } @@ -911,7 +911,7 @@ static void gpencil_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* color strength */ - if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + if (brush_settings->flag & GP_BRUSH_USE_STRENGTH_PRESSURE) { float curvef = BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, curve_pressure); strength *= curvef; strength *= brush_settings->draw_strength; diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 62e53513927..a339006bd08 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2622,18 +2622,19 @@ static void widget_state_numslider(uiWidgetType *wt, int state, int drawflag) /* labels use theme colors for text */ static void widget_state_option_menu(uiWidgetType *wt, int state, int drawflag) { - bTheme *btheme = UI_GetTheme(); /* XXX */ + const bTheme *btheme = UI_GetTheme(); + + const uiWidgetColors *old_wcol = wt->wcol_theme; + uiWidgetColors wcol_menu_option = *wt->wcol_theme; + + /* Override the checkbox theme colors to use the menu-back text colors. */ + copy_v3_v3_uchar(wcol_menu_option.text, btheme->tui.wcol_menu_back.text); + copy_v3_v3_uchar(wcol_menu_option.text_sel, btheme->tui.wcol_menu_back.text_sel); + wt->wcol_theme = &wcol_menu_option; - /* call this for option button */ widget_state(wt, state, drawflag); - /* if not selected we get theme from menu back */ - if (state & UI_SELECT) { - copy_v3_v3_uchar(wt->wcol.text, btheme->tui.wcol_menu_back.text_sel); - } - else { - copy_v3_v3_uchar(wt->wcol.text, btheme->tui.wcol_menu_back.text); - } + wt->wcol_theme = old_wcol; } static void widget_state_nothing(uiWidgetType *wt, int UNUSED(state), int UNUSED(drawflag)) diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index 61b40dd3e60..dd4b8146154 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -1158,12 +1158,12 @@ void MESH_OT_bevel(wmOperatorType *ot) PROFILE_HARD_MIN, 1.0f); - prop = RNA_def_enum(ot->srna, - "affect", - prop_affect_items, - BEVEL_AFFECT_EDGES, - "Affect", - "Affect Edges or Vertices"); + RNA_def_enum(ot->srna, + "affect", + prop_affect_items, + BEVEL_AFFECT_EDGES, + "Affect", + "Affect Edges or Vertices"); RNA_def_boolean(ot->srna, "clamp_overlap", diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 8a736c380bf..517e791e8fa 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1347,7 +1347,7 @@ static bool modifier_apply_poll_ex(bContext *C, bool allow_shared) Object *ob = (ptr.owner_id != NULL) ? (Object *)ptr.owner_id : ED_object_active_context(C); ModifierData *md = ptr.data; /* May be NULL. */ - if (ID_IS_OVERRIDE_LIBRARY(ob) || ID_IS_OVERRIDE_LIBRARY(ob->data)) { + if (ID_IS_OVERRIDE_LIBRARY(ob) || ((ob->data != NULL) && ID_IS_OVERRIDE_LIBRARY(ob->data))) { CTX_wm_operator_poll_msg_set(C, "Modifiers cannot be applied on override data"); return false; } @@ -2813,7 +2813,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) /* make a copy of ocean to use for baking - threadsafety */ ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(ocean, omd); + BKE_ocean_init_from_modifier(ocean, omd, omd->resolution); #if 0 BKE_ocean_bake(ocean, och); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 7c822bd01e5..decb8aea4e4 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2130,7 +2130,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi area->spacetype = type; area->type = st; - /* If st->new may be called, don't use context until then. The + /* If st->create may be called, don't use context until then. The * area->type->context() callback has changed but data may be invalid * (e.g. with properties editor) until space-data is properly created */ @@ -2170,7 +2170,7 @@ void ED_area_newspace(bContext *C, ScrArea *area, int type, const bool skip_regi if (st) { /* Don't get scene from context here which may depend on space-data. */ Scene *scene = WM_window_get_active_scene(win); - sl = st->new (area, scene); + sl = st->create(area, scene); BLI_addhead(&area->spacedata, sl); /* swap regions */ diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index ee998e0605a..81afb06ac27 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -897,7 +897,7 @@ static void screen_global_area_refresh(wmWindow *win, else { area = screen_area_create_with_geometry(&win->global_areas, rect, space_type); SpaceType *stype = BKE_spacetype_from_id(space_type); - SpaceLink *slink = stype->new (area, WM_window_get_active_scene(win)); + SpaceLink *slink = stype->create(area, WM_window_get_active_scene(win)); area->regionbase = slink->regionbase; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index a3396a80444..cde4039d20f 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -8947,7 +8947,7 @@ static void SCULPT_OT_mask_by_color(wmOperatorType *ot) "preserve_previous_mask", false, "Preserve Previous Mask", - "Preserve the previous mask and add or substract the new one generated by the colors"); + "Preserve the previous mask and add or subtract the new one generated by the colors"); RNA_def_float(ot->srna, "threshold", diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_color.c b/source/blender/editors/sculpt_paint/sculpt_filter_color.c index 878a08ceeb7..912dfd808b0 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_color.c @@ -322,6 +322,6 @@ void SCULPT_OT_color_filter(struct wmOperatorType *ot) ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f); PropertyRNA *prop = RNA_def_float_color( - ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "fill color", 0.0f, 1.0f); + ot->srna, "fill_color", 3, NULL, 0.0f, FLT_MAX, "Fill Color", "", 0.0f, 1.0f); RNA_def_property_subtype(prop, PROP_COLOR_GAMMA); } diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 079cee290ae..db55eff8284 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -60,7 +60,7 @@ /* ******************** default callbacks for action space ***************** */ -static SpaceLink *action_new(const ScrArea *area, const Scene *scene) +static SpaceLink *action_create(const ScrArea *area, const Scene *scene) { SpaceAction *saction; ARegion *region; @@ -863,7 +863,7 @@ void ED_spacetype_action(void) st->spaceid = SPACE_ACTION; strncpy(st->name, "Action", BKE_ST_MAXNAME); - st->new = action_new; + st->create = action_create; st->free = action_free; st->init = action_init; st->duplicate = action_duplicate; diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 3ae203b563b..1656a76e2d4 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -280,7 +280,7 @@ void ED_region_draw_cb_draw(const bContext *C, ARegion *region, int type) void ED_spacetype_xxx(void); /* allocate and init some vars */ -static SpaceLink *xxx_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *xxx_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { return NULL; } @@ -324,7 +324,7 @@ void ED_spacetype_xxx(void) st.spaceid = SPACE_VIEW3D; - st.new = xxx_new; + st.create = xxx_create; st.free = xxx_free; st.init = xxx_init; st.duplicate = xxx_duplicate; diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c index 67efd8f4b8e..dc34e56dc92 100644 --- a/source/blender/editors/space_buttons/space_buttons.c +++ b/source/blender/editors/space_buttons/space_buttons.c @@ -54,7 +54,7 @@ /* ******************** default callbacks for buttons space ***************** */ -static SpaceLink *buttons_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *buttons_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceProperties *sbuts; @@ -584,6 +584,10 @@ static void buttons_area_listener(wmWindow *UNUSED(win), if (wmn->data == ND_SPACE_PROPERTIES) { ED_area_tag_redraw(area); } + else if (wmn->data == ND_SPACE_CHANGED) { + ED_area_tag_redraw(area); + sbuts->preview = 1; + } break; case NC_ID: if (wmn->action == NA_RENAME) { @@ -624,6 +628,12 @@ static void buttons_area_listener(wmWindow *UNUSED(win), sbuts->preview = 1; } break; + case NC_SCREEN: + if (wmn->data == ND_LAYOUTSET) { + ED_area_tag_redraw(area); + sbuts->preview = 1; + } + break; #ifdef WITH_FREESTYLE case NC_LINESTYLE: ED_area_tag_redraw(area); @@ -699,7 +709,7 @@ void ED_spacetype_buttons(void) st->spaceid = SPACE_PROPERTIES; strncpy(st->name, "Buttons", BKE_ST_MAXNAME); - st->new = buttons_new; + st->create = buttons_create; st->free = buttons_free; st->init = buttons_init; st->duplicate = buttons_duplicate; diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 3b1cc6fcab0..71f75d96cb1 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -259,6 +259,8 @@ typedef struct { MovieTrackingTrack *track; MovieTrackingMarker *marker; + /** current frame number */ + int framenr; /** position of marker in pixel coords */ float marker_pos[2]; /** position and dimensions of marker pattern in pixel coords */ @@ -286,7 +288,8 @@ static void marker_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) return; } - MovieTrackingMarker *marker = cb->marker; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(cb->clip, cb->framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_ensure(cb->track, clip_framenr); marker->flag = cb->marker_flag; WM_event_add_notifier(C, NC_MOVIECLIP | NA_EDITED, NULL); @@ -300,7 +303,9 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) BKE_movieclip_get_size(cb->clip, cb->user, &width, &height); - MovieTrackingMarker *marker = cb->marker; + int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(cb->clip, cb->framenr); + MovieTrackingMarker *marker = BKE_tracking_marker_ensure(cb->track, clip_framenr); + if (event == B_MARKER_POS) { marker->pos[0] = cb->marker_pos[0] / width; marker->pos[1] = cb->marker_pos[1] / height; @@ -456,6 +461,7 @@ void uiTemplateMarker(uiLayout *layout, cb->track = track; cb->marker = marker; cb->marker_flag = marker->flag; + cb->framenr = user->framenr; if (compact) { block = uiLayoutGetBlock(layout); diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 0aea7e4b73c..d27b80efd40 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -237,7 +237,7 @@ static void clip_area_sync_frame_from_scene(ScrArea *area, Scene *scene) /* ******************** default callbacks for clip space ***************** */ -static SpaceLink *clip_new(const ScrArea *area, const Scene *scene) +static SpaceLink *clip_create(const ScrArea *area, const Scene *scene) { ARegion *region; SpaceClip *sc; @@ -1351,7 +1351,7 @@ void ED_spacetype_clip(void) st->spaceid = SPACE_CLIP; strncpy(st->name, "Clip", BKE_ST_MAXNAME); - st->new = clip_new; + st->create = clip_create; st->free = clip_free; st->init = clip_init; st->duplicate = clip_duplicate; diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index 3c62aeb1759..3a0125356f7 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -46,7 +46,7 @@ /* ******************** default callbacks for console space ***************** */ -static SpaceLink *console_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *console_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceConsole *sconsole; @@ -312,7 +312,7 @@ void ED_spacetype_console(void) st->spaceid = SPACE_CONSOLE; strncpy(st->name, "Console", BKE_ST_MAXNAME); - st->new = console_new; + st->create = console_create; st->free = console_free; st->init = console_init; st->duplicate = console_duplicate; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 355597cddf1..f520f91b89b 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -91,7 +91,7 @@ static ARegion *file_tool_props_region_ensure(ScrArea *area, ARegion *region_pre /* ******************** default callbacks for file space ***************** */ -static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *file_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceFile *sfile; @@ -693,7 +693,7 @@ void ED_spacetype_file(void) st->spaceid = SPACE_FILE; strncpy(st->name, "File", BKE_ST_MAXNAME); - st->new = file_new; + st->create = file_create; st->free = file_free; st->init = file_init; st->exit = file_exit; diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index b1d995a7a0b..a4f76384cc6 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -64,7 +64,7 @@ /* ******************** default callbacks for ipo space ***************** */ -static SpaceLink *graph_new(const ScrArea *UNUSED(area), const Scene *scene) +static SpaceLink *graph_create(const ScrArea *UNUSED(area), const Scene *scene) { ARegion *region; SpaceGraph *sipo; @@ -838,7 +838,7 @@ void ED_spacetype_ipo(void) st->spaceid = SPACE_GRAPH; strncpy(st->name, "Graph", BKE_ST_MAXNAME); - st->new = graph_new; + st->create = graph_create; st->free = graph_free; st->init = graph_init; st->duplicate = graph_duplicate; diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index cb0fdcf23ca..4eb4e6649d9 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -400,7 +400,10 @@ bool ED_image_slot_cycle(struct Image *image, int direction) } } - if (i == num_slots) { + if (num_slots == 1) { + image->render_slot = 0; + } + else if (i == num_slots) { image->render_slot = ((cur == 1) ? 0 : 1); } diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index d7d85112497..11af71586a5 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -117,7 +117,7 @@ static void image_user_refresh_scene(const bContext *C, SpaceImage *sima) /* ******************** default callbacks for image space ***************** */ -static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *image_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceImage *simage; @@ -1093,7 +1093,7 @@ void ED_spacetype_image(void) st->spaceid = SPACE_IMAGE; strncpy(st->name, "Image", BKE_ST_MAXNAME); - st->new = image_new; + st->create = image_create; st->free = image_free; st->init = image_init; st->duplicate = image_duplicate; diff --git a/source/blender/editors/space_info/space_info.c b/source/blender/editors/space_info/space_info.c index 836830916ed..b9153ec0cbd 100644 --- a/source/blender/editors/space_info/space_info.c +++ b/source/blender/editors/space_info/space_info.c @@ -53,7 +53,7 @@ /* ******************** default callbacks for info space ***************** */ -static SpaceLink *info_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *info_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceInfo *sinfo; @@ -287,7 +287,7 @@ void ED_spacetype_info(void) st->spaceid = SPACE_INFO; strncpy(st->name, "Info", BKE_ST_MAXNAME); - st->new = info_new; + st->create = info_create; st->free = info_free; st->init = info_init; st->duplicate = info_duplicate; diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c index b09536e0621..7bbfe451eed 100644 --- a/source/blender/editors/space_nla/space_nla.c +++ b/source/blender/editors/space_nla/space_nla.c @@ -57,7 +57,7 @@ /* ******************** default callbacks for nla space ***************** */ -static SpaceLink *nla_new(const ScrArea *area, const Scene *scene) +static SpaceLink *nla_create(const ScrArea *area, const Scene *scene) { ARegion *region; SpaceNla *snla; @@ -608,7 +608,7 @@ void ED_spacetype_nla(void) st->spaceid = SPACE_NLA; strncpy(st->name, "NLA", BKE_ST_MAXNAME); - st->new = nla_new; + st->create = nla_create; st->free = nla_free; st->init = nla_init; st->duplicate = nla_duplicate; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 4203eac16c4..207f67aed1b 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3576,6 +3576,8 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout break; } } + + uiItemR(layout, ptr, "hide_value", DEFAULT_FLAGS, NULL, 0); } void ED_init_standard_node_socket_type(bNodeSocketType *stype) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index ef468c63d77..8dc67ad48f5 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -56,6 +56,7 @@ #include "UI_resources.h" #include "NOD_common.h" +#include "NOD_socket.h" #include "node_intern.h" /* own include */ static bool node_group_operator_active(bContext *C) @@ -685,7 +686,8 @@ static bool node_group_make_test_selected(bNodeTree *ntree, return true; } -static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, float *max) +static int node_get_selected_minmax( + bNodeTree *ntree, bNode *gnode, float *min, float *max, bool use_size) { bNode *node; float loc[2]; @@ -696,6 +698,11 @@ static int node_get_selected_minmax(bNodeTree *ntree, bNode *gnode, float *min, if (node_group_make_use_node(node, gnode)) { nodeToView(node, 0.0f, 0.0f, &loc[0], &loc[1]); minmax_v2v2_v2(min, max, loc); + if (use_size) { + loc[0] += node->width; + loc[1] -= node->height; + minmax_v2v2_v2(min, max, loc); + } totselect++; } } @@ -713,10 +720,10 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, Main *bmain = CTX_data_main(C); bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeLink *link, *linkn; - bNode *node, *nextn; - bNodeSocket *sock; + bNode *node, *nextn, *link_node; + bNodeSocket *sock, *link_sock; ListBase anim_basepaths = {NULL, NULL}; - float min[2], max[2], center[2]; + float min[2], max[2], real_min[2], real_max[2], center[2]; int totselect; bool expose_visible = false; bNode *input_node, *output_node; @@ -730,10 +737,12 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, nodeSetSelected(node, false); } - totselect = node_get_selected_minmax(ntree, gnode, min, max); + totselect = node_get_selected_minmax(ntree, gnode, min, max, false); add_v2_v2v2(center, min, max); mul_v2_fl(center, 0.5f); + node_get_selected_minmax(ntree, gnode, real_min, real_max, true); + /* auto-add interface for "solo" nodes */ if (totselect == 1) { expose_visible = true; @@ -792,12 +801,12 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, /* create input node */ input_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_INPUT); - input_node->locx = min[0] - center[0] - offsetx; + input_node->locx = real_min[0] - center[0] - offsetx; input_node->locy = -offsety; /* create output node */ output_node = nodeAddStaticNode(C, ngroup, NODE_GROUP_OUTPUT); - output_node->locx = max[0] - center[0] + offsetx; + output_node->locx = real_max[0] - center[0] + offsetx * 0.25f; output_node->locy = -offsety; /* relink external sockets */ @@ -813,12 +822,9 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, */ nodeRemLink(ntree, link); } - else if (fromselect && toselect) { - BLI_remlink(&ntree->links, link); - BLI_addtail(&ngroup->links, link); - } - else if (toselect) { - bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link->tonode, link->tosock); + else if (toselect && !fromselect) { + node_socket_skip_reroutes(&ntree->links, link->tonode, link->tosock, &link_node, &link_sock); + bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link_node, link_sock); bNodeSocket *input_sock; /* update the group node and interface node sockets, @@ -835,7 +841,7 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, link->tonode = gnode; link->tosock = node_group_find_input_socket(gnode, iosock->identifier); } - else if (fromselect) { + else if (fromselect && !toselect) { /* First check whether the source of this link is already connected to an output. * If yes, reuse that output instead of duplicating it. */ bool connected = false; @@ -851,8 +857,9 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, } if (!connected) { - bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket( - ngroup, link->fromnode, link->fromsock); + node_socket_skip_reroutes( + &ntree->links, link->fromnode, link->fromsock, &link_node, &link_sock); + bNodeSocket *iosock = ntreeAddSocketInterfaceFromSocket(ngroup, link_node, link_sock); bNodeSocket *output_sock; /* update the group node and interface node sockets, @@ -872,6 +879,19 @@ static void node_group_make_insert_selected(const bContext *C, bNodeTree *ntree, } } + /* move internal links */ + for (link = ntree->links.first; link; link = linkn) { + int fromselect = node_group_make_use_node(link->fromnode, gnode); + int toselect = node_group_make_use_node(link->tonode, gnode); + + linkn = link->next; + + if (fromselect && toselect) { + BLI_remlink(&ntree->links, link); + BLI_addtail(&ngroup->links, link); + } + } + /* move nodes in the group to the center */ for (node = ngroup->nodes.first; node; node = node->next) { if (node_group_make_use_node(node, gnode) && !node->parent) { @@ -953,7 +973,7 @@ static bNode *node_group_make_from_selected(const bContext *C, float min[2], max[2]; int totselect; - totselect = node_get_selected_minmax(ntree, NULL, min, max); + totselect = node_get_selected_minmax(ntree, NULL, min, max, false); /* don't make empty group */ if (totselect == 0) { return NULL; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index d4adad3fc25..6d570001347 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -244,7 +244,7 @@ void snode_group_offset(SpaceNode *snode, float *x, float *y) /* ******************** default callbacks for node space ***************** */ -static SpaceLink *node_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *node_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceNode *snode; @@ -954,7 +954,7 @@ void ED_spacetype_node(void) st->spaceid = SPACE_NODE; strncpy(st->name, "Node", BKE_ST_MAXNAME); - st->new = node_new; + st->create = node_create; st->free = node_free; st->init = node_init; st->duplicate = node_duplicate; diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index aa1663dff01..8a78211f145 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -294,7 +294,7 @@ static void outliner_header_region_listener(wmWindow *UNUSED(win), /* ******************** default callbacks for outliner space ***************** */ -static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *outliner_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceOutliner *soutliner; @@ -407,7 +407,7 @@ void ED_spacetype_outliner(void) st->spaceid = SPACE_OUTLINER; strncpy(st->name, "Outliner", BKE_ST_MAXNAME); - st->new = outliner_new; + st->create = outliner_create; st->free = outliner_free; st->init = outliner_init; st->duplicate = outliner_duplicate; diff --git a/source/blender/editors/space_script/space_script.c b/source/blender/editors/space_script/space_script.c index 343f35421a4..4d0c2b658c6 100644 --- a/source/blender/editors/space_script/space_script.c +++ b/source/blender/editors/space_script/space_script.c @@ -51,7 +51,7 @@ /* ******************** default callbacks for script space ***************** */ -static SpaceLink *script_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *script_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceScript *sscript; @@ -179,7 +179,7 @@ void ED_spacetype_script(void) st->spaceid = SPACE_SCRIPT; strncpy(st->name, "Script", BKE_ST_MAXNAME); - st->new = script_new; + st->create = script_create; st->free = script_free; st->init = script_init; st->duplicate = script_duplicate; diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 5c60ece747a..6a63578a363 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2151,7 +2151,7 @@ static int sequencer_reassign_inputs_exec(bContext *C, wmOperator *op) if (BKE_sequencer_render_loop_check(seq1, last_seq) || BKE_sequencer_render_loop_check(seq2, last_seq) || BKE_sequencer_render_loop_check(seq3, last_seq)) { - BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected."); + BKE_report(op->reports, RPT_ERROR, "Cannot reassign inputs: recursion detected"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index fa5e2ea02ff..b8bb3e4d43b 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -86,7 +86,7 @@ static ARegion *sequencer_find_region(ScrArea *area, short type) /* ******************** default callbacks for sequencer space ***************** */ -static SpaceLink *sequencer_new(const ScrArea *UNUSED(area), const Scene *scene) +static SpaceLink *sequencer_create(const ScrArea *UNUSED(area), const Scene *scene) { ARegion *region; SpaceSeq *sseq; @@ -852,7 +852,7 @@ void ED_spacetype_sequencer(void) st->spaceid = SPACE_SEQ; strncpy(st->name, "Sequencer", BKE_ST_MAXNAME); - st->new = sequencer_new; + st->create = sequencer_create; st->free = sequencer_free; st->init = sequencer_init; st->duplicate = sequencer_duplicate; diff --git a/source/blender/editors/space_statusbar/space_statusbar.c b/source/blender/editors/space_statusbar/space_statusbar.c index 34d7f8b0216..ae56b111360 100644 --- a/source/blender/editors/space_statusbar/space_statusbar.c +++ b/source/blender/editors/space_statusbar/space_statusbar.c @@ -42,7 +42,7 @@ /* ******************** default callbacks for statusbar space ******************** */ -static SpaceLink *statusbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *statusbar_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceStatusBar *sstatusbar; @@ -158,7 +158,7 @@ void ED_spacetype_statusbar(void) st->spaceid = SPACE_STATUSBAR; strncpy(st->name, "Status Bar", BKE_ST_MAXNAME); - st->new = statusbar_new; + st->create = statusbar_create; st->free = statusbar_free; st->init = statusbar_init; st->duplicate = statusbar_duplicate; diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index a2af99ee9f9..f6d00ec94bf 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -53,7 +53,7 @@ /* ******************** default callbacks for text space ***************** */ -static SpaceLink *text_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *text_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceText *stext; @@ -445,7 +445,7 @@ void ED_spacetype_text(void) st->spaceid = SPACE_TEXT; strncpy(st->name, "Text", BKE_ST_MAXNAME); - st->new = text_new; + st->create = text_create; st->free = text_free; st->init = text_init; st->duplicate = text_duplicate; diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c index d06c567988d..dc357cdd355 100644 --- a/source/blender/editors/space_topbar/space_topbar.c +++ b/source/blender/editors/space_topbar/space_topbar.c @@ -52,7 +52,7 @@ /* ******************** default callbacks for topbar space ***************** */ -static SpaceLink *topbar_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) +static SpaceLink *topbar_create(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { ARegion *region; SpaceTopBar *stopbar; @@ -250,7 +250,7 @@ void ED_spacetype_topbar(void) st->spaceid = SPACE_TOPBAR; strncpy(st->name, "Top Bar", BKE_ST_MAXNAME); - st->new = topbar_new; + st->create = topbar_create; st->free = topbar_free; st->init = topbar_init; st->duplicate = topbar_duplicate; diff --git a/source/blender/editors/space_userpref/space_userpref.c b/source/blender/editors/space_userpref/space_userpref.c index 92f9c187ce5..0242bb4fe24 100644 --- a/source/blender/editors/space_userpref/space_userpref.c +++ b/source/blender/editors/space_userpref/space_userpref.c @@ -45,7 +45,7 @@ /* ******************** default callbacks for userpref space ***************** */ -static SpaceLink *userpref_new(const ScrArea *area, const Scene *UNUSED(scene)) +static SpaceLink *userpref_create(const ScrArea *area, const Scene *UNUSED(scene)) { ARegion *region; SpaceUserPref *spref; @@ -235,7 +235,7 @@ void ED_spacetype_userpref(void) st->spaceid = SPACE_USERPREF; strncpy(st->name, "Userpref", BKE_ST_MAXNAME); - st->new = userpref_new; + st->create = userpref_create; st->free = userpref_free; st->init = userpref_init; st->duplicate = userpref_duplicate; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index c88303daa16..e5ba27cef07 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -260,7 +260,7 @@ void ED_view3d_shade_update(Main *bmain, View3D *v3d, ScrArea *area) /* ******************** default callbacks for view3d space ***************** */ -static SpaceLink *view3d_new(const ScrArea *UNUSED(area), const Scene *scene) +static SpaceLink *view3d_create(const ScrArea *UNUSED(area), const Scene *scene) { ARegion *region; View3D *v3d; @@ -616,11 +616,12 @@ static void view3d_lightcache_update(bContext *C) return; } - WM_operator_properties_create(&op_ptr, "SCENE_OT_light_cache_bake"); + wmOperatorType *ot = WM_operatortype_find("SCENE_OT_light_cache_bake", true); + WM_operator_properties_create_ptr(&op_ptr, ot); RNA_int_set(&op_ptr, "delay", 200); RNA_enum_set_identifier(C, &op_ptr, "subset", "DIRTY"); - WM_operator_name_call(C, "SCENE_OT_light_cache_bake", WM_OP_INVOKE_DEFAULT, &op_ptr); + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_ptr); WM_operator_properties_free(&op_ptr); } @@ -1610,7 +1611,7 @@ void ED_spacetype_view3d(void) st->spaceid = SPACE_VIEW3D; strncpy(st->name, "View3D", BKE_ST_MAXNAME); - st->new = view3d_new; + st->create = view3d_create; st->free = view3d_free; st->init = view3d_init; st->listener = space_view3d_listener; diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 2c8ea396a99..e23dd48b8b9 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -2112,7 +2112,7 @@ static bool ed_object_select_pick(bContext *C, if (hits > 0) { /* note: bundles are handling in the same way as bones */ - const bool has_bones = selectbuffer_has_bones(buffer, hits); + const bool has_bones = object ? false : selectbuffer_has_bones(buffer, hits); /* note; shift+alt goes to group-flush-selecting */ if (enumerate) { diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index ad98321c458..956c094c19b 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2109,7 +2109,7 @@ void ED_operatormacros_uvedit(void) ot = WM_operatortype_append_macro("UV_OT_rip_move", "UV Rip Move", - "unstitch UV's and move the result", + "Unstitch UV's and move the result", OPTYPE_UNDO | OPTYPE_REGISTER); WM_operatortype_macro_define(ot, "UV_OT_rip"); otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index a95c4ee63fc..e3511d9645e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -195,7 +195,7 @@ static void panel_draw(const bContext *C, Panel *panel) row = uiLayoutRow(layout, true); uiItemR(row, &ptr, "use_edit_position", UI_ITEM_R_TOGGLE, IFACE_("Position"), ICON_NONE); - uiItemR(row, &ptr, "use_edit_strength", UI_ITEM_R_TOGGLE, IFACE_("Stength"), ICON_NONE); + uiItemR(row, &ptr, "use_edit_strength", UI_ITEM_R_TOGGLE, IFACE_("Strength"), ICON_NONE); uiItemR(row, &ptr, "use_edit_thickness", UI_ITEM_R_TOGGLE, IFACE_("Thickness"), ICON_NONE); uiItemR(row, &ptr, "use_edit_uv", UI_ITEM_R_TOGGLE, IFACE_("UV"), ICON_NONE); diff --git a/source/blender/ikplugin/BIK_api.h b/source/blender/ikplugin/BIK_api.h index 99f68983c21..38a48864cc0 100644 --- a/source/blender/ikplugin/BIK_api.h +++ b/source/blender/ikplugin/BIK_api.h @@ -37,9 +37,9 @@ struct bPose; struct bPoseChannel; void BIK_init_tree(struct Depsgraph *depsgraph, - struct Scene *scene, - struct Object *ob, - float ctime); + struct Scene *scene, + struct Object *ob, + float ctime); void BIK_execute_tree(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c index 0d532b0e1fb..247122065de 100644 --- a/source/blender/imbuf/intern/stereoimbuf.c +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -670,16 +670,16 @@ static void imb_stereo3d_squeeze_rect( /*************************** preparing to call the write functions **************************/ static void imb_stereo3d_data_init(Stereo3DData *s3d_data, - const bool is_float, - const size_t x, - const size_t y, - const size_t channels, - int *rect_left, - int *rect_right, - int *rect_stereo, - float *rectf_left, - float *rectf_right, - float *rectf_stereo) + const bool is_float, + const size_t x, + const size_t y, + const size_t channels, + int *rect_left, + int *rect_right, + int *rect_stereo, + float *rectf_left, + float *rectf_right, + float *rectf_stereo) { s3d_data->is_float = is_float; s3d_data->x = x; @@ -760,16 +760,16 @@ ImBuf *IMB_stereo3d_ImBuf(ImageFormatData *im_format, ImBuf *ibuf_left, ImBuf *i ibuf_stereo->flags = ibuf_left->flags; imb_stereo3d_data_init(&s3d_data, - is_float, - ibuf_left->x, - ibuf_left->y, - 4, - (int *)ibuf_left->rect, - (int *)ibuf_right->rect, - (int *)ibuf_stereo->rect, - ibuf_left->rect_float, - ibuf_right->rect_float, - ibuf_stereo->rect_float); + is_float, + ibuf_left->x, + ibuf_left->y, + 4, + (int *)ibuf_left->rect, + (int *)ibuf_right->rect, + (int *)ibuf_stereo->rect, + ibuf_left->rect_float, + ibuf_right->rect_float, + ibuf_stereo->rect_float); imb_stereo3d_write_doit(&s3d_data, &im_format->stereo3d_format); imb_stereo3d_squeeze_ImBuf(ibuf_stereo, &im_format->stereo3d_format, ibuf_left->x, ibuf_left->y); @@ -1287,16 +1287,16 @@ void IMB_ImBufFromStereo3d(Stereo3dFormat *s3d, imb_stereo3d_unsqueeze_ImBuf(ibuf_stereo3d, s3d, width, height); imb_stereo3d_data_init(&s3d_data, - is_float, - ibuf_left->x, - ibuf_left->y, - 4, - (int *)ibuf_left->rect, - (int *)ibuf_right->rect, - (int *)ibuf_stereo3d->rect, - ibuf_left->rect_float, - ibuf_right->rect_float, - ibuf_stereo3d->rect_float); + is_float, + ibuf_left->x, + ibuf_left->y, + 4, + (int *)ibuf_left->rect, + (int *)ibuf_right->rect, + (int *)ibuf_stereo3d->rect, + ibuf_left->rect_float, + ibuf_right->rect_float, + ibuf_stereo3d->rect_float); imb_stereo3d_read_doit(&s3d_data, s3d); @@ -1311,16 +1311,16 @@ void IMB_ImBufFromStereo3d(Stereo3dFormat *s3d, } imb_stereo3d_data_init(&s3d_data, - is_float, - ibuf_left->x, - ibuf_left->y, - 1, - (int *)ibuf_left->zbuf, - (int *)ibuf_right->zbuf, - (int *)ibuf_stereo3d->zbuf, - ibuf_left->zbuf_float, - ibuf_right->zbuf_float, - ibuf_stereo3d->zbuf_float); + is_float, + ibuf_left->x, + ibuf_left->y, + 1, + (int *)ibuf_left->zbuf, + (int *)ibuf_right->zbuf, + (int *)ibuf_stereo3d->zbuf, + ibuf_left->zbuf_float, + ibuf_right->zbuf_float, + ibuf_stereo3d->zbuf_float); imb_stereo3d_read_doit(&s3d_data, s3d); } diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc index 98c551c635c..8c5f3d89870 100644 --- a/source/blender/io/alembic/exporter/abc_export_capi.cc +++ b/source/blender/io/alembic/exporter/abc_export_capi.cc @@ -48,6 +48,7 @@ static CLG_LogRef LOG = {"io.alembic"}; #include <algorithm> +#include <memory> struct ExportJobData { Main *bmain; @@ -103,17 +104,41 @@ static void export_startjob(void *customdata, const bool export_animation = (data->params.frame_start != data->params.frame_end); // Create the Alembic archive. - ABCArchive abc_archive(data->bmain, scene, data->params, std::string(data->filename)); + std::unique_ptr<ABCArchive> abc_archive; + try { + abc_archive = std::make_unique<ABCArchive>( + data->bmain, scene, data->params, std::string(data->filename)); + } + catch (const std::exception &ex) { + std::stringstream error_message_stream; + error_message_stream << "Error writing to " << data->filename; + const std::string &error_message = error_message_stream.str(); + + // The exception message can be very cryptic (just "iostream error" on Linux, for example), so + // better not to include it in the report. + CLOG_ERROR(&LOG, "%s: %s", error_message.c_str(), ex.what()); + WM_report(RPT_ERROR, error_message.c_str()); + data->export_ok = false; + return; + } + catch (...) { + // Unknown exception class, so we cannot include its message. + std::stringstream error_message_stream; + error_message_stream << "Unknown error writing to " << data->filename; + WM_report(RPT_ERROR, error_message_stream.str().c_str()); + data->export_ok = false; + return; + } - ABCHierarchyIterator iter(data->depsgraph, &abc_archive, data->params); + ABCHierarchyIterator iter(data->depsgraph, abc_archive.get(), data->params); if (export_animation) { CLOG_INFO(&LOG, 2, "Exporting animation"); // Writing the animated frames is not 100% of the work, but it's our best guess. - const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive.total_frame_count()); - ABCArchive::Frames::const_iterator frame_it = abc_archive.frames_begin(); - const ABCArchive::Frames::const_iterator frames_end = abc_archive.frames_end(); + const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive->total_frame_count()); + ABCArchive::Frames::const_iterator frame_it = abc_archive->frames_begin(); + const ABCArchive::Frames::const_iterator frames_end = abc_archive->frames_end(); for (; frame_it != frames_end; frame_it++) { double frame = *frame_it; @@ -128,7 +153,7 @@ static void export_startjob(void *customdata, BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain); CLOG_INFO(&LOG, 2, "Exporting frame %.2f", frame); - ExportSubset export_subset = abc_archive.export_subset_for_frame(frame); + ExportSubset export_subset = abc_archive->export_subset_for_frame(frame); iter.set_export_subset(export_subset); iter.iterate_and_write(); diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index 89eb9ed41a1..eba7f64db02 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -48,18 +48,13 @@ #include "BKE_lib_id.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "ED_undo.h" -/* SpaceType struct has a member called 'new' which obviously conflicts with C++ - * so temporarily redefining the new keyword to make it compile. */ -#define new extern_new -#include "BKE_screen.h" -#undef new - #include "BLI_compiler_compat.h" #include "BLI_fileops.h" #include "BLI_ghash.h" diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 98e858dbf41..74293e25c5c 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -30,6 +30,7 @@ #include "DNA_ID.h" #include "DNA_listBase.h" +#include "DNA_session_uuid_types.h" #include "DNA_userdef_types.h" /* ThemeWireColor */ #include "DNA_vec_types.h" #include "DNA_view2d_types.h" @@ -188,6 +189,8 @@ struct DualQuat; struct Mat4; typedef struct bPoseChannel_Runtime { + SessionUUID session_uuid; + /* Cached dual quaternion for deformation. */ struct DualQuat deform_dual_quat; diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 8b42f1a936d..152c5e25910 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -191,7 +191,7 @@ typedef enum eGPDbrush_Flag { /* brush use pressure */ GP_BRUSH_USE_PRESSURE = (1 << 0), /* brush use pressure for alpha factor */ - GP_BRUSH_USE_STENGTH_PRESSURE = (1 << 1), + GP_BRUSH_USE_STRENGTH_PRESSURE = (1 << 1), /* brush use pressure for alpha factor */ GP_BRUSH_USE_JITTER_PRESSURE = (1 << 2), /* fill hide transparent */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 9b1543d0f79..2669ca37132 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1277,7 +1277,11 @@ typedef struct OceanModifierData { struct Ocean *ocean; struct OceanCache *oceancache; + /** Render resolution. */ int resolution; + /** Viewport resolution for the non-render case. */ + int viewport_resolution; + int spatial_size; float wind_velocity; @@ -1294,8 +1298,6 @@ typedef struct OceanModifierData { float foam_coverage; float time; - char _pad1[4]; - /* Spectrum being used. */ int spectrum; diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 00ce5488636..f28222d0947 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1525,7 +1525,7 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); prop = RNA_def_property(srna, "use_strength_pressure", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_STENGTH_PRESSURE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_STRENGTH_PRESSURE); RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); RNA_def_property_ui_text( prop, "Use Pressure Strength", "Use tablet pressure for color strength"); @@ -2289,7 +2289,7 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Wet Persistence", - "Amount of wet paint that stays in the brush after applyig paint to the surface"); + "Amount of wet paint that stays in the brush after applying paint to the surface"); RNA_def_property_update(prop, 0, "rna_Brush_update"); prop = RNA_def_property(srna, "density", PROP_FLOAT, PROP_FACTOR); diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c index 00cd95c4492..c25cea1b4b3 100644 --- a/source/blender/makesrna/intern/rna_cachefile.c +++ b/source/blender/makesrna/intern/rna_cachefile.c @@ -180,7 +180,6 @@ static void rna_def_cachefile(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Velocity Attribute", "Name of the Alembic attribute used for generating motion blur data"); - RNA_def_struct_name_property(srna, prop); RNA_def_property_update(prop, 0, "rna_CacheFile_update"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 3af783f1bb1..feb26f8c775 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1024,14 +1024,18 @@ static void rna_Fluid_flowtype_set(struct PointerRNA *ptr, int value) FluidFlowSettings *settings = (FluidFlowSettings *)ptr->data; if (value != settings->type) { + short prev_value = settings->type; settings->type = value; - /* Force flow source to mesh */ + /* Force flow source to mesh for liquids. + * Also use different surface emission. Liquids should by default not emit around surface. */ if (value == FLUID_FLOW_TYPE_LIQUID) { rna_Fluid_flowsource_set(ptr, FLUID_FLOW_SOURCE_MESH); settings->surface_distance = 0.0f; } - else { + /* Use some surface emission when switching to a gas emitter. Gases should by default emit a + * bit around surface. */ + if (prev_value == FLUID_FLOW_TYPE_LIQUID) { settings->surface_distance = 1.5f; } } @@ -2394,7 +2398,7 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "openvdb_cache_compress_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "openvdb_compression"); RNA_def_property_enum_items(prop, prop_compression_items); - RNA_def_property_ui_text(prop, "Compression", "facession method to be used"); + RNA_def_property_ui_text(prop, "Compression", "Compression method to be used"); prop = RNA_def_property(srna, "openvdb_data_depth", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "openvdb_data_depth"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index ea33307060c..a891194550f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -113,7 +113,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { {0, "", 0, N_("Generate"), ""}, {eModifierType_Array, "ARRAY", - ICON_MOD_ARRAY, + ICON_MOD_ARRAY, "Array", "Create copies of the shape with offsets"}, {eModifierType_Bevel, @@ -5712,7 +5712,17 @@ static void rna_def_modifier_ocean(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 1, 1024); RNA_def_property_ui_range(prop, 1, 32, 1, -1); - RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface"); + RNA_def_property_ui_text( + prop, "Render Resolution", "Resolution of the generated surface for rendering and baking"); + RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); + + prop = RNA_def_property(srna, "viewport_resolution", PROP_INT, PROP_UNSIGNED); + RNA_def_property_int_sdna(prop, NULL, "viewport_resolution"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_range(prop, 1, 1024); + RNA_def_property_ui_range(prop, 1, 32, 1, -1); + RNA_def_property_ui_text( + prop, "Viewport Resolution", "Viewport resolution of the generated surface"); RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update"); prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0359b2ed959..95ea9eced1a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -8475,6 +8475,12 @@ static void rna_def_node_socket_interface(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Is Output", "True if the socket is an output, otherwise input"); + prop = RNA_def_property(srna, "hide_value", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", SOCK_HIDE_VALUE); + RNA_def_property_ui_text( + prop, "Hide Value", "Hide the socket input value even when the socket is not connected"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); + /* registration */ prop = RNA_def_property(srna, "bl_socket_idname", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "typeinfo->idname"); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index d360e37588c..0cfc6fd569c 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -872,7 +872,7 @@ static void rna_Sequence_input_set(PointerRNA *ptr, Sequence *input = ptr_value.data; if (BKE_sequencer_render_loop_check(input, seq)) { - BKE_report(reports, RPT_ERROR, "Cannot reassign inputs: recursion detected."); + BKE_report(reports, RPT_ERROR, "Cannot reassign inputs: recursion detected"); return; } diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c index e1970a57a91..7b039b91188 100644 --- a/source/blender/makesrna/intern/rna_shader_fx.c +++ b/source/blender/makesrna/intern/rna_shader_fx.c @@ -338,7 +338,7 @@ static void rna_def_shader_fx_pixel(BlenderRNA *brna) prop = RNA_def_property(srna, "use_antialiasing", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", FX_PIXEL_FILTER_NEAREST); - RNA_def_property_ui_text(prop, "Antialiasing", "Antialiase pixels"); + RNA_def_property_ui_text(prop, "Antialiasing", "Antialias pixels"); RNA_def_property_update(prop, NC_OBJECT | ND_SHADERFX, "rna_ShaderFx_update"); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 6ce6098d0c3..0567b22d23f 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4595,7 +4595,7 @@ static void rna_def_userdef_view(BlenderRNA *brna) "no matter opening direction"); static const EnumPropertyItem header_align_items[] = { - {0, "NONE", 0, "Default", "Keep existing header alignment"}, + {0, "NONE", 0, "Keep Existing", "Keep existing header alignment"}, {USER_HEADER_FROM_PREF, "TOP", 0, "Top", "Top aligned on load"}, {USER_HEADER_FROM_PREF | USER_HEADER_BOTTOM, "BOTTOM", diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 0d3468f4bb8..746f9e56c06 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -23,6 +23,7 @@ #include "BLI_utildefines.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLT_translation.h" @@ -140,7 +141,10 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte struct HookData_cb { float (*vertexCos)[3]; - MDeformVert *dvert; + /** + * When anything other than -1, use deform groups. + * This is not the same as checking `dvert` for NULL when we have edit-meshes. + */ int defgrp_index; struct CurveMapping *curfalloff; @@ -161,6 +165,20 @@ struct HookData_cb { bool invert_vgroup; }; +static BLI_bitmap *hook_index_array_to_bitmap(HookModifierData *hmd, const int numVerts) +{ + BLI_bitmap *indexar_used = BLI_BITMAP_NEW(numVerts, __func__); + int i; + int *index_pt; + for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { + const int j = *index_pt; + if (j < numVerts) { + BLI_BITMAP_ENABLE(indexar_used, i); + } + } + return indexar_used; +} + static float hook_falloff(const struct HookData_cb *hd, const float len_sq) { BLI_assert(hd->falloff_sq); @@ -227,7 +245,7 @@ static float hook_falloff(const struct HookData_cb *hd, const float len_sq) } } -static void hook_co_apply(struct HookData_cb *hd, const int j) +static void hook_co_apply(struct HookData_cb *hd, int j, const MDeformVert *dv) { float *co = hd->vertexCos[j]; float fac; @@ -251,9 +269,9 @@ static void hook_co_apply(struct HookData_cb *hd, const int j) } if (fac) { - if (hd->dvert) { - fac *= hd->invert_vgroup ? 1.0f - BKE_defvert_find_weight(&hd->dvert[j], hd->defgrp_index) : - BKE_defvert_find_weight(&hd->dvert[j], hd->defgrp_index); + if (dv != NULL) { + fac *= hd->invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, hd->defgrp_index) : + BKE_defvert_find_weight(dv, hd->defgrp_index); } if (fac) { @@ -268,6 +286,7 @@ static void deformVerts_do(HookModifierData *hmd, const ModifierEvalContext *UNUSED(ctx), Object *ob, Mesh *mesh, + BMEditMesh *em, float (*vertexCos)[3], int numVerts) { @@ -275,6 +294,7 @@ static void deformVerts_do(HookModifierData *hmd, bPoseChannel *pchan = BKE_pose_channel_find_name(ob_target->pose, hmd->subtarget); float dmat[4][4]; int i, *index_pt; + MDeformVert *dvert; struct HookData_cb hd; const bool invert_vgroup = (hmd->flag & MOD_HOOK_INVERT_VGROUP) != 0; @@ -289,7 +309,16 @@ static void deformVerts_do(HookModifierData *hmd, /* Generic data needed for applying per-vertex calculations (initialize all members) */ hd.vertexCos = vertexCos; - MOD_get_vgroup(ob, mesh, hmd->name, &hd.dvert, &hd.defgrp_index); + + MOD_get_vgroup(ob, mesh, hmd->name, &dvert, &hd.defgrp_index); + int cd_dvert_offset = -1; + + if ((em != NULL) && (hd.defgrp_index != -1)) { + cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + if (cd_dvert_offset == -1) { + hd.defgrp_index = -1; + } + } hd.curfalloff = hmd->curfalloff; @@ -338,32 +367,62 @@ static void deformVerts_do(HookModifierData *hmd, } else if (hmd->indexar) { /* vertex indices? */ const int *origindex_ar; - /* if mesh is present and has original index data, use it */ if (mesh && (origindex_ar = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX))) { - for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { - if (*index_pt < numVerts) { - int j; - - for (j = 0; j < numVerts; j++) { - if (origindex_ar[j] == *index_pt) { - hook_co_apply(&hd, j); - } - } + int numVerts_orig = numVerts; + if (ob->type == OB_MESH) { + const Mesh *me_orig = ob->data; + numVerts_orig = me_orig->totvert; + } + BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts_orig); + for (i = 0; i < numVerts; i++) { + int i_orig = origindex_ar[i]; + BLI_assert(i_orig < numVerts_orig); + if (BLI_BITMAP_TEST(indexar_used, i_orig)) { + hook_co_apply(&hd, i, dvert ? &dvert[i] : NULL); } } + MEM_freeN(indexar_used); } else { /* missing mesh or ORIGINDEX */ - for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { - if (*index_pt < numVerts) { - hook_co_apply(&hd, *index_pt); + if ((em != NULL) && (hd.defgrp_index != -1)) { + BLI_assert(em->bm->totvert == numVerts); + BLI_bitmap *indexar_used = hook_index_array_to_bitmap(hmd, numVerts); + BMIter iter; + BMVert *v; + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { + if (BLI_BITMAP_TEST(indexar_used, i)) { + const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset); + hook_co_apply(&hd, i, dv); + } + } + MEM_freeN(indexar_used); + } + else { + for (i = 0, index_pt = hmd->indexar; i < hmd->totindex; i++, index_pt++) { + const int j = *index_pt; + if (j < numVerts) { + hook_co_apply(&hd, j, dvert ? &dvert[j] : NULL); + } } } } } - else if (hd.dvert) { /* vertex group hook */ - for (i = 0; i < numVerts; i++) { - hook_co_apply(&hd, i); + else if (hd.defgrp_index != -1) { /* vertex group hook */ + if (em != NULL) { + BLI_assert(em->bm->totvert == numVerts); + BMIter iter; + BMVert *v; + BM_ITER_MESH_INDEX (v, &iter, em->bm, BM_VERTS_OF_MESH, i) { + const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset); + hook_co_apply(&hd, i, dv); + } + } + else { + BLI_assert(dvert != NULL); + for (i = 0; i < numVerts; i++) { + hook_co_apply(&hd, i, &dvert[i]); + } } } } @@ -377,7 +436,7 @@ static void deformVerts(struct ModifierData *md, HookModifierData *hmd = (HookModifierData *)md; Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); - deformVerts_do(hmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); + deformVerts_do(hmd, ctx, ctx->object, mesh_src, NULL, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { BKE_id_free(NULL, mesh_src); @@ -392,19 +451,8 @@ static void deformVertsEM(struct ModifierData *md, int numVerts) { HookModifierData *hmd = (HookModifierData *)md; - Mesh *mesh_src = MOD_deform_mesh_eval_get( - ctx->object, editData, mesh, NULL, numVerts, false, false); - - /* TODO(Campbell): use edit-mode data only (remove this line). */ - if (mesh_src != NULL) { - BKE_mesh_wrapper_ensure_mdata(mesh_src); - } - - deformVerts_do(hmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); - if (!ELEM(mesh_src, NULL, mesh)) { - BKE_id_free(NULL, mesh_src); - } + deformVerts_do(hmd, ctx, ctx->object, mesh, mesh ? NULL : editData, vertexCos, numVerts); } static void panel_draw(const bContext *C, Panel *panel) diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 93fb7749392..7b09d3c470d 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -44,12 +44,7 @@ #include "BKE_lib_query.h" #include "BKE_mesh.h" #include "BKE_modifier.h" - -/* SpaceType struct has a member called 'new' which obviously conflicts with C++ - * so temporarily redefining the new keyword to make it compile. */ -#define new extern_new #include "BKE_screen.h" -#undef new #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index 6374f081581..7b31886a220 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -59,7 +59,7 @@ #include "MOD_ui_common.h" #ifdef WITH_OCEANSIM -static void init_cache_data(Object *ob, struct OceanModifierData *omd) +static void init_cache_data(Object *ob, struct OceanModifierData *omd, const int resolution) { const char *relbase = BKE_modifier_path_relbase_from_global(ob); @@ -71,7 +71,7 @@ static void init_cache_data(Object *ob, struct OceanModifierData *omd) omd->chop_amount, omd->foam_coverage, omd->foam_fade, - omd->resolution); + resolution); } static void simulate_ocean_modifier(struct OceanModifierData *omd) @@ -87,7 +87,11 @@ static void initData(ModifierData *md) #ifdef WITH_OCEANSIM OceanModifierData *omd = (OceanModifierData *)md; + /* Render resolution */ omd->resolution = 7; + /* Display resolution for the non-render case */ + omd->viewport_resolution = 7; + omd->spatial_size = 50; omd->wave_alignment = 0.0; @@ -126,7 +130,7 @@ static void initData(ModifierData *md) omd->spraylayername[0] = '\0'; /* layer name empty by default */ omd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(omd->ocean, omd); + BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution); simulate_ocean_modifier(omd); #else /* WITH_OCEANSIM */ /* unused */ @@ -164,7 +168,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tomd->oceancache = NULL; tomd->ocean = BKE_ocean_add(); - BKE_ocean_init_from_modifier(tomd->ocean, tomd); + BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution); simulate_ocean_modifier(tomd); #else /* WITH_OCEANSIM */ /* unused */ @@ -288,7 +292,7 @@ static void generate_ocean_geometry_uvs(void *__restrict userdata, } } -static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig) +static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, const int resolution) { Mesh *result; @@ -297,10 +301,10 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig) int num_verts; int num_polys; - const bool use_threading = omd->resolution > 4; + const bool use_threading = resolution > 4; - gogd.rx = omd->resolution * omd->resolution; - gogd.ry = omd->resolution * omd->resolution; + gogd.rx = resolution * resolution; + gogd.ry = resolution * resolution; gogd.res_x = gogd.rx * omd->repeat_x; gogd.res_y = gogd.ry * omd->repeat_y; @@ -362,6 +366,9 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes Mesh *result = NULL; OceanResult ocr; + const int resolution = (ctx->flag & MOD_APPLY_RENDER) ? omd->resolution : + omd->viewport_resolution; + MVert *mverts; int cfra_for_cache; @@ -383,7 +390,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes /* do ocean simulation */ if (omd->cached == true) { if (!omd->oceancache) { - init_cache_data(ob, omd); + init_cache_data(ob, omd, resolution); } BKE_ocean_simulate_cache(omd->oceancache, cfra_scene); } @@ -393,12 +400,12 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes * This function is only called on an original object when applying the modifier * using the 'Apply Modifier' button, and thus it is not called frequently for * simulation. */ - allocated_ocean |= BKE_ocean_ensure(omd); + allocated_ocean |= BKE_ocean_ensure(omd, resolution); simulate_ocean_modifier(omd); } if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) { - result = generate_ocean_geometry(omd, mesh); + result = generate_ocean_geometry(omd, mesh, resolution); BKE_mesh_ensure_normals(result); } else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) { @@ -558,7 +565,10 @@ static void panel_draw(const bContext *C, Panel *panel) uiItemR(sub, &ptr, "repeat_x", 0, IFACE_("Repeat X"), ICON_NONE); uiItemR(sub, &ptr, "repeat_y", 0, IFACE_("Y"), ICON_NONE); } - uiItemR(col, &ptr, "resolution", 0, NULL, ICON_NONE); + + sub = uiLayoutColumn(col, true); + uiItemR(sub, &ptr, "viewport_resolution", 0, IFACE_("Resolution Viewport"), ICON_NONE); + uiItemR(sub, &ptr, "resolution", 0, IFACE_("Render"), ICON_NONE); uiItemR(col, &ptr, "time", 0, NULL, ICON_NONE); diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc index edfcc16af85..92ad02ae34a 100644 --- a/source/blender/modifiers/intern/MOD_simulation.cc +++ b/source/blender/modifiers/intern/MOD_simulation.cc @@ -46,16 +46,11 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_pointcloud.h" +#include "BKE_screen.h" #include "BKE_simulation.h" #include "BLO_read_write.h" -/* SpaceType struct has a member called 'new' which obviously conflicts with C++ - * so temporarily redefining the new keyword to make it compile. */ -#define new extern_new -#include "BKE_screen.h" -#undef new - #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/nodes/NOD_socket.h b/source/blender/nodes/NOD_socket.h index ce6f0da4aee..212a3d35a24 100644 --- a/source/blender/nodes/NOD_socket.h +++ b/source/blender/nodes/NOD_socket.h @@ -48,6 +48,11 @@ void node_verify_socket_templates(struct bNodeTree *ntree, struct bNode *node); void node_socket_init_default_value(struct bNodeSocket *sock); void node_socket_copy_default_value(struct bNodeSocket *to, const struct bNodeSocket *from); +void node_socket_skip_reroutes(struct ListBase *links, + struct bNode *node, + struct bNodeSocket *socket, + struct bNode **r_node, + struct bNodeSocket **r_socket); void register_standard_node_socket_types(void); #ifdef __cplusplus diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 996fb93eb76..439e41b963b 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -132,6 +132,9 @@ static bNodeSocket *group_verify_socket( if (sock) { strcpy(sock->name, iosock->name); + const int mask = SOCK_HIDE_VALUE; + sock->flag = (sock->flag & ~mask) | (iosock->flag & mask); + if (iosock->typeinfo->interface_verify_socket) { iosock->typeinfo->interface_verify_socket(ntree, iosock, gnode, sock, "interface"); } diff --git a/source/blender/nodes/intern/node_socket.cc b/source/blender/nodes/intern/node_socket.cc index 57c8d51975e..0dfae7424cb 100644 --- a/source/blender/nodes/intern/node_socket.cc +++ b/source/blender/nodes/intern/node_socket.cc @@ -356,6 +356,54 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from) to->flag |= (from->flag & SOCK_HIDE_VALUE); } +void node_socket_skip_reroutes( + ListBase *links, bNode *node, bNodeSocket *socket, bNode **r_node, bNodeSocket **r_socket) +{ + const int loop_limit = 100; /* Limit in case there is a connection cycle. */ + + if (socket->in_out == SOCK_IN) { + bNodeLink *first_link = (bNodeLink *)links->first; + + for (int i = 0; node->type == NODE_REROUTE && i < loop_limit; i++) { + bNodeLink *link = first_link; + + for (; link; link = link->next) { + if (link->fromnode == node && link->tonode != node) { + break; + } + } + + if (link) { + node = link->tonode; + socket = link->tosock; + } + else { + break; + } + } + } + else { + for (int i = 0; node->type == NODE_REROUTE && i < loop_limit; i++) { + bNodeSocket *input = (bNodeSocket *)node->inputs.first; + + if (input && input->link) { + node = input->link->fromnode; + socket = input->link->fromsock; + } + else { + break; + } + } + } + + if (r_node) { + *r_node = node; + } + if (r_socket) { + *r_socket = socket; + } +} + static void standard_node_socket_interface_init_socket(bNodeTree *UNUSED(ntree), bNodeSocket *stemp, bNode *UNUSED(node), diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index a1f9d4afc51..830acd987d9 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2961,7 +2961,7 @@ PyDoc_STRVAR(BPy_StringProperty_doc, "default=\"\", " "maxlen=0, " "options={'ANIMATABLE'}, " - "options=set(), " + "override=set(), " "tags=set(), " "subtype='NONE', " "update=None, " diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 3d4c84805f9..c0b2643d78d 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -99,7 +99,7 @@ void WM_main(struct bContext *C) ATTR_NORETURN; void WM_init_splash(struct bContext *C); -void WM_init_opengl(struct Main *bmain); +void WM_init_opengl(void); void WM_check(struct bContext *C); void WM_reinit_gizmomap_all(struct Main *bmain); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 0390bc1e4ef..85694dec9c8 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -171,7 +171,7 @@ void WM_init_state_start_with_console_set(bool value) */ static bool opengl_is_init = false; -void WM_init_opengl(Main *UNUSED(bmain)) +void WM_init_opengl(void) { /* must be called only once */ BLI_assert(opengl_is_init == false); @@ -312,7 +312,7 @@ void WM_init(bContext *C, int argc, const char **argv) /* sets 3D mouse deadzone */ WM_ndof_deadzone_set(U.ndof_deadzone); #endif - WM_init_opengl(G_MAIN); + WM_init_opengl(); if (!WM_platform_support_perform_checks()) { exit(-1); diff --git a/source/tools b/source/tools -Subproject 6a252de776d0b9dca3167c30a7621a4f1e9bc91 +Subproject 896c5f78952adb2d091d28c65086d46992dabda |