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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-12-02 18:58:44 +0300
committerJacques Lucke <jacques@blender.org>2020-12-02 18:58:44 +0300
commit390c4efa0c15b39e2d1971bc81464cffae56d102 (patch)
treed55cdaa779698bdf4b856221a8f826bbf43e2ce4
parentf14c9444c82662114c6e6015cbd5c187a07a297b (diff)
parent3d0c5455edf4e32e6e8120b280710cb4b531e38a (diff)
Merge branch 'master' into geometry-nodes
-rw-r--r--.git-blame-ignore-revs76
-rw-r--r--CMakeLists.txt16
-rw-r--r--build_files/buildbot/codesign/windows_code_signer.py7
-rw-r--r--build_files/cmake/Modules/FindPugiXML.cmake2
-rw-r--r--build_files/cmake/platform/platform_apple.cmake8
-rw-r--r--build_files/cmake/platform/platform_unix.cmake11
-rw-r--r--intern/cycles/render/volume.cpp6
-rw-r--r--intern/libmv/libmv/logging/logging.h19
m---------release/scripts/addons0
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h1
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c744
-rw-r--r--source/blender/blenloader/intern/versioning_290.c12
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c5
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c26
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c8
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c70
-rw-r--r--source/blender/editors/transform/transform_mode.c4
-rw-r--r--source/blender/editors/transform/transform_mode.h2
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c149
-rw-r--r--source/blender/editors/transform/transform_ops.c3
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc26
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_brush.c14
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c7
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c5
-rw-r--r--source/blender/makesrna/intern/rna_sequencer_api.c267
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c62
m---------source/tools0
33 files changed, 1184 insertions, 385 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index d36bce18613..d864e08c953 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -91,3 +91,79 @@ c42a6b77b52560d257279de2cb624b4ef2c0d24c
# Cleanup: use doxy sections for imbuf
c207f7c22e1439e0b285fba5d2c072bdae23f981
+
+# Cleanup: Clang-Tidy, modernize-use-bool-literals
+af35ada2f3fa8da4d46b3a71de724d353d716820
+
+# Cleanup: Use nullptr everywhere in fluid code
+311031ecd03dbfbf43e1df672a395f24b2e7d4d3
+
+# Cleanup: Clang-Tidy, modernize-redundant-void-arg
+a331d5c99299c4514ca33c843b1c79b872f2728d
+
+# Cleanup: Clang-Tidy modernize-use-nullptr
+16732def37c5a66f3ea28dbe247b09cc6bca6677
+
+# Cleanup: Clang-tidy, modernize-concat-nested-namespaces
+4525049aa0cf818f6483dce589ac9791eb562338
+
+# Cleanup: Clang-tidy else-after-return
+ae342ed4511cf2e144dcd27ce2c635d3d536f9ad
+
+# Cleanup: Clang-Tidy, readability-redundant-member-init
+190170d4cc92ff34abe1744a10474ac4f1074086
+
+# Cleanup: use 'filepath' instead of 'name' for ImBuf utilities
+99f56b4c16323f96c0cbf54e392fb509fcac5bda
+
+# Cleanup: clang-format
+c4d8f6a4a8ddc29ed27311ed7578b3c8c31399d2
+b5d310b569e07a937798a2d38539cfd290149f1c
+8c846cccd6bdfd3e90a695fabbf05f53e5466a57
+40d4a4cb1a6b4c3c2a486e8f2868f547530e0811
+4eac03d821fa17546f562485f7d073813a5e5943
+
+# Cleanup: use preprocessor version check for PyTypeObject declaration
+cd9acfed4f7674b84be965d469a367aef96f8af3
+
+# Cycles: fix compilation of OSL shaders following API change
+b980cd163a9d5d77eeffc2e353333e739fa9e719
+
+# Cleanup: clang-tidy suppress warnings for PyTypeObject.tp_print
+efd71aad4f22ec0073d80b8dd296015d3f395aa8
+
+# Cleanup: fix wrong merge, remove extra unique_ptr.
+6507449e54a167c63a72229e4d0119dd2af68ae5
+
+# Cleanup: fix some clang tidy issues
+525a042c5c7513c41240b118acca002f6c60cc12
+
+# Fix T82520: error building freestyle with Python3.8
+e118426e4695a97d67e65d69677f3c4e2db50a56
+
+# Cleanup: Clang-tidy, readability-else-after-return
+7be47dadea5066ae095c644e0b4f1f10d75f5ab3
+
+# Cleanup: Add `r_` to return parameter
+45dca05b1cd2a5ead59144c93d790fdfe7c35ee6
+
+# Cleanup: Typo in `print_default_info` function name.
+41a73909dec716642f044e60b40a28335c9fdb10
+
+# Cleanup: Reduce indentation
+1cc3a0e2cf73a5ff4f9e0a7f5338eda77266b300
+
+# Build-system: Force C linkage for all DNA type headers
+ad4b7741dba45a2be210942c18af6b6e4438f129
+
+# Cleanup: Move function to proper section
+c126e27cdc8b28365a9d5f9fafc4d521d1eb83df
+
+# Cleanup: remove break after return statements
+bbdfeb751e16d939482d2e4b95c4d470f53f18a5
+
+# Cleanup: clang-tidy
+af013ff76feef7e8b8ba642279c62a5dc275d59f
+
+# Cleanup: Make panel type flag names more clear
+9d28353b525ecfbcca1501be72e4276dfb2bbc2a
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 580aa1e8d79..81fe4739da4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -178,9 +178,7 @@ mark_as_advanced(BUILDINFO_OVERRIDE_TIME)
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
option(WITH_IK_SOLVER "Enable Legacy IK solver (only disable for development)" ON)
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke, ocean sim, and audio effects)" ON)
-if(WIN32)
- option(WITH_PUGIXML "Enable PugiXML support (Used for OpenImageIO, Grease Pencil SVG export)" ON)
-endif()
+option(WITH_PUGIXML "Enable PugiXML support (Used for OpenImageIO, Grease Pencil SVG export)" ON)
option(WITH_BULLET "Enable Bullet (Physics Engine)" ON)
option(WITH_SYSTEM_BULLET "Use the systems bullet library (currently unsupported due to missing features in upstream!)" )
mark_as_advanced(WITH_SYSTEM_BULLET)
@@ -701,10 +699,8 @@ set_and_warn_dependency(WITH_BOOST WITH_OPENCOLORIO OFF)
set_and_warn_dependency(WITH_BOOST WITH_QUADRIFLOW OFF)
set_and_warn_dependency(WITH_BOOST WITH_USD OFF)
set_and_warn_dependency(WITH_BOOST WITH_ALEMBIC OFF)
-if(WIN32)
- set_and_warn_dependency(WITH_PUGIXML WITH_CYCLES_OSL OFF)
- set_and_warn_dependency(WITH_PUGIXML WITH_OPENIMAGEIO OFF)
-endif()
+set_and_warn_dependency(WITH_PUGIXML WITH_CYCLES_OSL OFF)
+set_and_warn_dependency(WITH_PUGIXML WITH_OPENIMAGEIO OFF)
if(WITH_BOOST AND NOT (WITH_CYCLES OR WITH_OPENIMAGEIO OR WITH_INTERNATIONAL OR
WITH_OPENVDB OR WITH_OPENCOLORIO OR WITH_USD OR WITH_ALEMBIC))
@@ -883,9 +879,11 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "Release")
if(APPLE AND COMPILER_ASAN_LIBRARY)
string(REPLACE " " ";" _list_COMPILER_ASAN_CFLAGS ${COMPILER_ASAN_CFLAGS})
- add_compile_options("$<$<NOT:$<CONFIG:Release>>:${_list_COMPILER_ASAN_CFLAGS}>")
- add_link_options("$<$<NOT:$<CONFIG:Release>>:-fno-omit-frame-pointer;-fsanitize=address>")
+ set(_is_CONFIG_DEBUG "$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>")
+ add_compile_options("$<${_is_CONFIG_DEBUG}:${_list_COMPILER_ASAN_CFLAGS}>")
+ add_link_options("$<${_is_CONFIG_DEBUG}:-fno-omit-frame-pointer;-fsanitize=address>")
unset(_list_COMPILER_ASAN_CFLAGS)
+ unset(_is_CONFIG_DEBUG)
elseif(COMPILER_ASAN_LIBRARY)
set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS};${COMPILER_ASAN_LIBRARY}")
set(PLATFORM_LINKFLAGS "${COMPILER_ASAN_LIBRARY} ${COMPILER_ASAN_LINKER_FLAGS}")
diff --git a/build_files/buildbot/codesign/windows_code_signer.py b/build_files/buildbot/codesign/windows_code_signer.py
index 251dd856c8a..db185788a56 100644
--- a/build_files/buildbot/codesign/windows_code_signer.py
+++ b/build_files/buildbot/codesign/windows_code_signer.py
@@ -64,7 +64,12 @@ class WindowsCodeSigner(BaseCodeSigner):
def run_codesign_tool(self, filepath: Path) -> None:
command = self.get_sign_command_prefix() + [filepath]
- codesign_output = self.check_output_or_mock(command, util.Platform.WINDOWS)
+
+ try:
+ codesign_output = self.check_output_or_mock(command, util.Platform.WINDOWS)
+ except subprocess.CalledProcessError as e:
+ raise SigntoolException(f'Error running signtool {e}')
+
logger_server.info(f'signtool output:\n{codesign_output}')
got_number_of_success = False
diff --git a/build_files/cmake/Modules/FindPugiXML.cmake b/build_files/cmake/Modules/FindPugiXML.cmake
index 5dced1c6df8..f5b1dfce4af 100644
--- a/build_files/cmake/Modules/FindPugiXML.cmake
+++ b/build_files/cmake/Modules/FindPugiXML.cmake
@@ -49,7 +49,7 @@ FIND_LIBRARY(PUGIXML_LIBRARY
# handle the QUIETLY and REQUIRED arguments and set PUGIXML_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PUGIXML DEFAULT_MSG
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PugiXML DEFAULT_MSG
PUGIXML_LIBRARY PUGIXML_INCLUDE_DIR)
IF(PUGIXML_FOUND)
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 586c72c9c7e..6baa2f3d855 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -270,6 +270,14 @@ if(WITH_INTERNATIONAL OR WITH_CODEC_FFMPEG)
string(APPEND PLATFORM_LINKFLAGS " -liconv") # boost_locale and ffmpeg needs it !
endif()
+if(WITH_PUGIXML)
+ find_package(PugiXML)
+ if(NOT PUGIXML_FOUND)
+ message(WARNING "PugiXML not found, disabling WITH_PUGIXML")
+ set(WITH_PUGIXML OFF)
+ endif()
+endif()
+
if(WITH_OPENIMAGEIO)
find_package(OpenImageIO)
list(APPEND OPENIMAGEIO_LIBRARIES
diff --git a/build_files/cmake/platform/platform_unix.cmake b/build_files/cmake/platform/platform_unix.cmake
index 97bd4981c22..c4d1383c767 100644
--- a/build_files/cmake/platform/platform_unix.cmake
+++ b/build_files/cmake/platform/platform_unix.cmake
@@ -350,15 +350,12 @@ if(WITH_BOOST)
endif()
endif()
+if(WITH_PUGIXML)
+ find_package_wrapper(PugiXML)
+endif()
+
if(WITH_OPENIMAGEIO)
find_package_wrapper(OpenImageIO)
- if(NOT OPENIMAGEIO_PUGIXML_FOUND AND WITH_CYCLES_STANDALONE)
- find_package_wrapper(PugiXML)
- else()
- set(PUGIXML_INCLUDE_DIR "${OPENIMAGEIO_INCLUDE_DIR/OpenImageIO}")
- set(PUGIXML_LIBRARIES "")
- endif()
-
set(OPENIMAGEIO_LIBRARIES
${OPENIMAGEIO_LIBRARIES}
${PNG_LIBRARIES}
diff --git a/intern/cycles/render/volume.cpp b/intern/cycles/render/volume.cpp
index 4baaae6856c..a1bd16798fb 100644
--- a/intern/cycles/render/volume.cpp
+++ b/intern/cycles/render/volume.cpp
@@ -528,8 +528,10 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
}
/* Clear existing volume mesh, done here in case we early out due to
- * empty grid or missing volume shader. */
- volume->clear();
+ * empty grid or missing volume shader.
+ * Also keep the shaders to avoid infinite loops when synchronizing, as this will tag the shaders
+ * as having changed. */
+ volume->clear(true);
volume->need_update_rebuild = true;
if (!volume_shader) {
diff --git a/intern/libmv/libmv/logging/logging.h b/intern/libmv/libmv/logging/logging.h
index 776d9d52f7a..0f4f99e3895 100644
--- a/intern/libmv/libmv/logging/logging.h
+++ b/intern/libmv/libmv/logging/logging.h
@@ -23,9 +23,20 @@
#include <glog/logging.h>
-#define LG LOG(INFO)
-#define V0 LOG(INFO)
-#define V1 LOG(INFO)
-#define V2 LOG(INFO)
+// Note on logging severity and verbosity level.
+//
+// Reserve LOG(INFO) for messages which are always to be put to log and don't
+// use the INFO severity for the debugging/troubleshooting type of messages.
+// Some reasoning behind:
+//
+// - Library integration would want to disable "noisy" messages coming from
+// algorithms.
+//
+// - It is not possible to disable INFO severity entirely: there is enough
+// of preparation being done for the message stream. What is even worse
+// is that such stream preparation causes measurable time spent in spin
+// lock, ruining multi-threading.
+
+#define LG VLOG(1)
#endif // LIBMV_LOGGING_LOGGING_H
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 866dcad5aa6e45737f0634b835adcbc0871201e
+Subproject ca74197440127e56c9f6f2a277c30957f34fd07
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index cd213b49c5b..fd600a41796 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -235,6 +235,7 @@ const struct CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh);
+int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh);
/* Only valid for type == PBVH_BMESH */
struct BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index ab87772d844..47d2ae8e283 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1707,6 +1707,12 @@ int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
return pbvh->totgrid * pbvh->gridkey.grid_area;
}
+int BKE_pbvh_get_grid_num_faces(const PBVH *pbvh)
+{
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->totgrid * (pbvh->gridkey.grid_size - 1) * (pbvh->gridkey.grid_size - 1);
+}
+
BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh)
{
BLI_assert(pbvh->type == PBVH_BMESH);
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index edd798b162a..05d1e427c14 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -41,39 +41,65 @@
#include "libmv-capi.h"
#include "tracking_private.h"
-typedef struct AutoTrackOptions {
- int clip_index; /** Index of the clip this track belongs to. */
- int track_index; /* Index of the track in AutoTrack tracks structure. */
- MovieTrackingTrack *track; /* Pointer to an original track/ */
- libmv_TrackRegionOptions track_region_options; /* Options for the region tracker. */
-
- /* Define which frame is used for reference marker. */
- eTrackFrameMatch frame_match;
-
- /* TODO(sergey): A bit awkward to keep it in here, only used to
- * place a disabled marker once the tracking fails,
- * Either find a clearer way to do it or call it track context
- * or state, not options.
- */
- bool is_failed;
- int failed_frame;
-} AutoTrackOptions;
+typedef struct AutoTrackClip {
+ MovieClip *clip;
+
+ /* Dimensions of movie frame, in pixels.
+ *
+ * NOTE: All frames within a clip are expected to have match3ed dimensions. */
+ int width, height;
+} AutoTrackClip;
+
+typedef struct AutoTrackTrack {
+ /* Index of a clip from `AutoTrackContext::autotrack_clips` this track belongs to. */
+ int clip_index;
+
+ MovieTrackingTrack *track;
+
+ /* Options for the region tracker. */
+ libmv_TrackRegionOptions track_region_options;
+
+ /* Denotes whether this track will be tracked.
+ * Is usually initialized based on track's selection. Non-trackable tracks are still added to the
+ * context to provide AutoTrack all knowledge about what is going on in the scene. */
+ bool is_trackable;
+} AutoTrackTrack;
+
+typedef struct AutoTrackMarker {
+ libmv_Marker libmv_marker;
+} AutoTrackMarker;
+
+/* Result of tracking step for a single marker.
+ *
+ * On success both marker and result are fully initialized to the position on the new frame.
+ *
+ * On failure marker's frame number is initialized to frame number where it was attempted to be
+ * tracked to. The position and other fields of tracked marker are the same as the input. */
+typedef struct AutoTrackTrackingResult {
+ struct AutoTrackTrackingResult *next, *prev;
+
+ bool success;
+ libmv_Marker libmv_marker;
+ libmv_TrackRegionResult libmv_result;
+} AutoTrackTrackingResult;
typedef struct AutoTrackContext {
+ /* --------------------------------------------------------------------
+ * Invariant part.
+ * Stays unchanged during the tracking process.
+ * If not the initialization process, all the fields here should be treated as `const`.
+ */
+
/* Frame at which tracking process started.
* NOTE: Measured in scene time frames, */
int start_scene_frame;
- /* Scene frame number from which tracker will perform the trackign step.
- * The direction of the step is denoted by `is_backwards`. */
- int current_scene_frame;
-
/* True when tracking backwards (from higher frame number to lower frame number.) */
bool is_backwards;
/* Movie clips used during the trackign process. */
int num_clips;
- MovieClip *clips[MAX_ACCESSOR_CLIP];
+ AutoTrackClip autotrack_clips[MAX_ACCESSOR_CLIP];
/* Tracks for which the context has been created for.
* This is a flat array of all tracks coming from all clips, regardless of whether track is
@@ -82,35 +108,41 @@ typedef struct AutoTrackContext {
*
* Indexed by AutoTrackOptions::track_index. */
int num_all_tracks;
- MovieTrackingTrack **all_tracks;
-
- /* Dimensions of movie frame, in pixels.
- *
- * NOTE: All clips and frames within a clip are expected to have match3ed dimensions.
- *
- * TODO(sergey): Make it more flexible to fully support multiple-clip tracking. Could either be
- * stored as a `pair<MovieClip, Dimensions>` or even be replaced with actual frame size access
- * to support variadic frame dimensions. */
- int frame_width, frame_height;
+ AutoTrackTrack *all_autotrack_tracks;
/* Accessor for images of clip. Used by the autotrack context. */
TrackingImageAccessor *image_accessor;
+ /* --------------------------------------------------------------------
+ * Variant part.
+ * Denotes tracing state and tracking result.
+ */
+
/* Auto-track context.
*
* NOTE: Is accessed from multiple threads at once. */
struct libmv_AutoTrack *autotrack;
- int num_track_options;
- AutoTrackOptions *track_options; /* Per-tracking track options. */
+ /* Markers from the current frame which will be tracked to the next frame upon the tracking
+ * context step.
+ *
+ * NOTE: This array is re-used across tracking steps, which might make it appear that the array
+ * is over-allocated when some tracks has failed to track. */
+ int num_autotrack_markers;
+ AutoTrackMarker *autotrack_markers;
- int sync_frame;
- bool first_sync;
- SpinLock spin_lock;
+ /* Tracking results which are to be synchronized from the AutoTrack context to the Blender's
+ * DNA to make the results visible for users. */
+ ListBase results_to_sync;
+ int synchronized_scene_frame;
- bool step_ok;
+ SpinLock spin_lock;
} AutoTrackContext;
+/* -------------------------------------------------------------------- */
+/** \name Marker coordinate system conversion.
+ * \{ */
+
static void normalized_to_libmv_frame(const float normalized[2],
const int frame_dimensions[2],
float result[2])
@@ -145,8 +177,14 @@ static void libmv_frame_to_normalized_relative(const float frame_coord[2],
result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1];
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Coversion of markers between Blender's DNA and Libmv.
+ * \{ */
+
static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
- /*const*/ MovieTrackingMarker *marker,
+ const MovieTrackingMarker *marker,
int clip,
int track_index,
int frame_width,
@@ -171,7 +209,9 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
normalized_relative_to_libmv_frame(
marker->search_max, marker->pos, frame_dimensions, libmv_marker->search_region_max);
- /* TODO(sergey): All the markers does have 1.0 weight. */
+ /* NOTE: All the markers does have 1.0 weight.
+ * Might support in the future, but will require more elaborated process which will involve
+ * F-Curve evaluation. */
libmv_marker->weight = 1.0f;
if (marker->flag & MARKER_TRACKED) {
@@ -184,13 +224,11 @@ static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track,
libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT;
libmv_marker->model_id = 0;
- /* TODO(sergey): We currently don't support reference marker from
- * different clip.
- */
+ /* NOTE: We currently don't support reference marker from different clip. */
libmv_marker->reference_clip = clip;
if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
- MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
+ const MovieTrackingMarker *keyframe_marker = tracking_get_keyframed_marker(
track, marker->framenr, backwards);
libmv_marker->reference_frame = keyframe_marker->framenr;
}
@@ -235,20 +273,17 @@ static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker,
}
}
-static bool check_track_trackable(const MovieClip *clip,
- MovieTrackingTrack *track,
- const MovieClipUser *user)
-{
- if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
- int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr);
- const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, frame);
- return (marker->flag & MARKER_DISABLED) == 0;
- }
- return false;
-}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name General helpers.
+ *
+ * TODO(sergey): Should be moved to tracking_util.c
+ *
+ * \{ */
/* Returns false if marker crossed margin area from frame bounds. */
-static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
+static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
int margin,
int frame_width,
int frame_height)
@@ -277,91 +312,234 @@ static bool tracking_check_marker_margin(libmv_Marker *libmv_marker,
return true;
}
-/* Provide Libmv side of auto track all information about given tracks. */
-static void fill_autotrack_tracks(const int frame_width,
- const int frame_height,
- const ListBase *tracksbase,
- const bool backwards,
- struct libmv_AutoTrack *autotrack)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Autotrack context initialization.
+ * \{ */
+
+static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
{
- /* Count number of markers to be put to a context. */
- size_t num_trackable_markers = 0;
- LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
- for (int i = 0; i < track->markersnr; i++) {
- const MovieTrackingMarker *marker = track->markers + i;
- if ((marker->flag & MARKER_DISABLED) == 0) {
- num_trackable_markers++;
+ if ((marker->flag & MARKER_DISABLED)) {
+ return false;
+ }
+ return true;
+}
+
+static bool autotrack_is_track_trackable(const AutoTrackContext *context,
+ const AutoTrackTrack *autotrack_track)
+{
+ /*const*/ MovieTrackingTrack *track = autotrack_track->track;
+ if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) {
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
+ MovieClip *clip = autotrack_clip->clip;
+ const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
+ clip, context->start_scene_frame);
+
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
+ return autotrack_is_marker_usable(marker);
+ }
+ return false;
+}
+
+static void autotrack_context_init_clips(AutoTrackContext *context,
+ MovieClip *clip,
+ MovieClipUser *user)
+{
+ /* NOTE: Currently only tracking within a single clip. */
+
+ context->num_clips = 1;
+
+ context->autotrack_clips[0].clip = clip;
+ BKE_movieclip_get_size(
+ clip, user, &context->autotrack_clips[0].width, &context->autotrack_clips[0].height);
+}
+
+/* Initialize flat list of tracks for quick index-based access for the specified clip.
+ * All the tracks from this clip are added at the end of the array of already-collected tracks.
+ *
+ * NOTE: Clips should be initialized first. */
+static void autotrack_context_init_tracks_for_clip(AutoTrackContext *context, int clip_index)
+{
+ BLI_assert(clip_index >= 0);
+ BLI_assert(clip_index < context->num_clips);
+
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
+ MovieClip *clip = autotrack_clip->clip;
+ MovieTracking *tracking = &clip->tracking;
+ ListBase *tracks_base = BKE_tracking_get_active_tracks(tracking);
+
+ const int num_clip_tracks = BLI_listbase_count(tracks_base);
+ if (num_clip_tracks == 0) {
+ return;
+ }
+
+ context->all_autotrack_tracks = MEM_reallocN(context->all_autotrack_tracks,
+ (context->num_all_tracks + num_clip_tracks) *
+ sizeof(AutoTrackTrack));
+
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_base) {
+ AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[context->num_all_tracks++];
+ autotrack_track->clip_index = clip_index;
+ autotrack_track->track = track;
+ autotrack_track->is_trackable = autotrack_is_track_trackable(context, autotrack_track);
+
+ tracking_configure_tracker(track, NULL, &autotrack_track->track_region_options);
+ }
+}
+
+/* Initialize flat list of tracks for quick index-based access for all clips used for tracking.
+ *
+ * NOTE: Clips should be initialized first. */
+static void autotrack_context_init_tracks(AutoTrackContext *context)
+{
+ BLI_assert(context->num_clips >= 1);
+
+ for (int clip_index = 0; clip_index < context->num_clips; ++clip_index) {
+ autotrack_context_init_tracks_for_clip(context, clip_index);
+ }
+}
+
+/* NOTE: Clips should be initialized first. */
+static void autotrack_context_init_image_accessor(AutoTrackContext *context)
+{
+ BLI_assert(context->num_clips >= 1);
+
+ /* Planarize arrays of clips and tracks, storing pointers to their base "objects".
+ * This allows image accessor to be independent, but adds some overhead here. Could be solved
+ * by either more strongly coupling accessor API with the AutoTrack, or by giving some functors
+ * to the accessor to access clip/track from their indices. */
+
+ MovieClip *clips[MAX_ACCESSOR_CLIP];
+ for (int i = 0; i < context->num_clips; ++i) {
+ clips[i] = context->autotrack_clips[i].clip;
+ }
+
+ MovieTrackingTrack **tracks = MEM_malloc_arrayN(
+ context->num_all_tracks, sizeof(MovieTrackingTrack *), "image accessor init tracks");
+ for (int i = 0; i < context->num_all_tracks; ++i) {
+ tracks[i] = context->all_autotrack_tracks[i].track;
+ }
+
+ context->image_accessor = tracking_image_accessor_new(clips, 1, tracks, context->num_all_tracks);
+
+ MEM_freeN(tracks);
+}
+
+/* Count markers which are usable to be passed to the AutoTrack context. */
+static size_t autotrack_count_all_usable_markers(AutoTrackContext *context)
+{
+ size_t num_usable_markers = 0;
+ for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
+ const MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
+ for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
+ const MovieTrackingMarker *marker = &track->markers[marker_index];
+ if (!autotrack_is_marker_usable(marker)) {
+ continue;
}
+ num_usable_markers++;
+ }
+ }
+ return num_usable_markers;
+}
+
+static int autotrack_count_trackable_markers(AutoTrackContext *context)
+{
+ int num_trackable_markers = 0;
+ for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ if (!autotrack_track->is_trackable) {
+ continue;
}
+ num_trackable_markers++;
}
- /* Early output if we don't have any markers. */
+ return num_trackable_markers;
+}
+
+/* Provide Libmv side of auto track all information about given tracks.
+ * Information from all clips is passed to the auto tracker.
+ *
+ * NOTE: Clips and all tracks are to be initialized before calling this. */
+static void autotrack_context_init_autotrack(AutoTrackContext *context)
+{
+ context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor);
+
+ /* Count number of markers to be put to a context. */
+ const size_t num_trackable_markers = autotrack_count_all_usable_markers(context);
if (num_trackable_markers == 0) {
return;
}
+
/* Allocate memory for all the markers. */
- libmv_Marker *libmv_markers = MEM_mallocN(sizeof(libmv_Marker) * num_trackable_markers,
- "libmv markers array");
+ libmv_Marker *libmv_markers = MEM_malloc_arrayN(
+ sizeof(libmv_Marker), num_trackable_markers, "libmv markers array");
+
/* Fill in markers array. */
- int track_index = 0, num_filled_libmv_markers = 0;
- LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
- for (int i = 0; i < track->markersnr; i++) {
- MovieTrackingMarker *marker = track->markers + i;
- if ((marker->flag & MARKER_DISABLED) != 0) {
+ int num_filled_libmv_markers = 0;
+ for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ /*const*/ MovieTrackingTrack *track = autotrack_track->track;
+ for (int marker_index = 0; marker_index < track->markersnr; ++marker_index) {
+ /*const*/ MovieTrackingMarker *marker = &track->markers[marker_index];
+ if (!autotrack_is_marker_usable(marker)) {
continue;
}
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
dna_marker_to_libmv_marker(track,
marker,
- 0,
+ autotrack_track->clip_index,
track_index,
- frame_width,
- frame_height,
- backwards,
+ autotrack_clip->width,
+ autotrack_clip->height,
+ context->is_backwards,
&libmv_markers[num_filled_libmv_markers++]);
}
- /* Put all markers to autotrack at once. */
- track_index++;
}
+
/* Add all markers to autotrack. */
- libmv_autoTrackSetMarkers(autotrack, libmv_markers, num_trackable_markers);
+ libmv_autoTrackSetMarkers(context->autotrack, libmv_markers, num_trackable_markers);
+
/* Free temporary memory. */
MEM_freeN(libmv_markers);
}
-static void create_per_track_tracking_options(const MovieClip *clip,
- const MovieClipUser *user,
- const ListBase *tracksbase,
- AutoTrackContext *context)
+static void autotrack_context_init_markers(AutoTrackContext *context)
{
/* Count number of trackable tracks. */
- LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
- if (check_track_trackable(clip, track, user)) {
- context->num_track_options++;
- }
+ context->num_autotrack_markers = autotrack_count_trackable_markers(context);
+ if (context->num_autotrack_markers == 0) {
+ return;
}
+
/* Allocate required memory. */
- context->track_options = MEM_callocN(sizeof(AutoTrackOptions) * context->num_track_options,
- "auto track options");
- /* Fill in all the settings. */
- int i = 0, track_index = 0;
- LISTBASE_FOREACH (MovieTrackingTrack *, track, tracksbase) {
- context->all_tracks[track_index] = track;
-
- if (!check_track_trackable(clip, track, user)) {
- track_index++;
+ context->autotrack_markers = MEM_calloc_arrayN(
+ sizeof(AutoTrackMarker), context->num_autotrack_markers, "auto track options");
+
+ /* Fill in all the markers. */
+ int autotrack_marker_index = 0;
+ for (int track_index = 0; track_index < context->num_all_tracks; ++track_index) {
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ if (!autotrack_track->is_trackable) {
continue;
}
- AutoTrackOptions *track_options = &context->track_options[i++];
-
- /* TODO(sergey): Single clip only for now. */
- track_options->clip_index = 0;
- track_options->track_index = track_index;
- track_options->track = track;
- track_options->frame_match = track->pattern_match;
-
- tracking_configure_tracker(track, NULL, &track_options->track_region_options);
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[autotrack_track->clip_index];
+ MovieClip *clip = autotrack_clip->clip;
+ const int clip_frame_number = BKE_movieclip_remap_scene_to_clip_frame(
+ clip, context->start_scene_frame);
- track_index++;
+ /*const*/ MovieTrackingTrack *track = context->all_autotrack_tracks[track_index].track;
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame_number);
+
+ AutoTrackMarker *autotrack_marker = &context->autotrack_markers[autotrack_marker_index++];
+ dna_marker_to_libmv_marker(track,
+ marker,
+ autotrack_track->clip_index,
+ track_index,
+ autotrack_clip->width,
+ autotrack_clip->height,
+ context->is_backwards,
+ &autotrack_marker->libmv_marker);
}
}
@@ -370,198 +548,247 @@ AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip,
const bool is_backwards)
{
AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), "autotrack context");
- MovieTracking *tracking = &clip->tracking;
- ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking);
- int frame_width, frame_height;
- /* get size of frame to convert normalized coordinates to a picture ones. */
- BKE_movieclip_get_size(clip, user, &frame_width, &frame_height);
- /* TODO(sergey): Currently using only a single clip. */
- context->clips[0] = clip;
- context->num_clips = 1;
- context->current_scene_frame = user->framenr;
- context->frame_width = frame_width;
- context->frame_height = frame_height;
- context->is_backwards = is_backwards;
+
context->start_scene_frame = user->framenr;
- context->sync_frame = user->framenr;
- context->first_sync = true;
+ context->is_backwards = is_backwards;
+ context->synchronized_scene_frame = context->start_scene_frame;
+
+ autotrack_context_init_clips(context, clip, user);
+ autotrack_context_init_tracks(context);
+ autotrack_context_init_image_accessor(context);
+ autotrack_context_init_autotrack(context);
+ autotrack_context_init_markers(context);
+
BLI_spin_init(&context->spin_lock);
- context->num_all_tracks = BLI_listbase_count(tracksbase);
- context->all_tracks = MEM_callocN(sizeof(MovieTrackingTrack *) * context->num_all_tracks,
- "auto track pointers");
- /* Create per-track tracking options. */
- create_per_track_tracking_options(clip, user, tracksbase, context);
- /* Initialize image accessor. */
- context->image_accessor = tracking_image_accessor_new(
- context->clips, 1, context->all_tracks, context->num_all_tracks);
- /* Initialize auto track context and provide all information about currently
- * tracked markers.
- */
- context->autotrack = libmv_autoTrackNew(context->image_accessor->libmv_accessor);
- fill_autotrack_tracks(frame_width, frame_height, tracksbase, is_backwards, context->autotrack);
+
return context;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Threaded context step (tracking process).
+ * \{ */
+
+/* NOTE: This is a TLS in a sense that this struct is never accessed from multiple threads, and
+ * that threads are re-using the struct as much as possible. */
+typedef struct AutoTrackTLS {
+ ListBase results; /* Elements of `AutoTrackTrackingResult`. */
+} AutoTrackTLS;
+
static void autotrack_context_step_cb(void *__restrict userdata,
- const int track,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const int marker_index,
+ const TaskParallelTLS *__restrict tls)
{
AutoTrackContext *context = userdata;
- const int frame_delta = context->is_backwards ? -1 : 1;
+ AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)tls->userdata_chunk;
- AutoTrackOptions *track_options = &context->track_options[track];
- if (track_options->is_failed) {
- return;
- }
+ const AutoTrackMarker *autotrack_marker = &context->autotrack_markers[marker_index];
+ const libmv_Marker *libmv_current_marker = &autotrack_marker->libmv_marker;
- const int track_index = track_options->track_index;
- const int clip_index = track_options->clip_index;
+ const int frame_delta = context->is_backwards ? -1 : 1;
+ const int clip_index = libmv_current_marker->clip;
+ const int track_index = libmv_current_marker->track;
- libmv_Marker libmv_current_marker, libmv_reference_marker, libmv_tracked_marker;
- libmv_TrackRegionResult libmv_result;
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ const MovieTrackingTrack *track = autotrack_track->track;
- MovieClip *clip = context->clips[clip_index];
- const int frame = BKE_movieclip_remap_scene_to_clip_frame(clip, context->current_scene_frame);
- BLI_spin_lock(&context->spin_lock);
- const bool has_marker = libmv_autoTrackGetMarker(
- context->autotrack, clip_index, frame, track_index, &libmv_current_marker);
- BLI_spin_unlock(&context->spin_lock);
- /* Check whether we've got marker to sync with. */
- if (!has_marker) {
- return;
- }
/* Check whether marker is going outside of allowed frame margin. */
- if (!tracking_check_marker_margin(&libmv_current_marker,
- track_options->track->margin,
- context->frame_width,
- context->frame_height)) {
+ if (!tracking_check_marker_margin(
+ libmv_current_marker, track->margin, autotrack_clip->width, autotrack_clip->height)) {
return;
}
- libmv_tracked_marker = libmv_current_marker;
- libmv_tracked_marker.frame = frame + frame_delta;
+
+ const int new_marker_frame = libmv_current_marker->frame + frame_delta;
+
+ AutoTrackTrackingResult *autotrack_result = MEM_mallocN(sizeof(AutoTrackTrackingResult),
+ "autotrack result");
+ autotrack_result->libmv_marker = *libmv_current_marker;
+ autotrack_result->libmv_marker.frame = new_marker_frame;
+
/* Update reference frame. */
- if (track_options->frame_match == TRACK_MATCH_KEYFRAME) {
- libmv_tracked_marker.reference_frame = libmv_current_marker.reference_frame;
+ libmv_Marker libmv_reference_marker;
+ if (track->pattern_match == TRACK_MATCH_KEYFRAME) {
+ autotrack_result->libmv_marker.reference_frame = libmv_current_marker->reference_frame;
libmv_autoTrackGetMarker(context->autotrack,
- track_options->clip_index,
- libmv_tracked_marker.reference_frame,
- track_options->track_index,
+ clip_index,
+ autotrack_result->libmv_marker.reference_frame,
+ track_index,
&libmv_reference_marker);
}
else {
- BLI_assert(track_options->frame_match == TRACK_MATCH_PREVIOS_FRAME);
- libmv_tracked_marker.reference_frame = frame;
- libmv_reference_marker = libmv_current_marker;
+ BLI_assert(track->pattern_match == TRACK_MATCH_PREVIOS_FRAME);
+ autotrack_result->libmv_marker.reference_frame = libmv_current_marker->frame;
+ libmv_reference_marker = *libmv_current_marker;
}
+
/* Perform actual tracking. */
- if (libmv_autoTrackMarker(context->autotrack,
- &track_options->track_region_options,
- &libmv_tracked_marker,
- &libmv_result)) {
- BLI_spin_lock(&context->spin_lock);
- libmv_autoTrackAddMarker(context->autotrack, &libmv_tracked_marker);
- BLI_spin_unlock(&context->spin_lock);
+ autotrack_result->success = libmv_autoTrackMarker(context->autotrack,
+ &autotrack_track->track_region_options,
+ &autotrack_result->libmv_marker,
+ &autotrack_result->libmv_result);
+
+ /* If tracking failed restore initial position.
+ * This is how Blender side is currently expecting failed track to be handled. Without this the
+ * marker is left in an arbitrary position which did not provide good correlation. */
+ if (!autotrack_result->success) {
+ autotrack_result->libmv_marker = *libmv_current_marker;
+ autotrack_result->libmv_marker.frame = new_marker_frame;
}
- else {
- track_options->is_failed = true;
- track_options->failed_frame = frame + frame_delta;
+
+ BLI_addtail(&autotrack_tls->results, autotrack_result);
+}
+
+static void autotrack_context_reduce(const void *__restrict UNUSED(userdata),
+ void *__restrict chunk_join,
+ void *__restrict chunk)
+{
+ AutoTrackTLS *autotrack_tls = (AutoTrackTLS *)chunk;
+ if (BLI_listbase_is_empty(&autotrack_tls->results)) {
+ /* Nothing to be joined from. */
+ return;
}
- /* Note: Atomic is probably not actually needed here, I doubt we could get
- * any other result than a true bool anyway.
- * But for sake of consistency, and since it costs nothing...
- */
- atomic_fetch_and_or_uint8((uint8_t *)&context->step_ok, true);
+ AutoTrackTLS *autotrack_tls_join = (AutoTrackTLS *)chunk_join;
+ BLI_movelisttolist(&autotrack_tls_join->results, &autotrack_tls->results);
}
bool BKE_autotrack_context_step(AutoTrackContext *context)
{
- const int frame_delta = context->is_backwards ? -1 : 1;
- context->step_ok = false;
+ if (context->num_autotrack_markers == 0) {
+ return false;
+ }
+
+ AutoTrackTLS tls;
+ BLI_listbase_clear(&tls.results);
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (context->num_track_options > 1);
+ settings.use_threading = (context->num_autotrack_markers > 1);
+ settings.userdata_chunk = &tls;
+ settings.userdata_chunk_size = sizeof(AutoTrackTLS);
+ settings.func_reduce = autotrack_context_reduce;
+
BLI_task_parallel_range(
- 0, context->num_track_options, context, autotrack_context_step_cb, &settings);
+ 0, context->num_autotrack_markers, context, autotrack_context_step_cb, &settings);
+
+ /* Prepare next tracking step by updating the AutoTrack context with new markers and moving
+ * tracked markers as an input for the next iteration. */
+ context->num_autotrack_markers = 0;
+ LISTBASE_FOREACH (AutoTrackTrackingResult *, autotrack_result, &tls.results) {
+ if (!autotrack_result->success) {
+ continue;
+ }
+
+ /* Insert tracking results to the AutoTrack context to make them usable for the next frame
+ * tracking iteration. */
+ libmv_autoTrackAddMarker(context->autotrack, &autotrack_result->libmv_marker);
+
+ /* Update the list of markers which will be tracked on the next iteration. */
+ context->autotrack_markers[context->num_autotrack_markers++].libmv_marker =
+ autotrack_result->libmv_marker;
+ }
- /* Advance the frame. */
BLI_spin_lock(&context->spin_lock);
- context->current_scene_frame += frame_delta;
+ BLI_movelisttolist(&context->results_to_sync, &tls.results);
BLI_spin_unlock(&context->spin_lock);
- return context->step_ok;
+
+ return true;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Context data synchronization.
+ *
+ * Used to copy trackign result to Blender side, while the trackign is still happening in its
+ * thread.
+ *
+ * \{ */
+
void BKE_autotrack_context_sync(AutoTrackContext *context)
{
- int newframe, frame_delta = context->is_backwards ? -1 : 1;
+ const int frame_delta = context->is_backwards ? -1 : 1;
BLI_spin_lock(&context->spin_lock);
- newframe = context->current_scene_frame;
- for (int frame = context->sync_frame;
- frame != (context->is_backwards ? newframe - 1 : newframe + 1);
- frame += frame_delta) {
+ ListBase results_to_sync = context->results_to_sync;
+ BLI_listbase_clear(&context->results_to_sync);
+ BLI_spin_unlock(&context->spin_lock);
+
+ LISTBASE_FOREACH_MUTABLE (AutoTrackTrackingResult *, autotrack_result, &results_to_sync) {
+ const libmv_Marker *libmv_marker = &autotrack_result->libmv_marker;
+ const int clip_index = libmv_marker->clip;
+ const int track_index = libmv_marker->track;
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
+ const MovieClip *clip = autotrack_clip->clip;
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ MovieTrackingTrack *track = autotrack_track->track;
+
+ const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
+ clip, context->start_scene_frame);
+ const int first_result_frame = start_clip_frame + frame_delta;
+
+ /* Insert marker which corresponds to the tracking result. */
MovieTrackingMarker marker;
- libmv_Marker libmv_marker;
- int clip = 0;
- for (int i = 0; i < context->num_track_options; i++) {
- AutoTrackOptions *track_options = &context->track_options[i];
- MovieTrackingTrack *track = track_options->track;
- const int clip_index = track_options->clip_index;
- const int track_index = track_options->track_index;
- const int track_frame = BKE_movieclip_remap_scene_to_clip_frame(context->clips[clip_index],
- frame);
- if (track_options->is_failed) {
- if (track_options->failed_frame == track_frame) {
- MovieTrackingMarker *prev_marker = BKE_tracking_marker_get_exact(
- track, context->is_backwards ? frame + 1 : frame - 1);
- if (prev_marker) {
- marker = *prev_marker;
- marker.framenr = track_frame;
- marker.flag |= MARKER_DISABLED;
- BKE_tracking_marker_insert(track, &marker);
- continue;
- }
- }
- if ((context->is_backwards && track_options->failed_frame > track_frame) ||
- (!context->is_backwards && track_options->failed_frame < track_frame)) {
- continue;
- }
- }
- if (libmv_autoTrackGetMarker(
- context->autotrack, clip, track_frame, track_index, &libmv_marker)) {
- libmv_marker_to_dna_marker(
- &libmv_marker, context->frame_width, context->frame_height, &marker);
- if (context->first_sync && frame == context->sync_frame) {
- tracking_marker_insert_disabled(track, &marker, !context->is_backwards, false);
- }
- BKE_tracking_marker_insert(track, &marker);
- tracking_marker_insert_disabled(track, &marker, context->is_backwards, false);
- }
+ libmv_marker_to_dna_marker(
+ &autotrack_result->libmv_marker, autotrack_clip->width, autotrack_clip->height, &marker);
+ if (!autotrack_result->success) {
+ marker.flag |= MARKER_DISABLED;
}
+ BKE_tracking_marker_insert(track, &marker);
+
+ /* Insetr disabled marker at the end of tracked segment.
+ * When tracking forward the disabled marker is added at the next frame from the result,
+ * when tracking backwards the marker is added at the previous frame. */
+ tracking_marker_insert_disabled(track, &marker, context->is_backwards, false);
+
+ if (marker.framenr == first_result_frame) {
+ MovieTrackingMarker *prev_marker = BKE_tracking_marker_get_exact(
+ track, marker.framenr - frame_delta);
+ BLI_assert(prev_marker != NULL);
+
+ tracking_marker_insert_disabled(track, prev_marker, !context->is_backwards, false);
+ }
+
+ /* Update synchronized frame to the latest tracked fame from the current results. */
+ const int marker_scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, marker.framenr);
+ if (context->is_backwards) {
+ context->synchronized_scene_frame = min_ii(context->synchronized_scene_frame,
+ marker_scene_frame);
+ }
+ else {
+ context->synchronized_scene_frame = max_ii(context->synchronized_scene_frame,
+ marker_scene_frame);
+ }
+
+ MEM_freeN(autotrack_result);
}
- BLI_spin_unlock(&context->spin_lock);
- for (int clip = 0; clip < context->num_clips; clip++) {
- MovieTracking *tracking = &context->clips[clip]->tracking;
+ for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
+ MovieTracking *tracking = &context->autotrack_clips[clip_index].clip->tracking;
BKE_tracking_dopesheet_tag_update(tracking);
}
-
- context->sync_frame = newframe;
- context->first_sync = false;
}
/* TODO(sergey): Find a way to avoid this, somehow making all needed logic in
* BKE_autotrack_context_sync(). */
void BKE_autotrack_context_sync_user(AutoTrackContext *context, MovieClipUser *user)
{
- user->framenr = context->sync_frame;
+ user->framenr = context->synchronized_scene_frame;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Finalization.
+ * \{ */
+
void BKE_autotrack_context_finish(AutoTrackContext *context)
{
for (int clip_index = 0; clip_index < context->num_clips; clip_index++) {
- MovieClip *clip = context->clips[clip_index];
+ const AutoTrackClip *autotrack_clip = &context->autotrack_clips[clip_index];
+ MovieClip *clip = autotrack_clip->clip;
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
const int start_clip_frame = BKE_movieclip_remap_scene_to_clip_frame(
clip, context->start_scene_frame);
@@ -570,9 +797,12 @@ void BKE_autotrack_context_finish(AutoTrackContext *context)
if ((plane_track->flag & PLANE_TRACK_AUTOKEY)) {
continue;
}
- for (int i = 0; i < context->num_track_options; i++) {
- const AutoTrackOptions *track_options = &context->track_options[i];
- MovieTrackingTrack *track = track_options->track;
+ for (int track_index = 0; track_index < context->num_all_tracks; track_index++) {
+ const AutoTrackTrack *autotrack_track = &context->all_autotrack_tracks[track_index];
+ if (!autotrack_track->is_trackable) {
+ continue;
+ }
+ MovieTrackingTrack *track = autotrack_track->track;
if (BKE_tracking_plane_track_has_point_track(plane_track, track)) {
BKE_tracking_track_plane_from_existing_motion(plane_track, start_clip_frame);
break;
@@ -584,10 +814,22 @@ void BKE_autotrack_context_finish(AutoTrackContext *context)
void BKE_autotrack_context_free(AutoTrackContext *context)
{
- libmv_autoTrackDestroy(context->autotrack);
- tracking_image_accessor_destroy(context->image_accessor);
- MEM_freeN(context->track_options);
- MEM_freeN(context->all_tracks);
+ if (context->autotrack != NULL) {
+ libmv_autoTrackDestroy(context->autotrack);
+ }
+
+ if (context->image_accessor != NULL) {
+ tracking_image_accessor_destroy(context->image_accessor);
+ }
+
+ MEM_SAFE_FREE(context->all_autotrack_tracks);
+ MEM_SAFE_FREE(context->autotrack_markers);
+
+ BLI_freelistN(&context->results_to_sync);
+
BLI_spin_end(&context->spin_lock);
+
MEM_freeN(context);
}
+
+/** \} */
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 7160d4fa41a..9278ff51b8d 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -1204,6 +1204,18 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
+ if (md->type == eModifierType_WeightVGProximity) {
+ WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
+ if (wmd->cmap_curve == NULL) {
+ wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
+ BKE_curvemapping_init(wmd->cmap_curve);
+ }
+ }
+ }
+ }
+
/* Hair and PointCloud attributes names. */
LISTBASE_FOREACH (Hair *, hair, &bmain->hairs) {
do_versions_point_attribute_names(&hair->pdata);
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index 1f95eec4486..cbd2589f20f 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -1910,7 +1910,7 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
edbo_compute_bbone_child(arm);
- for (eBone = arm->edbo->first, index = ob->runtime.select_id; eBone;
+ for (eBone = arm->edbo->first, index = ob_orig->runtime.select_id; eBone;
eBone = eBone->next, index += 0x10000) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
@@ -2005,7 +2005,8 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
DRW_state_is_select();
if (is_pose_select) {
- index = ob->runtime.select_id;
+ const Object *ob_orig = DEG_get_original_object(ob);
+ index = ob_orig->runtime.select_id;
}
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index 24943ab5318..f7caf8e4c6a 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -78,11 +78,21 @@ typedef struct SnapGizmo3D {
} SnapGizmo3D;
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
-static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm, const wmEvent *event)
+static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
{
- wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap);
+ if (!wm || !wm->winactive) {
+ return false;
+ }
+ if (snap_gizmo->keymap == NULL) {
+ /* Lazy initialization. */
+ snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
+ RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on);
+ }
const int snap_on = snap_gizmo->snap_on;
+
+ wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap);
+ const wmEvent *event = wm->winactive->eventstate;
for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
if (kmi->flag & KMI_INACTIVE) {
continue;
@@ -254,9 +264,7 @@ short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
}
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- if (wm && wm->winactive) {
- snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm, wm->winactive->eventstate);
- }
+ snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm);
if (snap_gizmo->use_snap_override == -1) {
const ToolSettings *ts = scene->toolsettings;
@@ -413,13 +421,7 @@ static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
wmWindowManager *wm = CTX_wm_manager(C);
- if (snap_gizmo->keymap == NULL) {
- snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
- RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on);
- }
-
- const bool invert = wm->winactive ? invert_snap(snap_gizmo, wm, wm->winactive->eventstate) :
- false;
+ const bool invert = invert_snap(snap_gizmo, wm);
if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] &&
snap_gizmo->mval[1] == mval[1]) {
/* Performance, do not update. */
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index d7ed3dca1b1..6467df0e87b 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1139,6 +1139,9 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
if (use_topology) {
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
+ if (respecthide && BM_elem_flag_test(v_mirr, BM_ELEM_HIDDEN)) {
+ v_mirr = NULL;
+ }
}
else {
int i_mirr;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 1ddfa0b9b17..b9427677745 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4025,13 +4025,13 @@ void SCULPT_flip_v3_by_symm_area(float v[3],
const ePaintSymmetryAreas symmarea,
const float pivot[3])
{
- for (char i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
ePaintSymmetryFlags symm_it = 1 << i;
if (symm & symm_it) {
if (symmarea & symm_it) {
flip_v3(v, symm_it);
}
- if (pivot[0] < 0) {
+ if (pivot[i] < 0.0f) {
flip_v3(v, symm_it);
}
}
@@ -4043,13 +4043,13 @@ void SCULPT_flip_quat_by_symm_area(float quat[3],
const ePaintSymmetryAreas symmarea,
const float pivot[3])
{
- for (char i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; i++) {
ePaintSymmetryFlags symm_it = 1 << i;
if (symm & symm_it) {
if (symmarea & symm_it) {
flip_qt(quat, symm_it);
}
- if (pivot[0] < 0) {
+ if (pivot[i] < 0.0f) {
flip_qt(quat, symm_it);
}
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 749e61955d9..9a36c88f6d1 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -659,7 +659,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
/* Draw Meta data of the image isn't added to the DrawManager as it is
* used in other areas as well. */
- if (sima->flag & SI_DRAW_METADATA) {
+ if (sima->overlay.flag & SI_OVERLAY_SHOW_OVERLAYS && sima->flag & SI_DRAW_METADATA) {
void *lock;
/* `ED_space_image_get_zoom` temporarily locks the image, so this needs to be done before
* the image is locked when calling `ED_space_image_acquire_buffer`. */
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index bf21b383ba6..890bb8a64bc 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -55,6 +55,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_pbvh.h"
#include "BKE_scene.h"
#include "BKE_subdiv_ccg.h"
@@ -69,9 +70,9 @@
#define MAX_INFO_NUM_LEN 16
typedef struct SceneStats {
- uint64_t totvert, totvertsel;
+ uint64_t totvert, totvertsel, totvertsculpt;
uint64_t totedge, totedgesel;
- uint64_t totface, totfacesel;
+ uint64_t totface, totfacesel, totfacesculpt;
uint64_t totbone, totbonesel;
uint64_t totobj, totobjsel;
uint64_t totlamp, totlampsel;
@@ -81,9 +82,9 @@ typedef struct SceneStats {
typedef struct SceneStatsFmt {
/* Totals */
- char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN];
+ char totvert[MAX_INFO_NUM_LEN], totvertsel[MAX_INFO_NUM_LEN], totvertsculpt[MAX_INFO_NUM_LEN];
char totface[MAX_INFO_NUM_LEN], totfacesel[MAX_INFO_NUM_LEN];
- char totedge[MAX_INFO_NUM_LEN], totedgesel[MAX_INFO_NUM_LEN];
+ char totedge[MAX_INFO_NUM_LEN], totedgesel[MAX_INFO_NUM_LEN], totfacesculpt[MAX_INFO_NUM_LEN];
char totbone[MAX_INFO_NUM_LEN], totbonesel[MAX_INFO_NUM_LEN];
char totobj[MAX_INFO_NUM_LEN], totobjsel[MAX_INFO_NUM_LEN];
char totlamp[MAX_INFO_NUM_LEN], totlampsel[MAX_INFO_NUM_LEN];
@@ -350,15 +351,38 @@ static void stats_object_pose(Object *ob, SceneStats *stats)
}
}
-static void stats_object_sculpt_dynamic_topology(Object *ob, SceneStats *stats)
+static bool stats_is_object_dynamic_topology_sculpt(Object *ob)
{
- stats->totvert = ob->sculpt->bm->totvert;
- stats->tottri = ob->sculpt->bm->totface;
+ if (ob == NULL) {
+ return false;
+ }
+ const eObjectMode object_mode = ob->mode;
+ return ((object_mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->bm);
}
-static bool stats_is_object_dynamic_topology_sculpt(Object *ob, const eObjectMode object_mode)
+static void stats_object_sculpt(Object *ob, SceneStats *stats)
{
- return (ob && (object_mode & OB_MODE_SCULPT) && ob->sculpt && ob->sculpt->bm);
+
+ SculptSession *ss = ob->sculpt;
+
+ if (!ss) {
+ return;
+ }
+
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ stats->totvertsculpt = ss->totvert;
+ stats->totfacesculpt = ss->totfaces;
+ break;
+ case PBVH_BMESH:
+ stats->totvertsculpt = ob->sculpt->bm->totvert;
+ stats->tottri = ob->sculpt->bm->totface;
+ break;
+ case PBVH_GRIDS:
+ stats->totvertsculpt = BKE_pbvh_get_grid_num_vertices(ss->pbvh);
+ stats->totfacesculpt = BKE_pbvh_get_grid_num_faces(ss->pbvh);
+ break;
+ }
}
/* Statistics displayed in info header. Called regularly on scene changes. */
@@ -385,9 +409,9 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
/* Pose Mode */
stats_object_pose(ob, &stats);
}
- else if (ob && stats_is_object_dynamic_topology_sculpt(ob, ob->mode)) {
- /* Dynamic-topology sculpt mode */
- stats_object_sculpt_dynamic_topology(ob, &stats);
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ /* Dynamic topology. Do not count all vertices, dynamic topology stats are initialized later as
+ * part of sculpt stats. */
}
else {
/* Objects */
@@ -399,6 +423,12 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer)
BLI_gset_free(objects_gset, NULL);
}
+ if (ob && (ob->mode & OB_MODE_SCULPT)) {
+ /* Sculpt Mode. When dynamic topology is not enabled both sculpt stats and scene stats are
+ * collected. */
+ stats_object_sculpt(ob, &stats);
+ }
+
if (!view_layer->stats) {
view_layer->stats = MEM_callocN(sizeof(SceneStats), "SceneStats");
}
@@ -437,12 +467,14 @@ static bool format_stats(Main *bmain,
SCENE_STATS_FMT_INT(totvert);
SCENE_STATS_FMT_INT(totvertsel);
+ SCENE_STATS_FMT_INT(totvertsculpt);
SCENE_STATS_FMT_INT(totedge);
SCENE_STATS_FMT_INT(totedgesel);
SCENE_STATS_FMT_INT(totface);
SCENE_STATS_FMT_INT(totfacesel);
+ SCENE_STATS_FMT_INT(totfacesculpt);
SCENE_STATS_FMT_INT(totbone);
SCENE_STATS_FMT_INT(totbonesel);
@@ -527,7 +559,7 @@ static void get_stats_string(
stats_fmt->totgpstroke,
stats_fmt->totgppoint);
}
- else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
+ else if (stats_is_object_dynamic_topology_sculpt(ob)) {
*ofs += BLI_snprintf(info + *ofs,
len - *ofs,
TIP_("Verts:%s | Tris:%s"),
@@ -727,9 +759,15 @@ void ED_info_draw_stats(
stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height);
stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height);
}
- else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) {
- stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
- stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
+ else if (ob && (object_mode & OB_MODE_SCULPT)) {
+ if (stats_is_object_dynamic_topology_sculpt(ob)) {
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, NULL, y, height);
+ stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height);
+ }
+ else {
+ stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsculpt, stats_fmt.totvert, y, height);
+ stats_row(col1, labels[FACES], col2, stats_fmt.totfacesculpt, stats_fmt.totface, y, height);
+ }
}
else {
stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height);
diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c
index af0a8e5e505..a4d999b868d 100644
--- a/source/blender/editors/transform/transform_mode.c
+++ b/source/blender/editors/transform/transform_mode.c
@@ -228,7 +228,7 @@ static void protectedAxisAngleBits(
}
}
-static void protectedSizeBits(short protectflag, float size[3])
+void protectedSizeBits(short protectflag, float size[3])
{
if (protectflag & OB_LOCK_SCALEX) {
size[0] = 1.0f;
@@ -431,7 +431,7 @@ static void constraintRotLim(TransInfo *UNUSED(t), TransData *td)
}
}
-static void constraintSizeLim(TransInfo *t, TransData *td)
+void constraintSizeLim(TransInfo *t, TransData *td)
{
if (td->con && td->ext) {
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT);
diff --git a/source/blender/editors/transform/transform_mode.h b/source/blender/editors/transform/transform_mode.h
index df7d10d1028..7a05506e12c 100644
--- a/source/blender/editors/transform/transform_mode.h
+++ b/source/blender/editors/transform/transform_mode.h
@@ -44,7 +44,9 @@ int transform_mode_really_used(struct bContext *C, int mode);
bool transdata_check_local_center(TransInfo *t, short around);
bool transform_mode_is_changeable(const int mode);
void protectedTransBits(short protectflag, float vec[3]);
+void protectedSizeBits(short protectflag, float size[3]);
void constraintTransLim(TransInfo *t, TransData *td);
+void constraintSizeLim(TransInfo *t, TransData *td);
void postInputRotation(TransInfo *t, float values[3]);
void headerRotation(TransInfo *t, char *str, float final);
void ElementRotation_ex(TransInfo *t,
diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c
index 1440553de51..3aa99975fda 100644
--- a/source/blender/editors/transform/transform_mode_mirror.c
+++ b/source/blender/editors/transform/transform_mode_mirror.c
@@ -24,8 +24,10 @@
#include <stdlib.h>
#include "BLI_math.h"
+#include "BLI_math_bits.h"
#include "BLI_string.h"
+#include "BKE_armature.h"
#include "BKE_context.h"
#include "ED_screen.h"
@@ -41,9 +43,130 @@
/** \name Transform (Mirror)
* \{ */
+/**
+ * Mirrors an object by negating the scale of the object on the mirror axis, reflecting the
+ * location and adjusting the rotation.
+ *
+ * \param axis: Either the axis to mirror on (0 = x, 1 = y, 2 = z) in transform space or -1 for no
+ * axis mirror.
+ * \param flip: If true, a mirror on all axis will be performed additionally (point
+ * reflection).
+ */
+static void ElementMirror(TransInfo *t, TransDataContainer *tc, TransData *td, int axis, bool flip)
+{
+ if ((t->flag & T_V3D_ALIGN) == 0 && td->ext) {
+ /* Size checked needed since the 3D cursor only uses rotation fields. */
+ if (td->ext->size) {
+ float fsize[] = {1.0, 1.0, 1.0};
+
+ if (axis >= 0) {
+ fsize[axis] = -fsize[axis];
+ }
+ if (flip) {
+ negate_v3(fsize);
+ }
+
+ protectedSizeBits(td->protectflag, fsize);
+
+ mul_v3_v3v3(td->ext->size, td->ext->isize, fsize);
+
+ constraintSizeLim(t, td);
+ }
+
+ float rmat[3][3];
+ if (axis >= 0) {
+ float imat[3][3];
+ mul_m3_m3m3(rmat, t->spacemtx_inv, td->axismtx);
+ rmat[axis][0] = -rmat[axis][0];
+ rmat[axis][1] = -rmat[axis][1];
+ rmat[axis][2] = -rmat[axis][2];
+ rmat[0][axis] = -rmat[0][axis];
+ rmat[1][axis] = -rmat[1][axis];
+ rmat[2][axis] = -rmat[2][axis];
+ invert_m3_m3(imat, td->axismtx);
+ mul_m3_m3m3(rmat, rmat, imat);
+ mul_m3_m3m3(rmat, t->spacemtx, rmat);
+
+ ElementRotation_ex(t, tc, td, rmat, td->center);
+
+ if (td->ext->rotAngle) {
+ *td->ext->rotAngle = -td->ext->irotAngle;
+ }
+ }
+ else {
+ unit_m3(rmat);
+ ElementRotation_ex(t, tc, td, rmat, td->center);
+
+ if (td->ext->rotAngle) {
+ *td->ext->rotAngle = td->ext->irotAngle;
+ }
+ }
+ }
+
+ if ((td->flag & TD_NO_LOC) == 0) {
+ float center[3], vec[3];
+
+ /* Local constraint shouldn't alter center. */
+ if (transdata_check_local_center(t, t->around)) {
+ copy_v3_v3(center, td->center);
+ }
+ else if (t->options & CTX_MOVIECLIP) {
+ if (td->flag & TD_INDIVIDUAL_SCALE) {
+ copy_v3_v3(center, td->center);
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+ }
+ else {
+ copy_v3_v3(center, tc->center_local);
+ }
+
+ /* For individual element center, Editmode need to use iloc. */
+ if (t->flag & T_POINTS) {
+ sub_v3_v3v3(vec, td->iloc, center);
+ }
+ else {
+ sub_v3_v3v3(vec, td->center, center);
+ }
+
+ if (axis >= 0) {
+ /* Always do the mirror in global space. */
+ if (t->flag & T_EDIT) {
+ mul_m3_v3(td->mtx, vec);
+ }
+ reflect_v3_v3v3(vec, vec, t->spacemtx[axis]);
+ if (t->flag & T_EDIT) {
+ mul_m3_v3(td->smtx, vec);
+ }
+ }
+ if (flip) {
+ negate_v3(vec);
+ }
+
+ add_v3_v3(vec, center);
+ if (t->flag & T_POINTS) {
+ sub_v3_v3(vec, td->iloc);
+ }
+ else {
+ sub_v3_v3(vec, td->center);
+ }
+
+ if (t->flag & (T_OBJECT | T_POSE)) {
+ mul_m3_v3(td->smtx, vec);
+ }
+
+ protectedTransBits(td->protectflag, vec);
+ if (td->loc) {
+ add_v3_v3v3(td->loc, td->iloc, vec);
+ }
+
+ constraintTransLim(t, td);
+ }
+}
+
static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
{
- float size[3], mat[3][3];
int i;
char str[UI_MAX_DRAW_STR];
copy_v3_v3(t->values_final, t->values);
@@ -54,12 +177,16 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
/* if an axis has been selected */
if (t->con.mode & CON_APPLY) {
- size[0] = size[1] = size[2] = -1;
-
- size_to_mat3(mat, size);
-
- if (t->con.applySize) {
- t->con.applySize(t, NULL, NULL, mat);
+ /* #special_axis is either the constraint plane normal or the constraint axis.
+ * Assuming that CON_AXIS0 < CON_AXIS1 < CON_AXIS2 and CON_AXIS2 is CON_AXIS0 << 2 */
+ BLI_assert(CON_AXIS2 == CON_AXIS0 << 2);
+ int axis_bitmap = (t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2)) / CON_AXIS0;
+ int special_axis_bitmap = 0;
+ int special_axis = -1;
+ int bitmap_len = count_bits_i(axis_bitmap);
+ if (LIKELY(!ELEM(bitmap_len, 0, 3))) {
+ special_axis_bitmap = (bitmap_len == 2) ? ~axis_bitmap : axis_bitmap;
+ special_axis = bitscan_forward_i(special_axis_bitmap);
}
BLI_snprintf(str, sizeof(str), TIP_("Mirror%s"), t->con.text);
@@ -71,7 +198,7 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
continue;
}
- ElementResize(t, tc, td, mat);
+ ElementMirror(t, tc, td, special_axis, bitmap_len >= 2);
}
}
@@ -80,10 +207,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
ED_area_status_text(t->area, str);
}
else {
- size[0] = size[1] = size[2] = 1;
-
- size_to_mat3(mat, size);
-
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
@@ -91,7 +214,7 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
continue;
}
- ElementResize(t, tc, td, mat);
+ ElementMirror(t, tc, td, -1, false);
}
}
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index aeb34e34d97..7282c35ea0f 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -1040,8 +1040,7 @@ static void TRANSFORM_OT_mirror(struct wmOperatorType *ot)
ot->poll = ED_operator_screenactive;
ot->poll_property = transform_poll_property;
- Transform_Properties(
- ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_GPENCIL_EDIT | P_CENTER);
+ Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_GPENCIL_EDIT | P_CENTER);
}
static void TRANSFORM_OT_bbone_resize(struct wmOperatorType *ot)
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index b444bd1859d..7e948149a7f 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -130,6 +130,32 @@ void GLBackend::platform_init()
GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
}
}
+
+ /* Since Blender 2.91 AMD TeraScale 2 GPUs crashes during startup. */
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) {
+ if (strstr(renderer, "Radeon HD 4") || strstr(renderer, "Radeon HD 5") ||
+ strstr(renderer, "Radeon HD 6") || strstr(renderer, "ATI FirePro V4") ||
+ strstr(renderer, "AMD Radeon R5 2")) {
+ GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED;
+ }
+ }
+ /* Driver 20.11.2 fixes a lot of issues for the Navi cards, but introduces new ones
+ * for Polaris based cards cards. The viewport has glitches but doesn't crash.
+ * See T82856 */
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_OFFICIAL) &&
+ strstr(version, " 20.11.2 ")) {
+ if (strstr(renderer, "Radeon RX 460 ") || strstr(renderer, "Radeon RX 470 ") ||
+ strstr(renderer, "Radeon RX 480 ") || strstr(renderer, "Radeon RX 490 ") ||
+ strstr(renderer, "Radeon RX 560 ") || strstr(renderer, "Radeon RX 570 ") ||
+ strstr(renderer, "Radeon RX 580 ") || strstr(renderer, "Radeon RX 590 ")) {
+ GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
+ }
+ }
+ if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
+ if (strstr(renderer, "AMD CEDAR")) {
+ GPG.support_level = GPU_SUPPORT_LEVEL_UNSUPPORTED;
+ }
+ }
}
GPG.create_key(GPG.support_level, vendor, renderer, version);
GPG.create_gpu_name(vendor, renderer, version);
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 14394509e49..edb0a4439d6 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -1588,6 +1588,10 @@ typedef struct WeightVGProximityModifierData {
/** Name of vertex group to modify/weight. MAX_VGROUP_NAME. */
char defgrp_name[64];
+
+ /* Mapping stuff. */
+ /** The custom mapping curve!. */
+ struct CurveMapping *cmap_curve;
/* Proximity modes. */
int proximity_mode;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 736edc61d74..1e5309e5869 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -786,10 +786,6 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
{
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
- static const EnumPropertyItem prop_default_items[] = {
- {0, NULL, 0, NULL, NULL},
- };
-
/* sculpt mode */
static const EnumPropertyItem prop_flatten_contrast_items[] = {
{BRUSH_DIR_IN, "CONTRAST", ICON_ADD, "Contrast", "Subtract effect of brush"},
@@ -849,10 +845,10 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
return prop_direction_items;
case BRUSH_MASK_SMOOTH:
- return prop_default_items;
+ return DummyRNA_DEFAULT_items;
default:
- return prop_default_items;
+ return DummyRNA_DEFAULT_items;
}
case SCULPT_TOOL_FLATTEN:
@@ -871,7 +867,7 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
return prop_inflate_deflate_items;
default:
- return prop_default_items;
+ return DummyRNA_DEFAULT_items;
}
case PAINT_MODE_TEXTURE_2D:
@@ -881,11 +877,11 @@ static const EnumPropertyItem *rna_Brush_direction_itemf(bContext *C,
return prop_soften_sharpen_items;
default:
- return prop_default_items;
+ return DummyRNA_DEFAULT_items;
}
default:
- return prop_default_items;
+ return DummyRNA_DEFAULT_items;
}
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 47d9c811609..31e920a6799 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -421,7 +421,7 @@ void RNA_api_space_node(struct StructRNA *srna);
void RNA_api_space_text(struct StructRNA *srna);
void RNA_api_region_view3d(struct StructRNA *srna);
void RNA_api_texture(struct StructRNA *srna);
-void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop);
+void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastrip);
void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_api_sound(struct StructRNA *srna);
void RNA_api_vfont(struct StructRNA *srna);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index fb2692910c5..f0836ae59ad 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -5339,7 +5339,7 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
static const EnumPropertyItem weightvg_proximity_falloff_type_items[] = {
{MOD_WVG_MAPPING_NONE, "LINEAR", ICON_LINCURVE, "Linear", "Null action"},
- /* No curve mapping here! */
+ {MOD_WVG_MAPPING_CURVE, "CURVE", ICON_RNDCURVE, "Custom Curve", ""},
{MOD_WVG_MAPPING_SHARP, "SHARP", ICON_SHARPCURVE, "Sharp", ""},
{MOD_WVG_MAPPING_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
{MOD_WVG_MAPPING_ROOT, "ROOT", ICON_ROOTCURVE, "Root", ""},
@@ -5427,6 +5427,11 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
"Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "map_curve", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "cmap_curve");
+ RNA_def_property_ui_text(prop, "Mapping Curve", "Custom mapping curve");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
RNA_define_lib_overridable(false);
/* Common masking properties. */
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 2ffb9612486..ac45cd5c5ff 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -1967,7 +1967,7 @@ static void rna_def_editor(BlenderRNA *brna)
RNA_def_property_collection_sdna(prop, NULL, "seqbase", NULL);
RNA_def_property_struct_type(prop, "Sequence");
RNA_def_property_ui_text(prop, "Sequences", "Top-level strips only");
- RNA_api_sequences(brna, prop);
+ RNA_api_sequences(brna, prop, false);
prop = RNA_def_property(srna, "sequences_all", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "seqbase", NULL);
@@ -2339,7 +2339,8 @@ static void rna_def_meta(BlenderRNA *brna)
prop = RNA_def_property(srna, "sequences", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "seqbase", NULL);
RNA_def_property_struct_type(prop, "Sequence");
- RNA_def_property_ui_text(prop, "Sequences", "");
+ RNA_def_property_ui_text(prop, "Sequences", "Sequences nested in meta strip");
+ RNA_api_sequences(brna, prop, true);
rna_def_filter_video(srna);
rna_def_proxy(srna);
diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c
index 5419fc4ac7c..6f97098900e 100644
--- a/source/blender/makesrna/intern/rna_sequencer_api.c
+++ b/source/blender/makesrna/intern/rna_sequencer_api.c
@@ -77,15 +77,15 @@ static void rna_Sequence_swap_internal(Sequence *seq_self,
}
static Sequence *alloc_generic_sequence(
- Editing *ed, const char *name, int frame_start, int channel, int type, const char *file)
+ ListBase *seqbase, const char *name, int frame_start, int channel, int type, const char *file)
{
Sequence *seq;
StripElem *se;
- seq = BKE_sequence_alloc(ed->seqbasep, frame_start, channel, type);
+ seq = BKE_sequence_alloc(seqbase, frame_start, channel, type);
BLI_strncpy(seq->name + 2, name, sizeof(seq->name) - 2);
- BKE_sequence_base_unique_name_recursive(&ed->seqbase, seq);
+ BKE_sequence_base_unique_name_recursive(seqbase, seq);
Strip *strip = seq->strip;
@@ -105,7 +105,7 @@ static Sequence *alloc_generic_sequence(
}
static Sequence *rna_Sequences_new_clip(ID *id,
- Editing *ed,
+ ListBase *seqbase,
Main *bmain,
const char *name,
MovieClip *clip,
@@ -115,7 +115,8 @@ static Sequence *rna_Sequences_new_clip(ID *id,
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->filepath);
+ seq = alloc_generic_sequence(
+ seqbase, name, frame_start, channel, SEQ_TYPE_MOVIECLIP, clip->filepath);
seq->clip = clip;
seq->len = BKE_movieclip_get_duration(clip);
id_us_plus((ID *)clip);
@@ -129,13 +130,40 @@ static Sequence *rna_Sequences_new_clip(ID *id,
return seq;
}
-static Sequence *rna_Sequences_new_mask(
- ID *id, Editing *ed, Main *bmain, const char *name, Mask *mask, int channel, int frame_start)
+static Sequence *rna_Sequences_editing_new_clip(ID *id,
+ Editing *ed,
+ Main *bmain,
+ const char *name,
+ MovieClip *clip,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_clip(id, &ed->seqbase, bmain, name, clip, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_clip(ID *id,
+ Sequence *seq,
+ Main *bmain,
+ const char *name,
+ MovieClip *clip,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_clip(id, &seq->seqbase, bmain, name, clip, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_new_mask(ID *id,
+ ListBase *seqbase,
+ Main *bmain,
+ const char *name,
+ Mask *mask,
+ int channel,
+ int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name);
+ seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MASK, mask->id.name);
seq->mask = mask;
seq->len = BKE_mask_get_duration(mask);
id_us_plus((ID *)mask);
@@ -149,9 +177,20 @@ static Sequence *rna_Sequences_new_mask(
return seq;
}
+static Sequence *rna_Sequences_editing_new_mask(
+ ID *id, Editing *ed, Main *bmain, const char *name, Mask *mask, int channel, int frame_start)
+{
+ return rna_Sequences_new_mask(id, &ed->seqbase, bmain, name, mask, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_mask(
+ ID *id, Sequence *seq, Main *bmain, const char *name, Mask *mask, int channel, int frame_start)
+{
+ return rna_Sequences_new_mask(id, &seq->seqbase, bmain, name, mask, channel, frame_start);
+}
static Sequence *rna_Sequences_new_scene(ID *id,
- Editing *ed,
+ ListBase *seqbase,
Main *bmain,
const char *name,
Scene *sce_seq,
@@ -161,7 +200,7 @@ static Sequence *rna_Sequences_new_scene(ID *id,
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_SCENE, NULL);
+ seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_SCENE, NULL);
seq->scene = sce_seq;
seq->len = sce_seq->r.efra - sce_seq->r.sfra + 1;
id_us_plus((ID *)sce_seq);
@@ -176,8 +215,30 @@ static Sequence *rna_Sequences_new_scene(ID *id,
return seq;
}
+static Sequence *rna_Sequences_editing_new_scene(ID *id,
+ Editing *ed,
+ Main *bmain,
+ const char *name,
+ Scene *sce_seq,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_scene(id, &ed->seqbase, bmain, name, sce_seq, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_scene(ID *id,
+ Sequence *seq,
+ Main *bmain,
+ const char *name,
+ Scene *sce_seq,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_scene(id, &seq->seqbase, bmain, name, sce_seq, channel, frame_start);
+}
+
static Sequence *rna_Sequences_new_image(ID *id,
- Editing *ed,
+ ListBase *seqbase,
Main *bmain,
ReportList *reports,
const char *name,
@@ -188,12 +249,12 @@ static Sequence *rna_Sequences_new_image(ID *id,
Scene *scene = (Scene *)id;
Sequence *seq;
- seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_IMAGE, file);
+ seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_IMAGE, file);
seq->len = 1;
if (seq->strip->stripdata->name[0] == '\0') {
BKE_report(reports, RPT_ERROR, "Sequences.new_image: unable to open image file");
- BLI_remlink(&ed->seqbase, seq);
+ BLI_remlink(seqbase, seq);
BKE_sequence_free(scene, seq, true);
return NULL;
}
@@ -208,14 +269,40 @@ static Sequence *rna_Sequences_new_image(ID *id,
return seq;
}
+static Sequence *rna_Sequences_editing_new_image(ID *id,
+ Editing *ed,
+ Main *bmain,
+ ReportList *reports,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_image(
+ id, &ed->seqbase, bmain, reports, name, file, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_image(ID *id,
+ Sequence *seq,
+ Main *bmain,
+ ReportList *reports,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_image(
+ id, &seq->seqbase, bmain, reports, name, file, channel, frame_start);
+}
+
static Sequence *rna_Sequences_new_movie(
- ID *id, Editing *ed, const char *name, const char *file, int channel, int frame_start)
+ ID *id, ListBase *seqbase, const char *name, const char *file, int channel, int frame_start)
{
Scene *scene = (Scene *)id;
Sequence *seq;
StripAnim *sanim;
- seq = alloc_generic_sequence(ed, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
+ seq = alloc_generic_sequence(seqbase, name, frame_start, channel, SEQ_TYPE_MOVIE, file);
struct anim *an = openanim(file, IB_rect, 0, NULL);
if (an == NULL) {
@@ -240,9 +327,21 @@ static Sequence *rna_Sequences_new_movie(
return seq;
}
+static Sequence *rna_Sequences_editing_new_movie(
+ ID *id, Editing *ed, const char *name, const char *file, int channel, int frame_start)
+{
+ return rna_Sequences_new_movie(id, &ed->seqbase, name, file, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_movie(
+ ID *id, Sequence *seq, const char *name, const char *file, int channel, int frame_start)
+{
+ return rna_Sequences_new_movie(id, &seq->seqbase, name, file, channel, frame_start);
+}
+
# ifdef WITH_AUDASPACE
static Sequence *rna_Sequences_new_sound(ID *id,
- Editing *ed,
+ ListBase *seqbase,
Main *bmain,
ReportList *reports,
const char *name,
@@ -262,7 +361,7 @@ static Sequence *rna_Sequences_new_sound(ID *id,
return NULL;
}
seq = alloc_generic_sequence(
- ed, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->filepath);
+ seqbase, name, frame_start, channel, SEQ_TYPE_SOUND_RAM, sound->filepath);
seq->sound = sound;
seq->len = ceil((double)info.length * FPS);
@@ -276,7 +375,7 @@ static Sequence *rna_Sequences_new_sound(ID *id,
}
# else /* WITH_AUDASPACE */
static Sequence *rna_Sequences_new_sound(ID *UNUSED(id),
- Editing *UNUSED(ed),
+ ListBase *UNUSED(seqbase),
Main *UNUSED(bmain),
ReportList *reports,
const char *UNUSED(name),
@@ -289,8 +388,34 @@ static Sequence *rna_Sequences_new_sound(ID *UNUSED(id),
}
# endif /* WITH_AUDASPACE */
+static Sequence *rna_Sequences_editing_new_sound(ID *id,
+ Editing *ed,
+ Main *bmain,
+ ReportList *reports,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_sound(
+ id, &ed->seqbase, bmain, reports, name, file, channel, frame_start);
+}
+
+static Sequence *rna_Sequences_meta_new_sound(ID *id,
+ Sequence *seq,
+ Main *bmain,
+ ReportList *reports,
+ const char *name,
+ const char *file,
+ int channel,
+ int frame_start)
+{
+ return rna_Sequences_new_sound(
+ id, &seq->seqbase, bmain, reports, name, file, channel, frame_start);
+}
+
static Sequence *rna_Sequences_new_effect(ID *id,
- Editing *ed,
+ ListBase *seqbase,
ReportList *reports,
const char *name,
int type,
@@ -340,7 +465,7 @@ static Sequence *rna_Sequences_new_effect(ID *id,
return NULL;
}
- seq = alloc_generic_sequence(ed, name, frame_start, channel, type, NULL);
+ seq = alloc_generic_sequence(seqbase, name, frame_start, channel, type, NULL);
sh = BKE_sequence_get_effect(seq);
@@ -367,20 +492,52 @@ static Sequence *rna_Sequences_new_effect(ID *id,
return seq;
}
+static Sequence *rna_Sequences_editing_new_effect(ID *id,
+ Editing *ed,
+ ReportList *reports,
+ const char *name,
+ int type,
+ int channel,
+ int frame_start,
+ int frame_end,
+ Sequence *seq1,
+ Sequence *seq2,
+ Sequence *seq3)
+{
+ return rna_Sequences_new_effect(
+ id, &ed->seqbase, reports, name, type, channel, frame_start, frame_end, seq1, seq2, seq3);
+}
+
+static Sequence *rna_Sequences_meta_new_effect(ID *id,
+ Sequence *seq,
+ ReportList *reports,
+ const char *name,
+ int type,
+ int channel,
+ int frame_start,
+ int frame_end,
+ Sequence *seq1,
+ Sequence *seq2,
+ Sequence *seq3)
+{
+ return rna_Sequences_new_effect(
+ id, &seq->seqbase, reports, name, type, channel, frame_start, frame_end, seq1, seq2, seq3);
+}
+
static void rna_Sequences_remove(
- ID *id, Editing *ed, Main *bmain, ReportList *reports, PointerRNA *seq_ptr)
+ ID *id, ListBase *seqbase, Main *bmain, ReportList *reports, PointerRNA *seq_ptr)
{
Sequence *seq = seq_ptr->data;
Scene *scene = (Scene *)id;
- if (BLI_findindex(&ed->seqbase, seq) == -1) {
+ if (BLI_findindex(seqbase, seq) == -1) {
BKE_reportf(
reports, RPT_ERROR, "Sequence '%s' not in scene '%s'", seq->name + 2, scene->id.name + 2);
return;
}
- BKE_sequencer_flag_for_removal(scene, &ed->seqbase, seq);
- BKE_sequencer_remove_flagged_sequences(scene, &ed->seqbase);
+ BKE_sequencer_flag_for_removal(scene, seqbase, seq);
+ BKE_sequencer_remove_flagged_sequences(scene, seqbase);
RNA_POINTER_INVALIDATE(seq_ptr);
DEG_relations_tag_update(bmain);
@@ -388,6 +545,18 @@ static void rna_Sequences_remove(
WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, scene);
}
+static void rna_Sequences_editing_remove(
+ ID *id, Editing *ed, Main *bmain, ReportList *reports, PointerRNA *seq_ptr)
+{
+ rna_Sequences_remove(id, &ed->seqbase, bmain, reports, seq_ptr);
+}
+
+static void rna_Sequences_meta_remove(
+ ID *id, Sequence *seq, Main *bmain, ReportList *reports, PointerRNA *seq_ptr)
+{
+ rna_Sequences_remove(id, &seq->seqbase, bmain, reports, seq_ptr);
+}
+
static StripElem *rna_SequenceElements_append(ID *id, Sequence *seq, const char *filename)
{
Scene *scene = (Scene *)id;
@@ -536,7 +705,7 @@ void RNA_api_sequence_elements(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
-void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
+void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop, const bool metastrip)
{
StructRNA *srna;
PropertyRNA *parm;
@@ -564,12 +733,38 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
{0, NULL, 0, NULL, NULL},
};
- RNA_def_property_srna(cprop, "Sequences");
- srna = RNA_def_struct(brna, "Sequences", NULL);
- RNA_def_struct_sdna(srna, "Editing");
+ const char *new_clip_func_name = "rna_Sequences_editing_new_clip";
+ const char *new_mask_func_name = "rna_Sequences_editing_new_mask";
+ const char *new_scene_func_name = "rna_Sequences_editing_new_scene";
+ const char *new_image_func_name = "rna_Sequences_editing_new_image";
+ const char *new_movie_func_name = "rna_Sequences_editing_new_movie";
+ const char *new_sound_func_name = "rna_Sequences_editing_new_sound";
+ const char *new_effect_func_name = "rna_Sequences_editing_new_effect";
+ const char *remove_func_name = "rna_Sequences_editing_remove";
+
+ if (metastrip) {
+ RNA_def_property_srna(cprop, "SequencesMeta");
+ srna = RNA_def_struct(brna, "SequencesMeta", NULL);
+ RNA_def_struct_sdna(srna, "Sequence");
+
+ new_clip_func_name = "rna_Sequences_meta_new_clip";
+ new_mask_func_name = "rna_Sequences_meta_new_mask";
+ new_scene_func_name = "rna_Sequences_meta_new_scene";
+ new_image_func_name = "rna_Sequences_meta_new_image";
+ new_movie_func_name = "rna_Sequences_meta_new_movie";
+ new_sound_func_name = "rna_Sequences_meta_new_sound";
+ new_effect_func_name = "rna_Sequences_meta_new_effect";
+ remove_func_name = "rna_Sequences_meta_remove";
+ }
+ else {
+ RNA_def_property_srna(cprop, "SequencesTopLevel");
+ srna = RNA_def_struct(brna, "SequencesTopLevel", NULL);
+ RNA_def_struct_sdna(srna, "Editing");
+ }
+
RNA_def_struct_ui_text(srna, "Sequences", "Collection of Sequences");
- func = RNA_def_function(srna, "new_clip", "rna_Sequences_new_clip");
+ func = RNA_def_function(srna, "new_clip", new_clip_func_name);
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new movie clip sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -593,7 +788,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_mask", "rna_Sequences_new_mask");
+ func = RNA_def_function(srna, "new_mask", new_mask_func_name);
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new mask sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -617,7 +812,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_scene", "rna_Sequences_new_scene");
+ func = RNA_def_function(srna, "new_scene", new_scene_func_name);
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new scene sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -641,7 +836,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_image", "rna_Sequences_new_image");
+ func = RNA_def_function(srna, "new_image", new_image_func_name);
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new image sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -665,7 +860,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_movie", "rna_Sequences_new_movie");
+ func = RNA_def_function(srna, "new_movie", new_movie_func_name);
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
RNA_def_function_ui_description(func, "Add a new movie sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -689,7 +884,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_sound", "rna_Sequences_new_sound");
+ func = RNA_def_function(srna, "new_sound", new_sound_func_name);
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Add a new sound sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -713,7 +908,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "new_effect", "rna_Sequences_new_effect");
+ func = RNA_def_function(srna, "new_effect", new_effect_func_name);
RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
RNA_def_function_ui_description(func, "Add a new effect sequence");
parm = RNA_def_string(func, "name", "Name", 0, "", "Name for the new sequence");
@@ -750,7 +945,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "New Sequence");
RNA_def_function_return(func, parm);
- func = RNA_def_function(srna, "remove", "rna_Sequences_remove");
+ func = RNA_def_function(srna, "remove", remove_func_name);
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_REPORTS | FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Remove a Sequence");
parm = RNA_def_pointer(func, "sequence", "Sequence", "", "Sequence to remove");
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index fd8084d933c..80c69398d15 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -985,7 +985,7 @@ static void panel_draw(const bContext *C, Panel *panel)
nullptr,
nullptr,
0,
- ICON_NONE,
+ false,
nullptr);
if (nmd->node_group != nullptr && nmd->settings.properties != nullptr) {
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 9b21c77268e..7232ffd3d9d 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -31,6 +31,7 @@
#include "BLT_translation.h"
+#include "DNA_color_types.h" /* CurveMapping. */
#include "DNA_defaults.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -39,6 +40,7 @@
#include "DNA_screen_types.h"
#include "BKE_bvhutils.h"
+#include "BKE_colortools.h" /* CurveMapping. */
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_customdata.h"
@@ -54,6 +56,8 @@
#include "UI_interface.h"
#include "UI_resources.h"
+#include "BLO_read_write.h"
+
#include "RNA_access.h"
#include "DEG_depsgraph_build.h"
@@ -258,7 +262,8 @@ static void do_map(Object *ob,
const float min_d,
const float max_d,
short mode,
- const bool do_invert_mapping)
+ const bool do_invert_mapping,
+ CurveMapping *cmap)
{
const float range_inv = 1.0f / (max_d - min_d); /* invert since multiplication is faster */
uint i = nidx;
@@ -294,7 +299,6 @@ static void do_map(Object *ob,
}
}
- BLI_assert(mode != MOD_WVG_MAPPING_CURVE);
if (do_invert_mapping || mode != MOD_WVG_MAPPING_NONE) {
RNG *rng = NULL;
@@ -302,7 +306,7 @@ static void do_map(Object *ob,
rng = BLI_rng_new_srandom(BLI_ghashutil_strhash(ob->id.name + 2));
}
- weightvg_do_map(nidx, weights, mode, do_invert_mapping, NULL, rng);
+ weightvg_do_map(nidx, weights, mode, do_invert_mapping, cmap, rng);
if (rng) {
BLI_rng_free(rng);
@@ -320,6 +324,25 @@ static void initData(ModifierData *md)
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(wmd, modifier));
MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WeightVGProximityModifierData), modifier);
+
+ wmd->cmap_curve = BKE_curvemapping_add(1, 0.0, 0.0, 1.0, 1.0);
+ BKE_curvemapping_init(wmd->cmap_curve);
+}
+
+static void freeData(ModifierData *md)
+{
+ WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
+ BKE_curvemapping_free(wmd->cmap_curve);
+}
+
+static void copyData(const ModifierData *md, ModifierData *target, const int flag)
+{
+ const WeightVGProximityModifierData *wmd = (const WeightVGProximityModifierData *)md;
+ WeightVGProximityModifierData *twmd = (WeightVGProximityModifierData *)target;
+
+ BKE_modifier_copydata_generic(md, target, flag);
+
+ twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve);
}
static void requiredDataMask(Object *UNUSED(ob),
@@ -587,7 +610,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
wmd->min_dist,
wmd->max_dist,
wmd->falloff_type,
- (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_FALLOFF) != 0);
+ (wmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_FALLOFF) != 0,
+ wmd->cmap_curve);
/* Do masking. */
struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
@@ -680,6 +704,9 @@ static void falloff_panel_draw(const bContext *UNUSED(C), Panel *panel)
sub = uiLayoutRow(row, true);
uiLayoutSetPropSep(sub, false);
uiItemR(row, ptr, "invert_falloff", 0, "", ICON_ARROW_LEFTRIGHT);
+ if (RNA_enum_get(ptr, "falloff_type") == MOD_WVG_MAPPING_CURVE) {
+ uiTemplateCurveMapping(layout, ptr, "map_curve", 0, false, false, false, false);
+ }
modifier_panel_end(layout, ptr);
}
@@ -703,6 +730,25 @@ static void panelRegister(ARegionType *region_type)
region_type, "influence", "Influence", NULL, influence_panel_draw, panel_type);
}
+static void blendWrite(BlendWriter *writer, const ModifierData *md)
+{
+ const WeightVGProximityModifierData *wmd = (const WeightVGProximityModifierData *)md;
+
+ if (wmd->cmap_curve) {
+ BKE_curvemapping_blend_write(writer, wmd->cmap_curve);
+ }
+}
+
+static void blendRead(BlendDataReader *reader, ModifierData *md)
+{
+ WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md;
+
+ BLO_read_data_address(reader, &wmd->cmap_curve);
+ if (wmd->cmap_curve) {
+ BKE_curvemapping_blend_read(reader, wmd->cmap_curve);
+ }
+}
+
ModifierTypeInfo modifierType_WeightVGProximity = {
/* name */ "VertexWeightProximity",
/* structName */ "WeightVGProximityModifierData",
@@ -713,7 +759,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview,
/* icon */ ICON_MOD_VERTEX_WEIGHT,
- /* copyData */ BKE_modifier_copydata_generic,
+ /* copyData */ copyData,
/* deformVerts */ NULL,
/* deformMatrices */ NULL,
@@ -726,7 +772,7 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* initData */ initData,
/* requiredDataMask */ requiredDataMask,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ dependsOnTime,
@@ -735,6 +781,6 @@ ModifierTypeInfo modifierType_WeightVGProximity = {
/* foreachTexLink */ foreachTexLink,
/* freeRuntimeData */ NULL,
/* panelRegister */ panelRegister,
- /* blendWrite */ NULL,
- /* blendRead */ NULL,
+ /* blendWrite */ blendWrite,
+ /* blendRead */ blendRead,
};
diff --git a/source/tools b/source/tools
-Subproject d7d7e9d41f7499aa4639f96c843156ff834385b
+Subproject 7011d02c292ac1c91a5c9cc1a075ea2727982ce