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:
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc33
-rw-r--r--source/blender/blenkernel/intern/attribute.cc55
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc4
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c43
-rw-r--r--source/blender/blenkernel/intern/image.cc6
-rw-r--r--source/blender/blenkernel/intern/lib_override.cc38
-rw-r--r--source/blender/blenkernel/intern/mesh_boolean_convert.cc24
-rw-r--r--source/blender/blenkernel/intern/mesh_calc_edges.cc6
-rw-r--r--source/blender/blenkernel/intern/mesh_wrapper.cc23
-rw-r--r--source/blender/blenkernel/intern/nla.c45
-rw-r--r--source/blender/blenkernel/intern/pbvh.c50
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c4
-rw-r--r--source/blender/blenkernel/intern/subdiv_modifier.c62
-rw-r--r--source/blender/blenkernel/intern/tracking.c10
-rw-r--r--source/blender/blenkernel/intern/unit.c16
16 files changed, 263 insertions, 160 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 8496692ceb3..b3a9d894944 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -52,6 +52,7 @@
#include "BKE_object.h"
#include "BKE_object_deform.h"
#include "BKE_paint.h"
+#include "BKE_subdiv_modifier.h"
#include "BLI_sys_types.h" /* for intptr_t support */
@@ -598,10 +599,10 @@ static bool mesh_has_modifier_final_normals(const Mesh *mesh_input,
/* Test if mesh has the required loop normals, in case an additional modifier
* evaluation from another instance or from an operator requests it but the
* initial normals were not loop normals. */
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
- (final_datamask->lmask & CD_MASK_NORMAL) != 0);
+ const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (final_datamask->lmask & CD_MASK_NORMAL) != 0);
- return (!do_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL));
+ return (!calc_loop_normals || CustomData_has_layer(&mesh_final->ldata, CD_NORMAL));
}
static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
@@ -610,16 +611,19 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
Mesh *mesh_final)
{
/* Compute normals. */
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
- (final_datamask->lmask & CD_MASK_NORMAL) != 0);
+ const bool calc_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (final_datamask->lmask & CD_MASK_NORMAL) != 0);
/* Needed as `final_datamask` is not preserved outside modifier stack evaluation. */
- mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals;
+ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
+ if (subsurf_runtime_data) {
+ subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
+ }
- if (do_loop_normals) {
+ if (calc_loop_normals) {
/* Compute loop normals (NOTE: will compute poly and vert normals as well, if needed!). In case
* of deferred CPU subdivision, this will be computed when the wrapper is generated. */
- if (mesh_final->runtime.subsurf_resolution == 0) {
+ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final);
}
}
@@ -1266,15 +1270,18 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
return;
}
- const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
- (final_datamask->lmask & CD_MASK_NORMAL) != 0);
+ const bool calc_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 ||
+ (final_datamask->lmask & CD_MASK_NORMAL) != 0);
- mesh_final->runtime.subsurf_do_loop_normals = do_loop_normals;
+ SubsurfRuntimeData *subsurf_runtime_data = mesh_final->runtime.subsurf_runtime_data;
+ if (subsurf_runtime_data) {
+ subsurf_runtime_data->calc_loop_normals = calc_loop_normals;
+ }
- if (do_loop_normals) {
+ if (calc_loop_normals) {
/* Compute loop normals. In case of deferred CPU subdivision, this will be computed when the
* wrapper is generated. */
- if (mesh_final->runtime.subsurf_resolution == 0) {
+ if (!subsurf_runtime_data || subsurf_runtime_data->resolution == 0) {
BKE_mesh_calc_normals_split(mesh_final);
}
}
diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc
index b2ea8b833b3..7c09b4a4ce3 100644
--- a/source/blender/blenkernel/intern/attribute.cc
+++ b/source/blender/blenkernel/intern/attribute.cc
@@ -208,53 +208,36 @@ CustomDataLayer *BKE_id_attribute_new(
return (index == -1) ? nullptr : &(customdata->layers[index]);
}
-CustomDataLayer *BKE_id_attribute_duplicate(ID *id, CustomDataLayer *layer, ReportList *reports)
+CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports)
{
- DomainInfo info[ATTR_DOMAIN_NUM];
- get_domains(id, info);
-
- eCustomDataType type = (eCustomDataType)layer->type;
- eAttrDomain domain = BKE_id_attribute_domain(id, layer);
-
- CustomData *customdata = info[domain].customdata;
- if (customdata == nullptr) {
- BKE_report(reports, RPT_ERROR, "Attribute domain not supported by this geometry type");
+ const CustomDataLayer *src_layer = BKE_id_attribute_search(
+ id, name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
+ if (src_layer == nullptr) {
+ BKE_report(reports, RPT_ERROR, "Attribute is not part of this geometry");
return nullptr;
}
- char name[MAX_CUSTOMDATA_LAYER_NAME];
- char uniquename[MAX_CUSTOMDATA_LAYER_NAME];
+ const eCustomDataType type = (eCustomDataType)src_layer->type;
+ const eAttrDomain domain = BKE_id_attribute_domain(id, src_layer);
/* Make a copy of name in case CustomData API reallocates the layers. */
- BLI_strncpy(name, layer->name, MAX_CUSTOMDATA_LAYER_NAME);
- BKE_id_attribute_calc_unique_name(id, layer->name, uniquename);
+ const std::string name_copy = name;
- switch (GS(id->name)) {
- case ID_ME: {
- Mesh *me = (Mesh *)id;
- BMEditMesh *em = me->edit_mesh;
- if (em != nullptr) {
- BM_data_layer_add_named(em->bm, customdata, type, uniquename);
- }
- else {
- CustomData_add_layer_named(
- customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename);
- }
- break;
- }
- default: {
- CustomData_add_layer_named(
- customdata, type, CD_DEFAULT, nullptr, info[domain].length, uniquename);
- break;
- }
+ DomainInfo info[ATTR_DOMAIN_NUM];
+ get_domains(id, info);
+ CustomData *customdata = info[domain].customdata;
+
+ CustomDataLayer *new_layer = BKE_id_attribute_new(id, name_copy.c_str(), type, domain, reports);
+ if (new_layer == nullptr) {
+ return nullptr;
}
- int from_index = CustomData_get_named_layer_index(customdata, type, name);
- int to_index = CustomData_get_named_layer_index(customdata, type, uniquename);
+ const int from_index = CustomData_get_named_layer_index(customdata, type, name_copy.c_str());
+ const int to_index = CustomData_get_named_layer_index(customdata, type, new_layer->name);
CustomData_copy_data_layer(
customdata, customdata, from_index, to_index, 0, 0, info[domain].length);
- return (to_index == -1) ? nullptr : &(customdata->layers[to_index]);
+ return new_layer;
}
bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
@@ -317,7 +300,7 @@ CustomDataLayer *BKE_id_attribute_find(const ID *id,
return nullptr;
}
-CustomDataLayer *BKE_id_attribute_search(const ID *id,
+CustomDataLayer *BKE_id_attribute_search(ID *id,
const char *name,
const eCustomDataMask type_mask,
const eAttrDomainMask domain_mask)
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 48f2d66c1cd..e5bb70f8cda 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2024,13 +2024,13 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
settings.use_threading = (sData->total_points > 1000);
BLI_task_parallel_range(
0, sData->total_points, &data, dynamic_paint_apply_surface_wave_cb, &settings);
- BKE_mesh_normals_tag_dirty(mesh);
+ BKE_mesh_normals_tag_dirty(result);
}
/* displace */
if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE) {
dynamicPaint_applySurfaceDisplace(surface, result);
- BKE_mesh_normals_tag_dirty(mesh);
+ BKE_mesh_normals_tag_dirty(result);
}
}
}
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index d3c3f41779a..2d6e0e05a97 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -32,9 +32,7 @@ static void add_final_mesh_as_geometry_component(const Object &object, GeometryS
if (mesh != nullptr) {
BKE_mesh_wrapper_ensure_mdata(mesh);
-
- MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
- mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
+ geometry_set.replace_mesh(mesh, GeometryOwnershipType::ReadOnly);
}
}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index faafd1e1040..0bf5418ea8f 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -647,32 +647,38 @@ static bGPdata *gpencil_copy_structure_for_eval(bGPdata *gpd)
return gpd_eval;
}
-static void copy_frame_to_eval_cb(bGPDlayer *UNUSED(gpl),
+static void copy_frame_to_eval_ex(bGPDframe *gpf_orig, bGPDframe *gpf_eval)
+{
+ /* Free any existing eval stroke data. This happens in case we have a single user on the data
+ * block and the strokes have not been deleted. */
+ if (!BLI_listbase_is_empty(&gpf_eval->strokes)) {
+ BKE_gpencil_free_strokes(gpf_eval);
+ }
+ /* Copy strokes to eval frame and update internal orig pointers. */
+ BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval);
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+}
+
+static void copy_frame_to_eval_cb(bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *UNUSED(gps),
void *UNUSED(thunk))
{
- /* Early return when callback is not provided with a frame. */
- if (gpf == NULL) {
+ /* Early return when callback:
+ * - Is not provided with a frame.
+ * - When the frame is the layer's active frame (already handled in
+ * gpencil_copy_visible_frames_to_eval).
+ */
+ if (gpf == NULL || gpf == gpl->actframe) {
return;
}
- /* Free any existing eval stroke data. This happens in case we have a single user on the data
- * block and the strokes have not been deleted. */
- if (!BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_free_strokes(gpf);
- }
-
- /* Get original frame. */
- bGPDframe *gpf_orig = gpf->runtime.gpf_orig;
- /* Copy strokes to eval frame and update internal orig pointers. */
- BKE_gpencil_frame_copy_strokes(gpf_orig, gpf);
- BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf);
+ copy_frame_to_eval_ex(gpf->runtime.gpf_orig, gpf);
}
static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- /* Remap layers' active frame with time modifiers applied. */
+ /* Remap layers active frame with time modifiers applied. */
bGPdata *gpd_eval = ob->data;
LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) {
bGPDframe *gpf_eval = gpl_eval->actframe;
@@ -680,9 +686,14 @@ static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *sce
if (gpf_eval == NULL || gpf_eval->framenum != remap_cfra) {
gpl_eval->actframe = BKE_gpencil_layer_frame_get(gpl_eval, remap_cfra, GP_GETFRAME_USE_PREV);
}
+ /* Always copy active frame to eval, because the modifiers always evaluate the active frame,
+ * even if it's not visible (e.g. the layer is hidden).*/
+ if (gpl_eval->actframe != NULL) {
+ copy_frame_to_eval_ex(gpl_eval->actframe->runtime.gpf_orig, gpl_eval->actframe);
+ }
}
- /* Copy only visible frames to evaluated version. */
+ /* Copy visible frames that are not the active one to evaluated version. */
BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, copy_frame_to_eval_cb, NULL, NULL, true, scene->r.cfra);
}
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index 06a5d877882..0c1f01c3796 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -1730,7 +1730,7 @@ static void stampdata_from_template(StampData *stamp_data,
stamp_data->file[0] = '\0';
}
if (scene->r.stamp & R_STAMP_NOTE) {
- SNPRINTF(stamp_data->note, "%s", stamp_data_template->note);
+ STRNCPY(stamp_data->note, stamp_data_template->note);
}
else {
stamp_data->note[0] = '\0';
@@ -3895,7 +3895,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
}
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) {
- IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+ IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]);
}
for (int i = 0; i < totviews; i++) {
@@ -4064,7 +4064,7 @@ static ImBuf *image_load_image_file(
/* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] &&
tot_viewfiles == 1 && totviews >= 2) {
- IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
+ IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], ibuf_arr.data(), &ibuf_arr[1]);
}
/* return the original requested ImBuf */
diff --git a/source/blender/blenkernel/intern/lib_override.cc b/source/blender/blenkernel/intern/lib_override.cc
index aa43ca94c99..22012662180 100644
--- a/source/blender/blenkernel/intern/lib_override.cc
+++ b/source/blender/blenkernel/intern/lib_override.cc
@@ -21,8 +21,10 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "BKE_anim_data.h"
#include "BKE_armature.h"
#include "BKE_collection.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_key.h"
@@ -312,7 +314,6 @@ bool BKE_lib_override_library_is_user_edited(const ID *id)
bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
{
-
if (ID_IS_OVERRIDE_LIBRARY(id)) {
const ID *override_owner_id;
lib_override_get(bmain, id, &override_owner_id);
@@ -322,6 +323,34 @@ bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
return false;
}
+bool BKE_lib_override_library_property_is_animated(const ID *id,
+ const IDOverrideLibraryProperty *override_prop,
+ const PropertyRNA *override_rna_prop,
+ const int rnaprop_index)
+{
+ AnimData *anim_data = BKE_animdata_from_id(id);
+ if (anim_data != nullptr) {
+ struct FCurve *fcurve;
+ char *index_token_start = const_cast<char *>(
+ RNA_path_array_index_token_find(override_prop->rna_path, override_rna_prop));
+ if (index_token_start != nullptr) {
+ const char index_token_start_backup = *index_token_start;
+ *index_token_start = '\0';
+ fcurve = BKE_animadata_fcurve_find_by_rna_path(
+ anim_data, override_prop->rna_path, rnaprop_index, nullptr, nullptr);
+ *index_token_start = index_token_start_backup;
+ }
+ else {
+ fcurve = BKE_animadata_fcurve_find_by_rna_path(
+ anim_data, override_prop->rna_path, 0, nullptr, nullptr);
+ }
+ if (fcurve != nullptr) {
+ return true;
+ }
+ }
+ return false;
+}
+
static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data)
{
ID *id_owner = cb_data->id_owner;
@@ -2677,11 +2706,12 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibra
bool BKE_lib_override_rna_property_find(PointerRNA *idpoin,
const IDOverrideLibraryProperty *library_prop,
PointerRNA *r_override_poin,
- PropertyRNA **r_override_prop)
+ PropertyRNA **r_override_prop,
+ int *r_index)
{
BLI_assert(RNA_struct_is_ID(idpoin->type) && ID_IS_OVERRIDE_LIBRARY(idpoin->data));
- return RNA_path_resolve_property(
- idpoin, library_prop->rna_path, r_override_poin, r_override_prop);
+ return RNA_path_resolve_property_full(
+ idpoin, library_prop->rna_path, r_override_poin, r_override_prop, r_index);
}
void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst,
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index 14bd6aa5b2f..a1ef2d2e6b5 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -791,7 +791,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
Span<Array<short>> material_remaps,
const bool use_self,
const bool hole_tolerant,
- const int boolean_mode)
+ const int boolean_mode,
+ Vector<int> *r_intersecting_edges)
{
#ifdef WITH_GMP
BLI_assert(meshes.size() == transforms.size());
@@ -828,7 +829,23 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
write_obj_mesh(m_out, "m_out");
}
- return imesh_to_mesh(&m_out, mim);
+ Mesh *result = imesh_to_mesh(&m_out, mim);
+
+ /* Store intersecting edge indices. */
+ if (r_intersecting_edges != nullptr) {
+ for (int fi : m_out.face_index_range()) {
+ const Face &face = *m_out.face(fi);
+ const MPoly &poly = result->mpoly[fi];
+ for (int corner_i : face.index_range()) {
+ if (face.is_intersect[corner_i]) {
+ int e_index = result->mloop[poly.loopstart + corner_i].e;
+ r_intersecting_edges->append(e_index);
+ }
+ }
+ }
+ }
+
+ return result;
#else // WITH_GMP
UNUSED_VARS(meshes,
transforms,
@@ -836,7 +853,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
target_transform,
use_self,
hole_tolerant,
- boolean_mode);
+ boolean_mode,
+ r_intersecting_edges);
return nullptr;
#endif // WITH_GMP
}
diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc
index 5895eb7fd71..31e20750cf2 100644
--- a/source/blender/blenkernel/intern/mesh_calc_edges.cc
+++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc
@@ -81,7 +81,7 @@ static void add_existing_edges_to_hash_maps(Mesh *mesh,
{
/* Assume existing edges are valid. */
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
- const int task_index = &edge_map - &edge_maps[0];
+ const int task_index = &edge_map - edge_maps.data();
for (const MEdge &edge : Span(mesh->medge, mesh->totedge)) {
OrderedEdge ordered_edge{edge.v1, edge.v2};
/* Only add the edge when it belongs into this map. */
@@ -98,7 +98,7 @@ static void add_polygon_edges_to_hash_maps(Mesh *mesh,
{
const Span<MLoop> loops{mesh->mloop, mesh->totloop};
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
- const int task_index = &edge_map - &edge_maps[0];
+ const int task_index = &edge_map - edge_maps.data();
for (const MPoly &poly : Span(mesh->mpoly, mesh->totpoly)) {
Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
const MLoop *prev_loop = &poly_loops.last();
@@ -131,7 +131,7 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg
}
threading::parallel_for_each(edge_maps, [&](EdgeMap &edge_map) {
- const int task_index = &edge_map - &edge_maps[0];
+ const int task_index = &edge_map - edge_maps.data();
int new_edge_index = edge_index_offsets[task_index];
for (EdgeMap::MutableItem item : edge_map.items()) {
diff --git a/source/blender/blenkernel/intern/mesh_wrapper.cc b/source/blender/blenkernel/intern/mesh_wrapper.cc
index c505a74724b..fdebf1d6a26 100644
--- a/source/blender/blenkernel/intern/mesh_wrapper.cc
+++ b/source/blender/blenkernel/intern/mesh_wrapper.cc
@@ -314,28 +314,23 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me)
return me;
}
+ SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
+ if (runtime_data == nullptr || runtime_data->settings.level == 0) {
+ return me;
+ }
+
/* Initialize the settings before ensuring the descriptor as this is checked to decide whether
* subdivision is needed at all, and checking the descriptor status might involve checking if the
* data is out-of-date, which is a very expensive operation. */
SubdivToMeshSettings mesh_settings;
- mesh_settings.resolution = me->runtime.subsurf_resolution;
- mesh_settings.use_optimal_display = me->runtime.subsurf_use_optimal_display;
+ mesh_settings.resolution = runtime_data->resolution;
+ mesh_settings.use_optimal_display = runtime_data->use_optimal_display;
if (mesh_settings.resolution < 3) {
return me;
}
- const bool apply_render = me->runtime.subsurf_apply_render;
-
- SubdivSettings subdiv_settings;
- BKE_subsurf_modifier_subdiv_settings_init(&subdiv_settings, smd, apply_render);
- if (subdiv_settings.level == 0) {
- return me;
- }
-
- SubsurfRuntimeData *runtime_data = BKE_subsurf_modifier_ensure_runtime(smd);
-
- Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(smd, &subdiv_settings, me, false);
+ Subdiv *subdiv = BKE_subsurf_modifier_subdiv_descriptor_ensure(runtime_data, me, false);
if (subdiv == nullptr) {
/* Happens on bad topology, but also on empty input mesh. */
return me;
@@ -358,7 +353,7 @@ static Mesh *mesh_wrapper_ensure_subdivision(const Object *ob, Mesh *me)
CustomData_set_layer_flag(&me->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
CustomData_set_layer_flag(&subdiv_mesh->ldata, CD_NORMAL, CD_FLAG_TEMPORARY);
}
- else if (me->runtime.subsurf_do_loop_normals) {
+ else if (runtime_data->calc_loop_normals) {
BKE_mesh_calc_normals_split(subdiv_mesh);
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index a5f6c453ed4..8f54d71108a 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -244,24 +244,42 @@ void BKE_nla_tracks_copy(Main *bmain, ListBase *dst, const ListBase *src, const
}
}
-static void update_active_strip_from_listbase(AnimData *adt_dest,
- NlaTrack *track_dest,
- const NlaStrip *active_strip,
- const ListBase /* NlaStrip */ *strips_source)
+/**
+ * Find `active_strip` in `strips_source`, then return the strip with the same
+ * index from `strips_dest`.
+ */
+static NlaStrip *find_active_strip_from_listbase(const NlaStrip *active_strip,
+ const ListBase /* NlaStrip */ *strips_source,
+ const ListBase /* NlaStrip */ *strips_dest)
{
- NlaStrip *strip_dest = track_dest->strips.first;
+ NlaStrip *strip_dest = strips_dest->first;
LISTBASE_FOREACH (const NlaStrip *, strip_source, strips_source) {
- if (strip_source == active_strip) {
- adt_dest->actstrip = strip_dest;
- return;
+ if (strip_dest == NULL) {
+ /* The tracks are assumed to have an equal number of strips, but this is not the case when
+ * dragging multiple strips. The transform system merges the selected strips into one
+ * meta-strip, reducing the number of strips in `track_dest`. */
+ break;
}
-
- if (strip_source->type == NLASTRIP_TYPE_META) {
- update_active_strip_from_listbase(adt_dest, track_dest, active_strip, &strip_source->strips);
+ if (strip_source == active_strip) {
+ return strip_dest;
+ }
+
+ const bool src_is_meta = strip_source->type == NLASTRIP_TYPE_META;
+ const bool dst_is_meta = strip_dest->type == NLASTRIP_TYPE_META;
+ BLI_assert_msg(src_is_meta == dst_is_meta,
+ "Expecting topology of source and destination strips to be equal");
+ if (src_is_meta && dst_is_meta) {
+ NlaStrip *found_in_meta = find_active_strip_from_listbase(
+ active_strip, &strip_source->strips, &strip_dest->strips);
+ if (found_in_meta != NULL) {
+ return found_in_meta;
+ }
}
strip_dest = strip_dest->next;
}
+
+ return NULL;
}
/* Set adt_dest->actstrip to the strip with the same index as adt_source->actstrip. */
@@ -272,8 +290,9 @@ static void update_active_strip(AnimData *adt_dest,
{
BLI_assert(BLI_listbase_count(&track_source->strips) == BLI_listbase_count(&track_dest->strips));
- update_active_strip_from_listbase(
- adt_dest, track_dest, adt_source->actstrip, &track_source->strips);
+ NlaStrip *active_strip = find_active_strip_from_listbase(
+ adt_source->actstrip, &track_source->strips, &track_dest->strips);
+ adt_dest->actstrip = active_strip;
}
/* Set adt_dest->act_track to the track with the same index as adt_source->act_track. */
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 8c9db339753..3b20bdc826c 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1391,8 +1391,7 @@ void pbvh_free_draw_buffers(PBVH *pbvh, PBVHNode *node)
}
}
-static void pbvh_update_draw_buffers(
- PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag, bool full_render)
+static void pbvh_check_draw_layout(PBVH *pbvh)
{
const CustomData *vdata;
const CustomData *ldata;
@@ -1420,10 +1419,14 @@ static void pbvh_update_draw_buffers(
break;
}
- const bool active_attrs_only = !full_render;
-
- /* rebuild all draw buffers if attribute layout changed */
- if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, active_attrs_only)) {
+ /* Rebuild all draw buffers if attribute layout changed.
+ *
+ * NOTE: The optimization where we only send active attributes
+ * to the GPU in workbench mode is disabled due to bugs
+ * (there's no guarantee there isn't another EEVEE viewport which would
+ * free the draw buffers and corrupt the draw cache).
+ */
+ if (GPU_pbvh_attribute_names_update(pbvh->type, pbvh->vbo_id, vdata, ldata, false)) {
/* attribute layout changed; force rebuild */
for (int i = 0; i < pbvh->totnode; i++) {
PBVHNode *node = pbvh->nodes + i;
@@ -1433,6 +1436,33 @@ static void pbvh_update_draw_buffers(
}
}
}
+}
+
+static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
+{
+ const CustomData *vdata;
+
+ if (!pbvh->vbo_id) {
+ pbvh->vbo_id = GPU_pbvh_make_format();
+ }
+
+ switch (pbvh->type) {
+ case PBVH_BMESH:
+ if (!pbvh->bm) {
+ /* BMesh hasn't been created yet */
+ return;
+ }
+
+ vdata = &pbvh->bm->vdata;
+ break;
+ case PBVH_FACES:
+ vdata = pbvh->vdata;
+ break;
+ case PBVH_GRIDS:
+ vdata = NULL;
+ break;
+ }
+ UNUSED_VARS(vdata);
if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
@@ -2837,10 +2867,8 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
PBVHFrustumPlanes *draw_frustum,
void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers),
void *user_data,
- bool full_render)
+ bool UNUSED(full_render))
{
- pbvh->draw_cache_invalid = false;
-
PBVHNode **nodes;
int totnode;
int update_flag = 0;
@@ -2862,9 +2890,11 @@ void BKE_pbvh_draw_cb(PBVH *pbvh,
update_flag = PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers;
}
+ pbvh_check_draw_layout(pbvh);
+
/* Update draw buffers. */
if (totnode != 0 && (update_flag & (PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers))) {
- pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag, full_render);
+ pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
}
MEM_SAFE_FREE(nodes);
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index ca4130d6bc4..433bad34479 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -5,9 +5,6 @@
* \ingroup bke
*/
-#include "BKE_mesh.h"
-#include "BKE_subdiv_mesh.h"
-
#include "atomic_ops.h"
#include "DNA_key_types.h"
@@ -24,6 +21,7 @@
#include "BKE_subdiv.h"
#include "BKE_subdiv_eval.h"
#include "BKE_subdiv_foreach.h"
+#include "BKE_subdiv_mesh.h"
#include "MEM_guardedalloc.h"
diff --git a/source/blender/blenkernel/intern/subdiv_modifier.c b/source/blender/blenkernel/intern/subdiv_modifier.c
index e43da956ce5..f5423dccc0f 100644
--- a/source/blender/blenkernel/intern/subdiv_modifier.c
+++ b/source/blender/blenkernel/intern/subdiv_modifier.c
@@ -3,8 +3,6 @@
#include "BKE_subdiv_modifier.h"
-#include "BLI_session_uuid.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
@@ -21,22 +19,40 @@
#include "opensubdiv_capi.h"
-void BKE_subsurf_modifier_subdiv_settings_init(SubdivSettings *settings,
- const SubsurfModifierData *smd,
- const bool use_render_params)
+bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, const bool use_render_params)
{
const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
- settings->is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
- settings->is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
- settings->level = settings->is_simple ?
- 1 :
- (settings->is_adaptive ? smd->quality : requested_levels);
- settings->use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
- settings->vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
+ SubdivSettings settings;
+ settings.is_simple = (smd->subdivType == SUBSURF_TYPE_SIMPLE);
+ settings.is_adaptive = !(smd->flags & eSubsurfModifierFlag_UseRecursiveSubdivision);
+ settings.level = settings.is_simple ? 1 :
+ (settings.is_adaptive ? smd->quality : requested_levels);
+ settings.use_creases = (smd->flags & eSubsurfModifierFlag_UseCrease);
+ settings.vtx_boundary_interpolation = BKE_subdiv_vtx_boundary_interpolation_from_subsurf(
smd->boundary_smooth);
- settings->fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
+ settings.fvar_linear_interpolation = BKE_subdiv_fvar_interpolation_from_uv_smooth(
smd->uv_smooth);
+
+ SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
+ if (settings.level == 0) {
+ /* Modifier is effectively disabled, but still update settings if runtime data
+ * was already allocated. */
+ if (runtime_data) {
+ runtime_data->settings = settings;
+ }
+
+ return false;
+ }
+ else {
+ /* Allocate runtime data if it did not exist yet. */
+ if (runtime_data == NULL) {
+ runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
+ smd->modifier.runtime = runtime_data;
+ }
+ runtime_data->settings = settings;
+ return true;
+ }
}
static ModifierData *modifier_get_last_enabled_for_mode(const Scene *scene,
@@ -133,37 +149,27 @@ bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene,
bool BKE_subsurf_modifier_has_gpu_subdiv(const Mesh *mesh)
{
- return BLI_session_uuid_is_generated(&mesh->runtime.subsurf_session_uuid);
+ SubsurfRuntimeData *runtime_data = mesh->runtime.subsurf_runtime_data;
+ return runtime_data && runtime_data->has_gpu_subdiv;
}
void (*BKE_subsurf_modifier_free_gpu_cache_cb)(Subdiv *subdiv) = NULL;
-Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(const SubsurfModifierData *smd,
- const SubdivSettings *subdiv_settings,
+Subdiv *BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data,
const Mesh *mesh,
const bool for_draw_code)
{
- SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
if (runtime_data->subdiv && runtime_data->set_by_draw_code != for_draw_code) {
BKE_subdiv_free(runtime_data->subdiv);
runtime_data->subdiv = NULL;
}
- Subdiv *subdiv = BKE_subdiv_update_from_mesh(runtime_data->subdiv, subdiv_settings, mesh);
+ Subdiv *subdiv = BKE_subdiv_update_from_mesh(
+ runtime_data->subdiv, &runtime_data->settings, mesh);
runtime_data->subdiv = subdiv;
runtime_data->set_by_draw_code = for_draw_code;
return subdiv;
}
-SubsurfRuntimeData *BKE_subsurf_modifier_ensure_runtime(SubsurfModifierData *smd)
-{
- SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)smd->modifier.runtime;
- if (runtime_data == NULL) {
- runtime_data = MEM_callocN(sizeof(*runtime_data), "subsurf runtime");
- smd->modifier.runtime = runtime_data;
- }
- return runtime_data;
-}
-
int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
{
if (is_final_render) {
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index f9d3a44e5cb..8b462cba7ed 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -336,7 +336,11 @@ void BKE_tracking_settings_init(MovieTracking *tracking)
tracking->stabilization.filter = TRACKING_FILTER_BILINEAR;
tracking->stabilization.flag |= TRACKING_SHOW_STAB_TRACKS;
- BKE_tracking_object_add(tracking, "Camera");
+ /* Descending order of average error: tracks with the highest error are on top. */
+ tracking->dopesheet.sort_method = TRACKING_DOPE_SORT_AVERAGE_ERROR;
+ tracking->dopesheet.flag |= TRACKING_DOPE_SORT_INVERSE;
+
+ BKE_tracking_object_add(tracking, DATA_("Camera"));
}
ListBase *BKE_tracking_get_active_tracks(MovieTracking *tracking)
@@ -2904,6 +2908,10 @@ static int channels_average_error_sort(const void *a, const void *b)
return 1;
}
+ if (channel_a->track->error == channel_b->track->error) {
+ return channels_alpha_sort(a, b);
+ }
+
return 0;
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 557fb2568fe..b31632f0234 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -462,11 +462,6 @@ static size_t unit_as_string(char *str,
double value_conv = (value / unit->scalar) - unit->bias;
bool strip_skip = false;
- /* Adjust precision to expected number of significant digits.
- * Note that here, we shall not have to worry about very big/small numbers, units are expected
- * to replace 'scientific notation' in those cases. */
- prec -= integer_digits_d(value_conv);
-
/* Negative precision is used to disable stripping of zeroes.
* This reduces text jumping when changing values. */
if (prec < 0) {
@@ -474,6 +469,11 @@ static size_t unit_as_string(char *str,
prec *= -1;
}
+ /* Adjust precision to expected number of significant digits.
+ * Note that here, we shall not have to worry about very big/small numbers, units are expected
+ * to replace 'scientific notation' in those cases. */
+ prec -= integer_digits_d(value_conv);
+
CLAMP(prec, 0, 6);
/* Convert to a string. */
@@ -491,10 +491,10 @@ static size_t unit_as_string(char *str,
while (i > 0 && str[i] == '0') { /* 4.300 -> 4.3 */
str[i--] = pad;
}
- }
- if (i > 0 && str[i] == '.') { /* 10. -> 10 */
- str[i--] = pad;
+ if (i > 0 && str[i] == '.') { /* 10. -> 10 */
+ str[i--] = pad;
+ }
}
}