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:
authorHans Goudey <h.goudey@me.com>2022-01-19 18:37:46 +0300
committerHans Goudey <h.goudey@me.com>2022-01-19 18:37:46 +0300
commitcee7c8f56c869033d6db2149b352a3ccee98585f (patch)
tree1d3a30723b803b2406e8d5ab77c93f32e1ffb211
parent0c0ba3a2ee97d6dccc6609d0b7a759082722bac3 (diff)
parentf179637222d1432b09c3c23201e1b7b75215b11a (diff)
Merge branch 'master' into temp-geometry-nodes-extrude-mesh
-rw-r--r--intern/cycles/blender/output_driver.cpp4
-rw-r--r--intern/cycles/util/array.h18
-rw-r--r--source/blender/blenkernel/BKE_customdata.h8
-rw-r--r--source/blender/blenkernel/BKE_main.h7
-rw-r--r--source/blender/blenkernel/BKE_mesh.h8
-rw-r--r--source/blender/blenkernel/BKE_mesh_runtime.h4
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/customdata.cc34
-rw-r--r--source/blender/blenkernel/intern/mesh.cc2
-rw-r--r--source/blender/blenkernel/intern/mesh_debug.cc115
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c121
-rw-r--r--source/blender/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/bmesh/bmesh.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c42
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.h13
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_convert.c19
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_debug.c86
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_debug.h30
-rw-r--r--source/blender/editors/space_node/drawnode.cc4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c144
-rw-r--r--source/blender/editors/space_sequencer/sequencer_thumbnails.c2
-rw-r--r--source/blender/editors/space_topbar/space_topbar.c11
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c1
-rw-r--r--source/blender/gpu/GPU_shader_shared.h4
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.cc1
-rw-r--r--source/blender/gpu/intern/gpu_shader_create_info.hh38
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc3
-rw-r--r--source/blender/gpu/opengl/gl_context.hh1
-rw-r--r--source/blender/gpu/opengl/gl_shader.cc51
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl8
-rw-r--r--source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh2
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c2
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.cc15
-rw-r--r--source/blender/python/gpu/gpu_py_framebuffer.c2
-rw-r--r--source/blender/sequencer/CMakeLists.txt2
-rw-r--r--source/blender/sequencer/SEQ_animation.h41
-rw-r--r--source/blender/sequencer/SEQ_clipboard.h1
-rw-r--r--source/blender/sequencer/SEQ_sequencer.h4
-rw-r--r--source/blender/sequencer/intern/animation.c122
-rw-r--r--source/blender/sequencer/intern/clipboard.c15
-rw-r--r--source/blender/sequencer/intern/proxy.c2
-rw-r--r--source/blender/sequencer/intern/sequencer.c142
-rw-r--r--source/blender/sequencer/intern/sequencer.h5
-rw-r--r--source/blender/sequencer/intern/strip_edit.c4
-rw-r--r--source/blender/sequencer/intern/strip_transform.c1
-rw-r--r--source/blender/sequencer/intern/utils.c5
-rw-r--r--source/blender/windowmanager/intern/wm_files.c43
47 files changed, 810 insertions, 381 deletions
diff --git a/intern/cycles/blender/output_driver.cpp b/intern/cycles/blender/output_driver.cpp
index 7b253e4cd3e..d5cc0c60bae 100644
--- a/intern/cycles/blender/output_driver.cpp
+++ b/intern/cycles/blender/output_driver.cpp
@@ -51,7 +51,7 @@ bool BlenderOutputDriver::read_render_tile(const Tile &tile)
BL::RenderLayer b_rlay = *b_single_rlay;
- vector<float> pixels(tile.size.x * tile.size.y * 4);
+ vector<float> pixels(static_cast<size_t>(tile.size.x) * tile.size.y * 4);
/* Copy each pass.
* TODO:copy only the required ones for better performance? */
@@ -109,7 +109,7 @@ void BlenderOutputDriver::write_render_tile(const Tile &tile)
BL::RenderLayer b_rlay = *b_single_rlay;
- vector<float> pixels(tile.size.x * tile.size.y * 4);
+ vector<float> pixels(static_cast<size_t>(tile.size.x) * tile.size.y * 4);
/* Copy each pass. */
for (BL::RenderPass &b_pass : b_rlay.passes) {
diff --git a/intern/cycles/util/array.h b/intern/cycles/util/array.h
index 4c905b09138..1c5e3e8d4ec 100644
--- a/intern/cycles/util/array.h
+++ b/intern/cycles/util/array.h
@@ -64,7 +64,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
else {
data_ = mem_allocate(from.datasize_);
if (from.datasize_ > 0) {
- memcpy(data_, from.data_, from.datasize_ * sizeof(T));
+ mem_copy(data_, from.data_, from.datasize_);
}
datasize_ = from.datasize_;
capacity_ = datasize_;
@@ -76,7 +76,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
if (this != &from) {
resize(from.size());
if (datasize_ > 0) {
- memcpy((void *)data_, from.data_, datasize_ * sizeof(T));
+ mem_copy(data_, from.data_, datasize_);
}
}
@@ -88,7 +88,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
resize(from.size());
if (from.size() > 0 && datasize_ > 0) {
- memcpy(data_, &from[0], datasize_ * sizeof(T));
+ mem_copy(data_, from.data(), datasize_);
}
return *this;
@@ -161,8 +161,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
return NULL;
}
else if (data_ != NULL) {
- memcpy(
- (void *)newdata, data_, ((datasize_ < newsize) ? datasize_ : newsize) * sizeof(T));
+ mem_copy(newdata, data_, ((datasize_ < newsize) ? datasize_ : newsize));
mem_free(data_, capacity_);
}
data_ = newdata;
@@ -246,7 +245,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
if (newcapacity > capacity_) {
T *newdata = mem_allocate(newcapacity);
if (data_ != NULL) {
- memcpy(newdata, data_, ((datasize_ < newcapacity) ? datasize_ : newcapacity) * sizeof(T));
+ mem_copy(newdata, data_, ((datasize_ < newcapacity) ? datasize_ : newcapacity));
mem_free(data_, capacity_);
}
data_ = newdata;
@@ -280,7 +279,7 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
if (from.size()) {
size_t old_size = size();
resize(old_size + from.size());
- memcpy(data_ + old_size, from.data(), sizeof(T) * from.size());
+ mem_copy(data_ + old_size, from.data(), from.size());
}
}
@@ -308,6 +307,11 @@ template<typename T, size_t alignment = MIN_ALIGNMENT_CPU_DATA_TYPES> class arra
}
}
+ inline void mem_copy(T *mem_to, const T *mem_from, const size_t N)
+ {
+ memcpy((void *)mem_to, mem_from, sizeof(T) * N);
+ }
+
T *data_;
size_t datasize_;
size_t capacity_;
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 17a44274712..00eae2e8e6e 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -747,6 +747,14 @@ void CustomData_blend_write(struct BlendWriter *writer,
struct ID *id);
void CustomData_blend_read(struct BlendDataReader *reader, struct CustomData *data, int count);
+#ifndef NDEBUG
+struct DynStr;
+/** Use to inspect mesh data when debugging. */
+void CustomData_debug_info_from_layers(const struct CustomData *data,
+ const char *indent,
+ struct DynStr *dynstr);
+#endif /* NDEBUG */
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index b7f675e4e97..4c6eb31db4b 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -406,6 +406,13 @@ int set_listbasepointers(struct Main *main, struct ListBase *lb[]);
((main)->versionfile < (ver) || \
((main)->versionfile == (ver) && (main)->subversionfile < (subver)))
+/**
+ * The size of thumbnails (optionally) stored in the `.blend` files header.
+ *
+ * NOTE(@campbellbarton): This is kept small as it's stored uncompressed in the `.blend` file,
+ * where a larger size would increase the size of every `.blend` file unreasonably.
+ * If we wanted to increase the size, we'd want to use compression (JPEG or similar).
+ */
#define BLEN_THUMB_SIZE 128
#define BLEN_THUMB_MEMSIZE(_x, _y) \
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index e7382ce448a..6554a9c72aa 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -23,6 +23,7 @@
*/
#include "BKE_mesh_types.h"
+#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
struct BLI_Stack;
@@ -1038,6 +1039,13 @@ void BKE_mesh_batch_cache_free(struct Mesh *me);
extern void (*BKE_mesh_batch_cache_dirty_tag_cb)(struct Mesh *me, eMeshBatchDirtyMode mode);
extern void (*BKE_mesh_batch_cache_free_cb)(struct Mesh *me);
+/* mesh_debug.c */
+#ifndef NDEBUG
+char *BKE_mesh_debug_info(const struct Mesh *me)
+ ATTR_NONNULL(1) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void BKE_mesh_debug_print(const struct Mesh *me) ATTR_NONNULL(1);
+#endif
+
/* Inlines */
/* NOTE(@sybren): Instead of -1 that function uses ORIGINDEX_NONE as defined in BKE_customdata.h,
diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h
index 5069fad6bb7..ad86f6d8f25 100644
--- a/source/blender/blenkernel/BKE_mesh_runtime.h
+++ b/source/blender/blenkernel/BKE_mesh_runtime.h
@@ -116,10 +116,6 @@ void BKE_mesh_runtime_eval_to_meshkey(struct Mesh *me_deformed,
struct KeyBlock *kb);
#ifndef NDEBUG
-char *BKE_mesh_runtime_debug_info(struct Mesh *me_eval);
-void BKE_mesh_runtime_debug_print(struct Mesh *me_eval);
-/* XXX Should go in customdata file? */
-void BKE_mesh_runtime_debug_print_cdlayers(struct CustomData *data);
bool BKE_mesh_runtime_is_valid(struct Mesh *me_eval);
#endif /* NDEBUG */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index b5b8f629970..cb32bc29463 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -197,6 +197,7 @@ set(SRC
intern/mesh.cc
intern/mesh_boolean_convert.cc
intern/mesh_convert.cc
+ intern/mesh_debug.cc
intern/mesh_evaluate.cc
intern/mesh_fair.cc
intern/mesh_iterators.c
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 711b571a640..10ee7108682 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -44,6 +44,10 @@
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
+#ifndef NDEBUG
+# include "BLI_dynstr.h"
+#endif
+
#include "BLT_translation.h"
#include "BKE_anonymous_attribute.h"
@@ -5188,3 +5192,33 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
CustomData_update_typemap(data);
}
+
+#ifndef NDEBUG
+
+void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
+{
+ for (int type = 0; type < CD_NUMTYPES; type++) {
+ if (CustomData_has_layer(data, type)) {
+ /* NOTE: doesn't account for multiple layers. */
+ const char *name = CustomData_layertype_name(type);
+ const int size = CustomData_sizeof(type);
+ const void *pt = CustomData_get_layer(data, type);
+ const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
+ const char *structname;
+ int structnum;
+ CustomData_file_write_info(type, &structname, &structnum);
+ BLI_dynstr_appendf(
+ dynstr,
+ "%sdict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
+ indent,
+ name,
+ structname,
+ type,
+ (const void *)pt,
+ size,
+ pt_size);
+ }
+ }
+}
+
+#endif /* NDEBUG */
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 1aa3477437a..9b0cf17a424 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -150,6 +150,8 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BKE_mesh_update_customdata_pointers(mesh_dst, do_tessface);
+ mesh_dst->cd_flag = mesh_src->cd_flag;
+
mesh_dst->edit_mesh = nullptr;
mesh_dst->mselect = (MSelect *)MEM_dupallocN(mesh_dst->mselect);
diff --git a/source/blender/blenkernel/intern/mesh_debug.cc b/source/blender/blenkernel/intern/mesh_debug.cc
new file mode 100644
index 00000000000..017f96c2ece
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_debug.cc
@@ -0,0 +1,115 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Evaluated mesh info printing function, to help track down differences output.
+ *
+ * Output from these functions can be evaluated as Python literals.
+ * See `bmesh_debug.c` for the equivalent #BMesh functionality.
+ */
+
+#ifndef NDEBUG
+
+# include <stdio.h>
+
+# include "MEM_guardedalloc.h"
+
+# include "DNA_mesh_types.h"
+# include "DNA_meshdata_types.h"
+# include "DNA_object_types.h"
+
+# include "BLI_utildefines.h"
+
+# include "BKE_customdata.h"
+
+# include "BKE_mesh.h"
+
+# include "BLI_dynstr.h"
+
+static void mesh_debug_info_from_cd_flag(const Mesh *me, DynStr *dynstr)
+{
+ BLI_dynstr_append(dynstr, "'cd_flag': {");
+ if (me->cd_flag & ME_CDFLAG_VERT_BWEIGHT) {
+ BLI_dynstr_append(dynstr, "'VERT_BWEIGHT', ");
+ }
+ if (me->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) {
+ BLI_dynstr_append(dynstr, "'EDGE_BWEIGHT', ");
+ }
+ if (me->cd_flag & ME_CDFLAG_EDGE_CREASE) {
+ BLI_dynstr_append(dynstr, "'EDGE_CREASE', ");
+ }
+ BLI_dynstr_append(dynstr, "},\n");
+}
+
+char *BKE_mesh_debug_info(const Mesh *me)
+{
+ DynStr *dynstr = BLI_dynstr_new();
+ char *ret;
+
+ const char *indent4 = " ";
+ const char *indent8 = " ";
+
+ BLI_dynstr_append(dynstr, "{\n");
+ BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)me);
+ BLI_dynstr_appendf(dynstr, " 'totvert': %d,\n", me->totvert);
+ BLI_dynstr_appendf(dynstr, " 'totedge': %d,\n", me->totedge);
+ BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me->totface);
+ BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me->totpoly);
+
+ BLI_dynstr_appendf(dynstr, " 'runtime.deformed_only': %d,\n", me->runtime.deformed_only);
+ BLI_dynstr_appendf(dynstr, " 'runtime.is_original': %d,\n", me->runtime.is_original);
+
+ BLI_dynstr_append(dynstr, " 'vert_layers': (\n");
+ CustomData_debug_info_from_layers(&me->vdata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'edge_layers': (\n");
+ CustomData_debug_info_from_layers(&me->edata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'loop_layers': (\n");
+ CustomData_debug_info_from_layers(&me->ldata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'poly_layers': (\n");
+ CustomData_debug_info_from_layers(&me->pdata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'tessface_layers': (\n");
+ CustomData_debug_info_from_layers(&me->fdata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, indent4);
+ mesh_debug_info_from_cd_flag(me, dynstr);
+
+ BLI_dynstr_append(dynstr, "}\n");
+
+ ret = BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+ return ret;
+}
+
+void BKE_mesh_debug_print(const Mesh *me)
+{
+ char *str = BKE_mesh_debug_info(me);
+ puts(str);
+ fflush(stdout);
+ MEM_freeN(str);
+}
+
+#endif /* NDEBUG */
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index 39dbd7d66a4..e7e5064df7c 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -298,129 +298,10 @@ void BKE_mesh_batch_cache_free(Mesh *me)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Mesh Runtime Debug Helpers
+/** \name Mesh Runtime Validation
* \{ */
-/* Evaluated mesh info printing function, to help track down differences output. */
-
#ifndef NDEBUG
-# include "BLI_dynstr.h"
-
-static void mesh_runtime_debug_info_layers(DynStr *dynstr, CustomData *cd)
-{
- int type;
-
- for (type = 0; type < CD_NUMTYPES; type++) {
- if (CustomData_has_layer(cd, type)) {
- /* NOTE: doesn't account for multiple layers. */
- const char *name = CustomData_layertype_name(type);
- const int size = CustomData_sizeof(type);
- const void *pt = CustomData_get_layer(cd, type);
- const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
- const char *structname;
- int structnum;
- CustomData_file_write_info(type, &structname, &structnum);
- BLI_dynstr_appendf(
- dynstr,
- " dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name,
- structname,
- type,
- (const void *)pt,
- size,
- pt_size);
- }
- }
-}
-
-char *BKE_mesh_runtime_debug_info(Mesh *me_eval)
-{
- DynStr *dynstr = BLI_dynstr_new();
- char *ret;
-
- BLI_dynstr_append(dynstr, "{\n");
- BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)me_eval);
-# if 0
- const char *tstr;
- switch (me_eval->type) {
- case DM_TYPE_CDDM:
- tstr = "DM_TYPE_CDDM";
- break;
- case DM_TYPE_CCGDM:
- tstr = "DM_TYPE_CCGDM";
- break;
- default:
- tstr = "UNKNOWN";
- break;
- }
- BLI_dynstr_appendf(dynstr, " 'type': '%s',\n", tstr);
-# endif
- BLI_dynstr_appendf(dynstr, " 'totvert': %d,\n", me_eval->totvert);
- BLI_dynstr_appendf(dynstr, " 'totedge': %d,\n", me_eval->totedge);
- BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", me_eval->totface);
- BLI_dynstr_appendf(dynstr, " 'totpoly': %d,\n", me_eval->totpoly);
- BLI_dynstr_appendf(dynstr, " 'deformed_only': %d,\n", me_eval->runtime.deformed_only);
-
- BLI_dynstr_append(dynstr, " 'vertexLayers': (\n");
- mesh_runtime_debug_info_layers(dynstr, &me_eval->vdata);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'edgeLayers': (\n");
- mesh_runtime_debug_info_layers(dynstr, &me_eval->edata);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'loopLayers': (\n");
- mesh_runtime_debug_info_layers(dynstr, &me_eval->ldata);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'polyLayers': (\n");
- mesh_runtime_debug_info_layers(dynstr, &me_eval->pdata);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, " 'tessFaceLayers': (\n");
- mesh_runtime_debug_info_layers(dynstr, &me_eval->fdata);
- BLI_dynstr_append(dynstr, " ),\n");
-
- BLI_dynstr_append(dynstr, "}\n");
-
- ret = BLI_dynstr_get_cstring(dynstr);
- BLI_dynstr_free(dynstr);
- return ret;
-}
-
-void BKE_mesh_runtime_debug_print(Mesh *me_eval)
-{
- char *str = BKE_mesh_runtime_debug_info(me_eval);
- puts(str);
- fflush(stdout);
- MEM_freeN(str);
-}
-
-void BKE_mesh_runtime_debug_print_cdlayers(CustomData *data)
-{
- int i;
- const CustomDataLayer *layer;
-
- printf("{\n");
-
- for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
-
- const char *name = CustomData_layertype_name(layer->type);
- const int size = CustomData_sizeof(layer->type);
- const char *structname;
- int structnum;
- CustomData_file_write_info(layer->type, &structname, &structnum);
- printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
- name,
- structname,
- layer->type,
- (const void *)layer->data,
- size,
- (int)(MEM_allocN_len(layer->data) / size));
- }
-
- printf("}\n");
-}
bool BKE_mesh_runtime_is_valid(Mesh *me_eval)
{
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 7bf80939980..f57d4da4d26 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -100,6 +100,8 @@ set(SRC
intern/bmesh_mesh.h
intern/bmesh_mesh_convert.c
intern/bmesh_mesh_convert.h
+ intern/bmesh_mesh_debug.c
+ intern/bmesh_mesh_debug.h
intern/bmesh_mesh_duplicate.c
intern/bmesh_mesh_duplicate.h
intern/bmesh_mesh_normals.c
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index 40db423ba2f..fc97c55091a 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -214,6 +214,7 @@ extern "C" {
#include "intern/bmesh_marking.h"
#include "intern/bmesh_mesh.h"
#include "intern/bmesh_mesh_convert.h"
+#include "intern/bmesh_mesh_debug.h"
#include "intern/bmesh_mesh_duplicate.h"
#include "intern/bmesh_mesh_normals.h"
#include "intern/bmesh_mesh_partial_update.h"
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 5a9d1ba7bc4..a127089ad2c 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -510,23 +510,51 @@ static BMFace *bm_mesh_copy_new_face(
return f_new;
}
-void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst,
- const Mesh *me_src,
- const BMAllocTemplate *allocsize)
+void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
+ const Mesh *me_src_array[],
+ const int me_src_array_len,
+ const BMAllocTemplate *allocsize)
+
{
if (allocsize == NULL) {
allocsize = &bm_mesh_allocsize_default;
}
- CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
- CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
- CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
- CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
+ char cd_flag = 0;
+
+ for (int i = 0; i < me_src_array_len; i++) {
+ const Mesh *me_src = me_src_array[i];
+ if (i == 0) {
+ CustomData_copy(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
+ CustomData_copy(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
+ CustomData_copy(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
+ CustomData_copy(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
+ }
+ else {
+ CustomData_merge(&me_src->vdata, &bm_dst->vdata, CD_MASK_BMESH.vmask, CD_CALLOC, 0);
+ CustomData_merge(&me_src->edata, &bm_dst->edata, CD_MASK_BMESH.emask, CD_CALLOC, 0);
+ CustomData_merge(&me_src->ldata, &bm_dst->ldata, CD_MASK_BMESH.lmask, CD_CALLOC, 0);
+ CustomData_merge(&me_src->pdata, &bm_dst->pdata, CD_MASK_BMESH.pmask, CD_CALLOC, 0);
+ }
+
+ cd_flag |= me_src->cd_flag;
+ }
+
+ cd_flag |= BM_mesh_cd_flag_from_bmesh(bm_dst);
CustomData_bmesh_init_pool(&bm_dst->vdata, allocsize->totvert, BM_VERT);
CustomData_bmesh_init_pool(&bm_dst->edata, allocsize->totedge, BM_EDGE);
CustomData_bmesh_init_pool(&bm_dst->ldata, allocsize->totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm_dst->pdata, allocsize->totface, BM_FACE);
+
+ BM_mesh_cd_flag_apply(bm_dst, cd_flag);
+}
+
+void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst,
+ const Mesh *me_src,
+ const BMAllocTemplate *allocsize)
+{
+ BM_mesh_copy_init_customdata_from_mesh_array(bm_dst, &me_src, 1, allocsize);
}
void BM_mesh_copy_init_customdata(BMesh *bm_dst, BMesh *bm_src, const BMAllocTemplate *allocsize)
diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h
index 7b25a5b5a2a..008219165a8 100644
--- a/source/blender/bmesh/intern/bmesh_construct.h
+++ b/source/blender/bmesh/intern/bmesh_construct.h
@@ -146,6 +146,19 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src,
void BM_elem_attrs_copy(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, void *ele_dst_v);
void BM_elem_select_copy(BMesh *bm_dst, void *ele_dst_v, const void *ele_src_v);
+/**
+ * Initialize the `bm_dst` layers in preparation for populating it's contents with multiple meshes.
+ * Typically done using multiple calls to #BM_mesh_bm_from_me with the same `bm` argument).
+ *
+ * \note While the custom-data layers of all meshes are created, the active layers are set
+ * by the first instance mesh containing that layer type.
+ * This means the first mesh should always be the main mesh (from the user perspective),
+ * as this is the mesh they have control over (active UV layer for rendering for example).
+ */
+void BM_mesh_copy_init_customdata_from_mesh_array(BMesh *bm_dst,
+ const struct Mesh *me_src_array[],
+ int me_src_array_len,
+ const struct BMAllocTemplate *allocsize);
void BM_mesh_copy_init_customdata_from_mesh(BMesh *bm_dst,
const struct Mesh *me_src,
const struct BMAllocTemplate *allocsize);
diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.c b/source/blender/bmesh/intern/bmesh_mesh_convert.c
index d99fefbcd02..6b44fe2c9ff 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_convert.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_convert.c
@@ -315,13 +315,20 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
CustomData_bmesh_init_pool(&bm->edata, me->totedge, BM_EDGE);
CustomData_bmesh_init_pool(&bm->ldata, me->totloop, BM_LOOP);
CustomData_bmesh_init_pool(&bm->pdata, me->totpoly, BM_FACE);
-
- BM_mesh_cd_flag_apply(bm, me->cd_flag);
}
-
- const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT);
- const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
- const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE);
+ BM_mesh_cd_flag_apply(bm, me->cd_flag | (is_new ? 0 : BM_mesh_cd_flag_from_bmesh(bm)));
+
+ /* Only copy these values over if the source mesh is flagged to be using them.
+ * Even if `bm` has these layers, they may have been added from another mesh, when `!is_new`. */
+ const int cd_vert_bweight_offset = (me->cd_flag & ME_CDFLAG_VERT_BWEIGHT) ?
+ CustomData_get_offset(&bm->vdata, CD_BWEIGHT) :
+ -1;
+ const int cd_edge_bweight_offset = (me->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) ?
+ CustomData_get_offset(&bm->edata, CD_BWEIGHT) :
+ -1;
+ const int cd_edge_crease_offset = (me->cd_flag & ME_CDFLAG_EDGE_CREASE) ?
+ CustomData_get_offset(&bm->edata, CD_CREASE) :
+ -1;
const int cd_shape_key_offset = tot_shape_keys ? CustomData_get_offset(&bm->vdata, CD_SHAPEKEY) :
-1;
const int cd_shape_keyindex_offset = is_new && (tot_shape_keys || params->add_key_index) ?
diff --git a/source/blender/bmesh/intern/bmesh_mesh_debug.c b/source/blender/bmesh/intern/bmesh_mesh_debug.c
new file mode 100644
index 00000000000..81a11df13f2
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh_debug.c
@@ -0,0 +1,86 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ *
+ * Evaluated mesh info printing function, to help track down differences output.
+ *
+ * Output from these functions can be evaluated as Python literals.
+ * See `mesh_debug.cc` for the equivalent #Mesh functionality.
+ */
+
+#ifndef NDEBUG
+
+# include <stdio.h>
+
+# include "MEM_guardedalloc.h"
+
+# include "BLI_utildefines.h"
+
+# include "BKE_customdata.h"
+
+# include "bmesh.h"
+
+# include "bmesh_mesh_debug.h"
+
+# include "BLI_dynstr.h"
+
+char *BM_mesh_debug_info(BMesh *bm)
+{
+ DynStr *dynstr = BLI_dynstr_new();
+ char *ret;
+
+ const char *indent8 = " ";
+
+ BLI_dynstr_append(dynstr, "{\n");
+ BLI_dynstr_appendf(dynstr, " 'ptr': '%p',\n", (void *)bm);
+ BLI_dynstr_appendf(dynstr, " 'totvert': %d,\n", bm->totvert);
+ BLI_dynstr_appendf(dynstr, " 'totedge': %d,\n", bm->totedge);
+ BLI_dynstr_appendf(dynstr, " 'totface': %d,\n", bm->totface);
+
+ BLI_dynstr_append(dynstr, " 'vert_layers': (\n");
+ CustomData_debug_info_from_layers(&bm->vdata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'edge_layers': (\n");
+ CustomData_debug_info_from_layers(&bm->edata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'loop_layers': (\n");
+ CustomData_debug_info_from_layers(&bm->ldata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, " 'poly_layers': (\n");
+ CustomData_debug_info_from_layers(&bm->pdata, indent8, dynstr);
+ BLI_dynstr_append(dynstr, " ),\n");
+
+ BLI_dynstr_append(dynstr, "}\n");
+
+ ret = BLI_dynstr_get_cstring(dynstr);
+ BLI_dynstr_free(dynstr);
+ return ret;
+}
+
+void BM_mesh_debug_print(BMesh *bm)
+{
+ char *str = BM_mesh_debug_info(bm);
+ puts(str);
+ fflush(stdout);
+ MEM_freeN(str);
+}
+
+#endif /* NDEBUG */
diff --git a/source/blender/bmesh/intern/bmesh_mesh_debug.h b/source/blender/bmesh/intern/bmesh_mesh_debug.h
new file mode 100644
index 00000000000..e903b627419
--- /dev/null
+++ b/source/blender/bmesh/intern/bmesh_mesh_debug.h
@@ -0,0 +1,30 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bmesh
+ */
+
+#include "BLI_compiler_attrs.h"
+
+#include "bmesh.h"
+
+#ifndef NDEBUG
+char *BM_mesh_debug_info(BMesh *bm) ATTR_NONNULL(1) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+void BM_mesh_debug_print(BMesh *bm) ATTR_NONNULL(1);
+#endif /* NDEBUG */
diff --git a/source/blender/editors/space_node/drawnode.cc b/source/blender/editors/space_node/drawnode.cc
index 9f0bc5cacef..8474192ca23 100644
--- a/source/blender/editors/space_node/drawnode.cc
+++ b/source/blender/editors/space_node/drawnode.cc
@@ -2073,7 +2073,7 @@ void node_draw_link_bezier(const bContext &C,
copy_v2_v2(node_link_data.bezierPts[i], vec[i]);
}
for (int i = 0; i < 3; i++) {
- copy_v2_v2(node_link_data.colors[i], colors[i]);
+ copy_v4_v4(node_link_data.colors[i], colors[i]);
}
node_link_data.doArrow = drawarrow;
node_link_data.doMuted = drawmuted;
@@ -2086,7 +2086,7 @@ void node_draw_link_bezier(const bContext &C,
GPUBatch *batch = g_batch_link.batch_single;
GPUUniformBuf *ubo = GPU_uniformbuf_create_ex(
- sizeof(node_link_data), &node_link_data, __func__);
+ sizeof(NodeLinkData), &node_link_data, __func__);
GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
GPU_batch_uniformbuf_bind(batch, "node_link_data", ubo);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index d43ff38edf9..3b5e16d84a9 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -39,6 +39,7 @@
#include "DNA_sound_types.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@@ -46,6 +47,7 @@
#include "BKE_sound.h"
#include "SEQ_add.h"
+#include "SEQ_animation.h"
#include "SEQ_clipboard.h"
#include "SEQ_edit.h"
#include "SEQ_effects.h"
@@ -66,6 +68,7 @@
#include "RNA_enum_types.h"
/* For menu, popup, icons, etc. */
+#include "ED_keyframing.h"
#include "ED_numinput.h"
#include "ED_outliner.h"
#include "ED_screen.h"
@@ -1655,6 +1658,35 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
/** \name Duplicate Strips Operator
* \{ */
+static void sequencer_backup_original_animation(Scene *scene, ListBase *list)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL ||
+ BLI_listbase_is_empty(&scene->adt->action->curves)) {
+ return;
+ }
+
+ BLI_movelisttolist(list, &scene->adt->action->curves);
+}
+
+static void sequencer_restore_original_animation(Scene *scene, ListBase *list)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL || BLI_listbase_is_empty(list)) {
+ return;
+ }
+
+ BLI_movelisttolist(&scene->adt->action->curves, list);
+}
+
+static void sequencer_duplicate_animation(Scene *scene, Sequence *seq, ListBase *curves_backup)
+{
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, curves_backup);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ FCurve *fcu_cpy = BKE_fcurve_copy(fcu);
+ BLI_addtail(&scene->adt->action->curves, fcu_cpy);
+ }
+ GSET_FOREACH_END();
+}
+
static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
@@ -1665,32 +1697,44 @@ static int sequencer_add_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
}
Sequence *active_seq = SEQ_select_active_get(scene);
- ListBase duplicated = {NULL, NULL};
+ ListBase duplicated_strips = {NULL, NULL};
- SEQ_sequence_base_dupli_recursive(scene, scene, &duplicated, ed->seqbasep, 0, 0);
+ SEQ_sequence_base_dupli_recursive(scene, scene, &duplicated_strips, ed->seqbasep, 0, 0);
ED_sequencer_deselect_all(scene);
- if (duplicated.first) {
- Sequence *seq = duplicated.first;
- /* Rely on the nseqbase list being added at the end.
- * Their UUIDs has been re-generated by the SEQ_sequence_base_dupli_recursive(), */
- BLI_movelisttolist(ed->seqbasep, &duplicated);
-
- /* Handle duplicated strips: set active, select, ensure unique name and duplicate animation
- * data. */
- for (; seq; seq = seq->next) {
- if (active_seq != NULL && STREQ(seq->name, active_seq->name)) {
- SEQ_select_active_set(scene, seq);
- }
- seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
- SEQ_ensure_unique_name(seq, scene);
- }
+ if (duplicated_strips.first == NULL) {
+ return OPERATOR_CANCELLED;
+ }
- WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
- return OPERATOR_FINISHED;
+ /* Duplicate animation.
+ * First backup original curves from scene and duplicate strip curves from backup into scene.
+ * This way, when pasted strips are renamed, curves are renamed with them. Finally, restore
+ * original curves from backup.
+ */
+ ListBase fcurves_original_backup = {NULL, NULL};
+ sequencer_backup_original_animation(scene, &fcurves_original_backup);
+
+ Sequence *seq = duplicated_strips.first;
+
+ /* Rely on the nseqbase list being added at the end.
+ * Their UUIDs has been re-generated by the SEQ_sequence_base_dupli_recursive(), */
+ BLI_movelisttolist(ed->seqbasep, &duplicated_strips);
+
+ /* Handle duplicated strips: set active, select, ensure unique name and duplicate animation
+ * data. */
+ for (; seq; seq = seq->next) {
+ if (active_seq != NULL && STREQ(seq->name, active_seq->name)) {
+ SEQ_select_active_set(scene, seq);
+ }
+ seq->flag &= ~(SEQ_LEFTSEL + SEQ_RIGHTSEL + SEQ_LOCK);
+ sequencer_duplicate_animation(scene, seq, &fcurves_original_backup);
+ SEQ_ensure_unique_name(seq, scene);
}
- return OPERATOR_CANCELLED;
+ sequencer_restore_original_animation(scene, &fcurves_original_backup);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
}
void SEQUENCER_OT_duplicate(wmOperatorType *ot)
@@ -1905,7 +1949,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
seq_next = seq->next;
- SEQ_sequence_free(scene, seq, true);
+ SEQ_edit_flag_for_removal(scene, seqbase, seq);
seq = seq_next;
}
else {
@@ -1913,6 +1957,8 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op)
}
}
+ SEQ_edit_remove_flagged_sequences(scene, seqbase);
+
SEQ_sort(seqbase);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
@@ -2441,6 +2487,22 @@ static void seq_copy_del_sound(Scene *scene, Sequence *seq)
}
}
+static void sequencer_copy_animation(Scene *scene, Sequence *seq)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL ||
+ BLI_listbase_is_empty(&scene->adt->action->curves)) {
+ return;
+ }
+
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, &scene->adt->action->curves);
+
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ BLI_addtail(&fcurves_clipboard, BKE_fcurve_copy(fcu));
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(fcurves, NULL);
+}
+
static int sequencer_copy_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2467,8 +2529,10 @@ static int sequencer_copy_exec(bContext *C, wmOperator *op)
seqbase_clipboard_frame = scene->r.cfra;
SEQ_clipboard_active_seq_name_store(scene);
- /* Remove anything that references the current scene. */
LISTBASE_FOREACH (Sequence *, seq, &seqbase_clipboard) {
+ /* Copy curves. */
+ sequencer_copy_animation(scene, seq);
+ /* Remove anything that references the current scene. */
seq_copy_del_sound(scene, seq);
}
@@ -2513,6 +2577,29 @@ void ED_sequencer_deselect_all(Scene *scene)
}
}
+static void sequencer_paste_animation(bContext *C)
+{
+ if (BLI_listbase_is_empty(&fcurves_clipboard)) {
+ return;
+ }
+
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ bAction *act;
+
+ if (scene->adt != NULL && scene->adt->action != NULL) {
+ act = scene->adt->action;
+ }
+ else {
+ /* get action to add F-Curve+keyframe to */
+ act = ED_id_action_ensure(bmain, &scene->id);
+ }
+
+ LISTBASE_FOREACH (FCurve *, fcu, &fcurves_clipboard) {
+ BLI_addtail(&act->curves, BKE_fcurve_copy(fcu));
+ }
+}
+
static int sequencer_paste_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
@@ -2542,6 +2629,17 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
ofs = scene->r.cfra - min_seq_startdisp;
}
+ /* Paste animation.
+ * Note: Only fcurves are copied. Drivers and NLA action strips are not copied.
+ * First backup original curves from scene and move curves from clipboard into scene. This way,
+ * when pasted strips are renamed, pasted fcurves are renamed with them. Finally restore original
+ * curves from backup.
+ */
+
+ ListBase fcurves_original_backup = {NULL, NULL};
+ sequencer_backup_original_animation(scene, &fcurves_original_backup);
+ sequencer_paste_animation(C);
+
/* Copy strips, temporarily restoring pointers to actual data-blocks. This
* must happen on the clipboard itself, so that copying does user counting
* on the actual data-blocks. */
@@ -2571,6 +2669,8 @@ static int sequencer_paste_exec(bContext *C, wmOperator *op)
}
}
+ sequencer_restore_original_animation(scene, &fcurves_original_backup);
+
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
diff --git a/source/blender/editors/space_sequencer/sequencer_thumbnails.c b/source/blender/editors/space_sequencer/sequencer_thumbnails.c
index c6fecdb1fc6..82ba17d4db1 100644
--- a/source/blender/editors/space_sequencer/sequencer_thumbnails.c
+++ b/source/blender/editors/space_sequencer/sequencer_thumbnails.c
@@ -66,7 +66,7 @@ typedef struct ThumbDataItem {
static void thumbnail_hash_data_free(void *val)
{
ThumbDataItem *item = val;
- SEQ_sequence_free(item->scene, item->seq_dupli, 0);
+ SEQ_sequence_free(item->scene, item->seq_dupli);
MEM_freeN(val);
}
diff --git a/source/blender/editors/space_topbar/space_topbar.c b/source/blender/editors/space_topbar/space_topbar.c
index 7f0f30624cb..82a0de9b845 100644
--- a/source/blender/editors/space_topbar/space_topbar.c
+++ b/source/blender/editors/space_topbar/space_topbar.c
@@ -243,8 +243,11 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
if (wm->undo_stack == NULL) {
return;
}
+
int undo_step_count = 0;
- for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next) {
+ int undo_step_count_all = 0;
+ for (UndoStep *us = wm->undo_stack->steps.last; us; us = us->prev) {
+ undo_step_count_all += 1;
if (us->skip) {
continue;
}
@@ -255,10 +258,12 @@ static void undo_history_draw_menu(const bContext *C, Menu *menu)
uiLayout *column = NULL;
const int col_size = 20 + (undo_step_count / 12);
- int i = 0;
undo_step_count = 0;
- for (UndoStep *us = wm->undo_stack->steps.first; us; us = us->next, i++) {
+
+ /* Reverse the order so the most recent state is first in the menu. */
+ int i = undo_step_count_all - 1;
+ for (UndoStep *us = wm->undo_stack->steps.last; us; us = us->prev, i--) {
if (us->skip) {
continue;
}
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 2244f82509f..01eae36e846 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -34,6 +34,7 @@
#include "ED_markers.h"
+#include "SEQ_animation.h"
#include "SEQ_edit.h"
#include "SEQ_effects.h"
#include "SEQ_iterator.h"
diff --git a/source/blender/gpu/GPU_shader_shared.h b/source/blender/gpu/GPU_shader_shared.h
index f400e151487..334b974acd8 100644
--- a/source/blender/gpu/GPU_shader_shared.h
+++ b/source/blender/gpu/GPU_shader_shared.h
@@ -34,7 +34,9 @@ using blender::float4x4;
struct NodeLinkData {
float4 colors[3];
- float2 bezierPts[4];
+ /* bezierPts Is actually a float2, but due to std140 each element needs to be aligned to 16
+ * bytes. */
+ float4 bezierPts[4];
bool1 doArrow;
bool1 doMuted;
float dim_factor;
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.cc b/source/blender/gpu/intern/gpu_shader_create_info.cc
index 3d4f27d2278..439eb735c95 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.cc
+++ b/source/blender/gpu/intern/gpu_shader_create_info.cc
@@ -85,6 +85,7 @@ void ShaderCreateInfo::finalize()
if (!info.geometry_source_.is_empty()) {
BLI_assert(geometry_source_.is_empty());
geometry_source_ = info.geometry_source_;
+ geometry_layout_ = info.geometry_layout_;
}
if (!info.fragment_source_.is_empty()) {
BLI_assert(fragment_source_.is_empty());
diff --git a/source/blender/gpu/intern/gpu_shader_create_info.hh b/source/blender/gpu/intern/gpu_shader_create_info.hh
index b4bd58630d5..a1ebdb0ec51 100644
--- a/source/blender/gpu/intern/gpu_shader_create_info.hh
+++ b/source/blender/gpu/intern/gpu_shader_create_info.hh
@@ -149,7 +149,7 @@ enum class Interpolation {
};
/** Input layout for geometry shader. */
-enum class InputLayout {
+enum class PrimitiveIn {
POINTS = 0,
LINES,
LINES_ADJACENCY,
@@ -158,7 +158,7 @@ enum class InputLayout {
};
/** Output layout for geometry shader. */
-enum class OutputLayout {
+enum class PrimitiveOut {
POINTS = 0,
LINE_STRIP,
TRIANGLE_STRIP,
@@ -233,16 +233,14 @@ struct ShaderCreateInfo {
};
Vector<VertIn> vertex_inputs_;
- struct GeomIn {
- InputLayout layout;
+ struct GeometryStageLayout {
+ PrimitiveIn primitive_in;
+ int invocations;
+ PrimitiveOut primitive_out;
+ /** Set to -1 by default to check if used. */
+ int max_vertices = -1;
};
- GeomIn geom_in_;
-
- struct GeomOut {
- OutputLayout layout;
- int max_vertices;
- };
- GeomOut geom_out_;
+ GeometryStageLayout geometry_layout_;
struct FragOut {
int index;
@@ -350,11 +348,21 @@ struct ShaderCreateInfo {
return *(Self *)this;
}
- Self &geometry_layout(InputLayout layout_in, OutputLayout layout_out, int max_vertices)
+ /**
+ * IMPORTANT: invocations count is only used if GL_ARB_gpu_shader5 is supported. On
+ * implementations that do not supports it, the max_vertices will be be multiplied by
+ * invocations. Your shader needs to account for this fact. Use `#ifdef GPU_ARB_gpu_shader5`
+ * and make a code path that does not rely on gl_InvocationID.
+ */
+ Self &geometry_layout(PrimitiveIn prim_in,
+ PrimitiveOut prim_out,
+ int max_vertices,
+ int invocations = -1)
{
- geom_in_.layout = layout_in;
- geom_out_.layout = layout_out;
- geom_out_.max_vertices = max_vertices;
+ geometry_layout_.primitive_in = prim_in;
+ geometry_layout_.primitive_out = prim_out;
+ geometry_layout_.max_vertices = max_vertices;
+ geometry_layout_.invocations = invocations;
return *(Self *)this;
}
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 33574da9f58..1a445ebd7eb 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -246,6 +246,7 @@ static void detect_workarounds()
GLContext::debug_layer_support = false;
GLContext::direct_state_access_support = false;
GLContext::fixed_restart_index_support = false;
+ GLContext::geometry_shader_invocations = false;
GLContext::multi_bind_support = false;
GLContext::multi_draw_indirect_support = false;
GLContext::shader_draw_parameters_support = false;
@@ -435,6 +436,7 @@ bool GLContext::copy_image_support = false;
bool GLContext::debug_layer_support = false;
bool GLContext::direct_state_access_support = false;
bool GLContext::explicit_location_support = false;
+bool GLContext::geometry_shader_invocations = false;
bool GLContext::fixed_restart_index_support = false;
bool GLContext::multi_bind_support = false;
bool GLContext::multi_draw_indirect_support = false;
@@ -494,6 +496,7 @@ void GLBackend::capabilities_init()
GLContext::debug_layer_support = GLEW_VERSION_4_3 || GLEW_KHR_debug || GLEW_ARB_debug_output;
GLContext::direct_state_access_support = GLEW_ARB_direct_state_access;
GLContext::explicit_location_support = GLEW_VERSION_4_3;
+ GLContext::geometry_shader_invocations = GLEW_ARB_gpu_shader5;
GLContext::fixed_restart_index_support = GLEW_ARB_ES3_compatibility;
GLContext::multi_bind_support = GLEW_ARB_multi_bind;
GLContext::multi_draw_indirect_support = GLEW_ARB_multi_draw_indirect;
diff --git a/source/blender/gpu/opengl/gl_context.hh b/source/blender/gpu/opengl/gl_context.hh
index eb365382d53..dd22418972b 100644
--- a/source/blender/gpu/opengl/gl_context.hh
+++ b/source/blender/gpu/opengl/gl_context.hh
@@ -70,6 +70,7 @@ class GLContext : public Context {
static bool debug_layer_support;
static bool direct_state_access_support;
static bool explicit_location_support;
+ static bool geometry_shader_invocations;
static bool fixed_restart_index_support;
static bool multi_bind_support;
static bool multi_draw_indirect_support;
diff --git a/source/blender/gpu/opengl/gl_shader.cc b/source/blender/gpu/opengl/gl_shader.cc
index fe5ffe5a2ad..cec85abae6f 100644
--- a/source/blender/gpu/opengl/gl_shader.cc
+++ b/source/blender/gpu/opengl/gl_shader.cc
@@ -127,32 +127,32 @@ static const char *to_string(const Type &type)
}
}
-static const char *to_string(const InputLayout &layout)
+static const char *to_string(const PrimitiveIn &layout)
{
switch (layout) {
- case InputLayout::POINTS:
+ case PrimitiveIn::POINTS:
return "points";
- case InputLayout::LINES:
+ case PrimitiveIn::LINES:
return "lines";
- case InputLayout::LINES_ADJACENCY:
+ case PrimitiveIn::LINES_ADJACENCY:
return "lines_adjacency";
- case InputLayout::TRIANGLES:
+ case PrimitiveIn::TRIANGLES:
return "triangles";
- case InputLayout::TRIANGLES_ADJACENCY:
+ case PrimitiveIn::TRIANGLES_ADJACENCY:
return "triangles_adjacency";
default:
return "unknown";
}
}
-static const char *to_string(const OutputLayout &layout)
+static const char *to_string(const PrimitiveOut &layout)
{
switch (layout) {
- case OutputLayout::POINTS:
+ case PrimitiveOut::POINTS:
return "points";
- case OutputLayout::LINE_STRIP:
+ case PrimitiveOut::LINE_STRIP:
return "line_strip";
- case OutputLayout::TRIANGLE_STRIP:
+ case PrimitiveOut::TRIANGLE_STRIP:
return "triangle_strip";
default:
return "unknown";
@@ -285,8 +285,7 @@ static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifie
static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &res)
{
- if (res.bind_type != ShaderCreateInfo::Resource::BindType::SAMPLER ||
- GLContext::explicit_location_support) {
+ if (GLContext::explicit_location_support) {
os << "layout(binding = " << res.slot;
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
os << ", " << res.image.format;
@@ -299,6 +298,9 @@ static void print_resource(std::ostream &os, const ShaderCreateInfo::Resource &r
}
os << ") ";
}
+ else if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
+ os << "layout(std140) ";
+ }
int64_t array_offset;
StringRef name_no_array;
@@ -468,11 +470,24 @@ std::string GLShader::fragment_interface_declare(const ShaderCreateInfo &info) c
std::string GLShader::geometry_layout_declare(const ShaderCreateInfo &info) const
{
+ int max_verts = info.geometry_layout_.max_vertices;
+ int invocations = info.geometry_layout_.invocations;
+
+ if (GLContext::geometry_shader_invocations == false && invocations != -1) {
+ max_verts *= invocations;
+ invocations = -1;
+ }
+
std::stringstream ss;
- ss << "\n/* Layout. */\n";
- ss << "layout(" << to_string(info.geom_in_.layout) << ") in;\n";
- ss << "layout(" << to_string(info.geom_out_.layout)
- << ", max_vertices = " << info.geom_out_.max_vertices << ") out;\n";
+ ss << "\n/* Geometry Layout. */\n";
+ ss << "layout(" << to_string(info.geometry_layout_.primitive_in);
+ if (invocations != -1) {
+ ss << ", invocations = " << invocations;
+ }
+ ss << ") in;\n";
+
+ ss << "layout(" << to_string(info.geometry_layout_.primitive_out)
+ << ", max_vertices = " << max_verts << ") out;\n";
ss << "\n";
return ss.str();
}
@@ -529,6 +544,10 @@ static char *glsl_patch_default_get()
STR_CONCAT(patch, slen, "#extension GL_ARB_shader_draw_parameters : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_shader_draw_parameters\n");
}
+ if (GLContext::geometry_shader_invocations) {
+ STR_CONCAT(patch, slen, "#extension GL_ARB_gpu_shader5 : enable\n");
+ STR_CONCAT(patch, slen, "#define GPU_ARB_gpu_shader5\n");
+ }
if (GLContext::texture_cube_map_array_support) {
STR_CONCAT(patch, slen, "#extension GL_ARB_texture_cube_map_array : enable\n");
STR_CONCAT(patch, slen, "#define GPU_ARB_texture_cube_map_array\n");
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
index 3d3a042de65..b83ea59a692 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl
@@ -64,10 +64,10 @@ flat out int isMainLine;
# define doMuted (domuted[0] != 0)
#else
-# define P0 node_link_data.bezierPts[0]
-# define P1 node_link_data.bezierPts[1]
-# define P2 node_link_data.bezierPts[2]
-# define P3 node_link_data.bezierPts[3]
+# define P0 node_link_data.bezierPts[0].xy
+# define P1 node_link_data.bezierPts[1].xy
+# define P2 node_link_data.bezierPts[2].xy
+# define P3 node_link_data.bezierPts[3].xy
# define cols node_link_data.colors
# define doArrow node_link_data.doArrow
# define doMuted node_link_data.doMuted
diff --git a/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh
index 5c8410baf04..c337c399f59 100644
--- a/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh
+++ b/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh
@@ -35,7 +35,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke)
.vertex_in(1, Type::VEC3, "pos")
.vertex_in(2, Type::FLOAT, "thickness")
.vertex_out(gpencil_stroke_vert_iface)
- .geometry_layout(InputLayout::LINES_ADJACENCY, OutputLayout::TRIANGLE_STRIP, 13)
+ .geometry_layout(PrimitiveIn::LINES_ADJACENCY, PrimitiveOut::TRIANGLE_STRIP, 13)
.geometry_out(gpencil_stroke_geom_iface)
.fragment_out(0, Type::VEC4, "fragColor")
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 63c4774d0e5..ec20fa54a44 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -729,7 +729,7 @@ void rna_Object_me_eval_info(
}
if (me_eval) {
- ret = BKE_mesh_runtime_debug_info(me_eval);
+ ret = BKE_mesh_debug_info(me_eval);
if (ret) {
strcpy(result, ret);
MEM_freeN(ret);
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index 2a303c7741c..bb05ae3e1b3 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -248,13 +248,14 @@ static BMesh *BMD_mesh_bm_create(
BMeshCreateParams bmesh_create_params{};
BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
- /* Needed so active layers are set based on `mesh` not `mesh_operand_ob`,
- * otherwise the wrong active render layer is used, see T92384. */
- BM_mesh_copy_init_customdata_from_mesh(bm, mesh, &allocsize);
-
- /* NOTE(@campbellbarton): Handle in #BM_mesh_bm_from_me, this is a local fix for T94197. */
- BM_mesh_cd_flag_apply(bm,
- mesh->cd_flag | mesh_operand_ob->cd_flag | BM_mesh_cd_flag_from_bmesh(bm));
+ /* Keep `mesh` first, needed so active layers are set based on `mesh` not `mesh_operand_ob`,
+ * otherwise the wrong active render layer is used, see T92384.
+ *
+ * NOTE: while initializing customer data layers the is not essential,
+ * it avoids the overhead of having to re-allocate #BMHeader.data when the 2nd mesh is added
+ * (if it contains additional custom-data layers). */
+ const Mesh *mesh_array[2] = {mesh, mesh_operand_ob};
+ BM_mesh_copy_init_customdata_from_mesh_array(bm, mesh_array, ARRAY_SIZE(mesh_array), &allocsize);
BMeshFromMeshParams bmesh_from_mesh_params{};
bmesh_from_mesh_params.calc_face_normal = true;
diff --git a/source/blender/python/gpu/gpu_py_framebuffer.c b/source/blender/python/gpu/gpu_py_framebuffer.c
index a9347b71723..412fcac02ca 100644
--- a/source/blender/python/gpu/gpu_py_framebuffer.c
+++ b/source/blender/python/gpu/gpu_py_framebuffer.c
@@ -530,6 +530,7 @@ static PyObject *pygpu_framebuffer_read_color(BPyGPUFrameBuffer *self,
PyErr_SetString(PyExc_BufferError, "the buffer size is smaller than expected");
return NULL;
}
+ Py_INCREF(py_buffer);
}
else {
py_buffer = BPyGPU_Buffer_CreatePyObject(
@@ -590,6 +591,7 @@ static PyObject *pygpu_framebuffer_read_depth(BPyGPUFrameBuffer *self,
PyErr_SetString(PyExc_BufferError, "the buffer size is smaller than expected");
return NULL;
}
+ Py_INCREF(py_buffer);
}
else {
py_buffer = BPyGPU_Buffer_CreatePyObject(GPU_DATA_FLOAT, (Py_ssize_t[]){h, w}, 2, NULL);
diff --git a/source/blender/sequencer/CMakeLists.txt b/source/blender/sequencer/CMakeLists.txt
index eccc336141a..54524e453d4 100644
--- a/source/blender/sequencer/CMakeLists.txt
+++ b/source/blender/sequencer/CMakeLists.txt
@@ -46,6 +46,7 @@ set(INC_SYS
set(SRC
SEQ_add.h
+ SEQ_animation.h
SEQ_clipboard.h
SEQ_edit.h
SEQ_effects.h
@@ -62,6 +63,7 @@ set(SRC
SEQ_transform.h
SEQ_utils.h
+ intern/animation.c
intern/clipboard.c
intern/disk_cache.c
intern/disk_cache.h
diff --git a/source/blender/sequencer/SEQ_animation.h b/source/blender/sequencer/SEQ_animation.h
new file mode 100644
index 00000000000..028f932344f
--- /dev/null
+++ b/source/blender/sequencer/SEQ_animation.h
@@ -0,0 +1,41 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2022 Blender Foundation.
+ * All rights reserved.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct GSet;
+struct ListBase;
+struct Scene;
+struct Sequence;
+
+void SEQ_free_animdata(struct Scene *scene, struct Sequence *seq);
+void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
+struct GSet *SEQ_fcurves_by_strip_get(const struct Sequence *seq, struct ListBase *fcurve_base);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/sequencer/SEQ_clipboard.h b/source/blender/sequencer/SEQ_clipboard.h
index 72388c5db64..dc78f8cc1a2 100644
--- a/source/blender/sequencer/SEQ_clipboard.h
+++ b/source/blender/sequencer/SEQ_clipboard.h
@@ -33,6 +33,7 @@ struct Scene;
struct Sequence;
extern struct ListBase seqbase_clipboard;
+extern struct ListBase fcurves_clipboard;
extern int seqbase_clipboard_frame;
void SEQ_clipboard_pointers_store(struct Main *bmain, struct ListBase *seqbase);
void SEQ_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain);
diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h
index 1229f6f7bea..2e340049dbd 100644
--- a/source/blender/sequencer/SEQ_sequencer.h
+++ b/source/blender/sequencer/SEQ_sequencer.h
@@ -84,7 +84,7 @@ struct ListBase *SEQ_active_seqbase_get(const struct Editing *ed);
*/
void SEQ_seqbase_active_set(struct Editing *ed, struct ListBase *seqbase);
struct Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int type);
-void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq, bool do_clean_animdata);
+void SEQ_sequence_free(struct Scene *scene, struct Sequence *seq);
/**
* Create and initialize #MetaStack, append it to `ed->metastack` ListBase
*
@@ -107,8 +107,6 @@ struct MetaStack *SEQ_meta_stack_active_get(const struct Editing *ed);
* \param ms: meta stack
*/
void SEQ_meta_stack_free(struct Editing *ed, struct MetaStack *ms);
-void SEQ_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs);
-void SEQ_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst);
struct Sequence *SEQ_sequence_dupli_recursive(const struct Scene *scene_src,
struct Scene *scene_dst,
struct ListBase *new_seq_list,
diff --git a/source/blender/sequencer/intern/animation.c b/source/blender/sequencer/intern/animation.c
new file mode 100644
index 00000000000..492b757a4b1
--- /dev/null
+++ b/source/blender/sequencer/intern/animation.c
@@ -0,0 +1,122 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2022 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup sequencer
+ */
+
+#include <string.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_sequence_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_fcurve.h"
+
+#include "BLI_ghash.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "DEG_depsgraph.h"
+
+#include "SEQ_animation.h"
+
+static bool seq_animation_curves_exist(Scene *scene)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL ||
+ BLI_listbase_is_empty(&scene->adt->action->curves)) {
+ return false;
+ }
+ return true;
+}
+
+/* r_prefix + [" + escaped_name + "] + \0 */
+#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1)
+
+static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name)
+{
+ char name_esc[SEQ_NAME_MAXSTR * 2];
+
+ BLI_str_escape(name_esc, name, sizeof(name_esc));
+ return BLI_snprintf_rlen(
+ str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
+}
+
+GSet *SEQ_fcurves_by_strip_get(const Sequence *seq, ListBase *fcurve_base)
+{
+ char rna_path[SEQ_RNAPATH_MAXSTR];
+ size_t rna_path_len = sequencer_rna_path_prefix(rna_path, seq->name + 2);
+
+ GSet *fcurves = BLI_gset_ptr_new(__func__);
+ LISTBASE_FOREACH (FCurve *, fcurve, fcurve_base) {
+ if (STREQLEN(fcurve->rna_path, rna_path, rna_path_len)) {
+ BLI_gset_add(fcurves, fcurve);
+ }
+ }
+
+ return fcurves;
+}
+
+#undef SEQ_RNAPATH_MAXSTR
+
+void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
+{
+ if (!seq_animation_curves_exist(scene) || ofs == 0) {
+ return;
+ }
+
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, &scene->adt->action->curves);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ unsigned int i;
+ if (fcu->bezt) {
+ for (i = 0; i < fcu->totvert; i++) {
+ BezTriple *bezt = &fcu->bezt[i];
+ bezt->vec[0][0] += ofs;
+ bezt->vec[1][0] += ofs;
+ bezt->vec[2][0] += ofs;
+ }
+ }
+ if (fcu->fpt) {
+ for (i = 0; i < fcu->totvert; i++) {
+ FPoint *fpt = &fcu->fpt[i];
+ fpt->vec[0] += ofs;
+ }
+ }
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(fcurves, NULL);
+
+ DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION);
+}
+
+void SEQ_free_animdata(Scene *scene, Sequence *seq)
+{
+ if (!seq_animation_curves_exist(scene)) {
+ return;
+ }
+
+ GSet *fcurves = SEQ_fcurves_by_strip_get(seq, &scene->adt->action->curves);
+ GSET_FOREACH_BEGIN (FCurve *, fcu, fcurves) {
+ BLI_remlink(&scene->adt->action->curves, fcu);
+ BKE_fcurve_free(fcu);
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(fcurves, NULL);
+}
diff --git a/source/blender/sequencer/intern/clipboard.c b/source/blender/sequencer/intern/clipboard.c
index 73e0f616da4..886ee89595b 100644
--- a/source/blender/sequencer/intern/clipboard.c
+++ b/source/blender/sequencer/intern/clipboard.c
@@ -28,6 +28,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_sound_types.h"
@@ -35,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_string.h"
+#include "BKE_fcurve.h"
#include "BKE_main.h"
#include "BKE_movieclip.h"
#include "BKE_scene.h"
@@ -58,6 +60,7 @@
*/
ListBase seqbase_clipboard;
+ListBase fcurves_clipboard;
int seqbase_clipboard_frame;
static char seq_clipboard_active_seq_name[SEQ_NAME_MAXSTR];
@@ -65,15 +68,17 @@ void seq_clipboard_pointers_free(struct ListBase *seqbase);
void SEQ_clipboard_free(void)
{
- Sequence *seq, *nseq;
-
seq_clipboard_pointers_free(&seqbase_clipboard);
- for (seq = seqbase_clipboard.first; seq; seq = nseq) {
- nseq = seq->next;
- seq_free_sequence_recurse(NULL, seq, false, true);
+ LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &seqbase_clipboard) {
+ seq_free_sequence_recurse(NULL, seq, false);
}
BLI_listbase_clear(&seqbase_clipboard);
+
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &fcurves_clipboard) {
+ BKE_fcurve_free(fcu);
+ }
+ BLI_listbase_clear(&fcurves_clipboard);
}
#define ID_PT (*id_pt)
diff --git a/source/blender/sequencer/intern/proxy.c b/source/blender/sequencer/intern/proxy.c
index 30afa3f9c59..2cb2ba13fb5 100644
--- a/source/blender/sequencer/intern/proxy.c
+++ b/source/blender/sequencer/intern/proxy.c
@@ -591,7 +591,7 @@ void SEQ_proxy_rebuild_finish(SeqIndexBuildContext *context, bool stop)
IMB_anim_index_rebuild_finish(context->index_context, stop);
}
- seq_free_sequence_recurse(NULL, context->seq, true, true);
+ seq_free_sequence_recurse(NULL, context->seq, true);
MEM_freeN(context);
}
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c
index e4120a3cf95..f0a45355143 100644
--- a/source/blender/sequencer/intern/sequencer.c
+++ b/source/blender/sequencer/intern/sequencer.c
@@ -34,10 +34,7 @@
#include "DNA_sound_types.h"
#include "BLI_listbase.h"
-#include "BLI_string.h"
-#include "BKE_animsys.h"
-#include "BKE_fcurve.h"
#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_sound.h"
@@ -65,8 +62,6 @@
#include "sequencer.h"
#include "utils.h"
-static void seq_free_animdata(Scene *scene, Sequence *seq);
-
/* -------------------------------------------------------------------- */
/** \name Allocate / Free Functions
* \{ */
@@ -156,8 +151,7 @@ Sequence *SEQ_sequence_alloc(ListBase *lb, int timeline_frame, int machine, int
static void seq_sequence_free_ex(Scene *scene,
Sequence *seq,
const bool do_cache,
- const bool do_id_user,
- const bool do_clean_animdata)
+ const bool do_id_user)
{
if (seq->strip) {
seq_free_strip(seq->strip);
@@ -191,11 +185,6 @@ static void seq_sequence_free_ex(Scene *scene,
if (seq->scene_sound && ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SCENE)) {
BKE_sound_remove_scene_sound(scene, seq->scene_sound);
}
-
- /* XXX This must not be done in BKE code. */
- if (do_clean_animdata) {
- seq_free_animdata(scene, seq);
- }
}
if (seq->prop) {
@@ -223,24 +212,21 @@ static void seq_sequence_free_ex(Scene *scene,
MEM_freeN(seq);
}
-void SEQ_sequence_free(Scene *scene, Sequence *seq, const bool do_clean_animdata)
+void SEQ_sequence_free(Scene *scene, Sequence *seq)
{
- seq_sequence_free_ex(scene, seq, true, true, do_clean_animdata);
+ seq_sequence_free_ex(scene, seq, true, true);
}
-void seq_free_sequence_recurse(Scene *scene,
- Sequence *seq,
- const bool do_id_user,
- const bool do_clean_animdata)
+void seq_free_sequence_recurse(Scene *scene, Sequence *seq, const bool do_id_user)
{
Sequence *iseq, *iseq_next;
for (iseq = seq->seqbase.first; iseq; iseq = iseq_next) {
iseq_next = iseq->next;
- seq_free_sequence_recurse(scene, iseq, do_id_user, do_clean_animdata);
+ seq_free_sequence_recurse(scene, iseq, do_id_user);
}
- seq_sequence_free_ex(scene, seq, false, do_id_user, do_clean_animdata);
+ seq_sequence_free_ex(scene, seq, false, do_id_user);
}
Editing *SEQ_editing_get(const Scene *scene)
@@ -276,7 +262,7 @@ void SEQ_editing_free(Scene *scene, const bool do_id_user)
/* handle cache freeing above */
LISTBASE_FOREACH_MUTABLE (Sequence *, seq, &ed->seqbase) {
- seq_free_sequence_recurse(scene, seq, do_id_user, false);
+ seq_free_sequence_recurse(scene, seq, do_id_user);
}
BLI_freelistN(&ed->metastack);
@@ -623,120 +609,6 @@ bool SEQ_valid_strip_channel(Sequence *seq)
return true;
}
-/* r_prefix + [" + escaped_name + "] + \0 */
-#define SEQ_RNAPATH_MAXSTR ((30 + 2 + (SEQ_NAME_MAXSTR * 2) + 2) + 1)
-
-static size_t sequencer_rna_path_prefix(char str[SEQ_RNAPATH_MAXSTR], const char *name)
-{
- char name_esc[SEQ_NAME_MAXSTR * 2];
-
- BLI_str_escape(name_esc, name, sizeof(name_esc));
- return BLI_snprintf_rlen(
- str, SEQ_RNAPATH_MAXSTR, "sequence_editor.sequences_all[\"%s\"]", name_esc);
-}
-
-void SEQ_offset_animdata(Scene *scene, Sequence *seq, int ofs)
-{
- /* XXX: hackish function needed for transforming strips!
- * TODO: have some better solution. */
-
- char str[SEQ_RNAPATH_MAXSTR];
- size_t str_len;
- FCurve *fcu;
-
- if (scene->adt == NULL || ofs == 0 || scene->adt->action == NULL) {
- return;
- }
-
- str_len = sequencer_rna_path_prefix(str, seq->name + 2);
-
- for (fcu = scene->adt->action->curves.first; fcu; fcu = fcu->next) {
- if (STREQLEN(fcu->rna_path, str, str_len)) {
- unsigned int i;
- if (fcu->bezt) {
- for (i = 0; i < fcu->totvert; i++) {
- BezTriple *bezt = &fcu->bezt[i];
- bezt->vec[0][0] += ofs;
- bezt->vec[1][0] += ofs;
- bezt->vec[2][0] += ofs;
- }
- }
- if (fcu->fpt) {
- for (i = 0; i < fcu->totvert; i++) {
- FPoint *fpt = &fcu->fpt[i];
- fpt->vec[0] += ofs;
- }
- }
- }
- }
-
- DEG_id_tag_update(&scene->adt->action->id, ID_RECALC_ANIMATION);
-}
-
-void SEQ_dupe_animdata(Scene *scene, const char *name_src, const char *name_dst)
-{
- char str_from[SEQ_RNAPATH_MAXSTR];
- size_t str_from_len;
- FCurve *fcu;
- FCurve *fcu_last;
- FCurve *fcu_cpy;
- ListBase lb = {NULL, NULL};
-
- if (scene->adt == NULL || scene->adt->action == NULL) {
- return;
- }
-
- str_from_len = sequencer_rna_path_prefix(str_from, name_src);
-
- fcu_last = scene->adt->action->curves.last;
-
- for (fcu = scene->adt->action->curves.first; fcu && fcu->prev != fcu_last; fcu = fcu->next) {
- if (STREQLEN(fcu->rna_path, str_from, str_from_len)) {
- fcu_cpy = BKE_fcurve_copy(fcu);
- BLI_addtail(&lb, fcu_cpy);
- }
- }
-
- /* notice validate is 0, keep this because the seq may not be added to the scene yet */
- BKE_animdata_fix_paths_rename(
- &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name_src, name_dst, 0, 0, 0);
-
- /* add the original fcurves back */
- BLI_movelisttolist(&scene->adt->action->curves, &lb);
-}
-
-/* XXX: hackish function needed to remove all fcurves belonging to a sequencer strip. */
-static void seq_free_animdata(Scene *scene, Sequence *seq)
-{
- char str[SEQ_RNAPATH_MAXSTR];
- size_t str_len;
- FCurve *fcu;
-
- if (scene->adt == NULL || scene->adt->action == NULL) {
- return;
- }
-
- str_len = sequencer_rna_path_prefix(str, seq->name + 2);
-
- fcu = scene->adt->action->curves.first;
-
- while (fcu) {
- if (STREQLEN(fcu->rna_path, str, str_len)) {
- FCurve *next_fcu = fcu->next;
-
- BLI_remlink(&scene->adt->action->curves, fcu);
- BKE_fcurve_free(fcu);
-
- fcu = next_fcu;
- }
- else {
- fcu = fcu->next;
- }
- }
-}
-
-#undef SEQ_RNAPATH_MAXSTR
-
SequencerToolSettings *SEQ_tool_settings_copy(SequencerToolSettings *tool_settings)
{
SequencerToolSettings *tool_settings_copy = MEM_dupallocN(tool_settings);
diff --git a/source/blender/sequencer/intern/sequencer.h b/source/blender/sequencer/intern/sequencer.h
index aff81255d7d..7d7ecbc8178 100644
--- a/source/blender/sequencer/intern/sequencer.h
+++ b/source/blender/sequencer/intern/sequencer.h
@@ -34,10 +34,7 @@ struct Sequence;
* Cache must be freed before calling this function
* since it leaves the seqbase in an invalid state.
*/
-void seq_free_sequence_recurse(struct Scene *scene,
- struct Sequence *seq,
- bool do_id_user,
- bool do_clean_animdata);
+void seq_free_sequence_recurse(struct Scene *scene, struct Sequence *seq, bool do_id_user);
#ifdef __cplusplus
}
diff --git a/source/blender/sequencer/intern/strip_edit.c b/source/blender/sequencer/intern/strip_edit.c
index cf303e5be4e..0479d3012fa 100644
--- a/source/blender/sequencer/intern/strip_edit.c
+++ b/source/blender/sequencer/intern/strip_edit.c
@@ -43,6 +43,7 @@
#include "utils.h"
#include "SEQ_add.h"
+#include "SEQ_animation.h"
#include "SEQ_edit.h"
#include "SEQ_effects.h"
#include "SEQ_iterator.h"
@@ -199,8 +200,9 @@ void SEQ_edit_remove_flagged_sequences(Scene *scene, ListBase *seqbase)
if (seq->type == SEQ_TYPE_META) {
SEQ_edit_remove_flagged_sequences(scene, &seq->seqbase);
}
+ SEQ_free_animdata(scene, seq);
BLI_remlink(seqbase, seq);
- SEQ_sequence_free(scene, seq, true);
+ SEQ_sequence_free(scene, seq);
SEQ_sequence_lookup_tag(scene, SEQ_LOOKUP_TAG_INVALID);
}
}
diff --git a/source/blender/sequencer/intern/strip_transform.c b/source/blender/sequencer/intern/strip_transform.c
index ce5917b999f..432fc1c166f 100644
--- a/source/blender/sequencer/intern/strip_transform.c
+++ b/source/blender/sequencer/intern/strip_transform.c
@@ -33,6 +33,7 @@
#include "BKE_scene.h"
#include "BKE_sound.h"
+#include "SEQ_animation.h"
#include "SEQ_effects.h"
#include "SEQ_iterator.h"
#include "SEQ_relations.h"
diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c
index 156c6ac4cb9..140aa2d67c5 100644
--- a/source/blender/sequencer/intern/utils.c
+++ b/source/blender/sequencer/intern/utils.c
@@ -35,10 +35,12 @@
#include "BLI_blenlib.h"
+#include "BKE_animsys.h"
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "SEQ_animation.h"
#include "SEQ_edit.h"
#include "SEQ_iterator.h"
#include "SEQ_relations.h"
@@ -583,7 +585,8 @@ void SEQ_ensure_unique_name(Sequence *seq, Scene *scene)
BLI_strncpy_utf8(name, seq->name + 2, sizeof(name));
SEQ_sequence_base_unique_name_recursive(scene, &scene->ed->seqbase, seq);
- SEQ_dupe_animdata(scene, name, seq->name + 2);
+ BKE_animdata_fix_paths_rename(
+ &scene->id, scene->adt, NULL, "sequence_editor.sequences_all", name, seq->name + 2, 0, 0, 0);
if (seq->type == SEQ_TYPE_META) {
LISTBASE_FOREACH (Sequence *, seq_child, &seq->seqbase) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 344f4959a93..1478712c3cd 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -1521,11 +1521,29 @@ static void wm_history_file_update(void)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Save Main Blend-File (internal) Screen-Shot
+/** \name Thumbnail Generation: Screen-Shot / Camera View
+ *
+ * Thumbnail Sizes
+ * ===============
+ *
+ * - `PREVIEW_RENDER_LARGE_HEIGHT * 2` is used to render a large thumbnail,
+ * giving some over-sampling when scaled down:
+ *
+ * - There are two outputs for this thumbnail:
+ *
+ * - An image is saved to the thumbnail cache, sized at #PREVIEW_RENDER_LARGE_HEIGHT.
+ *
+ * - A smaller thumbnail is stored in the `.blend` file it's self, sized at #BLEN_THUMB_SIZE.
+ * The size is kept small to prevent thumbnails bloating the size of `.blend` files.
+ *
+ * The this thumbnail will be extracted if the file is shared or the local thumbnail cache
+ * is cleared. see: `blendthumb_extract.cc` for logic that extracts the thumbnail.
*
- * Screen-shot the active window.
* \{ */
+/**
+ * Screen-shot the active window.
+ */
static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **r_thumb)
{
*r_thumb = NULL;
@@ -1571,15 +1589,11 @@ static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **r_t
return ibuf;
}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Save Main Blend-File (internal) Camera View
- *
+/**
* Render the current scene with the active camera.
- * \{ */
-
-/* screen can be NULL */
+ *
+ * \param screen: can be NULL.
+ */
static ImBuf *blend_file_thumb_from_camera(const bContext *C,
Scene *scene,
bScreen *screen,
@@ -1617,7 +1631,6 @@ static ImBuf *blend_file_thumb_from_camera(const bContext *C,
return NULL;
}
- /* gets scaled to BLEN_THUMB_SIZE */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* Note that with scaling, this ends up being 0.5,
@@ -1689,6 +1702,12 @@ static ImBuf *blend_file_thumb_from_camera(const bContext *C,
return ibuf;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Write Main Blend-File (internal)
+ * \{ */
+
bool write_crash_blend(void)
{
char path[FILE_MAX];
@@ -2017,7 +2036,7 @@ void wm_autosave_delete(void)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Initialize WM_OT_open_xxx properties
+/** \name Initialize `WM_OT_open_*` Properties
*
* Check if load_ui was set by the caller.
* Fall back to user preference when file flags not specified.