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.cc36
-rw-r--r--source/blender/blenkernel/intern/action.c21
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c6
-rw-r--r--source/blender/blenkernel/intern/armature.c35
-rw-r--r--source/blender/blenkernel/intern/armature_test.cc6
-rw-r--r--source/blender/blenkernel/intern/autoexec.c2
-rw-r--r--source/blender/blenkernel/intern/blendfile.c4
-rw-r--r--source/blender/blenkernel/intern/boids.c30
-rw-r--r--source/blender/blenkernel/intern/brush.c78
-rw-r--r--source/blender/blenkernel/intern/cachefile.c140
-rw-r--r--source/blender/blenkernel/intern/camera.c19
-rw-r--r--source/blender/blenkernel/intern/cloth.c17
-rw-r--r--source/blender/blenkernel/intern/collection.c31
-rw-r--r--source/blender/blenkernel/intern/colortools.c20
-rw-r--r--source/blender/blenkernel/intern/constraint.c165
-rw-r--r--source/blender/blenkernel/intern/context.c4
-rw-r--r--source/blender/blenkernel/intern/curve.c98
-rw-r--r--source/blender/blenkernel/intern/customdata.c7
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c6
-rw-r--r--source/blender/blenkernel/intern/deform.c5
-rw-r--r--source/blender/blenkernel/intern/displist.cc2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c10
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/fluid.c32
-rw-r--r--source/blender/blenkernel/intern/font.c132
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc4
-rw-r--r--source/blender/blenkernel/intern/gpencil.c78
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc255
-rw-r--r--source/blender/blenkernel/intern/hair.c49
-rw-r--r--source/blender/blenkernel/intern/icons.cc2
-rw-r--r--source/blender/blenkernel/intern/image.c146
-rw-r--r--source/blender/blenkernel/intern/image_gpu.c3
-rw-r--r--source/blender/blenkernel/intern/image_save.c19
-rw-r--r--source/blender/blenkernel/intern/key.c54
-rw-r--r--source/blender/blenkernel/intern/lattice.c33
-rw-r--r--source/blender/blenkernel/intern/layer.c84
-rw-r--r--source/blender/blenkernel/intern/lib_id.c14
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c35
-rw-r--r--source/blender/blenkernel/intern/lib_override.c30
-rw-r--r--source/blender/blenkernel/intern/lib_query.c4
-rw-r--r--source/blender/blenkernel/intern/light.c31
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c15
-rw-r--r--source/blender/blenkernel/intern/linestyle.c35
-rw-r--r--source/blender/blenkernel/intern/mask.c61
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c10
-rw-r--r--source/blender/blenkernel/intern/material.c40
-rw-r--r--source/blender/blenkernel/intern/mball.c43
-rw-r--r--source/blender/blenkernel/intern/mesh.c515
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c9
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c17
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc574
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c12
-rw-r--r--source/blender/blenkernel/intern/mesh_remesh_voxel.cc134
-rw-r--r--source/blender/blenkernel/intern/modifier.c4
-rw-r--r--source/blender/blenkernel/intern/movieclip.c45
-rw-r--r--source/blender/blenkernel/intern/multires.c10
-rw-r--r--source/blender/blenkernel/intern/node.cc26
-rw-r--r--source/blender/blenkernel/intern/object.c169
-rw-r--r--source/blender/blenkernel/intern/object_deform.c10
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc6
-rw-r--r--source/blender/blenkernel/intern/ocean.c117
-rw-r--r--source/blender/blenkernel/intern/ocean_spectrum.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c22
-rw-r--r--source/blender/blenkernel/intern/particle.c110
-rw-r--r--source/blender/blenkernel/intern/particle_system.c18
-rw-r--r--source/blender/blenkernel/intern/pbvh.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c14
-rw-r--r--source/blender/blenkernel/intern/pointcloud.cc41
-rw-r--r--source/blender/blenkernel/intern/scene.c31
-rw-r--r--source/blender/blenkernel/intern/screen.c22
-rw-r--r--source/blender/blenkernel/intern/simulation.cc29
-rw-r--r--source/blender/blenkernel/intern/softbody.c18
-rw-r--r--source/blender/blenkernel/intern/sound.c48
-rw-r--r--source/blender/blenkernel/intern/speaker.c15
-rw-r--r--source/blender/blenkernel/intern/spline_base.cc16
-rw-r--r--source/blender/blenkernel/intern/studiolight.c24
-rw-r--r--source/blender/blenkernel/intern/text.c5
-rw-r--r--source/blender/blenkernel/intern/text_suggestions.c10
-rw-r--r--source/blender/blenkernel/intern/texture.c53
-rw-r--r--source/blender/blenkernel/intern/tracking_auto.c4
-rw-r--r--source/blender/blenkernel/intern/volume.cc31
-rw-r--r--source/blender/blenkernel/intern/volume_to_mesh.cc2
-rw-r--r--source/blender/blenkernel/intern/workspace.c2
-rw-r--r--source/blender/blenkernel/intern/world.c29
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c44
85 files changed, 2256 insertions, 1937 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index ba8cf8debe9..59e81938e79 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -360,7 +360,7 @@ void DM_init(DerivedMesh *dm,
dm->needsFree = 1;
dm->dirty = (DMDirtyFlag)0;
- /* Don't use CustomData_reset(...); because we don't want to touch custom-data. */
+ /* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
copy_vn_i(dm->edgeData.typemap, CD_NUMTYPES, -1);
copy_vn_i(dm->faceData.typemap, CD_NUMTYPES, -1);
@@ -816,15 +816,14 @@ static void mesh_calc_modifier_final_normals(const Mesh *mesh_input,
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
- BKE_mesh_calc_normals_poly(mesh_final->mvert,
- nullptr,
- mesh_final->totvert,
- mesh_final->mloop,
- mesh_final->mpoly,
- mesh_final->totloop,
- mesh_final->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
+ mesh_final->totvert,
+ mesh_final->mloop,
+ mesh_final->totloop,
+ mesh_final->mpoly,
+ mesh_final->totpoly,
+ polynors,
+ nullptr);
}
}
@@ -1536,15 +1535,14 @@ static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final,
if (!CustomData_has_layer(&mesh_final->pdata, CD_NORMAL)) {
float(*polynors)[3] = (float(*)[3])CustomData_add_layer(
&mesh_final->pdata, CD_NORMAL, CD_CALLOC, nullptr, mesh_final->totpoly);
- BKE_mesh_calc_normals_poly(mesh_final->mvert,
- nullptr,
- mesh_final->totvert,
- mesh_final->mloop,
- mesh_final->mpoly,
- mesh_final->totloop,
- mesh_final->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh_final->mvert,
+ mesh_final->totvert,
+ mesh_final->mloop,
+ mesh_final->totloop,
+ mesh_final->mpoly,
+ mesh_final->totpoly,
+ polynors,
+ nullptr);
}
}
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index d55f023d209..981815f400a 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -186,22 +186,21 @@ static void action_foreach_id(ID *id, LibraryForeachIDData *data)
static void action_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bAction *act = (bAction *)id;
- if (act->id.us > 0 || BLO_write_is_undo(writer)) {
- BLO_write_id_struct(writer, bAction, id_address, &act->id);
- BKE_id_blend_write(writer, &act->id);
- BKE_fcurve_blend_write(writer, &act->curves);
+ BLO_write_id_struct(writer, bAction, id_address, &act->id);
+ BKE_id_blend_write(writer, &act->id);
- LISTBASE_FOREACH (bActionGroup *, grp, &act->groups) {
- BLO_write_struct(writer, bActionGroup, grp);
- }
+ BKE_fcurve_blend_write(writer, &act->curves);
- LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
- BLO_write_struct(writer, TimeMarker, marker);
- }
+ LISTBASE_FOREACH (bActionGroup *, grp, &act->groups) {
+ BLO_write_struct(writer, bActionGroup, grp);
+ }
- BKE_previewimg_blend_write(writer, act->preview);
+ LISTBASE_FOREACH (TimeMarker *, marker, &act->markers) {
+ BLO_write_struct(writer, TimeMarker, marker);
}
+
+ BKE_previewimg_blend_write(writer, act->preview);
}
static void action_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index fae75762cde..92b0db5b214 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -426,7 +426,7 @@ bool BKE_animsys_rna_path_resolve(PointerRNA *ptr,
}
/* less than 1.0 evaluates to false, use epsilon to avoid float error */
-#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON)))
+#define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > (1.0f - FLT_EPSILON))
bool BKE_animsys_read_from_rna_path(PathResolvedRNA *anim_rna, float *r_value)
{
@@ -2625,7 +2625,7 @@ static void animsys_create_action_track_strip(const AnimData *adt,
bAction *action = adt->action;
- if ((adt->flag & ADT_NLA_EDIT_ON)) {
+ if (adt->flag & ADT_NLA_EDIT_ON) {
action = adt->tmpact;
}
@@ -2671,7 +2671,7 @@ static void animsys_create_action_track_strip(const AnimData *adt,
static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
{
/* Skip disabled tracks unless it contains the tweaked strip. */
- const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) &&
+ const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) && adt->act_track &&
(nlt->index == adt->act_track->index);
if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
return false;
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b8ed519e8d1..87320c88b1b 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -212,25 +212,24 @@ static void write_bone(BlendWriter *writer, Bone *bone)
static void armature_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bArmature *arm = (bArmature *)id;
- if (arm->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- arm->bonehash = NULL;
- arm->edbo = NULL;
- /* Must always be cleared (armatures don't have their own edit-data). */
- arm->needs_flush_to_id = 0;
- arm->act_edbone = NULL;
- BLO_write_id_struct(writer, bArmature, id_address, &arm->id);
- BKE_id_blend_write(writer, &arm->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ arm->bonehash = NULL;
+ arm->edbo = NULL;
+ /* Must always be cleared (armatures don't have their own edit-data). */
+ arm->needs_flush_to_id = 0;
+ arm->act_edbone = NULL;
- if (arm->adt) {
- BKE_animdata_blend_write(writer, arm->adt);
- }
+ BLO_write_id_struct(writer, bArmature, id_address, &arm->id);
+ BKE_id_blend_write(writer, &arm->id);
- /* Direct data */
- LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
- write_bone(writer, bone);
- }
+ if (arm->adt) {
+ BKE_animdata_blend_write(writer, arm->adt);
+ }
+
+ /* Direct data */
+ LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) {
+ write_bone(writer, bone);
}
}
@@ -1882,7 +1881,7 @@ void BKE_bone_parent_transform_invert(struct BoneParentTransform *bpt)
{
invert_m4(bpt->rotscale_mat);
invert_m4(bpt->loc_mat);
- invert_v3(bpt->post_scale);
+ invert_v3_safe(bpt->post_scale);
}
void BKE_bone_parent_transform_combine(const struct BoneParentTransform *in1,
@@ -2663,7 +2662,7 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
}
}
- /* printf("rebuild pose %s, %d bones\n", ob->id.name, counter); */
+ // printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
/* synchronize protected layers with proxy */
/* HACK! To preserve 2.7x behavior that you always can pose even locked bones,
diff --git a/source/blender/blenkernel/intern/armature_test.cc b/source/blender/blenkernel/intern/armature_test.cc
index 47853deec3e..99eb064d061 100644
--- a/source/blender/blenkernel/intern/armature_test.cc
+++ b/source/blender/blenkernel/intern/armature_test.cc
@@ -180,7 +180,7 @@ class BKE_armature_find_selected_bones_test : public testing::Test {
BLI_addtail(&arm.bonebase, &bone2); // bone2 is root bone
BLI_addtail(&bone2.childbase, &bone3); // bone3 has bone2 as parent
- // Make sure the armature & its bones are visible, to make them selectable.
+ /* Make sure the armature & its bones are visible, to make them selectable. */
arm.layer = bone1.layer = bone2.layer = bone3.layer = 1;
}
};
@@ -200,8 +200,8 @@ TEST_F(BKE_armature_find_selected_bones_test, some_bones_selected)
EXPECT_EQ(seen_bones[0], &bone1);
EXPECT_EQ(seen_bones[1], &bone3);
- EXPECT_FALSE(result.all_bones_selected); // Bone 2 was not selected.
- EXPECT_FALSE(result.no_bones_selected); // Bones 1 and 3 were selected.
+ EXPECT_FALSE(result.all_bones_selected); /* Bone 2 was not selected. */
+ EXPECT_FALSE(result.no_bones_selected); /* Bones 1 and 3 were selected. */
}
TEST_F(BKE_armature_find_selected_bones_test, no_bones_selected)
diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c
index 07b096af941..3aec646b024 100644
--- a/source/blender/blenkernel/intern/autoexec.c
+++ b/source/blender/blenkernel/intern/autoexec.c
@@ -56,7 +56,7 @@ bool BKE_autoexec_match(const char *path)
if (path_cmp->path[0] == '\0') {
/* pass */
}
- else if ((path_cmp->flag & USER_PATHCMP_GLOB)) {
+ else if (path_cmp->flag & USER_PATHCMP_GLOB) {
if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) {
return true;
}
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 61827be08e5..1c5d8804280 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -660,10 +660,6 @@ UserDef *BKE_blendfile_userdef_from_defaults(void)
BKE_studiolight_default(userdef->light_param, userdef->light_ambient);
BKE_preferences_asset_library_default_add(userdef);
- /* Enable asset browser features by default for alpha testing.
- * BLO_sanitize_experimental_features_userpref_blend() will disable it again for non-alpha
- * builds. */
- userdef->experimental.use_asset_browser = true;
return userdef;
}
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 9caf416cd0c..a7257133821 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -342,10 +342,7 @@ static bool rule_avoid_collision(BoidRule *rule,
}
}
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* check boids in other systems */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -401,10 +398,7 @@ static bool rule_avoid_collision(BoidRule *rule,
}
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
@@ -435,10 +429,7 @@ static bool rule_separate(BoidRule *UNUSED(rule),
len = ptn[1].dist;
ret = 1;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* check other boid systems */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -457,10 +448,7 @@ static bool rule_separate(BoidRule *UNUSED(rule),
ret = true;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
return ret;
@@ -723,10 +711,7 @@ static bool rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Part
f_strength += bbd->part->boids->strength * health;
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
/* add other friendlies and calculate enemy strength and find closest enemy */
for (pt = bbd->sim->psys->targets.first; pt; pt = pt->next) {
@@ -755,10 +740,7 @@ static bool rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Part
f_strength += epsys->part->boids->strength * health;
}
- if (ptn) {
- MEM_freeN(ptn);
- ptn = NULL;
- }
+ MEM_SAFE_FREE(ptn);
}
}
/* decide action if enemy presence found */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index abf7bab7612..7b81187be21 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -202,49 +202,48 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Brush *brush = (Brush *)id;
- if (brush->id.us > 0 || BLO_write_is_undo(writer)) {
- BLO_write_id_struct(writer, Brush, id_address, &brush->id);
- BKE_id_blend_write(writer, &brush->id);
- if (brush->curve) {
- BKE_curvemapping_blend_write(writer, brush->curve);
- }
+ BLO_write_id_struct(writer, Brush, id_address, &brush->id);
+ BKE_id_blend_write(writer, &brush->id);
- if (brush->gpencil_settings) {
- BLO_write_struct(writer, BrushGpencilSettings, brush->gpencil_settings);
+ if (brush->curve) {
+ BKE_curvemapping_blend_write(writer, brush->curve);
+ }
- if (brush->gpencil_settings->curve_sensitivity) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_sensitivity);
- }
- if (brush->gpencil_settings->curve_strength) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_strength);
- }
- if (brush->gpencil_settings->curve_jitter) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_jitter);
- }
- if (brush->gpencil_settings->curve_rand_pressure) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_pressure);
- }
- if (brush->gpencil_settings->curve_rand_strength) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_strength);
- }
- if (brush->gpencil_settings->curve_rand_uv) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_uv);
- }
- if (brush->gpencil_settings->curve_rand_hue) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_hue);
- }
- if (brush->gpencil_settings->curve_rand_saturation) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_saturation);
- }
- if (brush->gpencil_settings->curve_rand_value) {
- BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_value);
- }
+ if (brush->gpencil_settings) {
+ BLO_write_struct(writer, BrushGpencilSettings, brush->gpencil_settings);
+
+ if (brush->gpencil_settings->curve_sensitivity) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_sensitivity);
+ }
+ if (brush->gpencil_settings->curve_strength) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_strength);
+ }
+ if (brush->gpencil_settings->curve_jitter) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_jitter);
+ }
+ if (brush->gpencil_settings->curve_rand_pressure) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_pressure);
+ }
+ if (brush->gpencil_settings->curve_rand_strength) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_strength);
+ }
+ if (brush->gpencil_settings->curve_rand_uv) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_uv);
+ }
+ if (brush->gpencil_settings->curve_rand_hue) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_hue);
+ }
+ if (brush->gpencil_settings->curve_rand_saturation) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_saturation);
}
- if (brush->gradient) {
- BLO_write_struct(writer, ColorBand, brush->gradient);
+ if (brush->gpencil_settings->curve_rand_value) {
+ BKE_curvemapping_blend_write(writer, brush->gpencil_settings->curve_rand_value);
}
}
+ if (brush->gradient) {
+ BLO_write_struct(writer, ColorBand, brush->gradient);
+ }
}
static void brush_blend_read_data(BlendDataReader *reader, ID *id)
@@ -660,10 +659,7 @@ static void brush_gpencil_curvemap_reset(CurveMap *cuma, int tot, int preset)
break;
}
- if (cuma->table) {
- MEM_freeN(cuma->table);
- cuma->table = NULL;
- }
+ MEM_SAFE_FREE(cuma->table);
}
void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index eaba5d33a20..87b1584d422 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -49,12 +49,18 @@
#include "DEG_depsgraph_query.h"
+#include "RE_engine.h"
+
#include "BLO_read_write.h"
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
#endif
+#ifdef WITH_USD
+# include "usd.h"
+#endif
+
static void cachefile_handle_free(CacheFile *cache_file);
static void cache_file_init_data(ID *id)
@@ -91,19 +97,18 @@ static void cache_file_free_data(ID *id)
static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
CacheFile *cache_file = (CacheFile *)id;
- if (cache_file->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- BLI_listbase_clear(&cache_file->object_paths);
- cache_file->handle = NULL;
- memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath));
- cache_file->handle_readers = NULL;
- BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
- BKE_id_blend_write(writer, &cache_file->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ BLI_listbase_clear(&cache_file->object_paths);
+ cache_file->handle = NULL;
+ memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath));
+ cache_file->handle_readers = NULL;
+
+ BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
+ BKE_id_blend_write(writer, &cache_file->id);
- if (cache_file->adt) {
- BKE_animdata_blend_write(writer, cache_file->adt);
- }
+ if (cache_file->adt) {
+ BKE_animdata_blend_write(writer, cache_file->adt);
}
}
@@ -166,15 +171,30 @@ void BKE_cachefile_reader_open(CacheFile *cache_file,
Object *object,
const char *object_path)
{
-#ifdef WITH_ALEMBIC
+#if defined(WITH_ALEMBIC) || defined(WITH_USD)
+
BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
if (cache_file->handle == NULL) {
return;
}
- /* Open Alembic cache reader. */
- *reader = CacheReader_open_alembic_object(cache_file->handle, *reader, object, object_path);
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ /* Open Alembic cache reader. */
+ *reader = CacheReader_open_alembic_object(cache_file->handle, *reader, object, object_path);
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ /* Open USD cache reader. */
+ *reader = CacheReader_open_usd_object(cache_file->handle, *reader, object, object_path);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
/* Multiple modifiers and constraints can call this function concurrently. */
BLI_spin_lock(&spin);
@@ -197,16 +217,30 @@ void BKE_cachefile_reader_open(CacheFile *cache_file,
void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader)
{
-#ifdef WITH_ALEMBIC
+#if defined(WITH_ALEMBIC) || defined(WITH_USD)
/* Multiple modifiers and constraints can call this function concurrently, and
* cachefile_handle_free() can also be called at the same time. */
BLI_spin_lock(&spin);
if (*reader != NULL) {
if (cache_file) {
BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
+
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ ABC_CacheReader_free(*reader);
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ USD_CacheReader_free(*reader);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
}
- CacheReader_free(*reader);
*reader = NULL;
if (cache_file && cache_file->handle_readers) {
@@ -221,7 +255,8 @@ void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reade
static void cachefile_handle_free(CacheFile *cache_file)
{
-#ifdef WITH_ALEMBIC
+#if defined(WITH_ALEMBIC) || defined(WITH_USD)
+
/* Free readers in all modifiers and constraints that use the handle, before
* we free the handle itself. */
BLI_spin_lock(&spin);
@@ -230,7 +265,21 @@ static void cachefile_handle_free(CacheFile *cache_file)
GSET_ITER (gs_iter, cache_file->handle_readers) {
struct CacheReader **reader = BLI_gsetIterator_getKey(&gs_iter);
if (*reader != NULL) {
- CacheReader_free(*reader);
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ ABC_CacheReader_free(*reader);
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ USD_CacheReader_free(*reader);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
+
*reader = NULL;
}
}
@@ -242,7 +291,22 @@ static void cachefile_handle_free(CacheFile *cache_file)
/* Free handle. */
if (cache_file->handle) {
- ABC_free_handle(cache_file->handle);
+
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ ABC_free_handle(cache_file->handle);
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ USD_free_handle(cache_file->handle);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
+
cache_file->handle = NULL;
}
@@ -289,12 +353,22 @@ void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file
BLI_freelistN(&cache_file->object_paths);
#ifdef WITH_ALEMBIC
- cache_file->handle = ABC_create_handle(bmain, filepath, &cache_file->object_paths);
- BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
+ if (BLI_path_extension_check_glob(filepath, "*abc")) {
+ cache_file->type = CACHEFILE_TYPE_ALEMBIC;
+ cache_file->handle = ABC_create_handle(bmain, filepath, &cache_file->object_paths);
+ BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
+ }
+#endif
+#ifdef WITH_USD
+ if (BLI_path_extension_check_glob(filepath, "*.usd;*.usda;*.usdc")) {
+ cache_file->type = CACHEFILE_TYPE_USD;
+ cache_file->handle = USD_create_handle(bmain, filepath, &cache_file->object_paths);
+ BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
+ }
#endif
if (DEG_is_active(depsgraph)) {
- /* Flush object paths back to original datablock for UI. */
+ /* Flush object paths back to original data-block for UI. */
CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id);
BLI_freelistN(&cache_file_orig->object_paths);
BLI_duplicatelist(&cache_file_orig->object_paths, &cache_file->object_paths);
@@ -336,3 +410,25 @@ float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, c
const float frame = (cache_file->override_frame ? cache_file->frame : time);
return cache_file->is_sequence ? frame : frame / fps - time_offset;
}
+
+/**
+ * Determine whether the #CacheFile should use a render engine procedural. If so, data is not read
+ * from the file and bounding boxes are used to represent the objects in the Scene.
+ * Render engines will receive the bounding box as a placeholder but can instead
+ * load the data directly if they support it.
+ */
+bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file,
+ Scene *scene,
+ const int dag_eval_mode)
+{
+ RenderEngineType *render_engine_type = RE_engines_find(scene->r.engine);
+
+ if (cache_file->type != CACHEFILE_TYPE_ALEMBIC ||
+ !RE_engine_supports_alembic_procedural(render_engine_type, scene)) {
+ return false;
+ }
+
+ /* The render time procedural is only enabled during viewport rendering. */
+ const bool is_final_render = (eEvaluationMode)dag_eval_mode == DAG_EVAL_RENDER;
+ return cache_file->use_render_procedural && !is_final_render;
+}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 5172b067eba..46b079fb42e 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -122,18 +122,17 @@ static void camera_foreach_id(ID *id, LibraryForeachIDData *data)
static void camera_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Camera *cam = (Camera *)id;
- if (cam->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, Camera, id_address, &cam->id);
- BKE_id_blend_write(writer, &cam->id);
- if (cam->adt) {
- BKE_animdata_blend_write(writer, cam->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Camera, id_address, &cam->id);
+ BKE_id_blend_write(writer, &cam->id);
- LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
- BLO_write_struct(writer, CameraBGImage, bgpic);
- }
+ if (cam->adt) {
+ BKE_animdata_blend_write(writer, cam->adt);
+ }
+
+ LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) {
+ BLO_write_struct(writer, CameraBGImage, bgpic);
}
}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 0fa58a74f2b..080a7c90c46 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -42,6 +42,7 @@
#include "BKE_cloth.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_lib_id.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@@ -447,11 +448,7 @@ void cloth_free_modifier(ClothModifierData *clmd)
SIM_cloth_solver_free(clmd);
/* Free the verts. */
- if (cloth->verts != NULL) {
- MEM_freeN(cloth->verts);
- }
-
- cloth->verts = NULL;
+ MEM_SAFE_FREE(cloth->verts);
cloth->mvert_num = 0;
/* Free the springs. */
@@ -529,11 +526,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd)
SIM_cloth_solver_free(clmd);
/* Free the verts. */
- if (cloth->verts != NULL) {
- MEM_freeN(cloth->verts);
- }
-
- cloth->verts = NULL;
+ MEM_SAFE_FREE(cloth->verts);
cloth->mvert_num = 0;
/* Free the springs. */
@@ -1582,7 +1575,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
BLI_edgeset_free(existing_vert_pairs);
free_bvhtree_from_mesh(&treedata);
if (tmp_mesh) {
- BKE_mesh_free(tmp_mesh);
+ BKE_id_free(NULL, &tmp_mesh->id);
}
return false;
}
@@ -1591,7 +1584,7 @@ static bool cloth_build_springs(ClothModifierData *clmd, Mesh *mesh)
BLI_edgeset_free(existing_vert_pairs);
free_bvhtree_from_mesh(&treedata);
if (tmp_mesh) {
- BKE_mesh_free(tmp_mesh);
+ BKE_id_free(NULL, &tmp_mesh->id);
}
BLI_rng_free(rng);
}
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index b90214f1814..d36e9b67d00 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -214,20 +214,19 @@ void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collectio
static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Collection *collection = (Collection *)id;
- if (collection->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
- collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
- collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
- collection->tag = 0;
- BLI_listbase_clear(&collection->object_cache);
- BLI_listbase_clear(&collection->object_cache_instanced);
- BLI_listbase_clear(&collection->parents);
- /* write LibData */
- BLO_write_id_struct(writer, Collection, id_address, &collection->id);
+ /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
+ collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE_INSTANCED;
+ collection->tag = 0;
+ BLI_listbase_clear(&collection->object_cache);
+ BLI_listbase_clear(&collection->object_cache_instanced);
+ BLI_listbase_clear(&collection->parents);
- BKE_collection_blend_write_nolib(writer, collection);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Collection, id_address, &collection->id);
+
+ BKE_collection_blend_write_nolib(writer, collection);
}
#ifdef USE_COLLECTION_COMPAT_28
@@ -508,7 +507,7 @@ void BKE_collection_add_from_collection(Main *bmain,
* \{ */
/** Free (or release) any data used by this collection (does not free the collection itself). */
-void BKE_collection_free(Collection *collection)
+void BKE_collection_free_data(Collection *collection)
{
BKE_libblock_free_data(&collection->id, false);
collection_free_data(&collection->id);
@@ -806,10 +805,10 @@ static void collection_object_cache_fill(ListBase *lb,
/* Only collection flags are checked here currently, object restrict flag is checked
* in FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN since it can be animated
* without updating the cache. */
- if (((child_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0)) {
+ if (((child_restrict & COLLECTION_HIDE_VIEWPORT) == 0)) {
base->flag |= BASE_ENABLED_VIEWPORT;
}
- if (((child_restrict & COLLECTION_RESTRICT_RENDER) == 0)) {
+ if (((child_restrict & COLLECTION_HIDE_RENDER) == 0)) {
base->flag |= BASE_ENABLED_RENDER;
}
}
@@ -1755,7 +1754,7 @@ static bool collection_objects_select(ViewLayer *view_layer, Collection *collect
{
bool changed = false;
- if (collection->flag & COLLECTION_RESTRICT_SELECT) {
+ if (collection->flag & COLLECTION_HIDE_SELECT) {
return false;
}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index a9f0f69b855..f2c2e552a9f 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -1716,22 +1716,10 @@ void BKE_scopes_update(Scopes *scopes,
void BKE_scopes_free(Scopes *scopes)
{
- if (scopes->waveform_1) {
- MEM_freeN(scopes->waveform_1);
- scopes->waveform_1 = NULL;
- }
- if (scopes->waveform_2) {
- MEM_freeN(scopes->waveform_2);
- scopes->waveform_2 = NULL;
- }
- if (scopes->waveform_3) {
- MEM_freeN(scopes->waveform_3);
- scopes->waveform_3 = NULL;
- }
- if (scopes->vecscope) {
- MEM_freeN(scopes->vecscope);
- scopes->vecscope = NULL;
- }
+ MEM_SAFE_FREE(scopes->waveform_1);
+ MEM_SAFE_FREE(scopes->waveform_2);
+ MEM_SAFE_FREE(scopes->waveform_3);
+ MEM_SAFE_FREE(scopes->vecscope);
}
void BKE_scopes_new(Scopes *scopes)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 47df31e3a2c..30aa22387d0 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -95,6 +95,10 @@
# include "ABC_alembic.h"
#endif
+#ifdef WITH_USD
+# include "usd.h"
+#endif
+
/* ---------------------------------------------------------------------------- */
/* Useful macros for testing various common flag combinations */
@@ -2978,6 +2982,16 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) {
switch (data->mix_mode) {
+ /* Simple matrix multiplication. */
+ case ACTCON_MIX_BEFORE_FULL:
+ mul_m4_m4m4(cob->matrix, ct->matrix, cob->matrix);
+ break;
+
+ case ACTCON_MIX_AFTER_FULL:
+ mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix);
+ break;
+
+ /* Aligned Inherit Scale emulation. */
case ACTCON_MIX_BEFORE:
mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
break;
@@ -2986,8 +3000,13 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
break;
- case ACTCON_MIX_AFTER_FULL:
- mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix);
+ /* Fully separate handling of channels. */
+ case ACTCON_MIX_BEFORE_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, ct->matrix, cob->matrix);
+ break;
+
+ case ACTCON_MIX_AFTER_SPLIT:
+ mul_m4_m4m4_split_channels(cob->matrix, cob->matrix, ct->matrix);
break;
default:
@@ -4612,9 +4631,7 @@ static void splineik_free(bConstraint *con)
bSplineIKConstraint *data = con->data;
/* binding array */
- if (data->points) {
- MEM_freeN(data->points);
- }
+ MEM_SAFE_FREE(data->points);
}
static void splineik_copy(bConstraint *con, bConstraint *srccon)
@@ -5403,7 +5420,7 @@ static void transformcache_id_looper(bConstraint *con, ConstraintIDFunc func, vo
static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
-#ifdef WITH_ALEMBIC
+#if defined(WITH_ALEMBIC) || defined(WITH_USD)
bTransformCacheConstraint *data = con->data;
Scene *scene = cob->scene;
@@ -5413,6 +5430,11 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
return;
}
+ /* Do not process data if using a render time procedural. */
+ if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(cob->depsgraph))) {
+ return;
+ }
+
const float frame = DEG_get_ctime(cob->depsgraph);
const float time = BKE_cachefile_time_offset(cache_file, frame, FPS);
@@ -5421,7 +5443,20 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa
BKE_cachefile_reader_open(cache_file, &data->reader, cob->ob, data->object_path);
}
- ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale);
+ switch (cache_file->type) {
+ case CACHEFILE_TYPE_ALEMBIC:
+# ifdef WITH_ALEMBIC
+ ABC_get_transform(data->reader, cob->matrix, time, cache_file->scale);
+# endif
+ break;
+ case CACHEFILE_TYPE_USD:
+# ifdef WITH_USD
+ USD_get_transform(data->reader, cob->matrix, time * FPS, cache_file->scale);
+# endif
+ break;
+ case CACHE_FILE_TYPE_INVALID:
+ break;
+ }
#else
UNUSED_VARS(con, cob);
#endif
@@ -5647,6 +5682,111 @@ bool BKE_constraint_remove_ex(ListBase *list, Object *ob, bConstraint *con, bool
return false;
}
+/* Apply the specified constraint in the given constraint stack */
+bool BKE_constraint_apply_for_object(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ bConstraint *con)
+{
+ if (!con) {
+ return false;
+ }
+
+ const float ctime = BKE_scene_frame_get(scene);
+
+ bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob));
+ ListBase single_con = {new_con, new_con};
+
+ bConstraintOb *cob = BKE_constraints_make_evalob(
+ depsgraph, scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
+ /* Undo the effect of the current constraint stack evaluation. */
+ mul_m4_m4m4(cob->matrix, ob->constinv, cob->matrix);
+
+ /* Evaluate single constraint. */
+ BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
+ /* Copy transforms back. This will leave the object in a bad state
+ * as ob->constinv will be wrong until next evaluation. */
+ BKE_constraints_clear_evalob(cob);
+
+ /* Free the copied constraint. */
+ BKE_constraint_free_data(new_con);
+ BLI_freelinkN(&single_con, new_con);
+
+ /* Apply transform from matrix. */
+ BKE_object_apply_mat4(ob, ob->obmat, true, true);
+
+ return true;
+}
+
+bool BKE_constraint_apply_and_remove_for_object(Depsgraph *depsgraph,
+ Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ Object *ob,
+ bConstraint *con)
+{
+ if (!BKE_constraint_apply_for_object(depsgraph, scene, ob, con)) {
+ return false;
+ }
+
+ return BKE_constraint_remove_ex(constraints, ob, con, true);
+}
+
+bool BKE_constraint_apply_for_pose(
+ Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, bConstraint *con)
+{
+ if (!con) {
+ return false;
+ }
+
+ const float ctime = BKE_scene_frame_get(scene);
+
+ bConstraint *new_con = BKE_constraint_duplicate_ex(con, 0, !ID_IS_LINKED(ob));
+ ListBase single_con;
+ single_con.first = new_con;
+ single_con.last = new_con;
+
+ float vec[3];
+ copy_v3_v3(vec, pchan->pose_mat[3]);
+
+ bConstraintOb *cob = BKE_constraints_make_evalob(
+ depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
+ /* Undo the effects of currently applied constraints. */
+ mul_m4_m4m4(cob->matrix, pchan->constinv, cob->matrix);
+ /* Evaluate single constraint. */
+ BKE_constraints_solve(depsgraph, &single_con, cob, ctime);
+ BKE_constraints_clear_evalob(cob);
+
+ /* Free the copied constraint. */
+ BKE_constraint_free_data(new_con);
+ BLI_freelinkN(&single_con, new_con);
+
+ /* Prevent constraints breaking a chain. */
+ if (pchan->bone->flag & BONE_CONNECTED) {
+ copy_v3_v3(pchan->pose_mat[3], vec);
+ }
+
+ /* Apply transform from matrix. */
+ float mat[4][4];
+ BKE_armature_mat_pose_to_bone(pchan, pchan->pose_mat, mat);
+ BKE_pchan_apply_mat4(pchan, mat, true);
+
+ return true;
+}
+
+bool BKE_constraint_apply_and_remove_for_pose(Depsgraph *depsgraph,
+ Scene *scene,
+ ListBase /*bConstraint*/ *constraints,
+ Object *ob,
+ bConstraint *con,
+ bPoseChannel *pchan)
+{
+ if (!BKE_constraint_apply_for_pose(depsgraph, scene, ob, pchan, con)) {
+ return false;
+ }
+
+ return BKE_constraint_remove_ex(constraints, ob, con, true);
+}
+
void BKE_constraint_panel_expand(bConstraint *con)
{
con->ui_expand_flag |= UI_PANEL_DATA_EXPAND_ROOT;
@@ -5752,6 +5892,17 @@ static bConstraint *add_new_constraint(Object *ob,
}
break;
}
+ case CONSTRAINT_TYPE_ACTION: {
+ /* The Before or Split modes require computing in local space, but
+ * for objects the Local space doesn't make sense (T78462, D6095 etc).
+ * So only default to Before (Split) if the constraint is on a bone. */
+ if (pchan) {
+ bActionConstraint *data = con->data;
+ data->mix_mode = ACTCON_MIX_BEFORE_SPLIT;
+ con->ownspace = CONSTRAINT_SPACE_LOCAL;
+ }
+ break;
+ }
}
return con;
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index dced945bea0..7763bb9ca08 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1448,9 +1448,9 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
-const AssetLibraryReference *CTX_wm_asset_library(const bContext *C)
+const AssetLibraryReference *CTX_wm_asset_library_ref(const bContext *C)
{
- return ctx_data_pointer_get(C, "asset_library");
+ return ctx_data_pointer_get(C, "asset_library_ref");
}
AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid)
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index f1369254347..397838e6904 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -146,51 +146,50 @@ static void curve_foreach_id(ID *id, LibraryForeachIDData *data)
static void curve_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Curve *cu = (Curve *)id;
- if (cu->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- cu->editnurb = NULL;
- cu->editfont = NULL;
- cu->batch_cache = NULL;
- /* write LibData */
- BLO_write_id_struct(writer, Curve, id_address, &cu->id);
- BKE_id_blend_write(writer, &cu->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ cu->editnurb = NULL;
+ cu->editfont = NULL;
+ cu->batch_cache = NULL;
+
+ /* write LibData */
+ BLO_write_id_struct(writer, Curve, id_address, &cu->id);
+ BKE_id_blend_write(writer, &cu->id);
- /* direct data */
- BLO_write_pointer_array(writer, cu->totcol, cu->mat);
- if (cu->adt) {
- BKE_animdata_blend_write(writer, cu->adt);
- }
+ /* direct data */
+ BLO_write_pointer_array(writer, cu->totcol, cu->mat);
+ if (cu->adt) {
+ BKE_animdata_blend_write(writer, cu->adt);
+ }
- if (cu->vfont) {
- BLO_write_raw(writer, cu->len + 1, cu->str);
- BLO_write_struct_array(writer, CharInfo, cu->len_char32 + 1, cu->strinfo);
- BLO_write_struct_array(writer, TextBox, cu->totbox, cu->tb);
+ if (cu->vfont) {
+ BLO_write_raw(writer, cu->len + 1, cu->str);
+ BLO_write_struct_array(writer, CharInfo, cu->len_char32 + 1, cu->strinfo);
+ BLO_write_struct_array(writer, TextBox, cu->totbox, cu->tb);
+ }
+ else {
+ /* is also the order of reading */
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
+ BLO_write_struct(writer, Nurb, nu);
}
- else {
- /* is also the order of reading */
- LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
- BLO_write_struct(writer, Nurb, nu);
+ LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
+ if (nu->type == CU_BEZIER) {
+ BLO_write_struct_array(writer, BezTriple, nu->pntsu, nu->bezt);
}
- LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) {
- if (nu->type == CU_BEZIER) {
- BLO_write_struct_array(writer, BezTriple, nu->pntsu, nu->bezt);
+ else {
+ BLO_write_struct_array(writer, BPoint, nu->pntsu * nu->pntsv, nu->bp);
+ if (nu->knotsu) {
+ BLO_write_float_array(writer, KNOTSU(nu), nu->knotsu);
}
- else {
- BLO_write_struct_array(writer, BPoint, nu->pntsu * nu->pntsv, nu->bp);
- if (nu->knotsu) {
- BLO_write_float_array(writer, KNOTSU(nu), nu->knotsu);
- }
- if (nu->knotsv) {
- BLO_write_float_array(writer, KNOTSV(nu), nu->knotsv);
- }
+ if (nu->knotsv) {
+ BLO_write_float_array(writer, KNOTSV(nu), nu->knotsv);
}
}
}
+ }
- if (cu->bevel_profile != NULL) {
- BKE_curveprofile_blend_write(writer, cu->bevel_profile);
- }
+ if (cu->bevel_profile != NULL) {
+ BKE_curveprofile_blend_write(writer, cu->bevel_profile);
}
}
@@ -638,7 +637,7 @@ void BKE_nurb_free(Nurb *nu)
MEM_freeN(nu->knotsv);
}
nu->knotsv = NULL;
- /* if (nu->trim.first) freeNurblist(&(nu->trim)); */
+ // if (nu->trim.first) freeNurblist(&(nu->trim));
MEM_freeN(nu);
}
@@ -2331,17 +2330,21 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
bevp1 = bevp2 + (bl->nr - 1);
bevp0 = bevp1 - 1;
- nr = bl->nr;
- while (nr--) {
+ /* The ordinal of the point being adjusted (bevp2). First point is 1. */
- if (nr + 3 > bl->nr) { /* first time and second time, otherwise first point adjusts last */
- vec_to_quat(bevp1->quat, bevp1->dir, 5, 1);
- }
- else {
- minimum_twist_between_two_points(bevp1, bevp0);
- }
+ /* First point is the reference, don't adjust.
+ * Skip this point in the following loop. */
+ if (bl->nr > 0) {
+ vec_to_quat(bevp2->quat, bevp2->dir, 5, 1);
- bevp0 = bevp1;
+ bevp0 = bevp1; /* bevp0 is unused */
+ bevp1 = bevp2;
+ bevp2++;
+ }
+ for (nr = 1; nr < bl->nr; nr++) {
+ minimum_twist_between_two_points(bevp2, bevp1);
+
+ bevp0 = bevp1; /* bevp0 is unused */
bevp1 = bevp2;
bevp2++;
}
@@ -5010,10 +5013,7 @@ bool BKE_nurb_type_convert(Nurb *nu,
MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */
}
nu->knotsu = NULL;
- if (nu->knotsv) {
- MEM_freeN(nu->knotsv);
- }
- nu->knotsv = NULL;
+ MEM_SAFE_FREE(nu->knotsv);
}
else if (type == CU_BEZIER) { /* to Bezier */
nr = nu->pntsu / 3;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 7aa9d1958eb..1a3200a9b6c 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -724,10 +724,7 @@ static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
GridPaintMask *gpm = data;
for (int i = 0; i < count; i++) {
- if (gpm[i].data) {
- MEM_freeN(gpm[i].data);
- }
- gpm[i].data = NULL;
+ MEM_SAFE_FREE(gpm[i].data);
gpm[i].level = 0;
}
}
@@ -4249,7 +4246,7 @@ void CustomData_blend_write_prepare(CustomData *data,
CustomDataLayer *layer = &data->layers[i];
if (layer->flag & CD_FLAG_NOCOPY) { /* Layers with this flag set are not written to file. */
data->totlayer--;
- /* CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name); */
+ // CLOG_WARN(&LOG, "skipping layer %p (%s)", layer, layer->name);
}
else {
if (UNLIKELY((size_t)j >= write_layers_size)) {
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 605061570b8..b83621e8b79 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -301,14 +301,12 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
}
if (dirty_nors_dst || do_poly_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
num_verts_dst,
loops_dst,
- polys_dst,
num_loops_dst,
+ polys_dst,
num_polys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
/* Cache loop nors into a temp CDLayer. */
loop_nors_dst = CustomData_get_layer(ldata_dst, CD_NORMAL);
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index f7ef84728b6..13222747a52 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -894,10 +894,7 @@ void BKE_defvert_remove_group(MDeformVert *dvert, MDeformWeight *dw)
void BKE_defvert_clear(MDeformVert *dvert)
{
- if (dvert->dw) {
- MEM_freeN(dvert->dw);
- dvert->dw = NULL;
- }
+ MEM_SAFE_FREE(dvert->dw);
dvert->totweight = 0;
}
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 99dc1db9d38..c97e07ad487 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -1003,7 +1003,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
modified = temp_mesh;
BKE_mesh_vert_coords_apply(modified, vertCos);
- BKE_mesh_calc_normals_mapping_simple(modified);
+ BKE_mesh_calc_normals(modified);
MEM_freeN(vertCos);
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 52996e3bcc7..8f94c407cae 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -844,10 +844,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface)
if (temp_s_num) {
MEM_freeN(temp_s_num);
}
- if (temp_t_index) {
- MEM_freeN(temp_t_index);
- }
- grid->temp_t_index = NULL;
+ MEM_SAFE_FREE(temp_t_index);
if (error || !grid->s_num) {
setError(surface->canvas, N_("Not enough free memory"));
@@ -988,10 +985,7 @@ void dynamicPaint_freeSurface(const DynamicPaintModifierData *pmd, DynamicPaintS
}
surface->pointcache = NULL;
- if (surface->effector_weights) {
- MEM_freeN(surface->effector_weights);
- }
- surface->effector_weights = NULL;
+ MEM_SAFE_FREE(surface->effector_weights);
BLI_remlink(&(surface->canvas->surfaces), surface);
dynamicPaint_freeSurfaceData(surface);
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index fc1721eaf3a..334118ddf3f 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -861,7 +861,7 @@ static void get_effector_tot(
int totpart = eff->psys->totpart;
int amount = eff->psys->part->effector_amount;
- *step = (totpart > amount) ? totpart / amount : 1;
+ *step = (totpart > amount) ? (int)ceil((float)totpart / (float)amount) : 1;
}
}
else {
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 92fd220549a..799d6553682 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -4153,7 +4153,7 @@ static void BKE_fluid_modifier_process(
{
const int scene_framenr = (int)DEG_get_ctime(depsgraph);
- if ((fmd->type & MOD_FLUID_TYPE_FLOW)) {
+ if (fmd->type & MOD_FLUID_TYPE_FLOW) {
BKE_fluid_modifier_processFlow(fmd, depsgraph, scene, ob, me, scene_framenr);
}
else if (fmd->type & MOD_FLUID_TYPE_EFFEC) {
@@ -4766,20 +4766,14 @@ static void BKE_fluid_modifier_freeDomain(FluidModifierData *fmd)
BLI_rw_mutex_free(fmd->domain->fluid_mutex);
}
- if (fmd->domain->effector_weights) {
- MEM_freeN(fmd->domain->effector_weights);
- }
- fmd->domain->effector_weights = NULL;
+ MEM_SAFE_FREE(fmd->domain->effector_weights);
if (!(fmd->modifier.flag & eModifierFlag_SharedCaches)) {
BKE_ptcache_free_list(&(fmd->domain->ptcaches[0]));
fmd->domain->point_cache[0] = NULL;
}
- if (fmd->domain->mesh_velocities) {
- MEM_freeN(fmd->domain->mesh_velocities);
- }
- fmd->domain->mesh_velocities = NULL;
+ MEM_SAFE_FREE(fmd->domain->mesh_velocities);
if (fmd->domain->coba) {
MEM_freeN(fmd->domain->coba);
@@ -4798,10 +4792,7 @@ static void BKE_fluid_modifier_freeFlow(FluidModifierData *fmd)
}
fmd->flow->mesh = NULL;
- if (fmd->flow->verts_old) {
- MEM_freeN(fmd->flow->verts_old);
- }
- fmd->flow->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->flow->verts_old);
fmd->flow->numverts = 0;
fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
@@ -4818,10 +4809,7 @@ static void BKE_fluid_modifier_freeEffector(FluidModifierData *fmd)
}
fmd->effector->mesh = NULL;
- if (fmd->effector->verts_old) {
- MEM_freeN(fmd->effector->verts_old);
- }
- fmd->effector->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->effector->verts_old);
fmd->effector->numverts = 0;
fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
@@ -4857,18 +4845,12 @@ static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *fmd, bool need
fmd->domain->active_fields = 0;
}
else if (fmd->flow) {
- if (fmd->flow->verts_old) {
- MEM_freeN(fmd->flow->verts_old);
- }
- fmd->flow->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->flow->verts_old);
fmd->flow->numverts = 0;
fmd->flow->flags &= ~FLUID_FLOW_NEEDS_UPDATE;
}
else if (fmd->effector) {
- if (fmd->effector->verts_old) {
- MEM_freeN(fmd->effector->verts_old);
- }
- fmd->effector->verts_old = NULL;
+ MEM_SAFE_FREE(fmd->effector->verts_old);
fmd->effector->numverts = 0;
fmd->effector->flags &= ~FLUID_EFFECTOR_NEEDS_UPDATE;
}
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index d0b9aeefa55..c1765967238 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -126,23 +126,22 @@ static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_addres
{
VFont *vf = (VFont *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (vf->id.us > 0 || is_undo) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- vf->data = NULL;
- vf->temp_pf = NULL;
-
- /* Do not store packed files in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) {
- vf->packedfile = NULL;
- }
- /* write LibData */
- BLO_write_id_struct(writer, VFont, id_address, &vf->id);
- BKE_id_blend_write(writer, &vf->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ vf->data = NULL;
+ vf->temp_pf = NULL;
- /* direct data */
- BKE_packedfile_blend_write(writer, vf->packedfile);
+ /* Do not store packed files in case this is a library override ID. */
+ if (ID_IS_OVERRIDE_LIBRARY(vf) && !is_undo) {
+ vf->packedfile = NULL;
}
+
+ /* write LibData */
+ BLO_write_id_struct(writer, VFont, id_address, &vf->id);
+ BKE_id_blend_write(writer, &vf->id);
+
+ /* direct data */
+ BKE_packedfile_blend_write(writer, vf->packedfile);
}
static void vfont_blend_read_data(BlendDataReader *reader, ID *id)
@@ -337,13 +336,9 @@ VFont *BKE_vfont_load(Main *bmain, const char *filepath)
vfd = BLI_vfontdata_from_freetypefont(pf);
if (vfd) {
- vfont = BKE_libblock_alloc(bmain, ID_VF, filename, 0);
+ /* If there's a font name, use it for the ID name. */
+ vfont = BKE_libblock_alloc(bmain, ID_VF, vfd->name[0] ? vfd->name : filename, 0);
vfont->data = vfd;
-
- /* if there's a font name, use it for the ID name */
- if (vfd->name[0] != '\0') {
- BLI_strncpy(vfont->id.name + 2, vfd->name, sizeof(vfont->id.name) - 2);
- }
BLI_strncpy(vfont->filepath, filepath, sizeof(vfont->filepath));
/* if autopack is on store the packedfile in de font structure */
@@ -719,6 +714,13 @@ typedef struct VFontToCurveIter {
float max;
} bisect;
bool ok;
+ /**
+ * Wrap words that extends beyond the text-box width (enabled by default).
+ *
+ * Currently only disabled when scale-to-fit is enabled,
+ * so floating-point error doesn't cause unexpected wrapping, see T89241.
+ */
+ bool word_wrap;
int status;
} VFontToCurveIter;
@@ -781,6 +783,7 @@ static bool vfont_to_curve(Object *ob,
char32_t ascii;
bool ok = false;
const float font_size = cu->fsize * iter_data->scale_to_fit;
+ const bool word_wrap = iter_data->word_wrap;
const float xof_scale = cu->xof / font_size;
const float yof_scale = cu->yof / font_size;
int last_line = -1;
@@ -951,43 +954,59 @@ static bool vfont_to_curve(Object *ob,
twidth = char_width(cu, che, info);
- /* Calculate positions */
- if ((tb_scale.w != 0.0f) && (ct->dobreak == 0) &&
- (((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w)) {
- // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
- for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
- bool dobreak = false;
- if (ELEM(mem[j], ' ', '-')) {
- ct -= (i - (j - 1));
- cnr -= (i - (j - 1));
- if (mem[j] == ' ') {
- wsnr--;
+ /* Calculate positions. */
+
+ if ((tb_scale.w != 0.0f) && (ct->dobreak == 0)) { /* May need wrapping. */
+ const float x_available = xof_scale + tb_scale.w;
+ const float x_used = (xof - tb_scale.x) + twidth;
+
+ if (word_wrap == false) {
+ /* When scale to fit is used, don't do any wrapping.
+ *
+ * Floating precision error can cause the text to be slightly larger.
+ * Assert this is a small value as large values indicate incorrect
+ * calculations with scale-to-fit which shouldn't be ignored. See T89241. */
+ if (x_used > x_available) {
+ BLI_assert_msg(compare_ff_relative(x_used, x_available, FLT_EPSILON, 64),
+ "VFontToCurveIter.scale_to_fit not set correctly!");
+ }
+ }
+ else if (x_used > x_available) {
+ // CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
+ for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
+ bool dobreak = false;
+ if (ELEM(mem[j], ' ', '-')) {
+ ct -= (i - (j - 1));
+ cnr -= (i - (j - 1));
+ if (mem[j] == ' ') {
+ wsnr--;
+ }
+ if (mem[j] == '-') {
+ wsnr++;
+ }
+ i = j - 1;
+ xof = ct->xof;
+ ct[1].dobreak = 1;
+ custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
+ dobreak = true;
}
- if (mem[j] == '-') {
- wsnr++;
+ else if (chartransdata[j].dobreak) {
+ // CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
+ ct->dobreak = 1;
+ custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
+ ct -= 1;
+ cnr -= 1;
+ i--;
+ xof = ct->xof;
+ dobreak = true;
}
- i = j - 1;
- xof = ct->xof;
- ct[1].dobreak = 1;
- custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
- dobreak = true;
- }
- else if (chartransdata[j].dobreak) {
- // CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
- ct->dobreak = 1;
- custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
- ct -= 1;
- cnr -= 1;
- i--;
- xof = ct->xof;
- dobreak = true;
- }
- if (dobreak) {
- if (tb_scale.h == 0.0f) {
- /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
- custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
+ if (dobreak) {
+ if (tb_scale.h == 0.0f) {
+ /* NOTE: If underlined text is truncated away, the extra space is also truncated. */
+ custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
+ }
+ goto makebreak;
}
- goto makebreak;
}
}
}
@@ -1549,6 +1568,7 @@ static bool vfont_to_curve(Object *ob,
const float total_text_height = lnr * linedist;
iter_data->scale_to_fit = tb_scale.h / total_text_height;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
else if (tb_scale.h == 0.0f) {
@@ -1556,10 +1576,10 @@ static bool vfont_to_curve(Object *ob,
if (longest_line_length > tb_scale.w) {
/* We make sure longest line before it broke can fit here. */
float scale_to_fit = tb_scale.w / longest_line_length;
- scale_to_fit -= FLT_EPSILON;
iter_data->scale_to_fit = scale_to_fit;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
}
@@ -1620,6 +1640,7 @@ static bool vfont_to_curve(Object *ob,
else {
iter_data->scale_to_fit = iter_data->bisect.min;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
+ iter_data->word_wrap = false;
}
}
}
@@ -1689,6 +1710,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
VFontToCurveIter data = {
.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
.scale_to_fit = 1.0f,
+ .word_wrap = true,
.ok = true,
.status = VFONT_TO_CURVE_INIT,
};
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 90a97264c8f..32a65ab47bf 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -491,6 +491,10 @@ static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGrou
}
}
+ /* A possible optimization is to only tag the normals dirty when there are transforms that change
+ * normals. */
+ BKE_mesh_normals_tag_dirty(new_mesh);
+
return new_mesh;
}
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 38397f8f307..9062fd2d39c 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -131,7 +131,7 @@ static void greasepencil_free_data(ID *id)
{
/* Really not ideal, but for now will do... In theory custom behaviors like not freeing cache
* should be handled through specific API, and not be part of the generic one. */
- BKE_gpencil_free((bGPdata *)id, true);
+ BKE_gpencil_free_data((bGPdata *)id, true);
}
static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data)
@@ -150,47 +150,46 @@ static void greasepencil_foreach_id(ID *id, LibraryForeachIDData *data)
static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bGPdata *gpd = (bGPdata *)id;
- if (gpd->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
- /* XXX not sure why the whole run-time data is not cleared in reading code,
- * for now mimicking it here. */
- gpd->runtime.sbuffer = NULL;
- gpd->runtime.sbuffer_used = 0;
- gpd->runtime.sbuffer_size = 0;
- gpd->runtime.tot_cp_points = 0;
- /* write gpd data block to file */
- BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
- BKE_id_blend_write(writer, &gpd->id);
+ /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
+ /* XXX not sure why the whole run-time data is not cleared in reading code,
+ * for now mimicking it here. */
+ gpd->runtime.sbuffer = NULL;
+ gpd->runtime.sbuffer_used = 0;
+ gpd->runtime.sbuffer_size = 0;
+ gpd->runtime.tot_cp_points = 0;
- if (gpd->adt) {
- BKE_animdata_blend_write(writer, gpd->adt);
- }
+ /* write gpd data block to file */
+ BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
+ BKE_id_blend_write(writer, &gpd->id);
- BKE_defbase_blend_write(writer, &gpd->vertex_group_names);
+ if (gpd->adt) {
+ BKE_animdata_blend_write(writer, gpd->adt);
+ }
- BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
+ BKE_defbase_blend_write(writer, &gpd->vertex_group_names);
- /* write grease-pencil layers to file */
- BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
- LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- /* Write mask list. */
- BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
- /* write this layer's frames to file */
- BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
- LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
- /* write strokes */
- BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
- LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
- BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
- BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
- BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
- if (gps->editcurve != NULL) {
- bGPDcurve *gpc = gps->editcurve;
- BLO_write_struct(writer, bGPDcurve, gpc);
- BLO_write_struct_array(
- writer, bGPDcurve_point, gpc->tot_curve_points, gpc->curve_points);
- }
+ BLO_write_pointer_array(writer, gpd->totcol, gpd->mat);
+
+ /* write grease-pencil layers to file */
+ BLO_write_struct_list(writer, bGPDlayer, &gpd->layers);
+ LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
+ /* Write mask list. */
+ BLO_write_struct_list(writer, bGPDlayer_Mask, &gpl->mask_layers);
+ /* write this layer's frames to file */
+ BLO_write_struct_list(writer, bGPDframe, &gpl->frames);
+ LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
+ /* write strokes */
+ BLO_write_struct_list(writer, bGPDstroke, &gpf->strokes);
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ BLO_write_struct_array(writer, bGPDspoint, gps->totpoints, gps->points);
+ BLO_write_struct_array(writer, bGPDtriangle, gps->tot_triangles, gps->triangles);
+ BKE_defvert_blend_write(writer, gps->totpoints, gps->dvert);
+ if (gps->editcurve != NULL) {
+ bGPDcurve *gpc = gps->editcurve;
+ BLO_write_struct(writer, bGPDcurve, gpc);
+ BLO_write_struct_array(
+ writer, bGPDcurve_point, gpc->tot_curve_points, gpc->curve_points);
}
}
}
@@ -496,7 +495,7 @@ void BKE_gpencil_free_layers(ListBase *list)
}
/** Free (or release) any data used by this grease pencil (does not free the gpencil itself). */
-void BKE_gpencil_free(bGPdata *gpd, bool free_all)
+void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
{
/* free layers */
BKE_gpencil_free_layers(&gpd->layers);
@@ -519,8 +518,9 @@ void BKE_gpencil_free(bGPdata *gpd, bool free_all)
*/
void BKE_gpencil_eval_delete(bGPdata *gpd_eval)
{
- BKE_gpencil_free(gpd_eval, true);
+ BKE_gpencil_free_data(gpd_eval, true);
BKE_libblock_free_data(&gpd_eval->id, false);
+ BLI_assert(!gpd_eval->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(gpd_eval);
}
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index f8a07939096..0f218d6166c 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "BLI_array_utils.h"
#include "BLI_blenlib.h"
#include "BLI_float3.hh"
#include "BLI_ghash.h"
@@ -2269,7 +2270,8 @@ static void gpencil_generate_edgeloops(Object *ob,
const int thickness,
const float offset,
const float matrix[4][4],
- const bool use_seams)
+ const bool use_seams,
+ const bool use_vgroups)
{
Mesh *me = (Mesh *)ob->data;
if (me->totedge == 0) {
@@ -2278,9 +2280,9 @@ static void gpencil_generate_edgeloops(Object *ob,
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
* This is reused for each edge-loop to create gpencil stroke. */
- uint *stroke = (uint *)MEM_callocN(sizeof(uint) * me->totedge * 2, __func__);
- uint *stroke_fw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
- uint *stroke_bw = (uint *)MEM_callocN(sizeof(uint) * me->totedge, __func__);
+ uint *stroke = (uint *)MEM_mallocN(sizeof(uint) * me->totedge * 2, __func__);
+ uint *stroke_fw = (uint *)MEM_mallocN(sizeof(uint) * me->totedge, __func__);
+ uint *stroke_bw = (uint *)MEM_mallocN(sizeof(uint) * me->totedge, __func__);
/* Create array with all edges. */
GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__);
@@ -2311,11 +2313,6 @@ static void gpencil_generate_edgeloops(Object *ob,
bool pending = true;
int e = 0;
while (pending) {
- /* Clear arrays of stroke. */
- memset(stroke_fw, 0, sizeof(uint) * me->totedge);
- memset(stroke_bw, 0, sizeof(uint) * me->totedge);
- memset(stroke, 0, sizeof(uint) * me->totedge * 2);
-
gped = &gp_edges[e];
/* Look first unused edge. */
if (gped->flag != 0) {
@@ -2330,7 +2327,7 @@ static void gpencil_generate_edgeloops(Object *ob,
stroke_bw[0] = e;
gped->flag = 1;
- /* Hash used to avoid loop over same vertice. */
+ /* Hash used to avoid loop over same vertices. */
GHash *v_table = BLI_ghash_int_new(__func__);
/* Look forward edges. */
int totedges = gpencil_walk_edge(v_table, gp_edges, me->totedge, stroke_fw, e, angle, false);
@@ -2354,38 +2351,41 @@ static void gpencil_generate_edgeloops(Object *ob,
bGPDstroke *gps_stroke = BKE_gpencil_stroke_add(
gpf_stroke, MAX2(stroke_mat_index, 0), array_len + 1, thickness * thickness, false);
+ /* Create dvert data. */
+ MDeformVert *me_dvert = me->dvert;
+ if (use_vgroups && me_dvert) {
+ gps_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (array_len + 1),
+ "gp_stroke_dverts");
+ }
+
/* Create first segment. */
float fpt[3];
- uint v = stroke[0];
- gped = &gp_edges[v];
- bGPDspoint *pt = &gps_stroke->points[0];
- mul_v3_v3fl(fpt, gped->n1, offset);
- add_v3_v3v3(&pt->x, gped->v1_co, fpt);
- mul_m4_v3(matrix, &pt->x);
-
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
-
- pt = &gps_stroke->points[1];
- mul_v3_v3fl(fpt, gped->n2, offset);
- add_v3_v3v3(&pt->x, gped->v2_co, fpt);
- mul_m4_v3(matrix, &pt->x);
-
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
-
- /* Add next segments. */
- for (int i = 1; i < array_len; i++) {
- v = stroke[i];
- gped = &gp_edges[v];
-
- pt = &gps_stroke->points[i + 1];
- mul_v3_v3fl(fpt, gped->n2, offset);
- add_v3_v3v3(&pt->x, gped->v2_co, fpt);
+ for (int i = 0; i < array_len + 1; i++) {
+ int vertex_index = i == 0 ? gp_edges[stroke[0]].v1 : gp_edges[stroke[i - 1]].v2;
+ MVert *mv = &me->mvert[vertex_index];
+
+ /* Add segment. */
+ bGPDspoint *pt = &gps_stroke->points[i];
+ normal_short_to_float_v3(fpt, mv->no);
+ mul_v3_v3fl(fpt, fpt, offset);
+ add_v3_v3v3(&pt->x, mv->co, fpt);
mul_m4_v3(matrix, &pt->x);
pt->pressure = 1.0f;
pt->strength = 1.0f;
+
+ /* Copy vertex groups from mesh. Assuming they already exist in the same order. */
+ if (use_vgroups && me_dvert) {
+ MDeformVert *dv = &gps_stroke->dvert[i];
+ MDeformVert *src_dv = &me_dvert[vertex_index];
+ dv->totweight = src_dv->totweight;
+ dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ "gp_stroke_dverts_dw");
+ for (int j = 0; j < dv->totweight; j++) {
+ dv->dw[j].weight = src_dv->dw[j].weight;
+ dv->dw[j].def_nr = src_dv->dw[j].def_nr;
+ }
+ }
}
BKE_gpencil_stroke_geometry_update(gpd, gps_stroke);
@@ -2488,7 +2488,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
const float matrix[4][4],
const int frame_offset,
const bool use_seams,
- const bool use_faces)
+ const bool use_faces,
+ const bool use_vgroups)
{
if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
return false;
@@ -2505,83 +2506,105 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
char element_name[200];
/* Need at least an edge. */
- if (me_eval->totvert < 2) {
+ if (me_eval->totedge < 1) {
return false;
}
+ /* Create matching vertex groups. */
+ BKE_defgroup_copy_list(&gpd->vertex_group_names, &me_eval->vertex_group_names);
+ gpd->vertex_group_active_index = me_eval->vertex_group_active_index;
+
const float default_colors[2][4] = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.7f, 0.7f, 0.7f, 1.0f}};
- /* Create stroke material. */
+ /* Lookup existing stroke material on gp object. */
make_element_name(ob_mesh->id.name + 2, "Stroke", 64, element_name);
int stroke_mat_index = gpencil_material_find_index_by_name(ob_gp, element_name);
if (stroke_mat_index == -1) {
+ /* Create new default stroke material as there is no existing material. */
gpencil_add_material(
bmain, ob_gp, element_name, default_colors[0], true, false, &stroke_mat_index);
}
/* Export faces as filled strokes. */
- if (use_faces) {
-
+ if (use_faces && mpoly_len > 0) {
/* Read all polygons and create fill for each. */
- if (mpoly_len > 0) {
- make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
- /* Create Layer and Frame. */
- bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name);
- if (gpl_fill == nullptr) {
- gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
- }
- bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
- gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
- int i;
- for (i = 0; i < mpoly_len; i++) {
- const MPoly *mp = &mpoly[i];
-
- /* Find material. */
- int mat_idx = 0;
- Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
- make_element_name(
- ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
- mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
- if (mat_idx == -1) {
- float color[4];
- if (ma != nullptr) {
- copy_v3_v3(color, &ma->r);
- color[3] = 1.0f;
- }
- else {
- copy_v4_v4(color, default_colors[1]);
- }
- gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx);
+ make_element_name(ob_mesh->id.name + 2, "Fills", 128, element_name);
+ /* Create Layer and Frame. */
+ bGPDlayer *gpl_fill = BKE_gpencil_layer_named_get(gpd, element_name);
+ if (gpl_fill == nullptr) {
+ gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
+ }
+ bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
+ gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
+ int i;
+ for (i = 0; i < mpoly_len; i++) {
+ const MPoly *mp = &mpoly[i];
+
+ /* Find material. */
+ int mat_idx = 0;
+ Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
+ make_element_name(
+ ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
+ mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
+ if (mat_idx == -1) {
+ float color[4];
+ if (ma != nullptr) {
+ copy_v3_v3(color, &ma->r);
+ color[3] = 1.0f;
+ }
+ else {
+ copy_v4_v4(color, default_colors[1]);
}
+ gpencil_add_material(bmain, ob_gp, element_name, color, false, true, &mat_idx);
+ }
- bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false);
- gps_fill->flag |= GP_STROKE_CYCLIC;
+ bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false);
+ gps_fill->flag |= GP_STROKE_CYCLIC;
- /* Add points to strokes. */
- for (int j = 0; j < mp->totloop; j++) {
- const MLoop *ml = &mloop[mp->loopstart + j];
- const MVert *mv = &me_eval->mvert[ml->v];
+ /* Create dvert data. */
+ MDeformVert *me_dvert = me_eval->dvert;
+ if (use_vgroups && me_dvert) {
+ gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * mp->totloop,
+ "gp_fill_dverts");
+ }
- bGPDspoint *pt = &gps_fill->points[j];
- copy_v3_v3(&pt->x, mv->co);
- mul_m4_v3(matrix, &pt->x);
- pt->pressure = 1.0f;
- pt->strength = 1.0f;
- }
- /* If has only 3 points subdivide. */
- if (mp->totloop == 3) {
- BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE);
+ /* Add points to strokes. */
+ for (int j = 0; j < mp->totloop; j++) {
+ const MLoop *ml = &mloop[mp->loopstart + j];
+ const MVert *mv = &me_eval->mvert[ml->v];
+
+ bGPDspoint *pt = &gps_fill->points[j];
+ copy_v3_v3(&pt->x, mv->co);
+ mul_m4_v3(matrix, &pt->x);
+ pt->pressure = 1.0f;
+ pt->strength = 1.0f;
+
+ /* Copy vertex groups from mesh. Assuming they already exist in the same order. */
+ if (use_vgroups && me_dvert) {
+ MDeformVert *dv = &gps_fill->dvert[j];
+ MDeformVert *src_dv = &me_dvert[ml->v];
+ dv->totweight = src_dv->totweight;
+ dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
+ "gp_fill_dverts_dw");
+ for (int k = 0; k < dv->totweight; k++) {
+ dv->dw[k].weight = src_dv->dw[k].weight;
+ dv->dw[k].def_nr = src_dv->dw[k].def_nr;
+ }
}
-
- BKE_gpencil_stroke_geometry_update(gpd, gps_fill);
}
+ /* If has only 3 points subdivide. */
+ if (mp->totloop == 3) {
+ BKE_gpencil_stroke_subdivide(gpd, gps_fill, 1, GP_SUBDIV_SIMPLE);
+ }
+
+ BKE_gpencil_stroke_geometry_update(gpd, gps_fill);
}
}
/* Create stroke from edges. */
- make_element_name(ob_mesh->id.name + 2, "Lines", 128, element_name);
/* Create Layer and Frame. */
+ make_element_name(ob_mesh->id.name + 2, "Lines", 128, element_name);
bGPDlayer *gpl_stroke = BKE_gpencil_layer_named_get(gpd, element_name);
if (gpl_stroke == nullptr) {
gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
@@ -2589,8 +2612,16 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get(
gpl_stroke, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
- gpencil_generate_edgeloops(
- ob_eval, gpd, gpf_stroke, stroke_mat_index, angle, thickness, offset, matrix, use_seams);
+ gpencil_generate_edgeloops(ob_eval,
+ gpd,
+ gpf_stroke,
+ stroke_mat_index,
+ angle,
+ thickness,
+ offset,
+ matrix,
+ use_seams,
+ use_vgroups);
/* Tag for recalculation */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
@@ -2787,46 +2818,12 @@ void BKE_gpencil_stroke_set_random_color(bGPDstroke *gps)
/* Flip stroke. */
void BKE_gpencil_stroke_flip(bGPDstroke *gps)
{
- int end = gps->totpoints - 1;
+ /* Reverse points. */
+ BLI_array_reverse(gps->points, gps->totpoints);
- for (int i = 0; i < gps->totpoints / 2; i++) {
- bGPDspoint *point, *point2;
- bGPDspoint pt;
-
- /* save first point */
- point = &gps->points[i];
- pt.x = point->x;
- pt.y = point->y;
- pt.z = point->z;
- pt.flag = point->flag;
- pt.pressure = point->pressure;
- pt.strength = point->strength;
- pt.time = point->time;
- copy_v4_v4(pt.vert_color, point->vert_color);
-
- /* replace first point with last point */
- point2 = &gps->points[end];
- point->x = point2->x;
- point->y = point2->y;
- point->z = point2->z;
- point->flag = point2->flag;
- point->pressure = point2->pressure;
- point->strength = point2->strength;
- point->time = point2->time;
- copy_v4_v4(point->vert_color, point2->vert_color);
-
- /* replace last point with first saved before */
- point = &gps->points[end];
- point->x = pt.x;
- point->y = pt.y;
- point->z = pt.z;
- point->flag = pt.flag;
- point->pressure = pt.pressure;
- point->strength = pt.strength;
- point->time = pt.time;
- copy_v4_v4(point->vert_color, pt.vert_color);
-
- end--;
+ /* Reverse vertex groups if available. */
+ if (gps->dvert) {
+ BLI_array_reverse(gps->dvert, gps->totpoints);
}
}
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 2894d6daf23..af7cc0acb57 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -114,32 +114,31 @@ static void hair_foreach_id(ID *id, LibraryForeachIDData *data)
static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Hair *hair = (Hair *)id;
- if (hair->id.us > 0 || BLO_write_is_undo(writer)) {
- CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
-
- /* Write LibData */
- BLO_write_id_struct(writer, Hair, id_address, &hair->id);
- BKE_id_blend_write(writer, &hair->id);
-
- /* Direct data */
- CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id);
- CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id);
-
- BLO_write_pointer_array(writer, hair->totcol, hair->mat);
- if (hair->adt) {
- BKE_animdata_blend_write(writer, hair->adt);
- }
- /* Remove temporary data. */
- if (players && players != players_buff) {
- MEM_freeN(players);
- }
- if (clayers && clayers != clayers_buff) {
- MEM_freeN(clayers);
- }
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *clayers = NULL, clayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
+
+ /* Write LibData */
+ BLO_write_id_struct(writer, Hair, id_address, &hair->id);
+ BKE_id_blend_write(writer, &hair->id);
+
+ /* Direct data */
+ CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id);
+ CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id);
+
+ BLO_write_pointer_array(writer, hair->totcol, hair->mat);
+ if (hair->adt) {
+ BKE_animdata_blend_write(writer, hair->adt);
+ }
+
+ /* Remove temporary data. */
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
+ if (clayers && clayers != clayers_buff) {
+ MEM_freeN(clayers);
}
}
diff --git a/source/blender/blenkernel/intern/icons.cc b/source/blender/blenkernel/intern/icons.cc
index 12a0a1e3ae7..5a4b2448a73 100644
--- a/source/blender/blenkernel/intern/icons.cc
+++ b/source/blender/blenkernel/intern/icons.cc
@@ -1,4 +1,4 @@
-/*
+/*
* 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
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index f4ba1ff8b92..d87290e1eb4 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -229,12 +229,26 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
{
Image *ima = (Image *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (ima->id.us > 0 || is_undo) {
- ImagePackedFile *imapf;
- BLI_assert(ima->packedfile == NULL);
+ /* Clear all data that isn't read to reduce false detection of changed image during memfile undo.
+ */
+ ima->lastused = 0;
+ ima->cache = NULL;
+ ima->gpuflag = 0;
+ BLI_listbase_clear(&ima->anims);
+ BLI_listbase_clear(&ima->gpu_refresh_areas);
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 2; j++) {
+ ima->gputexture[i][j] = NULL;
+ }
+ }
+
+ ImagePackedFile *imapf;
+
+ BLI_assert(ima->packedfile == NULL);
+ if (!is_undo) {
/* Do not store packed files in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(ima) && !is_undo) {
+ if (ID_IS_OVERRIDE_LIBRARY(ima)) {
BLI_listbase_clear(&ima->packedfiles);
}
else {
@@ -244,29 +258,29 @@ static void image_blend_write(BlendWriter *writer, ID *id, const void *id_addres
ima->packedfile = imapf->packedfile;
}
}
+ }
- /* write LibData */
- BLO_write_id_struct(writer, Image, id_address, &ima->id);
- BKE_id_blend_write(writer, &ima->id);
+ /* write LibData */
+ BLO_write_id_struct(writer, Image, id_address, &ima->id);
+ BKE_id_blend_write(writer, &ima->id);
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
- BLO_write_struct(writer, ImagePackedFile, imapf);
- BKE_packedfile_blend_write(writer, imapf->packedfile);
- }
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ BLO_write_struct(writer, ImagePackedFile, imapf);
+ BKE_packedfile_blend_write(writer, imapf->packedfile);
+ }
- BKE_previewimg_blend_write(writer, ima->preview);
+ BKE_previewimg_blend_write(writer, ima->preview);
- LISTBASE_FOREACH (ImageView *, iv, &ima->views) {
- BLO_write_struct(writer, ImageView, iv);
- }
- BLO_write_struct(writer, Stereo3dFormat, ima->stereo3d_format);
+ LISTBASE_FOREACH (ImageView *, iv, &ima->views) {
+ BLO_write_struct(writer, ImageView, iv);
+ }
+ BLO_write_struct(writer, Stereo3dFormat, ima->stereo3d_format);
- BLO_write_struct_list(writer, ImageTile, &ima->tiles);
+ BLO_write_struct_list(writer, ImageTile, &ima->tiles);
- ima->packedfile = NULL;
+ ima->packedfile = NULL;
- BLO_write_struct_list(writer, RenderSlot, &ima->renderslots);
- }
+ BLO_write_struct_list(writer, RenderSlot, &ima->renderslots);
}
static void image_blend_read_data(BlendDataReader *reader, ID *id)
@@ -300,6 +314,7 @@ static void image_blend_read_data(BlendDataReader *reader, ID *id)
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
tile->ok = IMA_OK;
}
+ ima->lastused = 0;
ima->gpuflag = 0;
BLI_listbase_clear(&ima->gpu_refresh_areas);
}
@@ -519,7 +534,7 @@ void BKE_image_free_buffers(Image *ima)
}
/** Free (or release) any data used by this image (does not free the image itself). */
-void BKE_image_free(Image *ima)
+void BKE_image_free_data(Image *ima)
{
image_free_data(&ima->id);
}
@@ -670,24 +685,27 @@ bool BKE_image_has_opengl_texture(Image *ima)
return false;
}
+static int image_get_tile_number_from_iuser(Image *ima, const ImageUser *iuser)
+{
+ BLI_assert(ima != NULL && ima->tiles.first);
+ ImageTile *tile = ima->tiles.first;
+ return (iuser && iuser->tile) ? iuser->tile : tile->tile_number;
+}
+
ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
{
if (ima == NULL) {
return NULL;
}
- /* Verify valid tile range. */
- if ((tile_number != 0) && (tile_number < 1001 || tile_number > IMA_UDIM_MAX)) {
- return NULL;
- }
-
- /* Tile number 0 is a special case and refers to the first tile, typically
+ /* Tiles 0 and 1001 are a special case and refer to the first tile, typically
* coming from non-UDIM-aware code. */
if (ELEM(tile_number, 0, 1001)) {
return ima->tiles.first;
}
- if (ima->source != IMA_SRC_TILED) {
+ /* Must have a tiled image and a valid tile number at this point. */
+ if (ima->source != IMA_SRC_TILED || tile_number < 1001 || tile_number > IMA_UDIM_MAX) {
return NULL;
}
@@ -702,7 +720,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number)
ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser)
{
- return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001);
+ return BKE_image_get_tile(ima, image_get_tile_number_from_iuser(ima, iuser));
}
int BKE_image_get_tile_from_pos(struct Image *ima,
@@ -1020,7 +1038,7 @@ Image *BKE_image_add_generated(Main *bmain,
int view_id;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- /* STRNCPY(ima->filepath, name); */ /* don't do this, this writes in ain invalid filepath! */
+ // STRNCPY(ima->filepath, name); /* don't do this, this writes in ain invalid filepath! */
ima->gen_x = width;
ima->gen_y = height;
ima->gen_type = gen_type;
@@ -3803,8 +3821,8 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
return false;
}
- if (tile == ima->tiles.first) {
- /* Can't remove first tile. */
+ if (BLI_listbase_is_single(&ima->tiles)) {
+ /* Can't remove the last remaining tile. */
return false;
}
@@ -3815,6 +3833,64 @@ bool BKE_image_remove_tile(struct Image *ima, ImageTile *tile)
return true;
}
+void BKE_image_reassign_tile(struct Image *ima, ImageTile *tile, int new_tile_number)
+{
+ if (ima == NULL || tile == NULL || ima->source != IMA_SRC_TILED) {
+ return;
+ }
+
+ if (new_tile_number < 1001 || new_tile_number > IMA_UDIM_MAX) {
+ return;
+ }
+
+ const int old_tile_number = tile->tile_number;
+ tile->tile_number = new_tile_number;
+
+ if (BKE_image_is_multiview(ima)) {
+ const int totviews = BLI_listbase_count(&ima->views);
+ for (int i = 0; i < totviews; i++) {
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, i, old_tile_number);
+ image_remove_ibuf(ima, i, old_tile_number);
+ image_assign_ibuf(ima, ibuf, i, new_tile_number);
+ IMB_freeImBuf(ibuf);
+ }
+ }
+ else {
+ ImBuf *ibuf = image_get_cached_ibuf_for_index_entry(ima, 0, old_tile_number);
+ image_remove_ibuf(ima, 0, old_tile_number);
+ image_assign_ibuf(ima, ibuf, 0, new_tile_number);
+ IMB_freeImBuf(ibuf);
+ }
+
+ for (int eye = 0; eye < 2; eye++) {
+ /* Reallocate GPU tile array. */
+ if (ima->gputexture[TEXTARGET_2D_ARRAY][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_2D_ARRAY][eye]);
+ ima->gputexture[TEXTARGET_2D_ARRAY][eye] = NULL;
+ }
+ if (ima->gputexture[TEXTARGET_TILE_MAPPING][eye] != NULL) {
+ GPU_texture_free(ima->gputexture[TEXTARGET_TILE_MAPPING][eye]);
+ ima->gputexture[TEXTARGET_TILE_MAPPING][eye] = NULL;
+ }
+ }
+}
+
+static int tile_sort_cb(const void *a, const void *b)
+{
+ const ImageTile *tile_a = a;
+ const ImageTile *tile_b = b;
+ return (tile_a->tile_number > tile_b->tile_number) ? 1 : 0;
+}
+
+void BKE_image_sort_tiles(struct Image *ima)
+{
+ if (ima == NULL || ima->source != IMA_SRC_TILED) {
+ return;
+ }
+
+ BLI_listbase_sort(&ima->tiles, tile_sort_cb);
+}
+
bool BKE_image_fill_tile(struct Image *ima,
ImageTile *tile,
int width,
@@ -4890,7 +4966,7 @@ static void image_get_entry_and_index(Image *ima, ImageUser *iuser, int *r_entry
}
}
else if (ima->source == IMA_SRC_TILED) {
- frame = (iuser && iuser->tile) ? iuser->tile : 1001;
+ frame = image_get_tile_number_from_iuser(ima, iuser);
}
*r_entry = frame;
@@ -4955,7 +5031,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry,
}
else if (ima->source == IMA_SRC_TILED) {
if (ELEM(ima->type, IMA_TYPE_IMAGE, IMA_TYPE_MULTILAYER)) {
- entry = (iuser && iuser->tile) ? iuser->tile : 1001;
+ entry = image_get_tile_number_from_iuser(ima, iuser);
ibuf = image_get_cached_ibuf_for_index_entry(ima, index, entry);
if ((ima->type == IMA_TYPE_IMAGE) && ibuf != NULL) {
@@ -5507,7 +5583,7 @@ void BKE_image_user_file_path(ImageUser *iuser, Image *ima, char *filepath)
index = iuser ? iuser->framenr : ima->lastframe;
}
else {
- index = (iuser && iuser->tile) ? iuser->tile : 1001;
+ index = image_get_tile_number_from_iuser(ima, iuser);
}
BLI_path_sequence_decode(filepath, head, tail, &numlen);
diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c
index bb7495437bb..d179dd40c33 100644
--- a/source/blender/blenkernel/intern/image_gpu.c
+++ b/source/blender/blenkernel/intern/image_gpu.c
@@ -108,8 +108,9 @@ static GPUTexture *gpu_texture_create_tile_mapping(Image *ima, const int multivi
float array_w = GPU_texture_width(tilearray);
float array_h = GPU_texture_height(tilearray);
+ /* Determine maximum tile number. */
+ BKE_image_sort_tiles(ima);
ImageTile *last_tile = (ImageTile *)ima->tiles.last;
- /* Tiles are sorted by number. */
int max_tile = last_tile->tile_number - 1001;
/* create image */
diff --git a/source/blender/blenkernel/intern/image_save.c b/source/blender/blenkernel/intern/image_save.c
index 360bad3e786..f93ede517a9 100644
--- a/source/blender/blenkernel/intern/image_save.c
+++ b/source/blender/blenkernel/intern/image_save.c
@@ -404,11 +404,13 @@ bool BKE_image_save(
if (ima->source == IMA_SRC_TILED) {
/* Verify filepath for tiles images. */
- if (BLI_path_sequence_decode(opts->filepath, NULL, NULL, NULL) != 1001) {
+ ImageTile *first_tile = ima->tiles.first;
+ if (BLI_path_sequence_decode(opts->filepath, NULL, NULL, NULL) != first_tile->tile_number) {
BKE_reportf(reports,
RPT_ERROR,
- "When saving a tiled image, the path '%s' must contain the UDIM tag 1001",
- opts->filepath);
+ "When saving a tiled image, the path '%s' must contain the UDIM tile number %d",
+ opts->filepath,
+ first_tile->tile_number);
return false;
}
@@ -430,9 +432,14 @@ bool BKE_image_save(
BLI_path_sequence_decode(filepath, head, tail, &numlen);
/* Save all other tiles. */
- LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
- /* Tile 1001 was already saved before the loop. */
- if (tile->tile_number == 1001 || !ok) {
+ int index;
+ LISTBASE_FOREACH_INDEX (ImageTile *, tile, &ima->tiles, index) {
+ /* First tile was already saved before the loop. */
+ if (index == 0) {
+ continue;
+ }
+
+ if (!ok) {
continue;
}
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 0f8c9bad798..f79058dcf21 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -114,27 +114,26 @@ static void shapekey_blend_write(BlendWriter *writer, ID *id, const void *id_add
{
Key *key = (Key *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (key->id.us > 0 || is_undo) {
- /* write LibData */
- BLO_write_id_struct(writer, Key, id_address, &key->id);
- BKE_id_blend_write(writer, &key->id);
-
- if (key->adt) {
- BKE_animdata_blend_write(writer, key->adt);
- }
-
- /* direct data */
- LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
- KeyBlock tmp_kb = *kb;
- /* Do not store actual geometry data in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(key) && !is_undo) {
- tmp_kb.totelem = 0;
- tmp_kb.data = NULL;
- }
- BLO_write_struct_at_address(writer, KeyBlock, kb, &tmp_kb);
- if (tmp_kb.data != NULL) {
- BLO_write_raw(writer, tmp_kb.totelem * key->elemsize, tmp_kb.data);
- }
+
+ /* write LibData */
+ BLO_write_id_struct(writer, Key, id_address, &key->id);
+ BKE_id_blend_write(writer, &key->id);
+
+ if (key->adt) {
+ BKE_animdata_blend_write(writer, key->adt);
+ }
+
+ /* direct data */
+ LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
+ KeyBlock tmp_kb = *kb;
+ /* Do not store actual geometry data in case this is a library override ID. */
+ if (ID_IS_OVERRIDE_LIBRARY(key) && !is_undo) {
+ tmp_kb.totelem = 0;
+ tmp_kb.data = NULL;
+ }
+ BLO_write_struct_at_address(writer, KeyBlock, kb, &tmp_kb);
+ if (tmp_kb.data != NULL) {
+ BLO_write_raw(writer, tmp_kb.totelem * key->elemsize, tmp_kb.data);
}
}
}
@@ -246,7 +245,7 @@ typedef struct WeightsArrayCache {
} WeightsArrayCache;
/** Free (or release) any data used by this shapekey (does not free the key itself). */
-void BKE_key_free(Key *key)
+void BKE_key_free_data(Key *key)
{
shapekey_free_data(&key->id);
}
@@ -2281,15 +2280,8 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
r_polynors = MEM_mallocN(sizeof(float[3]) * me.totpoly, __func__);
free_polynors = true;
}
- BKE_mesh_calc_normals_poly(me.mvert,
- r_vertnors,
- me.totvert,
- me.mloop,
- me.mpoly,
- me.totloop,
- me.totpoly,
- r_polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(
+ me.mvert, me.totvert, me.mloop, me.totloop, me.mpoly, me.totpoly, r_polynors, r_vertnors);
if (r_loopnors) {
short(*clnors)[2] = CustomData_get_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL); /* May be NULL. */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 9875d776d33..e804f32e5a6 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -137,26 +137,25 @@ static void lattice_foreach_id(ID *id, LibraryForeachIDData *data)
static void lattice_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Lattice *lt = (Lattice *)id;
- if (lt->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- lt->editlatt = NULL;
- lt->batch_cache = NULL;
-
- /* write LibData */
- BLO_write_id_struct(writer, Lattice, id_address, &lt->id);
- BKE_id_blend_write(writer, &lt->id);
-
- /* write animdata */
- if (lt->adt) {
- BKE_animdata_blend_write(writer, lt->adt);
- }
- /* direct data */
- BLO_write_struct_array(writer, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ lt->editlatt = NULL;
+ lt->batch_cache = NULL;
+
+ /* write LibData */
+ BLO_write_id_struct(writer, Lattice, id_address, &lt->id);
+ BKE_id_blend_write(writer, &lt->id);
- BKE_defbase_blend_write(writer, &lt->vertex_group_names);
- BKE_defvert_blend_write(writer, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ /* write animdata */
+ if (lt->adt) {
+ BKE_animdata_blend_write(writer, lt->adt);
}
+
+ /* direct data */
+ BLO_write_struct_array(writer, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+
+ BKE_defbase_blend_write(writer, &lt->vertex_group_names);
+ BKE_defvert_blend_write(writer, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
}
static void lattice_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index ae1863f0a47..b489675cd74 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -602,7 +602,7 @@ static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
}
/* Check visiblilty restriction flags */
- if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
+ if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_HIDE_VIEWPORT) {
return true;
}
@@ -1005,22 +1005,22 @@ static void layer_collection_objects_sync(ViewLayer *view_layer,
BLI_addtail(r_lb_new_object_bases, base);
}
- if ((collection_restrict & COLLECTION_RESTRICT_VIEWPORT) == 0) {
+ if ((collection_restrict & COLLECTION_HIDE_VIEWPORT) == 0) {
base->flag_from_collection |= (BASE_ENABLED_VIEWPORT | BASE_VISIBLE_DEPSGRAPH);
if ((layer_restrict & LAYER_COLLECTION_HIDE) == 0) {
base->flag_from_collection |= BASE_VISIBLE_VIEWLAYER;
}
- if (((collection_restrict & COLLECTION_RESTRICT_SELECT) == 0)) {
+ if (((collection_restrict & COLLECTION_HIDE_SELECT) == 0)) {
base->flag_from_collection |= BASE_SELECTABLE;
}
}
- if ((collection_restrict & COLLECTION_RESTRICT_RENDER) == 0) {
+ if ((collection_restrict & COLLECTION_HIDE_RENDER) == 0) {
base->flag_from_collection |= BASE_ENABLED_RENDER;
}
/* Holdout and indirect only */
- if (layer->flag & LAYER_COLLECTION_HOLDOUT) {
+ if ((layer->flag & LAYER_COLLECTION_HOLDOUT) || (base->object->visibility_flag & OB_HOLDOUT)) {
base->flag_from_collection |= BASE_HOLDOUT;
}
if (layer->flag & LAYER_COLLECTION_INDIRECT_ONLY) {
@@ -1150,11 +1150,11 @@ static void layer_collection_sync(ViewLayer *view_layer,
/* We separate restrict viewport and visible view layer because a layer collection can be
* hidden in the view layer yet (locally) visible in a viewport (if it is not restricted). */
- if (child_collection_restrict & COLLECTION_RESTRICT_VIEWPORT) {
- child_layer->runtime_flag |= LAYER_COLLECTION_RESTRICT_VIEWPORT;
+ if (child_collection_restrict & COLLECTION_HIDE_VIEWPORT) {
+ child_layer->runtime_flag |= LAYER_COLLECTION_HIDE_VIEWPORT;
}
- if (((child_layer->runtime_flag & LAYER_COLLECTION_RESTRICT_VIEWPORT) == 0) &&
+ if (((child_layer->runtime_flag & LAYER_COLLECTION_HIDE_VIEWPORT) == 0) &&
((child_layer_restrict & LAYER_COLLECTION_HIDE) == 0)) {
child_layer->runtime_flag |= LAYER_COLLECTION_VISIBLE_VIEW_LAYER;
}
@@ -1174,6 +1174,52 @@ static void layer_collection_sync(ViewLayer *view_layer,
parent_local_collections_bits);
}
+#ifndef NDEBUG
+static bool view_layer_objects_base_cache_validate(ViewLayer *view_layer, LayerCollection *layer)
+{
+ bool is_valid = true;
+
+ if (layer == NULL) {
+ layer = view_layer->layer_collections.first;
+ }
+
+ /* Only check for a collection's objects if its layer is not excluded. */
+ if ((layer->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &layer->collection->gobject) {
+ if (cob->ob == NULL) {
+ continue;
+ }
+ if (BLI_ghash_lookup(view_layer->object_bases_hash, cob->ob) == NULL) {
+ CLOG_FATAL(
+ &LOG,
+ "Object '%s' from collection '%s' has no entry in view layer's object bases cache",
+ cob->ob->id.name + 2,
+ layer->collection->id.name + 2);
+ is_valid = false;
+ break;
+ }
+ }
+ }
+
+ if (is_valid) {
+ LISTBASE_FOREACH (LayerCollection *, layer_child, &layer->layer_collections) {
+ if (!view_layer_objects_base_cache_validate(view_layer, layer_child)) {
+ is_valid = false;
+ break;
+ }
+ }
+ }
+
+ return is_valid;
+}
+#else
+static bool view_layer_objects_base_cache_validate(ViewLayer *UNUSED(view_layer),
+ LayerCollection *UNUSED(layer))
+{
+ return true;
+}
+#endif
+
/**
* Update view layer collection tree from collections used in the scene.
* This is used when collections are removed or added, both while editing
@@ -1240,6 +1286,12 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
}
if (base->object) {
+ /* Those asserts are commented, since they are too expensive to perform even in debug, as
+ * this layer resync function currently gets called way too often. */
+#if 0
+ BLI_assert(BLI_findindex(&new_object_bases, base) == -1);
+ BLI_assert(BLI_findptr(&new_object_bases, base->object, offsetof(Base, object)) == NULL);
+#endif
BLI_ghash_remove(view_layer->object_bases_hash, base->object, NULL, NULL);
}
}
@@ -1247,6 +1299,8 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
BLI_freelistN(&view_layer->object_bases);
view_layer->object_bases = new_object_bases;
+ view_layer_objects_base_cache_validate(view_layer, NULL);
+
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
BKE_base_eval_flags(base);
}
@@ -1333,7 +1387,7 @@ void BKE_main_collection_sync_remap(const Main *bmain)
*/
bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection *lc, bool deselect)
{
- if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) {
+ if (lc->collection->flag & COLLECTION_HIDE_SELECT) {
return false;
}
@@ -1369,7 +1423,7 @@ bool BKE_layer_collection_objects_select(ViewLayer *view_layer, LayerCollection
bool BKE_layer_collection_has_selected_objects(ViewLayer *view_layer, LayerCollection *lc)
{
- if (lc->collection->flag & COLLECTION_RESTRICT_SELECT) {
+ if (lc->collection->flag & COLLECTION_HIDE_SELECT) {
return false;
}
@@ -1457,7 +1511,7 @@ bool BKE_object_is_visible_in_viewport(const View3D *v3d, const struct Object *o
{
BLI_assert(v3d != NULL);
- if (ob->restrictflag & OB_RESTRICT_VIEWPORT) {
+ if (ob->visibility_flag & OB_HIDE_VIEWPORT) {
return false;
}
@@ -2146,14 +2200,14 @@ void BKE_base_eval_flags(Base *base)
base->flag |= (base->flag_from_collection & g_base_collection_flags);
/* Apply object restrictions. */
- const int object_restrict = base->object->restrictflag;
- if (object_restrict & OB_RESTRICT_VIEWPORT) {
+ const int object_restrict = base->object->visibility_flag;
+ if (object_restrict & OB_HIDE_VIEWPORT) {
base->flag &= ~BASE_ENABLED_VIEWPORT;
}
- if (object_restrict & OB_RESTRICT_RENDER) {
+ if (object_restrict & OB_HIDE_RENDER) {
base->flag &= ~BASE_ENABLED_RENDER;
}
- if (object_restrict & OB_RESTRICT_SELECT) {
+ if (object_restrict & OB_HIDE_SELECT) {
base->flag &= ~BASE_SELECTABLE;
}
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 62d29188c5a..0f880d16358 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -73,6 +73,7 @@
#include "BKE_rigidbody.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "RNA_access.h"
@@ -141,7 +142,8 @@ static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *
{
ID *id = cb_data->user_data;
if (*cb_data->id_pointer == id) {
- DEG_id_tag_update_ex(cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO);
+ DEG_id_tag_update_ex(
+ cb_data->bmain, cb_data->id_owner, ID_RECALC_TAG_FOR_UNDO | ID_RECALC_COPY_ON_WRITE);
return IDWALK_RET_STOP_ITER;
}
return IDWALK_RET_NOP;
@@ -193,6 +195,8 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
if (key != NULL) {
lib_id_clear_library_data_ex(bmain, &key->id);
}
+
+ DEG_relations_tag_update(bmain);
}
void BKE_lib_id_clear_library_data(Main *bmain, ID *id)
@@ -1317,14 +1321,6 @@ void *BKE_libblock_copy(Main *bmain, const ID *id)
return idn;
}
-/* XXX TODO: get rid of this useless wrapper at some point... */
-void *BKE_libblock_copy_for_localize(const ID *id)
-{
- ID *idn;
- BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA);
- return idn;
-}
-
/* ***************** ID ************************ */
ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *name)
{
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index a9407860c06..43afac5a376 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -142,14 +142,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
DEG_id_type_tag(bmain, type);
}
-#ifdef WITH_PYTHON
-# ifdef WITH_PYTHON_SAFETY
- BPY_id_release(id);
-# endif
- if (id->py_instance) {
- BPY_DECREF_RNA_INVALIDATE(id->py_instance);
- }
-#endif
+ BKE_libblock_free_data_py(id);
Key *key = ((flag & LIB_ID_FREE_NO_MAIN) == 0) ? BKE_key_from_id(id) : NULL;
@@ -406,3 +399,29 @@ size_t BKE_id_multi_tagged_delete(Main *bmain)
{
return id_delete(bmain, true);
}
+
+/* -------------------------------------------------------------------- */
+/** \name Python Data Handling
+ * \{ */
+
+/**
+ * In most cases #BKE_id_free_ex handles this, when lower level functions are called directly
+ * this function will need to be called too, if Python has access to the data.
+ *
+ * ID data-blocks such as #Material.nodetree are not stored in #Main.
+ */
+void BKE_libblock_free_data_py(ID *id)
+{
+#ifdef WITH_PYTHON
+# ifdef WITH_PYTHON_SAFETY
+ BPY_id_release(id);
+# endif
+ if (id->py_instance) {
+ BPY_DECREF_RNA_INVALIDATE(id->py_instance);
+ }
+#else
+ UNUSED_VARS(id);
+#endif
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 8e67547b719..8083585b594 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -571,7 +571,7 @@ static void lib_override_linked_group_tag_recursive(LibOverrideGroupTagData *dat
* would use one of those.
* NOTE: missing IDs (aka placeholders) are never overridden. */
if (ELEM(GS(to_id->name), ID_OB, ID_GR)) {
- if ((to_id->tag & LIB_TAG_MISSING)) {
+ if (to_id->tag & LIB_TAG_MISSING) {
to_id->tag |= missing_tag;
}
else {
@@ -604,7 +604,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
const bool is_resync = data->is_resync;
BLI_assert(!data->is_override);
- if ((id_root->tag & LIB_TAG_MISSING)) {
+ if (id_root->tag & LIB_TAG_MISSING) {
id_root->tag |= data->missing_tag;
}
else {
@@ -654,7 +654,7 @@ static void lib_override_linked_group_tag(LibOverrideGroupTagData *data)
if (instantiating_collection == NULL &&
instantiating_collection_override_candidate != NULL) {
- if ((instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING)) {
+ if (instantiating_collection_override_candidate->id.tag & LIB_TAG_MISSING) {
instantiating_collection_override_candidate->id.tag |= data->missing_tag;
}
else {
@@ -730,7 +730,7 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
BLI_assert(data->is_override);
- if ((id_root->override_library->reference->tag & LIB_TAG_MISSING)) {
+ if (id_root->override_library->reference->tag & LIB_TAG_MISSING) {
id_root->tag |= data->missing_tag;
}
else {
@@ -855,8 +855,8 @@ static void lib_override_library_create_post_process(Main *bmain,
default_instantiating_collection = BKE_collection_add(
bmain, (Collection *)id_root, "OVERRIDE_HIDDEN");
/* Hide the collection from viewport and render. */
- default_instantiating_collection->flag |= COLLECTION_RESTRICT_VIEWPORT |
- COLLECTION_RESTRICT_RENDER;
+ default_instantiating_collection->flag |= COLLECTION_HIDE_VIEWPORT |
+ COLLECTION_HIDE_RENDER;
break;
}
case ID_OB: {
@@ -1020,7 +1020,7 @@ bool BKE_lib_override_library_resync(Main *bmain,
if (id_root_reference->tag & LIB_TAG_MISSING) {
BKE_reportf(reports != NULL ? reports->reports : NULL,
RPT_ERROR,
- "impossible to resync data-block %s and its dependencies, as its linked reference "
+ "Impossible to resync data-block %s and its dependencies, as its linked reference "
"is missing",
id_root->name + 2);
return false;
@@ -1599,6 +1599,17 @@ static void lib_override_library_main_resync_on_library_indirect_level(
(!ID_IS_LINKED(id) && library_indirect_level != 0)) {
continue;
}
+
+ /* We cannot resync a scene that is currently active. */
+ if (id == &scene->id) {
+ id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
+ BKE_reportf(reports->reports,
+ RPT_WARNING,
+ "Scene '%s' was not resynced as it is the currently active one",
+ scene->id.name + 2);
+ continue;
+ }
+
Library *library = id->lib;
int level = 0;
@@ -1620,7 +1631,7 @@ static void lib_override_library_main_resync_on_library_indirect_level(
CLOG_INFO(&LOG, 2, "\tSuccess: %d", success);
if (success) {
reports->count.resynced_lib_overrides++;
- if (library_indirect_level > 0 &&
+ if (library_indirect_level > 0 && reports->do_resynced_lib_overrides_libraries_list &&
BLI_linklist_index(reports->resynced_lib_overrides_libraries, library) < 0) {
BLI_linklist_prepend(&reports->resynced_lib_overrides_libraries, library);
reports->resynced_lib_overrides_libraries_count++;
@@ -1731,8 +1742,7 @@ void BKE_lib_override_library_main_resync(Main *bmain,
override_resync_residual_storage = BKE_collection_add(
bmain, scene->master_collection, OVERRIDE_RESYNC_RESIDUAL_STORAGE_NAME);
/* Hide the collection from viewport and render. */
- override_resync_residual_storage->flag |= COLLECTION_RESTRICT_VIEWPORT |
- COLLECTION_RESTRICT_RENDER;
+ override_resync_residual_storage->flag |= COLLECTION_HIDE_VIEWPORT | COLLECTION_HIDE_RENDER;
}
/* Necessary to improve performances, and prevent layers matching override sub-collections to be
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 977e53c8474..9400458376d 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -88,8 +88,8 @@ bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int
/* Update the callback flags with some extra information regarding overrides: all 'loopback',
* 'internal', 'embedded' etc. ID pointers are never overridable. */
- if (cb_flag & (IDWALK_CB_INTERNAL | IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK |
- IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
+ if (cb_flag &
+ (IDWALK_CB_INTERNAL | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
cb_flag |= IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE;
}
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index d91d80ac683..c2b71b85973 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -136,27 +136,26 @@ static void light_foreach_id(ID *id, LibraryForeachIDData *data)
static void light_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Light *la = (Light *)id;
- if (la->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, Light, id_address, &la->id);
- BKE_id_blend_write(writer, &la->id);
- if (la->adt) {
- BKE_animdata_blend_write(writer, la->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Light, id_address, &la->id);
+ BKE_id_blend_write(writer, &la->id);
- if (la->curfalloff) {
- BKE_curvemapping_blend_write(writer, la->curfalloff);
- }
+ if (la->adt) {
+ BKE_animdata_blend_write(writer, la->adt);
+ }
- /* Node-tree is integral part of lights, no libdata. */
- if (la->nodetree) {
- BLO_write_struct(writer, bNodeTree, la->nodetree);
- ntreeBlendWrite(writer, la->nodetree);
- }
+ if (la->curfalloff) {
+ BKE_curvemapping_blend_write(writer, la->curfalloff);
+ }
- BKE_previewimg_blend_write(writer, la->preview);
+ /* Node-tree is integral part of lights, no libdata. */
+ if (la->nodetree) {
+ BLO_write_struct(writer, bNodeTree, la->nodetree);
+ ntreeBlendWrite(writer, la->nodetree);
}
+
+ BKE_previewimg_blend_write(writer, la->preview);
}
static void light_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index b09aed82921..15733af8ef0 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -60,14 +60,13 @@ static void lightprobe_foreach_id(ID *id, LibraryForeachIDData *data)
static void lightprobe_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
LightProbe *prb = (LightProbe *)id;
- if (prb->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, LightProbe, id_address, &prb->id);
- BKE_id_blend_write(writer, &prb->id);
-
- if (prb->adt) {
- BKE_animdata_blend_write(writer, prb->adt);
- }
+
+ /* write LibData */
+ BLO_write_id_struct(writer, LightProbe, id_address, &prb->id);
+ BKE_id_blend_write(writer, &prb->id);
+
+ if (prb->adt) {
+ BKE_animdata_blend_write(writer, prb->adt);
}
}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 26d9ab7a8c7..19030fca38b 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -457,28 +457,27 @@ static void write_linestyle_geometry_modifiers(BlendWriter *writer, ListBase *mo
static void linestyle_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id;
- if (linestyle->id.us > 0 || BLO_write_is_undo(writer)) {
- BLO_write_id_struct(writer, FreestyleLineStyle, id_address, &linestyle->id);
- BKE_id_blend_write(writer, &linestyle->id);
- if (linestyle->adt) {
- BKE_animdata_blend_write(writer, linestyle->adt);
- }
+ BLO_write_id_struct(writer, FreestyleLineStyle, id_address, &linestyle->id);
+ BKE_id_blend_write(writer, &linestyle->id);
- write_linestyle_color_modifiers(writer, &linestyle->color_modifiers);
- write_linestyle_alpha_modifiers(writer, &linestyle->alpha_modifiers);
- write_linestyle_thickness_modifiers(writer, &linestyle->thickness_modifiers);
- write_linestyle_geometry_modifiers(writer, &linestyle->geometry_modifiers);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (linestyle->mtex[a]) {
- BLO_write_struct(writer, MTex, linestyle->mtex[a]);
- }
- }
- if (linestyle->nodetree) {
- BLO_write_struct(writer, bNodeTree, linestyle->nodetree);
- ntreeBlendWrite(writer, linestyle->nodetree);
+ if (linestyle->adt) {
+ BKE_animdata_blend_write(writer, linestyle->adt);
+ }
+
+ write_linestyle_color_modifiers(writer, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(writer, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(writer, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(writer, &linestyle->geometry_modifiers);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (linestyle->mtex[a]) {
+ BLO_write_struct(writer, MTex, linestyle->mtex[a]);
}
}
+ if (linestyle->nodetree) {
+ BLO_write_struct(writer, bNodeTree, linestyle->nodetree);
+ ntreeBlendWrite(writer, linestyle->nodetree);
+ }
}
static void direct_link_linestyle_color_modifier(BlendDataReader *reader,
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 34dd38164c2..a93fcb6e8e0 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -101,48 +101,47 @@ static void mask_foreach_id(ID *id, LibraryForeachIDData *data)
static void mask_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Mask *mask = (Mask *)id;
- if (mask->id.us > 0 || BLO_write_is_undo(writer)) {
- MaskLayer *masklay;
- BLO_write_id_struct(writer, Mask, id_address, &mask->id);
- BKE_id_blend_write(writer, &mask->id);
+ MaskLayer *masklay;
- if (mask->adt) {
- BKE_animdata_blend_write(writer, mask->adt);
- }
+ BLO_write_id_struct(writer, Mask, id_address, &mask->id);
+ BKE_id_blend_write(writer, &mask->id);
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- MaskLayerShape *masklay_shape;
+ if (mask->adt) {
+ BKE_animdata_blend_write(writer, mask->adt);
+ }
- BLO_write_struct(writer, MaskLayer, masklay);
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ MaskLayerShape *masklay_shape;
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
+ BLO_write_struct(writer, MaskLayer, masklay);
- void *points_deform = spline->points_deform;
- spline->points_deform = NULL;
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
- BLO_write_struct(writer, MaskSpline, spline);
- BLO_write_struct_array(writer, MaskSplinePoint, spline->tot_point, spline->points);
+ void *points_deform = spline->points_deform;
+ spline->points_deform = NULL;
- spline->points_deform = points_deform;
+ BLO_write_struct(writer, MaskSpline, spline);
+ BLO_write_struct_array(writer, MaskSplinePoint, spline->tot_point, spline->points);
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ spline->points_deform = points_deform;
- if (point->tot_uw) {
- BLO_write_struct_array(writer, MaskSplinePointUW, point->tot_uw, point->uw);
- }
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
+
+ if (point->tot_uw) {
+ BLO_write_struct_array(writer, MaskSplinePointUW, point->tot_uw, point->uw);
}
}
+ }
- for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
- masklay_shape = masklay_shape->next) {
- BLO_write_struct(writer, MaskLayerShape, masklay_shape);
- BLO_write_float_array(
- writer, masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data);
- }
+ for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
+ masklay_shape = masklay_shape->next) {
+ BLO_write_struct(writer, MaskLayerShape, masklay_shape);
+ BLO_write_float_array(
+ writer, masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data);
}
}
}
@@ -429,7 +428,7 @@ MaskLayer *BKE_mask_layer_copy(const MaskLayer *masklay)
masklay_new->blend_flag = masklay->blend_flag;
masklay_new->flag = masklay->flag;
masklay_new->falloff = masklay->falloff;
- masklay_new->restrictflag = masklay->restrictflag;
+ masklay_new->visibility_flag = masklay->visibility_flag;
for (spline = masklay->splines.first; spline; spline = spline->next) {
MaskSpline *spline_new = BKE_mask_spline_copy(spline);
@@ -2092,7 +2091,7 @@ void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer)
MaskSpline *spline;
/* Nothing to do if selection if disabled for the given layer. */
- if (mask_layer->restrictflag & MASK_RESTRICT_SELECT) {
+ if (mask_layer->visibility_flag & MASK_HIDE_SELECT) {
return;
}
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index 81c161a4a7d..e04e5fceec6 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -106,7 +106,7 @@
/* for debugging add... */
#ifndef NDEBUG
-/* printf("%u %u %u %u\n", _t[0], _t[1], _t[2], _t[3]); \ */
+// printf("%u %u %u %u\n", _t[0], _t[1], _t[2], _t[3]);
# define FACE_ASSERT(face, vert_max) \
{ \
unsigned int *_t = face; \
@@ -292,10 +292,10 @@ static void maskrasterize_spline_differentiate_point_outset(float (*diff_feather
co_curr = diff_points[k_curr];
co_next = diff_points[k_next];
- /* sub_v2_v2v2(d_prev, co_prev, co_curr); */ /* precalc */
+ // sub_v2_v2v2(d_prev, co_prev, co_curr); /* precalc */
sub_v2_v2v2(d_next, co_curr, co_next);
- /* normalize_v2(d_prev); */ /* precalc */
+ // normalize_v2(d_prev); /* precalc */
normalize_v2(d_next);
if ((do_test == false) ||
@@ -619,7 +619,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
unsigned int tot_boundary_found = 0;
#endif
- if (masklay->restrictflag & MASK_RESTRICT_RENDER) {
+ if (masklay->visibility_flag & MASK_HIDE_RENDER) {
/* skip the layer */
mr_handle->layers_tot--;
masklay_index--;
@@ -1213,7 +1213,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
layer->falloff = masklay->falloff;
}
- /* printf("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads); */
+ // printf("tris %d, feather tris %d\n", sf_tri_tot, tot_feather_quads);
}
/* add trianges */
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 4f0b2a718ed..13b5bca5638 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -179,31 +179,30 @@ static void material_foreach_id(ID *id, LibraryForeachIDData *data)
static void material_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Material *ma = (Material *)id;
- if (ma->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- ma->texpaintslot = NULL;
- BLI_listbase_clear(&ma->gpumaterial);
- /* write LibData */
- BLO_write_id_struct(writer, Material, id_address, &ma->id);
- BKE_id_blend_write(writer, &ma->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ ma->texpaintslot = NULL;
+ BLI_listbase_clear(&ma->gpumaterial);
- if (ma->adt) {
- BKE_animdata_blend_write(writer, ma->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Material, id_address, &ma->id);
+ BKE_id_blend_write(writer, &ma->id);
- /* nodetree is integral part of material, no libdata */
- if (ma->nodetree) {
- BLO_write_struct(writer, bNodeTree, ma->nodetree);
- ntreeBlendWrite(writer, ma->nodetree);
- }
+ if (ma->adt) {
+ BKE_animdata_blend_write(writer, ma->adt);
+ }
- BKE_previewimg_blend_write(writer, ma->preview);
+ /* nodetree is integral part of material, no libdata */
+ if (ma->nodetree) {
+ BLO_write_struct(writer, bNodeTree, ma->nodetree);
+ ntreeBlendWrite(writer, ma->nodetree);
+ }
- /* grease pencil settings */
- if (ma->gp_style) {
- BLO_write_struct(writer, MaterialGPencilStyle, ma->gp_style);
- }
+ BKE_previewimg_blend_write(writer, ma->preview);
+
+ /* grease pencil settings */
+ if (ma->gp_style) {
+ BLO_write_struct(writer, MaterialGPencilStyle, ma->gp_style);
}
}
@@ -1802,6 +1801,7 @@ void BKE_material_copybuf_free(void)
{
if (matcopybuf.nodetree) {
ntreeFreeLocalTree(matcopybuf.nodetree);
+ BLI_assert(!matcopybuf.nodetree->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(matcopybuf.nodetree);
matcopybuf.nodetree = NULL;
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 6a2b56306d6..45cf0f17840 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -119,28 +119,27 @@ static void metaball_foreach_id(ID *id, LibraryForeachIDData *data)
static void metaball_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
MetaBall *mb = (MetaBall *)id;
- if (mb->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- BLI_listbase_clear(&mb->disp);
- mb->editelems = NULL;
- /* Must always be cleared (meta's don't have their own edit-data). */
- mb->needs_flush_to_id = 0;
- mb->lastelem = NULL;
- mb->batch_cache = NULL;
-
- /* write LibData */
- BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
- BKE_id_blend_write(writer, &mb->id);
-
- /* direct data */
- BLO_write_pointer_array(writer, mb->totcol, mb->mat);
- if (mb->adt) {
- BKE_animdata_blend_write(writer, mb->adt);
- }
- LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
- BLO_write_struct(writer, MetaElem, ml);
- }
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ BLI_listbase_clear(&mb->disp);
+ mb->editelems = NULL;
+ /* Must always be cleared (meta's don't have their own edit-data). */
+ mb->needs_flush_to_id = 0;
+ mb->lastelem = NULL;
+ mb->batch_cache = NULL;
+
+ /* write LibData */
+ BLO_write_id_struct(writer, MetaBall, id_address, &mb->id);
+ BKE_id_blend_write(writer, &mb->id);
+
+ /* direct data */
+ BLO_write_pointer_array(writer, mb->totcol, mb->mat);
+ if (mb->adt) {
+ BKE_animdata_blend_write(writer, mb->adt);
+ }
+
+ LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
+ BLO_write_struct(writer, MetaElem, ml);
}
}
@@ -289,7 +288,7 @@ void BKE_mball_texspace_calc(Object *ob)
bb = ob->runtime.bb;
/* Weird one, this. */
- /* INIT_MINMAX(min, max); */
+ // INIT_MINMAX(min, max);
(min)[0] = (min)[1] = (min)[2] = 1.0e30f;
(max)[0] = (max)[1] = (max)[2] = -1.0e30f;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 8d74002ad79..eb8e6aad736 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -179,95 +179,90 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
{
Mesh *mesh = (Mesh *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (mesh->id.us > 0 || is_undo) {
- CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
-
- /* cache only - don't write */
- mesh->mface = NULL;
- mesh->totface = 0;
- memset(&mesh->fdata, 0, sizeof(mesh->fdata));
- memset(&mesh->runtime, 0, sizeof(mesh->runtime));
- flayers = flayers_buff;
-
- /* Do not store actual geometry data in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
- mesh->mvert = NULL;
- mesh->totvert = 0;
- memset(&mesh->vdata, 0, sizeof(mesh->vdata));
- vlayers = vlayers_buff;
-
- mesh->medge = NULL;
- mesh->totedge = 0;
- memset(&mesh->edata, 0, sizeof(mesh->edata));
- elayers = elayers_buff;
-
- mesh->mloop = NULL;
- mesh->totloop = 0;
- memset(&mesh->ldata, 0, sizeof(mesh->ldata));
- llayers = llayers_buff;
-
- mesh->mpoly = NULL;
- mesh->totpoly = 0;
- memset(&mesh->pdata, 0, sizeof(mesh->pdata));
- players = players_buff;
- }
- else {
- CustomData_blend_write_prepare(
- &mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
- CustomData_blend_write_prepare(
- &mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
- CustomData_blend_write_prepare(
- &mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
- CustomData_blend_write_prepare(
- &mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- }
- BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
- BKE_id_blend_write(writer, &mesh->id);
+ CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
- /* direct data */
- if (mesh->adt) {
- BKE_animdata_blend_write(writer, mesh->adt);
- }
+ /* cache only - don't write */
+ mesh->mface = NULL;
+ mesh->totface = 0;
+ memset(&mesh->fdata, 0, sizeof(mesh->fdata));
+ memset(&mesh->runtime, 0, sizeof(mesh->runtime));
+ flayers = flayers_buff;
+
+ /* Do not store actual geometry data in case this is a library override ID. */
+ if (ID_IS_OVERRIDE_LIBRARY(mesh) && !is_undo) {
+ mesh->mvert = NULL;
+ mesh->totvert = 0;
+ memset(&mesh->vdata, 0, sizeof(mesh->vdata));
+ vlayers = vlayers_buff;
+
+ mesh->medge = NULL;
+ mesh->totedge = 0;
+ memset(&mesh->edata, 0, sizeof(mesh->edata));
+ elayers = elayers_buff;
+
+ mesh->mloop = NULL;
+ mesh->totloop = 0;
+ memset(&mesh->ldata, 0, sizeof(mesh->ldata));
+ llayers = llayers_buff;
+
+ mesh->mpoly = NULL;
+ mesh->totpoly = 0;
+ memset(&mesh->pdata, 0, sizeof(mesh->pdata));
+ players = players_buff;
+ }
+ else {
+ CustomData_blend_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_blend_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ CustomData_blend_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_blend_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ }
- BKE_defbase_blend_write(writer, &mesh->vertex_group_names);
+ BLO_write_id_struct(writer, Mesh, id_address, &mesh->id);
+ BKE_id_blend_write(writer, &mesh->id);
- BLO_write_pointer_array(writer, mesh->totcol, mesh->mat);
- BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect);
+ /* direct data */
+ if (mesh->adt) {
+ BKE_animdata_blend_write(writer, mesh->adt);
+ }
+
+ BKE_defbase_blend_write(writer, &mesh->vertex_group_names);
- CustomData_blend_write(
- writer, &mesh->vdata, vlayers, mesh->totvert, CD_MASK_MESH.vmask, &mesh->id);
- CustomData_blend_write(
- writer, &mesh->edata, elayers, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
- /* fdata is really a dummy - written so slots align */
- CustomData_blend_write(
- writer, &mesh->fdata, flayers, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
- CustomData_blend_write(
- writer, &mesh->ldata, llayers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
- CustomData_blend_write(
- writer, &mesh->pdata, players, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id);
+ BLO_write_pointer_array(writer, mesh->totcol, mesh->mat);
+ BLO_write_raw(writer, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- /* Free temporary data */
+ CustomData_blend_write(
+ writer, &mesh->vdata, vlayers, mesh->totvert, CD_MASK_MESH.vmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->edata, elayers, mesh->totedge, CD_MASK_MESH.emask, &mesh->id);
+ /* fdata is really a dummy - written so slots align */
+ CustomData_blend_write(
+ writer, &mesh->fdata, flayers, mesh->totface, CD_MASK_MESH.fmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->ldata, llayers, mesh->totloop, CD_MASK_MESH.lmask, &mesh->id);
+ CustomData_blend_write(
+ writer, &mesh->pdata, players, mesh->totpoly, CD_MASK_MESH.pmask, &mesh->id);
-/* Free custom-data layers, when not assigned a buffer value. */
+ /* Free temporary data */
+
+ /* Free custom-data layers, when not assigned a buffer value. */
#define CD_LAYERS_FREE(id) \
if (id && id != id##_buff) { \
MEM_freeN(id); \
} \
((void)0)
- CD_LAYERS_FREE(vlayers);
- CD_LAYERS_FREE(elayers);
- /* CD_LAYER_FREE(flayers); */ /* Never allocated. */
- CD_LAYERS_FREE(llayers);
- CD_LAYERS_FREE(players);
+ CD_LAYERS_FREE(vlayers);
+ CD_LAYERS_FREE(elayers);
+ // CD_LAYER_FREE(flayers); /* Never allocated. */
+ CD_LAYERS_FREE(llayers);
+ CD_LAYERS_FREE(players);
#undef CD_LAYERS_FREE
- }
}
static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
@@ -389,6 +384,7 @@ enum {
MESHCMP_EDGEUNKNOWN,
MESHCMP_VERTCOMISMATCH,
MESHCMP_CDLAYERS_MISMATCH,
+ MESHCMP_ATTRIBUTE_VALUE_MISMATCH,
};
static const char *cmpcode_to_str(int code)
@@ -416,6 +412,8 @@ static const char *cmpcode_to_str(int code)
return "Vertex Coordinate Mismatch";
case MESHCMP_CDLAYERS_MISMATCH:
return "CustomData Layer Count Mismatch";
+ case MESHCMP_ATTRIBUTE_VALUE_MISMATCH:
+ return "Attribute Value Mismatch";
default:
return "Mesh Comparison Code Unknown";
}
@@ -423,171 +421,233 @@ static const char *cmpcode_to_str(int code)
/** Thresh is threshold for comparing vertices, UV's, vertex colors, weights, etc. */
static int customdata_compare(
- CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2, const float thresh)
+ CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh)
{
const float thresh_sq = thresh * thresh;
CustomDataLayer *l1, *l2;
- int i, i1 = 0, i2 = 0, tot, j;
-
- for (i = 0; i < c1->totlayer; i++) {
- if (ELEM(c1->layers[i].type,
- CD_MVERT,
- CD_MEDGE,
- CD_MPOLY,
- CD_MLOOPUV,
- CD_MLOOPCOL,
- CD_MDEFORMVERT)) {
- i1++;
+ int layer_count1 = 0, layer_count2 = 0, j;
+ const uint64_t cd_mask_non_generic = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MPOLY |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MDEFORMVERT;
+ const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic;
+
+ for (int i = 0; i < c1->totlayer; i++) {
+ if (CD_TYPE_AS_MASK(c1->layers[i].type) & cd_mask_all_attr) {
+ layer_count1++;
}
}
- for (i = 0; i < c2->totlayer; i++) {
- if (ELEM(c2->layers[i].type,
- CD_MVERT,
- CD_MEDGE,
- CD_MPOLY,
- CD_MLOOPUV,
- CD_MLOOPCOL,
- CD_MDEFORMVERT)) {
- i2++;
+ for (int i = 0; i < c2->totlayer; i++) {
+ if (CD_TYPE_AS_MASK(c2->layers[i].type) & cd_mask_all_attr) {
+ layer_count2++;
}
}
- if (i1 != i2) {
+ if (layer_count1 != layer_count2) {
return MESHCMP_CDLAYERS_MISMATCH;
}
l1 = c1->layers;
l2 = c2->layers;
- tot = i1;
- i1 = 0;
- i2 = 0;
- for (i = 0; i < tot; i++) {
- while (
- i1 < c1->totlayer &&
- !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) {
- i1++;
- l1++;
- }
-
- while (
- i2 < c2->totlayer &&
- !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) {
- i2++;
- l2++;
- }
- if (l1->type == CD_MVERT) {
- MVert *v1 = l1->data;
- MVert *v2 = l2->data;
- int vtot = m1->totvert;
-
- for (j = 0; j < vtot; j++, v1++, v2++) {
- if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) {
- return MESHCMP_VERTCOMISMATCH;
- }
- /* I don't care about normals, let's just do coordinates. */
+ for (int i1 = 0; i1 < c1->totlayer; i1++) {
+ l1 = c1->layers + i1;
+ for (int i2 = 0; i2 < c2->totlayer; i2++) {
+ l2 = c2->layers + i2;
+ if (l1->type != l2->type || !STREQ(l1->name, l2->name)) {
+ continue;
}
- }
+ /* At this point `l1` and `l2` have the same name and type, so they should be compared. */
- /* We're order-agnostic for edges here. */
- if (l1->type == CD_MEDGE) {
- MEdge *e1 = l1->data;
- MEdge *e2 = l2->data;
- int etot = m1->totedge;
- EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
+ switch (l1->type) {
- for (j = 0; j < etot; j++, e1++) {
- BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
- }
+ case CD_MVERT: {
+ MVert *v1 = l1->data;
+ MVert *v2 = l2->data;
+ int vtot = m1->totvert;
- for (j = 0; j < etot; j++, e2++) {
- if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) {
- return MESHCMP_EDGEUNKNOWN;
+ for (j = 0; j < vtot; j++, v1++, v2++) {
+ if (len_squared_v3v3(v1->co, v2->co) > thresh_sq) {
+ return MESHCMP_VERTCOMISMATCH;
+ }
+ /* I don't care about normals, let's just do coordinates. */
+ }
+ break;
}
- }
- BLI_edgehash_free(eh, NULL);
- }
- if (l1->type == CD_MPOLY) {
- MPoly *p1 = l1->data;
- MPoly *p2 = l2->data;
- int ptot = m1->totpoly;
+ /* We're order-agnostic for edges here. */
+ case CD_MEDGE: {
+ MEdge *e1 = l1->data;
+ MEdge *e2 = l2->data;
+ int etot = m1->totedge;
+ EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot);
- for (j = 0; j < ptot; j++, p1++, p2++) {
- MLoop *lp1, *lp2;
- int k;
+ for (j = 0; j < etot; j++, e1++) {
+ BLI_edgehash_insert(eh, e1->v1, e1->v2, e1);
+ }
- if (p1->totloop != p2->totloop) {
- return MESHCMP_POLYMISMATCH;
+ for (j = 0; j < etot; j++, e2++) {
+ if (!BLI_edgehash_lookup(eh, e2->v1, e2->v2)) {
+ return MESHCMP_EDGEUNKNOWN;
+ }
+ }
+ BLI_edgehash_free(eh, NULL);
+ break;
}
-
- lp1 = m1->mloop + p1->loopstart;
- lp2 = m2->mloop + p2->loopstart;
-
- for (k = 0; k < p1->totloop; k++, lp1++, lp2++) {
- if (lp1->v != lp2->v) {
- return MESHCMP_POLYVERTMISMATCH;
+ case CD_MPOLY: {
+ MPoly *p1 = l1->data;
+ MPoly *p2 = l2->data;
+ int ptot = m1->totpoly;
+
+ for (j = 0; j < ptot; j++, p1++, p2++) {
+ MLoop *lp1, *lp2;
+ int k;
+
+ if (p1->totloop != p2->totloop) {
+ return MESHCMP_POLYMISMATCH;
+ }
+
+ lp1 = m1->mloop + p1->loopstart;
+ lp2 = m2->mloop + p2->loopstart;
+
+ for (k = 0; k < p1->totloop; k++, lp1++, lp2++) {
+ if (lp1->v != lp2->v) {
+ return MESHCMP_POLYVERTMISMATCH;
+ }
+ }
}
+ break;
}
- }
- }
- if (l1->type == CD_MLOOP) {
- MLoop *lp1 = l1->data;
- MLoop *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (lp1->v != lp2->v) {
- return MESHCMP_LOOPMISMATCH;
+ case CD_MLOOP: {
+ MLoop *lp1 = l1->data;
+ MLoop *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (lp1->v != lp2->v) {
+ return MESHCMP_LOOPMISMATCH;
+ }
+ }
+ break;
}
- }
- }
- if (l1->type == CD_MLOOPUV) {
- MLoopUV *lp1 = l1->data;
- MLoopUV *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) {
- return MESHCMP_LOOPUVMISMATCH;
+ case CD_MLOOPUV: {
+ MLoopUV *lp1 = l1->data;
+ MLoopUV *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) {
+ return MESHCMP_LOOPUVMISMATCH;
+ }
+ }
+ break;
}
- }
- }
-
- if (l1->type == CD_MLOOPCOL) {
- MLoopCol *lp1 = l1->data;
- MLoopCol *lp2 = l2->data;
- int ltot = m1->totloop;
-
- for (j = 0; j < ltot; j++, lp1++, lp2++) {
- if (abs(lp1->r - lp2->r) > thresh || abs(lp1->g - lp2->g) > thresh ||
- abs(lp1->b - lp2->b) > thresh || abs(lp1->a - lp2->a) > thresh) {
- return MESHCMP_LOOPCOLMISMATCH;
+ case CD_MLOOPCOL: {
+ MLoopCol *lp1 = l1->data;
+ MLoopCol *lp2 = l2->data;
+ int ltot = m1->totloop;
+
+ for (j = 0; j < ltot; j++, lp1++, lp2++) {
+ if (abs(lp1->r - lp2->r) > thresh || abs(lp1->g - lp2->g) > thresh ||
+ abs(lp1->b - lp2->b) > thresh || abs(lp1->a - lp2->a) > thresh) {
+ return MESHCMP_LOOPCOLMISMATCH;
+ }
+ }
+ break;
}
- }
- }
-
- if (l1->type == CD_MDEFORMVERT) {
- MDeformVert *dv1 = l1->data;
- MDeformVert *dv2 = l2->data;
- int dvtot = m1->totvert;
-
- for (j = 0; j < dvtot; j++, dv1++, dv2++) {
- int k;
- MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw;
-
- if (dv1->totweight != dv2->totweight) {
- return MESHCMP_DVERT_TOTGROUPMISMATCH;
+ case CD_MDEFORMVERT: {
+ MDeformVert *dv1 = l1->data;
+ MDeformVert *dv2 = l2->data;
+ int dvtot = m1->totvert;
+
+ for (j = 0; j < dvtot; j++, dv1++, dv2++) {
+ int k;
+ MDeformWeight *dw1 = dv1->dw, *dw2 = dv2->dw;
+
+ if (dv1->totweight != dv2->totweight) {
+ return MESHCMP_DVERT_TOTGROUPMISMATCH;
+ }
+
+ for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) {
+ if (dw1->def_nr != dw2->def_nr) {
+ return MESHCMP_DVERT_GROUPMISMATCH;
+ }
+ if (fabsf(dw1->weight - dw2->weight) > thresh) {
+ return MESHCMP_DVERT_WEIGHTMISMATCH;
+ }
+ }
+ }
+ break;
}
-
- for (k = 0; k < dv1->totweight; k++, dw1++, dw2++) {
- if (dw1->def_nr != dw2->def_nr) {
- return MESHCMP_DVERT_GROUPMISMATCH;
+ case CD_PROP_FLOAT: {
+ const float *l1_data = l1->data;
+ const float *l2_data = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (fabsf(l1_data[i] - l2_data[i]) > thresh) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_PROP_FLOAT2: {
+ const float(*l1_data)[2] = l1->data;
+ const float(*l2_data)[2] = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (len_squared_v2v2(l1_data[i], l2_data[i]) > thresh_sq) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ const float(*l1_data)[3] = l1->data;
+ const float(*l2_data)[3] = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (len_squared_v3v3(l1_data[i], l2_data[i]) > thresh_sq) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_PROP_INT32: {
+ const int *l1_data = l1->data;
+ const int *l2_data = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (l1_data[i] != l2_data[i]) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
}
- if (fabsf(dw1->weight - dw2->weight) > thresh) {
- return MESHCMP_DVERT_WEIGHTMISMATCH;
+ break;
+ }
+ case CD_PROP_BOOL: {
+ const bool *l1_data = l1->data;
+ const bool *l2_data = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (l1_data[i] != l2_data[i]) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
+ case CD_PROP_COLOR: {
+ const MPropCol *l1_data = l1->data;
+ const MPropCol *l2_data = l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ for (j = 0; j < 4; j++) {
+ if (fabsf(l1_data[i].color[j] - l2_data[i].color[j]) > thresh) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
}
+ break;
+ }
+ default: {
+ break;
}
}
}
@@ -626,19 +686,19 @@ const char *BKE_mesh_cmp(Mesh *me1, Mesh *me2, float thresh)
return "Number of loops don't match";
}
- if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1, me2, thresh))) {
+ if ((c = customdata_compare(&me1->vdata, &me2->vdata, me1->totvert, me1, me2, thresh))) {
return cmpcode_to_str(c);
}
- if ((c = customdata_compare(&me1->edata, &me2->edata, me1, me2, thresh))) {
+ if ((c = customdata_compare(&me1->edata, &me2->edata, me1->totedge, me1, me2, thresh))) {
return cmpcode_to_str(c);
}
- if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1, me2, thresh))) {
+ if ((c = customdata_compare(&me1->ldata, &me2->ldata, me1->totloop, me1, me2, thresh))) {
return cmpcode_to_str(c);
}
- if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1, me2, thresh))) {
+ if ((c = customdata_compare(&me1->pdata, &me2->pdata, me1->totpoly, me1, me2, thresh))) {
return cmpcode_to_str(c);
}
@@ -801,8 +861,11 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
return CustomData_has_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
}
-/** Free (or release) any data used by this mesh (does not free the mesh itself). */
-void BKE_mesh_free(Mesh *me)
+/**
+ * Free (or release) any data used by this mesh (does not free the mesh itself).
+ * Only use for undo, in most cases `BKE_id_free(NULL, me)` should be used.
+ */
+void BKE_mesh_free_data_for_undo(Mesh *me)
{
mesh_free_data(&me->id);
}
@@ -890,7 +953,7 @@ Mesh *BKE_mesh_new_nomain(
NULL, ID_ME, BKE_idtype_idcode_to_name(ID_ME), LIB_ID_CREATE_LOCALIZE);
BKE_libblock_init_empty(&mesh->id);
- /* Don't use CustomData_reset(...); because we don't want to touch custom-data. */
+ /* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(mesh->vdata.typemap, CD_NUMTYPES, -1);
copy_vn_i(mesh->edata.typemap, CD_NUMTYPES, -1);
copy_vn_i(mesh->fdata.typemap, CD_NUMTYPES, -1);
@@ -1018,7 +1081,7 @@ void BKE_mesh_eval_delete(struct Mesh *mesh_eval)
{
/* Evaluated mesh may point to edit mesh, but never owns it. */
mesh_eval->edit_mesh = NULL;
- BKE_mesh_free(mesh_eval);
+ mesh_free_data(&mesh_eval->id);
BKE_libblock_free_data(&mesh_eval->id, false);
MEM_freeN(mesh_eval);
}
@@ -1621,10 +1684,7 @@ void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh)
void BKE_mesh_mselect_clear(Mesh *me)
{
- if (me->mselect) {
- MEM_freeN(me->mselect);
- me->mselect = NULL;
- }
+ MEM_SAFE_FREE(me->mselect);
me->totselect = 0;
}
@@ -1841,15 +1901,14 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spac
}
else {
polynors = MEM_malloc_arrayN(mesh->totpoly, sizeof(float[3]), __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert,
- NULL,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ polynors,
+ NULL);
free_polynors = true;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 0e4fe91e577..4b1eb5b39ce 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -38,6 +38,7 @@
#include "BLI_utildefines.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_key.h"
@@ -271,8 +272,8 @@ static int mesh_nurbs_displist_to_mdata(const Curve *cu,
}
if (totvert == 0) {
- /* error("can't convert"); */
- /* Make Sure you check ob->data is a curve */
+ /* Make Sure you check ob->data is a curve. */
+ // error("can't convert");
return -1;
}
@@ -1665,6 +1666,10 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
/* skip the listbase */
MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev);
+ BLI_freelistN(&mesh_dst->vertex_group_names);
+ BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names);
+ mesh_dst->vertex_group_active_index = mesh_src->vertex_group_active_index;
+
if (take_ownership) {
if (alloctype == CD_ASSIGN) {
CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask);
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index 9aeaa1ada52..b20d81e7b9c 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -393,15 +393,14 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* calculate custom normals into loop_normals, then mirror first half into second half */
- BKE_mesh_calc_normals_poly(result->mvert,
- NULL,
- result->totvert,
- result->mloop,
- result->mpoly,
- totloop,
- totpoly,
- poly_normals,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(result->mvert,
+ result->totvert,
+ result->mloop,
+ totloop,
+ result->mpoly,
+ totpoly,
+ poly_normals,
+ NULL);
BKE_mesh_normals_loop_split(result->mvert,
result->totvert,
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index f496d6eada1..9a761c6fa11 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -27,8 +27,6 @@
#include <climits>
-#include "CLG_log.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_mesh_types.h"
@@ -50,6 +48,8 @@
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "atomic_ops.h"
+
// #define DEBUG_TIME
#ifdef DEBUG_TIME
@@ -57,319 +57,257 @@
# include "PIL_time_utildefines.h"
#endif
-static CLG_LogRef LOG = {"bke.mesh_normals"};
-
/* -------------------------------------------------------------------- */
-/** \name Mesh Normal Calculation
+/** \name Private Utility Functions
* \{ */
/**
- * Call when there are no polygons.
+ * A thread-safe version of #add_v3_v3 that uses a spin-lock.
+ *
+ * \note Avoid using this when the chance of contention is high.
*/
-static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts)
+static void add_v3_v3_atomic(float r[3], const float a[3])
{
- for (int i = 0; i < numVerts; i++) {
- MVert *mv = &mverts[i];
- float no[3];
+#define FLT_EQ_NONAN(_fa, _fb) (*((const uint32_t *)&_fa) == *((const uint32_t *)&_fb))
- normalize_v3_v3(no, mv->co);
- normal_float_to_short_v3(mv->no, no);
+ float virtual_lock = r[0];
+ while (true) {
+ /* This loops until following conditions are met:
+ * - `r[0]` has same value as virtual_lock (i.e. it did not change since last try).
+ * - `r[0]` was not `FLT_MAX`, i.e. it was not locked by another thread. */
+ const float test_lock = atomic_cas_float(&r[0], virtual_lock, FLT_MAX);
+ if (_ATOMIC_LIKELY(FLT_EQ_NONAN(test_lock, virtual_lock) && (test_lock != FLT_MAX))) {
+ break;
+ }
+ virtual_lock = test_lock;
}
-}
+ virtual_lock += a[0];
+ r[1] += a[1];
+ r[2] += a[2];
-/* TODO(Sybren): we can probably rename this to BKE_mesh_calc_normals_mapping(),
- * and remove the function of the same name below, as that one doesn't seem to be
- * called anywhere. */
-void BKE_mesh_calc_normals_mapping_simple(struct Mesh *mesh)
-{
- const bool only_face_normals = CustomData_is_referenced_layer(&mesh->vdata, CD_MVERT);
-
- BKE_mesh_calc_normals_mapping_ex(mesh->mvert,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- nullptr,
- mesh->mface,
- mesh->totface,
- nullptr,
- nullptr,
- only_face_normals);
-}
+ /* Second atomic operation to 'release'
+ * our lock on that vector and set its first scalar value. */
+ /* Note that we do not need to loop here, since we 'locked' `r[0]`,
+ * nobody should have changed it in the mean time. */
+ virtual_lock = atomic_cas_float(&r[0], FLT_MAX, virtual_lock);
+ BLI_assert(virtual_lock == FLT_MAX);
-/* Calculate vertex and face normals, face normals are returned in *r_faceNors if non-nullptr
- * and vertex normals are stored in actual mverts.
- */
-void BKE_mesh_calc_normals_mapping(MVert *mverts,
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3])
-{
- BKE_mesh_calc_normals_mapping_ex(mverts,
- numVerts,
- mloop,
- mpolys,
- numLoops,
- numPolys,
- r_polyNors,
- mfaces,
- numFaces,
- origIndexFace,
- r_faceNors,
- false);
+#undef FLT_EQ_NONAN
}
-/* extended version of 'BKE_mesh_calc_normals_poly' with option not to calc vertex normals */
-void BKE_mesh_calc_normals_mapping_ex(MVert *mverts,
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polyNors)[3],
- const MFace *mfaces,
- int numFaces,
- const int *origIndexFace,
- float (*r_faceNors)[3],
- const bool only_face_normals)
-{
- float(*pnors)[3] = r_polyNors, (*fnors)[3] = r_faceNors;
-
- if (numPolys == 0) {
- if (only_face_normals == false) {
- mesh_calc_normals_vert_fallback(mverts, numVerts);
- }
- return;
- }
- /* if we are not calculating verts and no verts were passes then we have nothing to do */
- if ((only_face_normals == true) && (r_polyNors == nullptr) && (r_faceNors == nullptr)) {
- CLOG_WARN(&LOG, "called with nothing to do");
- return;
- }
-
- if (!pnors) {
- pnors = (float(*)[3])MEM_calloc_arrayN((size_t)numPolys, sizeof(float[3]), __func__);
- }
- /* NO NEED TO ALLOC YET */
- /* if (!fnors) fnors = MEM_calloc_arrayN(numFaces, sizeof(float[3]), "face nors mesh.c"); */
+/** \} */
- if (only_face_normals == false) {
- /* vertex normals are optional, they require some extra calculations,
- * so make them optional */
- BKE_mesh_calc_normals_poly(
- mverts, nullptr, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
- }
- else {
- /* only calc poly normals */
- const MPoly *mp = mpolys;
- for (int i = 0; i < numPolys; i++, mp++) {
- BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mverts, pnors[i]);
- }
- }
+/* -------------------------------------------------------------------- */
+/** \name Public Utility Functions
+ *
+ * Related to managing normals but not directly related to calculating normals.
+ * \{ */
- if (origIndexFace &&
- /* fnors == r_faceNors */ /* NO NEED TO ALLOC YET */
- fnors != nullptr &&
- numFaces) {
- const MFace *mf = mfaces;
- for (int i = 0; i < numFaces; i++, mf++, origIndexFace++) {
- if (*origIndexFace < numPolys) {
- copy_v3_v3(fnors[i], pnors[*origIndexFace]);
- }
- else {
- /* eek, we're not corresponding to polys */
- CLOG_ERROR(&LOG, "tessellation face indices are incorrect. normals may look bad.");
- }
- }
- }
+void BKE_mesh_normals_tag_dirty(Mesh *mesh)
+{
+ mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ mesh->runtime.cd_dirty_poly |= CD_MASK_NORMAL;
+}
- if (pnors != r_polyNors) {
- MEM_freeN(pnors);
- }
- /* if (fnors != r_faceNors) MEM_freeN(fnors); */ /* NO NEED TO ALLOC YET */
+/** \} */
- fnors = pnors = nullptr;
-}
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation (Polygons)
+ * \{ */
-struct MeshCalcNormalsData {
- const MPoly *mpolys;
+struct MeshCalcNormalsData_Poly {
+ const MVert *mvert;
const MLoop *mloop;
- MVert *mverts;
+ const MPoly *mpoly;
+
+ /** Polygon normal output. */
float (*pnors)[3];
- float (*lnors_weighted)[3];
- float (*vnors)[3];
};
-static void mesh_calc_normals_poly_cb(void *__restrict userdata,
+static void mesh_calc_normals_poly_fn(void *__restrict userdata,
const int pidx,
const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
- const MPoly *mp = &data->mpolys[pidx];
+ const MeshCalcNormalsData_Poly *data = (MeshCalcNormalsData_Poly *)userdata;
+ const MPoly *mp = &data->mpoly[pidx];
+ BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mvert, data->pnors[pidx]);
+}
+
+void BKE_mesh_calc_normals_poly(const MVert *mvert,
+ int UNUSED(mvert_len),
+ const MLoop *mloop,
+ int UNUSED(mloop_len),
+ const MPoly *mpoly,
+ int mpoly_len,
+ float (*r_poly_normals)[3])
+{
+ TaskParallelSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+
+ BLI_assert((r_poly_normals != nullptr) || (mpoly_len == 0));
+
+ MeshCalcNormalsData_Poly data = {};
+ data.mpoly = mpoly;
+ data.mloop = mloop;
+ data.mvert = mvert;
+ data.pnors = r_poly_normals;
- BKE_mesh_calc_poly_normal(mp, data->mloop + mp->loopstart, data->mverts, data->pnors[pidx]);
+ BLI_task_parallel_range(0, mpoly_len, &data, mesh_calc_normals_poly_fn, &settings);
}
-static void mesh_calc_normals_poly_prepare_cb(void *__restrict userdata,
- const int pidx,
- const TaskParallelTLS *__restrict UNUSED(tls))
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation (Polygons & Vertices)
+ *
+ * Implement #BKE_mesh_calc_normals_poly_and_vertex,
+ *
+ * Take care making optimizations to this function as improvements to low-poly
+ * meshes can slow down high-poly meshes. For details on performance, see D11993.
+ * \{ */
+
+struct MeshCalcNormalsData_PolyAndVertex {
+ /** Write into vertex normals #MVert.no. */
+ MVert *mvert;
+ const MLoop *mloop;
+ const MPoly *mpoly;
+
+ /** Polygon normal output. */
+ float (*pnors)[3];
+ /** Vertex normal output (may be freed, copied into #MVert.no). */
+ float (*vnors)[3];
+};
+
+static void mesh_calc_normals_poly_and_vertex_accum_fn(
+ void *__restrict userdata, const int pidx, const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
- const MPoly *mp = &data->mpolys[pidx];
+ const MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
+ const MPoly *mp = &data->mpoly[pidx];
const MLoop *ml = &data->mloop[mp->loopstart];
- const MVert *mverts = data->mverts;
+ const MVert *mverts = data->mvert;
+ float(*vnors)[3] = data->vnors;
float pnor_temp[3];
float *pnor = data->pnors ? data->pnors[pidx] : pnor_temp;
- float(*lnors_weighted)[3] = data->lnors_weighted;
- const int nverts = mp->totloop;
- float(*edgevecbuf)[3] = (float(*)[3])BLI_array_alloca(edgevecbuf, (size_t)nverts);
+ const int i_end = mp->totloop - 1;
- /* Polygon Normal and edge-vector */
- /* inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors */
+ /* Polygon Normal and edge-vector. */
+ /* Inline version of #BKE_mesh_calc_poly_normal, also does edge-vectors. */
{
- int i_prev = nverts - 1;
- const float *v_prev = mverts[ml[i_prev].v].co;
- const float *v_curr;
-
zero_v3(pnor);
/* Newell's Method */
- for (int i = 0; i < nverts; i++) {
- v_curr = mverts[ml[i].v].co;
- add_newell_cross_v3_v3v3(pnor, v_prev, v_curr);
-
- /* Unrelated to normalize, calculate edge-vector */
- sub_v3_v3v3(edgevecbuf[i_prev], v_prev, v_curr);
- normalize_v3(edgevecbuf[i_prev]);
- i_prev = i;
-
- v_prev = v_curr;
+ const float *v_curr = mverts[ml[i_end].v].co;
+ for (int i_next = 0; i_next <= i_end; i_next++) {
+ const float *v_next = mverts[ml[i_next].v].co;
+ add_newell_cross_v3_v3v3(pnor, v_curr, v_next);
+ v_curr = v_next;
}
if (UNLIKELY(normalize_v3(pnor) == 0.0f)) {
- pnor[2] = 1.0f; /* other axes set to 0.0 */
+ pnor[2] = 1.0f; /* Other axes set to zero. */
}
}
- /* accumulate angle weighted face normal */
- /* inline version of #accumulate_vertex_normals_poly_v3,
- * split between this threaded callback and #mesh_calc_normals_poly_accum_cb. */
+ /* Accumulate angle weighted face normal into the vertex normal. */
+ /* Inline version of #accumulate_vertex_normals_poly_v3. */
{
- const float *prev_edge = edgevecbuf[nverts - 1];
-
- for (int i = 0; i < nverts; i++) {
- const int lidx = mp->loopstart + i;
- const float *cur_edge = edgevecbuf[i];
-
- /* calculate angle between the two poly edges incident on
- * this vertex */
- const float fac = saacos(-dot_v3v3(cur_edge, prev_edge));
+ float edvec_prev[3], edvec_next[3], edvec_end[3];
+ const float *v_curr = mverts[ml[i_end].v].co;
+ sub_v3_v3v3(edvec_prev, mverts[ml[i_end - 1].v].co, v_curr);
+ normalize_v3(edvec_prev);
+ copy_v3_v3(edvec_end, edvec_prev);
+
+ for (int i_next = 0, i_curr = i_end; i_next <= i_end; i_curr = i_next++) {
+ const float *v_next = mverts[ml[i_next].v].co;
+
+ /* Skip an extra normalization by reusing the first calculated edge. */
+ if (i_next != i_end) {
+ sub_v3_v3v3(edvec_next, v_curr, v_next);
+ normalize_v3(edvec_next);
+ }
+ else {
+ copy_v3_v3(edvec_next, edvec_end);
+ }
- /* Store for later accumulation */
- mul_v3_v3fl(lnors_weighted[lidx], pnor, fac);
+ /* Calculate angle between the two poly edges incident on this vertex. */
+ const float fac = saacos(-dot_v3v3(edvec_prev, edvec_next));
+ const float vnor_add[3] = {pnor[0] * fac, pnor[1] * fac, pnor[2] * fac};
- prev_edge = cur_edge;
+ add_v3_v3_atomic(vnors[ml[i_curr].v], vnor_add);
+ v_curr = v_next;
+ copy_v3_v3(edvec_prev, edvec_next);
}
}
}
-static void mesh_calc_normals_poly_finalize_cb(void *__restrict userdata,
- const int vidx,
- const TaskParallelTLS *__restrict UNUSED(tls))
+static void mesh_calc_normals_poly_and_vertex_finalize_fn(
+ void *__restrict userdata, const int vidx, const TaskParallelTLS *__restrict UNUSED(tls))
{
- MeshCalcNormalsData *data = (MeshCalcNormalsData *)userdata;
+ MeshCalcNormalsData_PolyAndVertex *data = (MeshCalcNormalsData_PolyAndVertex *)userdata;
- MVert *mv = &data->mverts[vidx];
+ MVert *mv = &data->mvert[vidx];
float *no = data->vnors[vidx];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ /* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
normalize_v3_v3(no, mv->co);
}
normal_float_to_short_v3(mv->no, no);
}
-void BKE_mesh_calc_normals_poly(MVert *mverts,
- float (*r_vertnors)[3],
- int numVerts,
- const MLoop *mloop,
- const MPoly *mpolys,
- int numLoops,
- int numPolys,
- float (*r_polynors)[3],
- const bool only_face_normals)
+void BKE_mesh_calc_normals_poly_and_vertex(MVert *mvert,
+ const int mvert_len,
+ const MLoop *mloop,
+ const int UNUSED(mloop_len),
+ const MPoly *mpoly,
+ const int mpoly_len,
+ float (*r_poly_normals)[3],
+ float (*r_vert_normals)[3])
{
- float(*pnors)[3] = r_polynors;
-
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
settings.min_iter_per_thread = 1024;
- if (only_face_normals) {
- BLI_assert((pnors != nullptr) || (numPolys == 0));
- BLI_assert(r_vertnors == nullptr);
-
- MeshCalcNormalsData data;
- data.mpolys = mpolys;
- data.mloop = mloop;
- data.mverts = mverts;
- data.pnors = pnors;
-
- BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_cb, &settings);
- return;
- }
-
- float(*vnors)[3] = r_vertnors;
- float(*lnors_weighted)[3] = (float(*)[3])MEM_malloc_arrayN(
- (size_t)numLoops, sizeof(*lnors_weighted), __func__);
+ float(*vnors)[3] = r_vert_normals;
bool free_vnors = false;
- /* first go through and calculate normals for all the polys */
+ /* First go through and calculate normals for all the polys. */
if (vnors == nullptr) {
- vnors = (float(*)[3])MEM_calloc_arrayN((size_t)numVerts, sizeof(*vnors), __func__);
+ vnors = (float(*)[3])MEM_calloc_arrayN((size_t)mvert_len, sizeof(*vnors), __func__);
free_vnors = true;
}
else {
- memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
+ memset(vnors, 0, sizeof(*vnors) * (size_t)mvert_len);
}
- MeshCalcNormalsData data;
- data.mpolys = mpolys;
+ MeshCalcNormalsData_PolyAndVertex data = {};
+ data.mpoly = mpoly;
data.mloop = mloop;
- data.mverts = mverts;
- data.pnors = pnors;
- data.lnors_weighted = lnors_weighted;
+ data.mvert = mvert;
+ data.pnors = r_poly_normals;
data.vnors = vnors;
- /* Compute poly normals, and prepare weighted loop normals. */
- BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings);
-
- /* Actually accumulate weighted loop normals into vertex ones. */
- /* Unfortunately, not possible to thread that
- * (not in a reasonable, totally lock- and barrier-free fashion),
- * since several loops will point to the same vertex... */
- for (int lidx = 0; lidx < numLoops; lidx++) {
- add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]);
- }
+ /* Compute poly normals (`pnors`), accumulating them into vertex normals (`vnors`). */
+ BLI_task_parallel_range(
+ 0, mpoly_len, &data, mesh_calc_normals_poly_and_vertex_accum_fn, &settings);
- /* Normalize and validate computed vertex normals. */
- BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings);
+ /* Normalize and validate computed vertex normals (`vnors`). */
+ BLI_task_parallel_range(
+ 0, mvert_len, &data, mesh_calc_normals_poly_and_vertex_finalize_fn, &settings);
if (free_vnors) {
MEM_freeN(vnors);
}
- MEM_freeN(lnors_weighted);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh Normal Calculation
+ * \{ */
+
void BKE_mesh_ensure_normals(Mesh *mesh)
{
if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
@@ -410,16 +348,26 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
(size_t)mesh->totpoly, sizeof(*poly_nors), __func__);
}
- /* calculate poly/vert normals */
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- poly_nors,
- !do_vert_normals);
+ /* Calculate poly/vert normals. */
+ if (do_vert_normals) {
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ poly_nors,
+ nullptr);
+ }
+ else {
+ BKE_mesh_calc_normals_poly(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ poly_nors);
+ }
if (do_add_poly_nors_cddata) {
CustomData_add_layer(&mesh->pdata, CD_NORMAL, CD_ASSIGN, poly_nors, mesh->totpoly);
@@ -430,22 +378,23 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
}
}
-/* Note that this does not update the CD_NORMAL layer,
- * but does update the normals in the CD_MVERT layer. */
+/**
+ * NOTE: this does not update the #CD_NORMAL layer,
+ * but does update the normals in the #CD_MVERT layer.
+ */
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- nullptr,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ nullptr,
+ nullptr);
#ifdef DEBUG_TIME
TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
#endif
@@ -488,7 +437,7 @@ void BKE_mesh_calc_normals_looptri(MVert *mverts,
mverts[vtri[2]].co);
}
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ /* Following Mesh convention; we use vertex coordinate itself for normal in this case. */
for (int i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
float *no = tnorms[i];
@@ -628,11 +577,11 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
BLI_stack_discard(edge_vectors);
nbr++;
}
- /* NOTE: In theory, this could be 'nbr > 2',
- * but there is one case where we only have two edges for two loops:
- * a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.).
+ /* NOTE: In theory, this could be `nbr > 2`,
+ * but there is one case where we only have two edges for two loops:
+ * a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.).
*/
- BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop... */
+ BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop. */
lnor_space->ref_alpha = alpha / (float)nbr;
}
else {
@@ -704,7 +653,7 @@ MINLINE float unit_short_to_float(const short val)
MINLINE short unit_float_to_short(const float val)
{
- /* Rounding... */
+ /* Rounding. */
return (short)floorf(val * (float)SHRT_MAX + 0.5f);
}
@@ -915,7 +864,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
- * other causes than angle threshold... */
+ * other causes than angle threshold. */
if (do_sharp_edges_tag && is_angle_sharp) {
BLI_BITMAP_SET(sharp_edges, ml_curr->e, true);
}
@@ -929,7 +878,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
e2l[1] = INDEX_INVALID;
/* We want to avoid tagging edges as sharp when it is already defined as such by
- * other causes than angle threshold... */
+ * other causes than angle threshold. */
if (do_sharp_edges_tag) {
BLI_BITMAP_SET(sharp_edges, ml_curr->e, false);
}
@@ -981,7 +930,7 @@ void BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
/* Simple mapping from a loop to its polygon index. */
int *loop_to_poly = (int *)MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
- LoopSplitTaskDataCommon common_data;
+ LoopSplitTaskDataCommon common_data = {};
common_data.mverts = mverts;
common_data.medges = medges;
common_data.mloops = mloops;
@@ -1011,14 +960,13 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
const MLoop *mlfan_next;
const MPoly *mpfan_next;
- /* Warning! This is rather complex!
+ /* WARNING: This is rather complex!
* We have to find our next edge around the vertex (fan mode).
* First we find the next loop, which is either previous or next to mlfan_curr_index, depending
* whether both loops using current edge are in the same direction or not, and whether
* mlfan_curr_index actually uses the vertex we are fanning around!
* mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
- * (i.e. not the future mlfan_curr)...
- */
+ * (i.e. not the future `mlfan_curr`). */
*r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
*r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index];
@@ -1043,7 +991,7 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
*r_mlfan_vert_index = *r_mlfan_curr_index;
}
*r_mlfan_curr = &mloops[*r_mlfan_curr_index];
- /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+ /* And now we are back in sync, mlfan_curr_index is the index of `mlfan_curr`! Pff! */
}
static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
@@ -1098,8 +1046,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
normalize_v3(vec_prev);
BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, nullptr);
- /* We know there is only one loop in this space,
- * no need to create a linklist in this case... */
+ /* We know there is only one loop in this space, no need to create a link-list in this case. */
BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, nullptr, true);
if (clnors_data) {
@@ -1135,24 +1082,24 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
BLI_Stack *edge_vectors = data->edge_vectors;
- /* Gah... We have to fan around current vertex, until we find the other non-smooth edge,
+ /* Sigh! we have to fan around current vertex, until we find the other non-smooth edge,
* and accumulate face normals into the vertex!
* Note in case this vertex has only one sharp edges, this is a waste because the normal is the
* same as the vertex normal, but I do not see any easy way to detect that (would need to count
* number of sharp edges per vertex, I doubt the additional memory usage would be worth it,
- * especially as it should not be a common case in real-life meshes anyway).
- */
+ * especially as it should not be a common case in real-life meshes anyway). */
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
const MVert *mv_pivot = &mverts[mv_pivot_index];
- /* ml_curr would be mlfan_prev if we needed that one. */
+ /* `ml_curr` would be mlfan_prev if we needed that one. */
const MEdge *me_org = &medges[ml_curr->e];
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
const MLoop *mlfan_curr;
float lnor[3] = {0.0f, 0.0f, 0.0f};
- /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
/* We validate clnors data on the fly - cheapest way to do! */
@@ -1189,14 +1136,14 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
}
}
- // printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
+ // printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
while (true) {
const MEdge *me_curr = &medges[mlfan_curr->e];
/* Compute edge vectors.
* NOTE: We could pre-compute those into an array, in the first iteration, instead of computing
* them twice (or more) here. However, time gained is not worth memory and time lost,
- * given the fact that this code should not be called that much in real-life meshes...
+ * given the fact that this code should not be called that much in real-life meshes.
*/
{
const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
@@ -1206,7 +1153,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
normalize_v3(vec_curr);
}
- // printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index);
+ // printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index);
{
/* Code similar to accumulate_vertex_normals_poly_v3. */
@@ -1246,9 +1193,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (IS_EDGE_SHARP(e2lfan_curr) || (me_curr == me_org)) {
/* Current edge is sharp and we have finished with this fan of faces around this vert,
- * or this vert is smooth, and we have completed a full turn around it.
- */
- // printf("FAN: Finished!\n");
+ * or this vert is smooth, and we have completed a full turn around it. */
+ // printf("FAN: Finished!\n");
break;
}
@@ -1389,12 +1335,13 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
const int *e2lfan_curr;
const MLoop *mlfan_curr;
- /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
e2lfan_curr = e2l_prev;
if (IS_EDGE_SHARP(e2lfan_curr)) {
- /* Sharp loop, so not a cyclic smooth fan... */
+ /* Sharp loop, so not a cyclic smooth fan. */
return false;
}
@@ -1425,21 +1372,21 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
e2lfan_curr = edge_to_loops[mlfan_curr->e];
if (IS_EDGE_SHARP(e2lfan_curr)) {
- /* Sharp loop/edge, so not a cyclic smooth fan... */
+ /* Sharp loop/edge, so not a cyclic smooth fan. */
return false;
}
- /* Smooth loop/edge... */
+ /* Smooth loop/edge. */
if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) {
if (mlfan_vert_index == ml_curr_index) {
/* We walked around a whole cyclic smooth fan without finding any already-processed loop,
- * means we can use initial ml_curr/ml_prev edge as start for this smooth fan. */
+ * means we can use initial `ml_curr` / `ml_prev` edge as start for this smooth fan. */
return true;
}
- /* ... already checked in some previous looping, we can abort. */
+ /* Already checked in some previous looping, we can abort. */
return false;
}
- /* ... we can skip it in future, and keep checking the smooth fan. */
+ /* We can skip it in future, and keep checking the smooth fan. */
BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
}
}
@@ -1501,7 +1448,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
const int *e2l_prev = edge_to_loops[ml_prev->e];
#if 0
- printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...",
+ printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)",
ml_curr_index,
ml_curr->e,
ml_curr->v,
@@ -1531,12 +1478,12 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
ml_curr_index,
ml_prev_index,
mp_index))) {
- // printf("SKIPPING!\n");
+ // printf("SKIPPING!\n");
}
else {
LoopSplitTaskData *data, data_local;
- // printf("PROCESSING!\n");
+ // printf("PROCESSING!\n");
if (pool) {
if (data_idx == 0) {
@@ -1605,7 +1552,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
}
}
- /* Last block of data... Since it is calloc'ed and we use first nullptr item as stopper,
+ /* Last block of data. Since it is calloc'ed and we use first nullptr item as stopper,
* everything is fine. */
if (pool && data_idx) {
BLI_task_pool_push(pool, loop_split_worker, data_buff, true, nullptr);
@@ -1652,8 +1599,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
* since we may want to use lnors even when mesh's 'autosmooth' is disabled
* (see e.g. mesh mapping code).
* As usual, we could handle that on case-by-case basis,
- * but simpler to keep it well confined here.
- */
+ * but simpler to keep it well confined here. */
int mp_index;
for (mp_index = 0; mp_index < numPolys; mp_index++) {
@@ -1736,7 +1682,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false);
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
- /* Not enough loops to be worth the whole threading overhead... */
+ /* Not enough loops to be worth the whole threading overhead. */
loop_split_generator(nullptr, &common_data);
}
else {
@@ -1791,13 +1737,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
short (*r_clnors_data)[2],
const bool use_vertices)
{
- /* We *may* make that poor BKE_mesh_normals_loop_split() even more complex by making it handling
+ /* We *may* make that poor #BKE_mesh_normals_loop_split() even more complex by making it handling
* that feature too, would probably be more efficient in absolute.
* However, this function *is not* performance-critical, since it is mostly expected to be called
- * by io addons when importing custom normals, and modifier
+ * by io add-ons when importing custom normals, and modifier
* (and perhaps from some editing tools later?).
- * So better to keep some simplicity here, and just call BKE_mesh_normals_loop_split() twice!
- */
+ * So better to keep some simplicity here, and just call #BKE_mesh_normals_loop_split() twice! */
MLoopNorSpaceArray lnors_spacearr = {nullptr};
BLI_bitmap *done_loops = BLI_BITMAP_NEW((size_t)numLoops, __func__);
float(*lnors)[3] = (float(*)[3])MEM_calloc_arrayN((size_t)numLoops, sizeof(*lnors), __func__);
@@ -1849,15 +1794,13 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans
* matching given custom lnors.
* Note this code *will never* unsharp edges! And quite obviously,
- * when we set custom normals per vertices, running this is absolutely useless.
- */
+ * when we set custom normals per vertices, running this is absolutely useless. */
if (!use_vertices) {
for (int i = 0; i < numLoops; i++) {
if (!lnors_spacearr.lspacearr[i]) {
/* This should not happen in theory, but in some rare case (probably ugly geometry)
* we can get some nullptr loopspacearr at this point. :/
- * Maybe we should set those loops' edges as sharp?
- */
+ * Maybe we should set those loops' edges as sharp? */
BLI_BITMAP_ENABLE(done_loops, i);
if (G.debug & G_DEBUG) {
printf("WARNING! Getting invalid nullptr loop space for loop %d!\n", i);
@@ -1867,12 +1810,12 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (!BLI_BITMAP_TEST(done_loops, i)) {
/* Notes:
- * * In case of mono-loop smooth fan, we have nothing to do.
- * * Loops in this linklist are ordered (in reversed order compared to how they were
+ * - In case of mono-loop smooth fan, we have nothing to do.
+ * - Loops in this linklist are ordered (in reversed order compared to how they were
* discovered by BKE_mesh_normals_loop_split(), but this is not a problem).
* Which means if we find a mismatching clnor,
* we know all remaining loops will have to be in a new, different smooth fan/lnor space.
- * * In smooth fan case, we compare each clnor against a ref one,
+ * - In smooth fan case, we compare each clnor against a ref one,
* to avoid small differences adding up into a real big one in the end!
*/
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
@@ -1897,8 +1840,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
/* Current normal differs too much from org one, we have to tag the edge between
* previous loop's face and current's one as sharp.
* We know those two loops do not point to the same edge,
- * since we do not allow reversed winding in a same smooth fan.
- */
+ * since we do not allow reversed winding in a same smooth fan. */
const MPoly *mp = &mpolys[loop_to_poly[lidx]];
const MLoop *mlp =
&mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
@@ -1970,8 +1912,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
if (BLI_BITMAP_TEST_BOOL(done_loops, i)) {
/* Note we accumulate and average all custom normals in current smooth fan,
* to avoid getting different clnors data (tiny differences in plain custom normals can
- * give rather huge differences in computed 2D factors).
- */
+ * give rather huge differences in computed 2D factors). */
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
BLI_assert(POINTER_AS_INT(loops) == i);
@@ -2087,15 +2028,14 @@ static void mesh_set_custom_normals(Mesh *mesh, float (*r_custom_nors)[3], const
bool free_polynors = false;
if (polynors == nullptr) {
polynors = (float(*)[3])MEM_mallocN(sizeof(float[3]) * (size_t)mesh->totpoly, __func__);
- BKE_mesh_calc_normals_poly(mesh->mvert,
- nullptr,
- mesh->totvert,
- mesh->mloop,
- mesh->mpoly,
- mesh->totloop,
- mesh->totpoly,
- polynors,
- false);
+ BKE_mesh_calc_normals_poly_and_vertex(mesh->mvert,
+ mesh->totvert,
+ mesh->mloop,
+ mesh->totloop,
+ mesh->mpoly,
+ mesh->totpoly,
+ polynors,
+ nullptr);
free_polynors = true;
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index c5e8858ea12..53a31cbbc7a 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1379,14 +1379,12 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
}
if (dirty_nors_dst || do_poly_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
numverts_dst,
loops_dst,
- polys_dst,
numloops_dst,
+ polys_dst,
numpolys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
}
if (need_lnors_dst) {
@@ -2231,14 +2229,12 @@ void BKE_mesh_remap_calc_polys_from_mesh(const int mode,
}
if (dirty_nors_dst) {
BKE_mesh_calc_normals_poly(verts_dst,
- NULL,
numverts_dst,
loops_dst,
- polys_dst,
numloops_dst,
+ polys_dst,
numpolys_dst,
- poly_nors_dst,
- true);
+ poly_nors_dst);
}
}
diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
index 8364b0ec024..9f5703a015d 100644
--- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
+++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc
@@ -33,6 +33,7 @@
#include "BLI_array.hh"
#include "BLI_float3.hh"
#include "BLI_index_range.hh"
+#include "BLI_span.hh"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -48,7 +49,9 @@
#include "bmesh_tools.h"
#ifdef WITH_OPENVDB
-# include "openvdb_capi.h"
+# include <openvdb/openvdb.h>
+# include <openvdb/tools/MeshToVolume.h>
+# include <openvdb/tools/VolumeToMesh.h>
#endif
#ifdef WITH_QUADRIFLOW
@@ -58,6 +61,8 @@
using blender::Array;
using blender::float3;
using blender::IndexRange;
+using blender::MutableSpan;
+using blender::Span;
#ifdef WITH_QUADRIFLOW
static Mesh *remesh_quadriflow(const Mesh *input_mesh,
@@ -192,91 +197,80 @@ Mesh *BKE_mesh_remesh_quadriflow(const Mesh *mesh,
}
#ifdef WITH_OPENVDB
-static struct OpenVDBLevelSet *remesh_voxel_level_set_create(const Mesh *mesh,
- struct OpenVDBTransform *transform)
+static openvdb::FloatGrid::Ptr remesh_voxel_level_set_create(const Mesh *mesh,
+ const float voxel_size)
{
- const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh);
- MVertTri *verttri = (MVertTri *)MEM_callocN(
- sizeof(*verttri) * BKE_mesh_runtime_looptri_len(mesh), "remesh_looptri");
- BKE_mesh_runtime_verttri_from_looptri(
- verttri, mesh->mloop, looptri, BKE_mesh_runtime_looptri_len(mesh));
+ Span<MLoop> mloop{mesh->mloop, mesh->totloop};
+ Span<MLoopTri> looptris{BKE_mesh_runtime_looptri_ensure(mesh),
+ BKE_mesh_runtime_looptri_len(mesh)};
- const int totfaces = BKE_mesh_runtime_looptri_len(mesh);
- const int totverts = mesh->totvert;
- Array<float3> verts(totverts);
- Array<int> faces(totfaces * 3);
+ std::vector<openvdb::Vec3s> points(mesh->totvert);
+ std::vector<openvdb::Vec3I> triangles(looptris.size());
- for (const int i : IndexRange(totverts)) {
- verts[i] = mesh->mvert[i].co;
+ for (const int i : IndexRange(mesh->totvert)) {
+ const float3 co = mesh->mvert[i].co;
+ points[i] = openvdb::Vec3s(co.x, co.y, co.z);
}
- for (const int i : IndexRange(totfaces)) {
- MVertTri &vt = verttri[i];
- faces[i * 3] = vt.tri[0];
- faces[i * 3 + 1] = vt.tri[1];
- faces[i * 3 + 2] = vt.tri[2];
+ for (const int i : IndexRange(looptris.size())) {
+ const MLoopTri &loop_tri = looptris[i];
+ triangles[i] = openvdb::Vec3I(
+ mloop[loop_tri.tri[0]].v, mloop[loop_tri.tri[1]].v, mloop[loop_tri.tri[2]].v);
}
- struct OpenVDBLevelSet *level_set = OpenVDBLevelSet_create(false, nullptr);
- OpenVDBLevelSet_mesh_to_level_set(
- level_set, (const float *)verts.data(), faces.data(), totverts, totfaces, transform);
-
- MEM_freeN(verttri);
+ openvdb::math::Transform::Ptr transform = openvdb::math::Transform::createLinearTransform(
+ voxel_size);
+ openvdb::FloatGrid::Ptr grid = openvdb::tools::meshToLevelSet<openvdb::FloatGrid>(
+ *transform, points, triangles, 1.0f);
- return level_set;
+ return grid;
}
-static Mesh *remesh_voxel_volume_to_mesh(struct OpenVDBLevelSet *level_set,
- double isovalue,
- double adaptivity,
- bool relax_disoriented_triangles)
+static Mesh *remesh_voxel_volume_to_mesh(const openvdb::FloatGrid::Ptr level_set_grid,
+ const float isovalue,
+ const float adaptivity,
+ const bool relax_disoriented_triangles)
{
- struct OpenVDBVolumeToMeshData output_mesh;
- OpenVDBLevelSet_volume_to_mesh(
- level_set, &output_mesh, isovalue, adaptivity, relax_disoriented_triangles);
-
- Mesh *mesh = BKE_mesh_new_nomain(output_mesh.totvertices,
- 0,
- 0,
- (output_mesh.totquads * 4) + (output_mesh.tottriangles * 3),
- output_mesh.totquads + output_mesh.tottriangles);
-
- for (const int i : IndexRange(output_mesh.totvertices)) {
- copy_v3_v3(mesh->mvert[i].co, &output_mesh.vertices[i * 3]);
+ std::vector<openvdb::Vec3s> vertices;
+ std::vector<openvdb::Vec4I> quads;
+ std::vector<openvdb::Vec3I> tris;
+ openvdb::tools::volumeToMesh<openvdb::FloatGrid>(
+ *level_set_grid, vertices, tris, quads, isovalue, adaptivity, relax_disoriented_triangles);
+
+ Mesh *mesh = BKE_mesh_new_nomain(
+ vertices.size(), 0, 0, quads.size() * 4 + tris.size() * 3, quads.size() + tris.size());
+ MutableSpan<MVert> mverts{mesh->mvert, mesh->totvert};
+ MutableSpan<MLoop> mloops{mesh->mloop, mesh->totloop};
+ MutableSpan<MPoly> mpolys{mesh->mpoly, mesh->totpoly};
+
+ for (const int i : mverts.index_range()) {
+ copy_v3_v3(mverts[i].co, float3(vertices[i].x(), vertices[i].y(), vertices[i].z()));
}
- for (const int i : IndexRange(output_mesh.totquads)) {
- MPoly &poly = mesh->mpoly[i];
+ for (const int i : IndexRange(quads.size())) {
+ MPoly &poly = mpolys[i];
const int loopstart = i * 4;
poly.loopstart = loopstart;
poly.totloop = 4;
- mesh->mloop[loopstart].v = output_mesh.quads[loopstart];
- mesh->mloop[loopstart + 1].v = output_mesh.quads[loopstart + 1];
- mesh->mloop[loopstart + 2].v = output_mesh.quads[loopstart + 2];
- mesh->mloop[loopstart + 3].v = output_mesh.quads[loopstart + 3];
+ mloops[loopstart].v = quads[i][0];
+ mloops[loopstart + 1].v = quads[i][3];
+ mloops[loopstart + 2].v = quads[i][2];
+ mloops[loopstart + 3].v = quads[i][1];
}
- const int triangle_poly_start = output_mesh.totquads;
- const int triangle_loop_start = output_mesh.totquads * 4;
- for (const int i : IndexRange(output_mesh.tottriangles)) {
- MPoly &poly = mesh->mpoly[triangle_poly_start + i];
+ const int triangle_loop_start = quads.size() * 4;
+ for (const int i : IndexRange(tris.size())) {
+ MPoly &poly = mpolys[quads.size() + i];
const int loopstart = triangle_loop_start + i * 3;
poly.loopstart = loopstart;
poly.totloop = 3;
- mesh->mloop[loopstart].v = output_mesh.triangles[i * 3 + 2];
- mesh->mloop[loopstart + 1].v = output_mesh.triangles[i * 3 + 1];
- mesh->mloop[loopstart + 2].v = output_mesh.triangles[i * 3];
+ mloops[loopstart].v = tris[i][2];
+ mloops[loopstart + 1].v = tris[i][1];
+ mloops[loopstart + 2].v = tris[i][0];
}
BKE_mesh_calc_edges(mesh, false, false);
- BKE_mesh_calc_normals(mesh);
-
- MEM_freeN(output_mesh.quads);
- MEM_freeN(output_mesh.vertices);
-
- if (output_mesh.tottriangles > 0) {
- MEM_freeN(output_mesh.triangles);
- }
+ BKE_mesh_normals_tag_dirty(mesh);
return mesh;
}
@@ -288,14 +282,8 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh,
const float isovalue)
{
#ifdef WITH_OPENVDB
- struct OpenVDBTransform *xform = OpenVDBTransform_create();
- OpenVDBTransform_create_linear_transform(xform, (double)voxel_size);
- struct OpenVDBLevelSet *level_set = remesh_voxel_level_set_create(mesh, xform);
- Mesh *new_mesh = remesh_voxel_volume_to_mesh(
- level_set, (double)isovalue, (double)adaptivity, false);
- OpenVDBLevelSet_free(level_set);
- OpenVDBTransform_free(xform);
- return new_mesh;
+ openvdb::FloatGrid::Ptr level_set = remesh_voxel_level_set_create(mesh, voxel_size);
+ return remesh_voxel_volume_to_mesh(level_set, isovalue, adaptivity, false);
#else
UNUSED_VARS(mesh, voxel_size, adaptivity, isovalue);
return nullptr;
@@ -304,7 +292,7 @@ Mesh *BKE_mesh_remesh_voxel(const Mesh *mesh,
void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
{
- BVHTreeFromMesh bvhtree = {{nullptr}};
+ BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
@@ -342,7 +330,7 @@ void BKE_mesh_remesh_reproject_paint_mask(Mesh *target, Mesh *source)
void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
{
- BVHTreeFromMesh bvhtree = {{nullptr}};
+ BVHTreeFromMesh bvhtree = {nullptr};
const MPoly *target_polys = (const MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
const MVert *target_verts = (const MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
@@ -389,7 +377,7 @@ void BKE_remesh_reproject_sculpt_face_sets(Mesh *target, Mesh *source)
void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
{
- BVHTreeFromMesh bvhtree = {{nullptr}};
+ BVHTreeFromMesh bvhtree = {nullptr};
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
int tot_color_layer = CustomData_number_of_layers(&source->vdata, CD_PROP_COLOR);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 2088c4268e6..821ca7b98b3 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -249,11 +249,11 @@ bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
return false;
}
-bool BKE_modifier_depends_ontime(ModifierData *md)
+bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md, const int dag_eval_mode)
{
const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type);
- return mti->dependsOnTime && mti->dependsOnTime(md);
+ return mti->dependsOnTime && mti->dependsOnTime(scene, md, dag_eval_mode);
}
bool BKE_modifier_supports_mapping(ModifierData *md)
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index f32b0c434c1..e507252307b 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -206,36 +206,35 @@ static void write_movieReconstruction(BlendWriter *writer,
static void movieclip_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
MovieClip *clip = (MovieClip *)id;
- if (clip->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- clip->anim = NULL;
- clip->tracking_context = NULL;
- clip->tracking.stats = NULL;
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ clip->anim = NULL;
+ clip->tracking_context = NULL;
+ clip->tracking.stats = NULL;
- BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
- BKE_id_blend_write(writer, &clip->id);
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
- if (clip->adt) {
- BKE_animdata_blend_write(writer, clip->adt);
- }
+ BLO_write_id_struct(writer, MovieClip, id_address, &clip->id);
+ BKE_id_blend_write(writer, &clip->id);
+
+ if (clip->adt) {
+ BKE_animdata_blend_write(writer, clip->adt);
+ }
- write_movieTracks(writer, &tracking->tracks);
- write_moviePlaneTracks(writer, &tracking->plane_tracks);
- write_movieReconstruction(writer, &tracking->reconstruction);
+ write_movieTracks(writer, &tracking->tracks);
+ write_moviePlaneTracks(writer, &tracking->plane_tracks);
+ write_movieReconstruction(writer, &tracking->reconstruction);
- object = tracking->objects.first;
- while (object) {
- BLO_write_struct(writer, MovieTrackingObject, object);
+ object = tracking->objects.first;
+ while (object) {
+ BLO_write_struct(writer, MovieTrackingObject, object);
- write_movieTracks(writer, &object->tracks);
- write_moviePlaneTracks(writer, &object->plane_tracks);
- write_movieReconstruction(writer, &object->reconstruction);
+ write_movieTracks(writer, &object->tracks);
+ write_moviePlaneTracks(writer, &object->plane_tracks);
+ write_movieReconstruction(writer, &object->reconstruction);
- object = object->next;
- }
+ object = object->next;
}
}
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 54f0da30a2b..eaa11a6683a 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -468,15 +468,9 @@ void multires_force_sculpt_rebuild(Object *object)
object->sculpt->pbvh = NULL;
}
- if (ss->pmap != NULL) {
- MEM_freeN(ss->pmap);
- ss->pmap = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap);
- if (ss->pmap_mem != NULL) {
- MEM_freeN(ss->pmap_mem);
- ss->pmap_mem = NULL;
- }
+ MEM_SAFE_FREE(ss->pmap_mem);
}
void multires_force_external_reload(Object *object)
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 9888e23a7bd..2a0e05a2616 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -606,19 +606,18 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bNodeTree *ntree = (bNodeTree *)id;
- if (ntree->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- ntree->init = 0; /* to set callbacks and force setting types */
- ntree->is_updating = false;
- ntree->typeinfo = nullptr;
- ntree->interface_type = nullptr;
- ntree->progress = nullptr;
- ntree->execdata = nullptr;
- BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ ntree->init = 0; /* to set callbacks and force setting types */
+ ntree->is_updating = false;
+ ntree->typeinfo = nullptr;
+ ntree->interface_type = nullptr;
+ ntree->progress = nullptr;
+ ntree->execdata = nullptr;
- ntreeBlendWrite(writer, ntree);
- }
+ BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
+
+ ntreeBlendWrite(writer, ntree);
}
static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
@@ -2364,7 +2363,7 @@ bNodeLink *nodeAddLink(
ntree->update |= NTREE_UPDATE_LINKS;
}
- if (link->tosock->flag & SOCK_MULTI_INPUT) {
+ if (link != nullptr && link->tosock->flag & SOCK_MULTI_INPUT) {
link->multi_input_socket_index = node_count_links(ntree, link->tosock) - 1;
}
@@ -3194,6 +3193,7 @@ void ntreeFreeEmbeddedTree(bNodeTree *ntree)
{
ntreeFreeTree(ntree);
BKE_libblock_free_data(&ntree->id, true);
+ BKE_libblock_free_data_py(&ntree->id);
}
void ntreeFreeLocalTree(bNodeTree *ntree)
@@ -5149,6 +5149,7 @@ static void registerGeometryNodes()
register_node_type_geo_curve_resample();
register_node_type_geo_curve_reverse();
register_node_type_geo_curve_set_handles();
+ register_node_type_geo_curve_spline_type();
register_node_type_geo_curve_subdivide();
register_node_type_geo_curve_to_mesh();
register_node_type_geo_curve_to_points();
@@ -5180,6 +5181,7 @@ static void registerGeometryNodes()
register_node_type_geo_points_to_volume();
register_node_type_geo_raycast();
register_node_type_geo_sample_texture();
+ register_node_type_geo_select_by_handle_type();
register_node_type_geo_select_by_material();
register_node_type_geo_separate_components();
register_node_type_geo_subdivision_surface();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 89de37d6e4b..1c08a46adc3 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -144,6 +144,7 @@
#include "DRW_engine.h"
#include "BLO_read_write.h"
+#include "BLO_readfile.h"
#include "SEQ_sequencer.h"
@@ -522,74 +523,72 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
Object *ob = (Object *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (ob->id.us > 0 || is_undo) {
- /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
- BKE_object_runtime_reset(ob);
- if (is_undo) {
- /* For undo we stay in object mode during undo presses, so keep edit-mode disabled on save as
- * well, can help reducing false detection of changed data-blocks. */
- ob->mode &= ~OB_MODE_EDIT;
- }
+ /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
+ BKE_object_runtime_reset(ob);
- /* write LibData */
- BLO_write_id_struct(writer, Object, id_address, &ob->id);
- BKE_id_blend_write(writer, &ob->id);
+ if (is_undo) {
+ /* For undo we stay in object mode during undo presses, so keep edit-mode disabled on save as
+ * well, can help reducing false detection of changed data-blocks. */
+ ob->mode &= ~OB_MODE_EDIT;
+ }
- if (ob->adt) {
- BKE_animdata_blend_write(writer, ob->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Object, id_address, &ob->id);
+ BKE_id_blend_write(writer, &ob->id);
+
+ if (ob->adt) {
+ BKE_animdata_blend_write(writer, ob->adt);
+ }
- /* direct data */
- BLO_write_pointer_array(writer, ob->totcol, ob->mat);
- BLO_write_raw(writer, sizeof(char) * ob->totcol, ob->matbits);
+ /* direct data */
+ BLO_write_pointer_array(writer, ob->totcol, ob->mat);
+ BLO_write_raw(writer, sizeof(char) * ob->totcol, ob->matbits);
- bArmature *arm = NULL;
- if (ob->type == OB_ARMATURE) {
- arm = ob->data;
- if (arm && ob->pose && arm->act_bone) {
- BLI_strncpy(
- ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
- }
+ bArmature *arm = NULL;
+ if (ob->type == OB_ARMATURE) {
+ arm = ob->data;
+ if (arm && ob->pose && arm->act_bone) {
+ BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
}
+ }
- BKE_pose_blend_write(writer, ob->pose, arm);
- write_fmaps(writer, &ob->fmaps);
- BKE_constraint_blend_write(writer, &ob->constraints);
- animviz_motionpath_blend_write(writer, ob->mpath);
+ BKE_pose_blend_write(writer, ob->pose, arm);
+ write_fmaps(writer, &ob->fmaps);
+ BKE_constraint_blend_write(writer, &ob->constraints);
+ animviz_motionpath_blend_write(writer, ob->mpath);
- BLO_write_struct(writer, PartDeflect, ob->pd);
- if (ob->soft) {
- /* Set deprecated pointers to prevent crashes of older Blenders */
- ob->soft->pointcache = ob->soft->shared->pointcache;
- ob->soft->ptcaches = ob->soft->shared->ptcaches;
- BLO_write_struct(writer, SoftBody, ob->soft);
- BLO_write_struct(writer, SoftBody_Shared, ob->soft->shared);
- BKE_ptcache_blend_write(writer, &(ob->soft->shared->ptcaches));
- BLO_write_struct(writer, EffectorWeights, ob->soft->effector_weights);
- }
+ BLO_write_struct(writer, PartDeflect, ob->pd);
+ if (ob->soft) {
+ /* Set deprecated pointers to prevent crashes of older Blenders */
+ ob->soft->pointcache = ob->soft->shared->pointcache;
+ ob->soft->ptcaches = ob->soft->shared->ptcaches;
+ BLO_write_struct(writer, SoftBody, ob->soft);
+ BLO_write_struct(writer, SoftBody_Shared, ob->soft->shared);
+ BKE_ptcache_blend_write(writer, &(ob->soft->shared->ptcaches));
+ BLO_write_struct(writer, EffectorWeights, ob->soft->effector_weights);
+ }
- if (ob->rigidbody_object) {
- /* TODO: if any extra data is added to handle duplis, will need separate function then */
- BLO_write_struct(writer, RigidBodyOb, ob->rigidbody_object);
- }
- if (ob->rigidbody_constraint) {
- BLO_write_struct(writer, RigidBodyCon, ob->rigidbody_constraint);
- }
+ if (ob->rigidbody_object) {
+ /* TODO: if any extra data is added to handle duplis, will need separate function then */
+ BLO_write_struct(writer, RigidBodyOb, ob->rigidbody_object);
+ }
+ if (ob->rigidbody_constraint) {
+ BLO_write_struct(writer, RigidBodyCon, ob->rigidbody_constraint);
+ }
- if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- BLO_write_struct(writer, ImageUser, ob->iuser);
- }
+ if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ BLO_write_struct(writer, ImageUser, ob->iuser);
+ }
- BKE_particle_system_blend_write(writer, &ob->particlesystem);
- BKE_modifier_blend_write(writer, &ob->modifiers);
- BKE_gpencil_modifier_blend_write(writer, &ob->greasepencil_modifiers);
- BKE_shaderfx_blend_write(writer, &ob->shader_fx);
+ BKE_particle_system_blend_write(writer, &ob->particlesystem);
+ BKE_modifier_blend_write(writer, &ob->modifiers);
+ BKE_gpencil_modifier_blend_write(writer, &ob->greasepencil_modifiers);
+ BKE_shaderfx_blend_write(writer, &ob->shader_fx);
- BLO_write_struct_list(writer, LinkData, &ob->pc_ids);
+ BLO_write_struct_list(writer, LinkData, &ob->pc_ids);
- BKE_previewimg_blend_write(writer, ob->preview);
- }
+ BKE_previewimg_blend_write(writer, ob->preview);
}
/* XXX deprecated - old animation system */
@@ -833,7 +832,7 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
{
Object *ob = (Object *)id;
- bool warn = false;
+ BlendFileReadReport *reports = BLO_read_lib_reports(reader);
/* XXX deprecated - old animation system <<< */
BLO_read_id_address(reader, ob->id.lib, &ob->ipo);
@@ -851,8 +850,8 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
else {
if (ob->instance_collection != NULL) {
ID *new_id = BLO_read_get_new_id_address(reader, ob->id.lib, &ob->instance_collection->id);
- BLO_reportf_wrap(BLO_read_lib_reports(reader),
- RPT_WARNING,
+ BLO_reportf_wrap(reports,
+ RPT_INFO,
TIP_("Non-Empty object '%s' cannot duplicate collection '%s' "
"anymore in Blender 2.80, removed instancing"),
ob->id.name + 2,
@@ -870,11 +869,17 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
ob->proxy = NULL;
if (ob->id.lib) {
- printf("Proxy lost from object %s lib %s\n", ob->id.name + 2, ob->id.lib->filepath);
+ BLO_reportf_wrap(reports,
+ RPT_INFO,
+ TIP_("Proxy lost from object %s lib %s\n"),
+ ob->id.name + 2,
+ ob->id.lib->filepath);
}
else {
- printf("Proxy lost from object %s lib <NONE>\n", ob->id.name + 2);
+ BLO_reportf_wrap(
+ reports, RPT_INFO, TIP_("Proxy lost from object %s lib <NONE>\n"), ob->id.name + 2);
}
+ reports->count.missing_obproxies++;
}
else {
/* this triggers object_update to always use a copy */
@@ -887,15 +892,7 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
BLO_read_id_address(reader, ob->id.lib, &ob->data);
if (ob->data == NULL && poin != NULL) {
- if (ob->id.lib) {
- printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->filepath);
- }
- else {
- printf("Object %s lost data.\n", ob->id.name + 2);
- }
-
ob->type = OB_EMPTY;
- warn = true;
if (ob->pose) {
/* we can't call #BKE_pose_free() here because of library linking
@@ -911,6 +908,18 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
ob->pose = NULL;
ob->mode &= ~OB_MODE_POSE;
}
+
+ if (ob->id.lib) {
+ BLO_reportf_wrap(reports,
+ RPT_INFO,
+ TIP_("Can't find object data of %s lib %s\n"),
+ ob->id.name + 2,
+ ob->id.lib->filepath);
+ }
+ else {
+ BLO_reportf_wrap(reports, RPT_INFO, TIP_("Object %s lost data\n"), ob->id.name + 2);
+ }
+ reports->count.missing_obdata++;
}
for (int a = 0; a < ob->totcol; a++) {
BLO_read_id_address(reader, ob->id.lib, &ob->mat[a]);
@@ -922,7 +931,7 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
const short *totcol_data = BKE_object_material_len_p(ob);
/* Only expand so as not to lose any object materials that might be set. */
if (totcol_data && (*totcol_data > ob->totcol)) {
- /* printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data); */
+ // printf("'%s' %d -> %d\n", ob->id.name, ob->totcol, *totcol_data);
BKE_object_material_resize(BLO_read_lib_get_main(reader), ob, *totcol_data, false);
}
}
@@ -992,10 +1001,6 @@ static void object_blend_read_lib(BlendLibReader *reader, ID *id)
BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob1);
BLO_read_id_address(reader, ob->id.lib, &ob->rigidbody_constraint->ob2);
}
-
- if (warn) {
- BLO_reportf_wrap(BLO_read_lib_reports(reader), RPT_WARNING, "Warning in console");
- }
}
/* XXX deprecated - old animation system */
@@ -2074,6 +2079,12 @@ static void object_init(Object *ob, const short ob_type)
if (ob->type == OB_GPENCIL) {
ob->dtx |= OB_USE_GPENCIL_LIGHTS;
}
+
+ if (ob->type == OB_LAMP) {
+ /* Lights are invisible to camera rays and are assumed to be a
+ * shadow catcher by default. */
+ ob->visibility_flag |= OB_HIDE_CAMERA | OB_SHADOW_CATCHER;
+ }
}
void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
@@ -4034,10 +4045,7 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value)
}
}
else {
- if (ob->iuser) {
- MEM_freeN(ob->iuser);
- ob->iuser = NULL;
- }
+ MEM_SAFE_FREE(ob->iuser);
}
}
@@ -5401,9 +5409,12 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
return tree;
}
-bool BKE_object_modifier_use_time(Object *ob, ModifierData *md)
+bool BKE_object_modifier_use_time(Scene *scene,
+ Object *ob,
+ ModifierData *md,
+ const int dag_eval_mode)
{
- if (BKE_modifier_depends_ontime(md)) {
+ if (BKE_modifier_depends_ontime(scene, md, dag_eval_mode)) {
return true;
}
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index c69326a23c6..511f5d4ae66 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -307,10 +307,7 @@ static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const in
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
+ MEM_SAFE_FREE(lt->dvert);
}
}
else if (BKE_object_defgroup_active_index_get(ob) < 1) {
@@ -465,10 +462,7 @@ void BKE_object_defgroup_remove_all_ex(struct Object *ob, bool only_unlocked)
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data));
- if (lt->dvert) {
- MEM_freeN(lt->dvert);
- lt->dvert = NULL;
- }
+ MEM_SAFE_FREE(lt->dvert);
}
/* Fix counters/indices */
BKE_object_defgroup_active_index_set(ob, 0);
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 77969328365..141a9a25eca 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -1554,15 +1554,15 @@ static const DupliGenerator gen_dupli_particles = {
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
{
int transflag = ctx->object->transflag;
- int restrictflag = ctx->object->restrictflag;
+ int visibility_flag = ctx->object->visibility_flag;
if ((transflag & OB_DUPLI) == 0 && ctx->object->runtime.geometry_set_eval == nullptr) {
return nullptr;
}
/* Should the dupli's be generated for this object? - Respect restrict flags. */
- if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) :
- (restrictflag & OB_RESTRICT_VIEWPORT)) {
+ if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (visibility_flag & OB_HIDE_RENDER) :
+ (visibility_flag & OB_HIDE_VIEWPORT)) {
return nullptr;
}
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 3aee5cd639d..e9683d3b52c 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -530,7 +530,7 @@ static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -563,7 +563,7 @@ static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -596,7 +596,7 @@ static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(t
for (j = 0; j <= o->_N / 2; j++) {
fftw_complex mul_param;
- /* init_complex(mul_param, -scale, 0); */
+ // init_complex(mul_param, -scale, 0);
init_complex(mul_param, -1, 0);
mul_complex_f(mul_param, mul_param, chop_amount);
@@ -650,6 +650,14 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskd
fftw_execute(o->_N_z_plan);
}
+/**
+ * Return true if the ocean is valid and can be used.
+ */
+bool BKE_ocean_is_valid(const struct Ocean *o)
+{
+ return o->_k != NULL;
+}
+
void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
{
TaskPool *pool;
@@ -769,7 +777,10 @@ bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution)
return true;
}
-void BKE_ocean_init_from_modifier(struct Ocean *ocean,
+/**
+ * Return true if the ocean data is valid and can be used.
+ */
+bool BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution)
{
@@ -783,31 +794,34 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean,
BKE_ocean_free_data(ocean);
- BKE_ocean_init(ocean,
- resolution * resolution,
- resolution * resolution,
- omd->spatial_size,
- omd->spatial_size,
- omd->wind_velocity,
- omd->smallest_wave,
- 1.0,
- omd->wave_direction,
- omd->damp,
- omd->wave_alignment,
- omd->depth,
- omd->time,
- omd->spectrum,
- omd->fetch_jonswap,
- omd->sharpen_peak_jonswap,
- do_heightfield,
- do_chop,
- do_spray,
- do_normals,
- do_jacobian,
- omd->seed);
-}
-
-void BKE_ocean_init(struct Ocean *o,
+ return BKE_ocean_init(ocean,
+ resolution * resolution,
+ resolution * resolution,
+ omd->spatial_size,
+ omd->spatial_size,
+ omd->wind_velocity,
+ omd->smallest_wave,
+ 1.0,
+ omd->wave_direction,
+ omd->damp,
+ omd->wave_alignment,
+ omd->depth,
+ omd->time,
+ omd->spectrum,
+ omd->fetch_jonswap,
+ omd->sharpen_peak_jonswap,
+ do_heightfield,
+ do_chop,
+ do_spray,
+ do_normals,
+ do_jacobian,
+ omd->seed);
+}
+
+/**
+ * Return true if the ocean data is valid and can be used.
+ */
+bool BKE_ocean_init(struct Ocean *o,
int M,
int N,
float Lx,
@@ -830,7 +844,6 @@ void BKE_ocean_init(struct Ocean *o,
short do_jacobian,
int seed)
{
- RNG *rng;
int i, j, ii;
BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE);
@@ -858,18 +871,34 @@ void BKE_ocean_init(struct Ocean *o,
o->_fetch_jonswap = fetch_jonswap;
o->_sharpen_peak_jonswap = sharpen_peak_jonswap * 10.0f;
+ /* NOTE: most modifiers don't account for failure to allocate.
+ * In this case however a large resolution can easily perform large allocations that fail,
+ * support early exiting in this case. */
+ if ((o->_k = (float *)MEM_mallocN(sizeof(float) * (size_t)M * (1 + N / 2), "ocean_k")) &&
+ (o->_h0 = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N, "ocean_h0")) &&
+ (o->_h0_minus = (fftw_complex *)MEM_mallocN(sizeof(fftw_complex) * (size_t)M * N,
+ "ocean_h0_minus")) &&
+ (o->_kx = (float *)MEM_mallocN(sizeof(float) * o->_M, "ocean_kx")) &&
+ (o->_kz = (float *)MEM_mallocN(sizeof(float) * o->_N, "ocean_kz"))) {
+ /* Success. */
+ }
+ else {
+ MEM_SAFE_FREE(o->_k);
+ MEM_SAFE_FREE(o->_h0);
+ MEM_SAFE_FREE(o->_h0_minus);
+ MEM_SAFE_FREE(o->_kx);
+ MEM_SAFE_FREE(o->_kz);
+
+ BLI_rw_mutex_unlock(&o->oceanmutex);
+ return false;
+ }
+
o->_do_disp_y = do_height_field;
o->_do_normals = do_normals;
o->_do_spray = do_spray;
o->_do_chop = do_chop;
o->_do_jacobian = do_jacobian;
- o->_k = (float *)MEM_mallocN(M * (1 + N / 2) * sizeof(float), "ocean_k");
- o->_h0 = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0");
- o->_h0_minus = (fftw_complex *)MEM_mallocN(M * N * sizeof(fftw_complex), "ocean_h0_minus");
- o->_kx = (float *)MEM_mallocN(o->_M * sizeof(float), "ocean_kx");
- o->_kz = (float *)MEM_mallocN(o->_N * sizeof(float), "ocean_kz");
-
/* make this robust in the face of erroneous usage */
if (o->_Lx == 0.0f) {
o->_Lx = 0.001f;
@@ -902,11 +931,11 @@ void BKE_ocean_init(struct Ocean *o,
/* pre-calculate the k matrix */
for (i = 0; i < o->_M; i++) {
for (j = 0; j <= o->_N / 2; j++) {
- o->_k[i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
+ o->_k[(size_t)i * (1 + o->_N / 2) + j] = sqrt(o->_kx[i] * o->_kx[i] + o->_kz[j] * o->_kz[j]);
}
}
- rng = BLI_rng_new(seed);
+ RNG *rng = BLI_rng_new(seed);
for (i = 0; i < o->_M; i++) {
for (j = 0; j < o->_N; j++) {
@@ -986,7 +1015,7 @@ void BKE_ocean_init(struct Ocean *o,
"ocean_fft_in_nz");
o->_N_x = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_x");
- /* o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); (MEM01) */
+ // o->_N_y = (float *) fftwf_malloc(o->_M * o->_N * sizeof(float)); /* (MEM01) */
o->_N_z = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_N_z");
o->_N_x_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_nx, o->_N_x, FFTW_ESTIMATE);
@@ -1029,6 +1058,8 @@ void BKE_ocean_init(struct Ocean *o,
set_height_normalize_factor(o);
BLI_rng_free(rng);
+
+ return true;
}
void BKE_ocean_free_data(struct Ocean *oc)
@@ -1052,7 +1083,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
fftw_destroy_plan(oc->_N_x_plan);
fftw_destroy_plan(oc->_N_z_plan);
MEM_freeN(oc->_N_x);
- /* fftwf_free(oc->_N_y); (MEM01) */
+ // fftwf_free(oc->_N_y); /* (MEM01) */
MEM_freeN(oc->_N_z);
}
@@ -1608,7 +1639,7 @@ struct Ocean *BKE_ocean_add(void)
return oc;
}
-void BKE_ocean_init(struct Ocean *UNUSED(o),
+bool BKE_ocean_init(struct Ocean *UNUSED(o),
int UNUSED(M),
int UNUSED(N),
float UNUSED(Lx),
@@ -1631,6 +1662,7 @@ void BKE_ocean_init(struct Ocean *UNUSED(o),
short UNUSED(do_jacobian),
int UNUSED(seed))
{
+ return false;
}
void BKE_ocean_free_data(struct Ocean *UNUSED(oc))
@@ -1700,10 +1732,11 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o),
(void)update_cb;
}
-void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean),
+bool BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean),
struct OceanModifierData const *UNUSED(omd),
int UNUSED(resolution))
{
+ return true;
}
#endif /* WITH_OCEANSIM */
diff --git a/source/blender/blenkernel/intern/ocean_spectrum.c b/source/blender/blenkernel/intern/ocean_spectrum.c
index 7ed70234baf..c5504b22b43 100644
--- a/source/blender/blenkernel/intern/ocean_spectrum.c
+++ b/source/blender/blenkernel/intern/ocean_spectrum.c
@@ -77,7 +77,7 @@ static float ocean_spectrum_wind_and_damp(const Ocean *oc,
float newval = val * pow(fabs(k_dot_w), oc->_wind_alignment);
/* Eliminate wavelengths smaller than cutoff. */
- /* val *= exp(-k2 * m_cutoff); */
+ // val *= exp(-k2 * m_cutoff);
/* Reduce reflected waves. */
if (k_dot_w < 0.0f) {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index a1fa6aae1ce..d6030941c6d 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -108,14 +108,13 @@ static void palette_free_data(ID *id)
static void palette_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Palette *palette = (Palette *)id;
- if (palette->id.us > 0 || BLO_write_is_undo(writer)) {
- PaletteColor *color;
- BLO_write_id_struct(writer, Palette, id_address, &palette->id);
- BKE_id_blend_write(writer, &palette->id);
- for (color = palette->colors.first; color; color = color->next) {
- BLO_write_struct(writer, PaletteColor, color);
- }
+ PaletteColor *color;
+ BLO_write_id_struct(writer, Palette, id_address, &palette->id);
+ BKE_id_blend_write(writer, &palette->id);
+
+ for (color = palette->colors.first; color; color = color->next) {
+ BLO_write_struct(writer, PaletteColor, color);
}
}
@@ -187,12 +186,11 @@ static void paint_curve_free_data(ID *id)
static void paint_curve_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
PaintCurve *pc = (PaintCurve *)id;
- if (pc->id.us > 0 || BLO_write_is_undo(writer)) {
- BLO_write_id_struct(writer, PaintCurve, id_address, &pc->id);
- BKE_id_blend_write(writer, &pc->id);
- BLO_write_struct_array(writer, PaintCurvePoint, pc->tot_points, pc->points);
- }
+ BLO_write_id_struct(writer, PaintCurve, id_address, &pc->id);
+ BKE_id_blend_write(writer, &pc->id);
+
+ BLO_write_struct_array(writer, PaintCurvePoint, pc->tot_points, pc->points);
}
static void paint_curve_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index f2f3c5d4ca6..29849c69b6f 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -255,60 +255,59 @@ static void write_boid_state(BlendWriter *writer, BoidState *state)
static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
ParticleSettings *part = (ParticleSettings *)id;
- if (part->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
- BKE_id_blend_write(writer, &part->id);
- if (part->adt) {
- BKE_animdata_blend_write(writer, part->adt);
- }
- BLO_write_struct(writer, PartDeflect, part->pd);
- BLO_write_struct(writer, PartDeflect, part->pd2);
- BLO_write_struct(writer, EffectorWeights, part->effector_weights);
+ /* write LibData */
+ BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id);
+ BKE_id_blend_write(writer, &part->id);
- if (part->clumpcurve) {
- BKE_curvemapping_blend_write(writer, part->clumpcurve);
- }
- if (part->roughcurve) {
- BKE_curvemapping_blend_write(writer, part->roughcurve);
- }
- if (part->twistcurve) {
- BKE_curvemapping_blend_write(writer, part->twistcurve);
- }
+ if (part->adt) {
+ BKE_animdata_blend_write(writer, part->adt);
+ }
+ BLO_write_struct(writer, PartDeflect, part->pd);
+ BLO_write_struct(writer, PartDeflect, part->pd2);
+ BLO_write_struct(writer, EffectorWeights, part->effector_weights);
- LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
- /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
- if (dw->ob != NULL) {
- dw->index = 0;
- if (part->instance_collection) { /* can be NULL if lining fails or set to None */
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
- if (object == dw->ob) {
- break;
- }
- dw->index++;
+ if (part->clumpcurve) {
+ BKE_curvemapping_blend_write(writer, part->clumpcurve);
+ }
+ if (part->roughcurve) {
+ BKE_curvemapping_blend_write(writer, part->roughcurve);
+ }
+ if (part->twistcurve) {
+ BKE_curvemapping_blend_write(writer, part->twistcurve);
+ }
+
+ LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) {
+ /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
+ if (dw->ob != NULL) {
+ dw->index = 0;
+ if (part->instance_collection) { /* can be NULL if lining fails or set to None */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) {
+ if (object == dw->ob) {
+ break;
}
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ dw->index++;
}
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
- BLO_write_struct(writer, ParticleDupliWeight, dw);
}
+ BLO_write_struct(writer, ParticleDupliWeight, dw);
+ }
- if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- BLO_write_struct(writer, BoidSettings, part->boids);
+ if (part->boids && part->phystype == PART_PHYS_BOIDS) {
+ BLO_write_struct(writer, BoidSettings, part->boids);
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- write_boid_state(writer, state);
- }
- }
- if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- BLO_write_struct(writer, SPHFluidSettings, part->fluid);
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ write_boid_state(writer, state);
}
+ }
+ if (part->fluid && part->phystype == PART_PHYS_FLUID) {
+ BLO_write_struct(writer, SPHFluidSettings, part->fluid);
+ }
- for (int a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- BLO_write_struct(writer, MTex, part->mtex[a]);
- }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part->mtex[a]) {
+ BLO_write_struct(writer, MTex, part->mtex[a]);
}
}
}
@@ -928,10 +927,7 @@ void free_hair(Object *object, ParticleSystem *psys, int dynamics)
LOOP_PARTICLES
{
- if (pa->hair) {
- MEM_freeN(pa->hair);
- }
- pa->hair = NULL;
+ MEM_SAFE_FREE(pa->hair);
pa->totkey = 0;
}
@@ -1044,25 +1040,13 @@ void psys_free_particles(ParticleSystem *psys)
void psys_free_pdd(ParticleSystem *psys)
{
if (psys->pdd) {
- if (psys->pdd->cdata) {
- MEM_freeN(psys->pdd->cdata);
- }
- psys->pdd->cdata = NULL;
+ MEM_SAFE_FREE(psys->pdd->cdata);
- if (psys->pdd->vdata) {
- MEM_freeN(psys->pdd->vdata);
- }
- psys->pdd->vdata = NULL;
+ MEM_SAFE_FREE(psys->pdd->vdata);
- if (psys->pdd->ndata) {
- MEM_freeN(psys->pdd->ndata);
- }
- psys->pdd->ndata = NULL;
+ MEM_SAFE_FREE(psys->pdd->ndata);
- if (psys->pdd->vedata) {
- MEM_freeN(psys->pdd->vedata);
- }
- psys->pdd->vedata = NULL;
+ MEM_SAFE_FREE(psys->pdd->vedata);
psys->pdd->totpoint = 0;
psys->pdd->totpart = 0;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 06d3daaf4d6..60edb78f8ba 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -169,10 +169,7 @@ void psys_reset(ParticleSystem *psys, int mode)
}
/* reset children */
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = NULL;
- }
+ MEM_SAFE_FREE(psys->child);
psys->totchild = 0;
@@ -182,10 +179,7 @@ void psys_reset(ParticleSystem *psys, int mode)
/* reset point cache */
BKE_ptcache_invalidate(psys->pointcache);
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
+ MEM_SAFE_FREE(psys->fluid_springs);
psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
}
@@ -3112,7 +3106,7 @@ static void collision_fail(ParticleData *pa, ParticleCollision *col)
copy_v3_v3(pa->state.vel, col->pce.vel);
mul_v3_fl(pa->state.vel, col->inv_timestep);
- /* printf("max iterations\n"); */
+ // printf("max iterations\n");
}
/* Particle - Mesh collision detection and response
@@ -4516,10 +4510,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
reset_all_particles(sim, 0.0, cfra, oldtotpart);
free_unexisting_particles(sim);
- if (psys->fluid_springs) {
- MEM_freeN(psys->fluid_springs);
- psys->fluid_springs = NULL;
- }
+ MEM_SAFE_FREE(psys->fluid_springs);
psys->tot_fluidsprings = psys->alloc_fluidsprings = 0;
@@ -4770,6 +4761,7 @@ static void particle_settings_free_local(ParticleSettings *particle_settings)
{
BKE_libblock_free_datablock(&particle_settings->id, 0);
BKE_libblock_free_data(&particle_settings->id, false);
+ BLI_assert(!particle_settings->id.py_instance); /* Or call #BKE_libblock_free_data_py. */
MEM_freeN(particle_settings);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 461ffa7765e..ca1fada8c76 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1026,7 +1026,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
PBVHNode *node = data->nodes[n];
float(*vnors)[3] = data->vnors;
- if ((node->flag & PBVH_UpdateNormals)) {
+ if (node->flag & PBVH_UpdateNormals) {
unsigned int mpoly_prev = UINT_MAX;
float fn[3];
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 9ed5b0230e6..57225872c7e 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -2753,18 +2753,18 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra)
pid->cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
}
-int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
+bool BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
{
if (!pid->cache) {
- return 0;
+ return false;
}
if (cfra < pid->cache->startframe || cfra > pid->cache->endframe) {
- return 0;
+ return false;
}
if (pid->cache->cached_frames && pid->cache->cached_frames[cfra - pid->cache->startframe] == 0) {
- return 0;
+ return false;
}
if (pid->cache->flag & PTCACHE_DISK_CACHE) {
@@ -2779,10 +2779,10 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
for (; pm; pm = pm->next) {
if (pm->frame == cfra) {
- return 1;
+ return true;
}
}
- return 0;
+ return false;
}
void BKE_ptcache_id_time(
PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
@@ -3369,7 +3369,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
/* NOTE: breaking baking should leave calculated frames in cache, not clear it */
- if ((cancel || G.is_break)) {
+ if (cancel || G.is_break) {
break;
}
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc
index d9a7a376e2e..837a772607f 100644
--- a/source/blender/blenkernel/intern/pointcloud.cc
+++ b/source/blender/blenkernel/intern/pointcloud.cc
@@ -112,28 +112,27 @@ static void pointcloud_foreach_id(ID *id, LibraryForeachIDData *data)
static void pointcloud_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
PointCloud *pointcloud = (PointCloud *)id;
- if (pointcloud->id.us > 0 || BLO_write_is_undo(writer)) {
- CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_blend_write_prepare(
- &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
-
- /* Write LibData */
- BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id);
- BKE_id_blend_write(writer, &pointcloud->id);
-
- /* Direct data */
- CustomData_blend_write(
- writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id);
-
- BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat);
- if (pointcloud->adt) {
- BKE_animdata_blend_write(writer, pointcloud->adt);
- }
- /* Remove temporary data. */
- if (players && players != players_buff) {
- MEM_freeN(players);
- }
+ CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_blend_write_prepare(
+ &pointcloud->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+
+ /* Write LibData */
+ BLO_write_id_struct(writer, PointCloud, id_address, &pointcloud->id);
+ BKE_id_blend_write(writer, &pointcloud->id);
+
+ /* Direct data */
+ CustomData_blend_write(
+ writer, &pointcloud->pdata, players, pointcloud->totpoint, CD_MASK_ALL, &pointcloud->id);
+
+ BLO_write_pointer_array(writer, pointcloud->totcol, pointcloud->mat);
+ if (pointcloud->adt) {
+ BKE_animdata_blend_write(writer, pointcloud->adt);
+ }
+
+ /* Remove temporary data. */
+ if (players && players != players_buff) {
+ MEM_freeN(players);
}
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 3f75d0963c6..3fe00adc4d5 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -109,6 +109,8 @@
#include "RE_engine.h"
+#include "RNA_access.h"
+
#include "SEQ_edit.h"
#include "SEQ_iterator.h"
#include "SEQ_modifier.h"
@@ -445,7 +447,8 @@ static void scene_free_data(ID *id)
* for objects directly in the master collection? then other
* collections in the scene need to do it too? */
if (scene->master_collection) {
- BKE_collection_free(scene->master_collection);
+ BKE_collection_free_data(scene->master_collection);
+ BKE_libblock_free_data_py(&scene->master_collection->id);
MEM_freeN(scene->master_collection);
scene->master_collection = NULL;
}
@@ -2178,7 +2181,7 @@ int BKE_scene_base_iter_next(
/* exception: empty scene layer */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene));
+ ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
*base = view_layer_set->object_bases.first;
*ob = (*base)->object;
@@ -2199,7 +2202,7 @@ int BKE_scene_base_iter_next(
/* (*scene) is finished, now do the set */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- ViewLayer *view_layer_set = BKE_view_layer_default_render((*scene));
+ ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
*base = view_layer_set->object_bases.first;
*ob = (*base)->object;
@@ -2305,7 +2308,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
Object *first_camera = NULL;
LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) {
- if (m->camera && (m->camera->restrictflag & OB_RESTRICT_RENDER) == 0) {
+ if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) {
if ((m->frame <= ctime) && (m->frame > frame)) {
camera = m->camera;
frame = m->frame;
@@ -2898,7 +2901,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
next_set:
/* Reached the end, get the next base in the set. */
while ((*sce_iter = (*sce_iter)->set)) {
- ViewLayer *view_layer_set = BKE_view_layer_default_render((*sce_iter));
+ ViewLayer *view_layer_set = BKE_view_layer_default_render(*sce_iter);
base = (Base *)view_layer_set->object_bases.first;
if (base) {
@@ -2937,6 +2940,22 @@ bool BKE_scene_uses_cycles(const Scene *scene)
return STREQ(scene->r.engine, RE_engine_id_CYCLES);
}
+/* This enumeration has to match the one defined in the Cycles addon. */
+typedef enum eCyclesFeatureSet {
+ CYCLES_FEATURES_SUPPORTED = 0,
+ CYCLES_FEATURES_EXPERIMENTAL = 1,
+} eCyclesFeatureSet;
+
+/* We cannot use const as RNA_id_pointer_create is not using a const ID. */
+bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
+{
+ BLI_assert(BKE_scene_uses_cycles(scene));
+ PointerRNA scene_ptr;
+ RNA_id_pointer_create(&scene->id, &scene_ptr);
+ PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
+ return RNA_enum_get(&cycles_ptr, "feature_set") == CYCLES_FEATURES_EXPERIMENTAL;
+}
+
void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
{
Base *base = view_layer->object_bases.first;
@@ -3118,7 +3137,7 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene
return false;
}
- if ((srv->viewflag & SCE_VIEW_DISABLE)) {
+ if (srv->viewflag & SCE_VIEW_DISABLE) {
return false;
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index c3885b5dcf7..065240bddbc 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -255,18 +255,16 @@ static void screen_foreach_id(ID *id, LibraryForeachIDData *data)
static void screen_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
bScreen *screen = (bScreen *)id;
- /* Screens are reference counted, only saved if used by a workspace. */
- if (screen->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
- BLO_write_struct_at_address_with_filecode(writer, ID_SCRN, bScreen, id_address, screen);
- BKE_id_blend_write(writer, &screen->id);
- BKE_previewimg_blend_write(writer, screen->preview);
+ /* write LibData */
+ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
+ BLO_write_struct_at_address_with_filecode(writer, ID_SCRN, bScreen, id_address, screen);
+ BKE_id_blend_write(writer, &screen->id);
- /* direct data */
- BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen));
- }
+ BKE_previewimg_blend_write(writer, screen->preview);
+
+ /* direct data */
+ BKE_screen_area_map_blend_write(writer, AREAMAP_FROM_SCREEN(screen));
}
/* Cannot use IDTypeInfo callback yet, because of the return value. */
@@ -730,7 +728,7 @@ void BKE_screen_area_map_free(ScrAreaMap *area_map)
}
/** Free (or release) any data used by this screen (does not free the screen itself). */
-void BKE_screen_free(bScreen *screen)
+void BKE_screen_free_data(bScreen *screen)
{
screen_free_data(&screen->id);
}
@@ -766,7 +764,7 @@ void BKE_screen_remove_double_scrverts(bScreen *screen)
while (v1) {
if (v1->newv == NULL) { /* !?! */
if (v1->vec.x == verg->vec.x && v1->vec.y == verg->vec.y) {
- /* printf("doublevert\n"); */
+ // printf("doublevert\n");
v1->newv = verg;
}
}
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 216563b860d..4c97ccdf8b1 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -49,14 +49,10 @@
#include "BKE_simulation.h"
#include "NOD_geometry.h"
-#include "NOD_node_tree_multi_function.hh"
#include "BLI_map.hh"
#include "BLT_translation.h"
-#include "FN_multi_function_network_evaluation.hh"
-#include "FN_multi_function_network_optimization.hh"
-
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -114,19 +110,18 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
static void simulation_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Simulation *simulation = (Simulation *)id;
- if (simulation->id.us > 0 || BLO_write_is_undo(writer)) {
- BLO_write_id_struct(writer, Simulation, id_address, &simulation->id);
- BKE_id_blend_write(writer, &simulation->id);
-
- if (simulation->adt) {
- BKE_animdata_blend_write(writer, simulation->adt);
- }
-
- /* nodetree is integral part of simulation, no libdata */
- if (simulation->nodetree) {
- BLO_write_struct(writer, bNodeTree, simulation->nodetree);
- ntreeBlendWrite(writer, simulation->nodetree);
- }
+
+ BLO_write_id_struct(writer, Simulation, id_address, &simulation->id);
+ BKE_id_blend_write(writer, &simulation->id);
+
+ if (simulation->adt) {
+ BKE_animdata_blend_write(writer, simulation->adt);
+ }
+
+ /* nodetree is integral part of simulation, no libdata */
+ if (simulation->nodetree) {
+ BLO_write_struct(writer, bNodeTree, simulation->nodetree);
+ ntreeBlendWrite(writer, simulation->nodetree);
}
}
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index e4e2ed94b41..fbc781f5eb9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -891,11 +891,7 @@ static void free_softbody_baked(SoftBody *sb)
MEM_freeN(key);
}
}
- if (sb->keys) {
- MEM_freeN(sb->keys);
- }
-
- sb->keys = NULL;
+ MEM_SAFE_FREE(sb->keys);
sb->totkey = 0;
}
static void free_scratch(SoftBody *sb)
@@ -2225,7 +2221,7 @@ static void sb_cf_threads_run(Scene *scene,
totthread--;
}
- /* printf("sb_cf_threads_run spawning %d threads\n", totthread); */
+ // printf("sb_cf_threads_run spawning %d threads\n", totthread);
sb_threads = MEM_callocN(sizeof(SB_thread_context) * totthread, "SBThread");
memset(sb_threads, 0, sizeof(SB_thread_context) * totthread);
@@ -2281,7 +2277,7 @@ static void softbody_calc_forces(
float fieldfactor = -1.0f, windfactor = 0.25;
int do_deflector /*, do_selfcollision */, do_springcollision, do_aero;
- /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
+ // gravity = sb->grav * sb_grav_force_scale(ob); /* UNUSED */
/* check conditions for various options */
do_deflector = query_external_colliders(depsgraph, sb->collision_group);
@@ -2753,7 +2749,7 @@ static void mesh_to_softbody(Object *ob)
build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
/* insert *other second order* springs if desired */
if (sb->secondspring > 0.0000001f) {
- /* exploits the first run of build_bps_springlist(ob); */
+ /* Exploits the first run of `build_bps_springlist(ob)`. */
add_2nd_order_springs(ob, sb->secondspring);
/* yes we need to do it again. */
build_bps_springlist(ob);
@@ -2812,7 +2808,7 @@ static void reference_to_scratch(Object *ob)
}
mul_v3_fl(accu_pos, 1.0f / accu_mass);
copy_v3_v3(sb->scratch->Ref.com, accu_pos);
- /* printf("reference_to_scratch\n"); */
+ // printf("reference_to_scratch\n");
}
/*
@@ -3447,10 +3443,10 @@ static void softbody_step(
float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */
if (sb->scratch->flag & SBF_DOFUZZY) {
- ///* stay with this stepsize unless err really small */
+ // /* stay with this stepsize unless err really small */
// if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) {
newtime = forcetime;
- //}
+ // }
}
else {
if (err > SoftHeunTol / 2.0f) { /* stay with this stepsize unless err really small */
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index fcb992e1535..c61fa793367 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -137,24 +137,23 @@ static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_addres
{
bSound *sound = (bSound *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (sound->id.us > 0 || is_undo) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- sound->tags = 0;
- sound->handle = NULL;
- sound->playback_handle = NULL;
- sound->spinlock = NULL;
- /* Do not store packed files in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(sound) && !is_undo) {
- sound->packedfile = NULL;
- }
-
- /* write LibData */
- BLO_write_id_struct(writer, bSound, id_address, &sound->id);
- BKE_id_blend_write(writer, &sound->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ sound->tags = 0;
+ sound->handle = NULL;
+ sound->playback_handle = NULL;
+ sound->spinlock = NULL;
- BKE_packedfile_blend_write(writer, sound->packedfile);
+ /* Do not store packed files in case this is a library override ID. */
+ if (ID_IS_OVERRIDE_LIBRARY(sound) && !is_undo) {
+ sound->packedfile = NULL;
}
+
+ /* write LibData */
+ BLO_write_id_struct(writer, bSound, id_address, &sound->id);
+ BKE_id_blend_write(writer, &sound->id);
+
+ BKE_packedfile_blend_write(writer, sound->packedfile);
}
static void sound_blend_read_data(BlendDataReader *reader, ID *id)
@@ -703,13 +702,13 @@ void *BKE_sound_scene_add_scene_sound(
Scene *scene, Sequence *sequence, int startframe, int endframe, int frameskip)
{
sound_verify_evaluated_id(&scene->id);
- if (sequence->scene && scene != sequence->scene) {
+ if (sequence->scene && scene != sequence->scene && sequence->sound) {
const double fps = FPS;
return AUD_Sequence_add(scene->sound_scene,
sequence->scene->sound_scene,
startframe / fps,
endframe / fps,
- frameskip / fps);
+ frameskip / fps + sequence->sound->offset_time);
}
return NULL;
}
@@ -737,7 +736,7 @@ void *BKE_sound_add_scene_sound(
sequence->sound->playback_handle,
startframe / fps,
endframe / fps,
- frameskip / fps);
+ frameskip / fps + sequence->sound->offset_time);
AUD_SequenceEntry_setMuted(handle, (sequence->flag & SEQ_MUTE) != 0);
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_VOLUME, CFRA, &sequence->volume, 0);
AUD_SequenceEntry_setAnimationData(handle, AUD_AP_PITCH, CFRA, &sequence->pitch, 0);
@@ -765,22 +764,23 @@ void BKE_sound_mute_scene_sound(void *handle, char mute)
}
void BKE_sound_move_scene_sound(
- Scene *scene, void *handle, int startframe, int endframe, int frameskip)
+ Scene *scene, void *handle, int startframe, int endframe, int frameskip, double audio_offset)
{
sound_verify_evaluated_id(&scene->id);
const double fps = FPS;
- AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps);
+ AUD_SequenceEntry_move(handle, startframe / fps, endframe / fps, frameskip / fps + audio_offset);
}
void BKE_sound_move_scene_sound_defaults(Scene *scene, Sequence *sequence)
{
sound_verify_evaluated_id(&scene->id);
- if (sequence->scene_sound) {
+ if (sequence->scene_sound && sequence->sound) {
BKE_sound_move_scene_sound(scene,
sequence->scene_sound,
sequence->startdisp,
sequence->enddisp,
- sequence->startofs + sequence->anim_startofs);
+ sequence->startofs + sequence->anim_startofs,
+ sequence->sound->offset_time);
}
}
@@ -1213,6 +1213,7 @@ static bool sound_info_from_playback_handle(void *playback_handle, SoundInfo *so
AUD_SoundInfo info = AUD_getInfo(playback_handle);
sound_info->specs.channels = (eSoundChannels)info.specs.channels;
sound_info->length = info.length;
+ sound_info->start_offset = info.start_offset;
return true;
}
@@ -1310,7 +1311,8 @@ void BKE_sound_move_scene_sound(Scene *UNUSED(scene),
void *UNUSED(handle),
int UNUSED(startframe),
int UNUSED(endframe),
- int UNUSED(frameskip))
+ int UNUSED(frameskip),
+ double UNUSED(audio_offset))
{
}
void BKE_sound_move_scene_sound_defaults(Scene *UNUSED(scene), Sequence *UNUSED(sequence))
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index af9b2268879..4b10522c375 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -56,14 +56,13 @@ static void speaker_foreach_id(ID *id, LibraryForeachIDData *data)
static void speaker_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Speaker *spk = (Speaker *)id;
- if (spk->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, Speaker, id_address, &spk->id);
- BKE_id_blend_write(writer, &spk->id);
-
- if (spk->adt) {
- BKE_animdata_blend_write(writer, spk->adt);
- }
+
+ /* write LibData */
+ BLO_write_id_struct(writer, Speaker, id_address, &spk->id);
+ BKE_id_blend_write(writer, &spk->id);
+
+ if (spk->adt) {
+ BKE_animdata_blend_write(writer, spk->adt);
}
}
diff --git a/source/blender/blenkernel/intern/spline_base.cc b/source/blender/blenkernel/intern/spline_base.cc
index a7caae967f6..dda7abea0fc 100644
--- a/source/blender/blenkernel/intern/spline_base.cc
+++ b/source/blender/blenkernel/intern/spline_base.cc
@@ -189,7 +189,11 @@ static float3 direction_bisect(const float3 &prev, const float3 &middle, const f
const float3 dir_prev = (middle - prev).normalized();
const float3 dir_next = (next - middle).normalized();
- return (dir_prev + dir_next).normalized();
+ const float3 result = (dir_prev + dir_next).normalized();
+ if (UNLIKELY(result.is_zero())) {
+ return float3(0.0f, 0.0f, 1.0f);
+ }
+ return result;
}
static void calculate_tangents(Span<float3> positions,
@@ -197,6 +201,7 @@ static void calculate_tangents(Span<float3> positions,
MutableSpan<float3> tangents)
{
if (positions.size() == 1) {
+ tangents.first() = float3(0.0f, 0.0f, 1.0f);
return;
}
@@ -237,13 +242,8 @@ Span<float3> Spline::evaluated_tangents() const
Span<float3> positions = this->evaluated_positions();
- if (eval_size == 1) {
- evaluated_tangents_cache_.first() = float3(1.0f, 0.0f, 0.0f);
- }
- else {
- calculate_tangents(positions, is_cyclic_, evaluated_tangents_cache_);
- this->correct_end_tangents();
- }
+ calculate_tangents(positions, is_cyclic_, evaluated_tangents_cache_);
+ this->correct_end_tangents();
tangent_cache_dirty_ = false;
return evaluated_tangents_cache_;
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index dc5162f201e..95436372a65 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -475,7 +475,7 @@ static void studiolight_load_equirect_image(StudioLight *sl)
NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4);
}
- if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) {
+ if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
sl->matcap_diffuse.ibuf = diffuse_ibuf;
sl->matcap_specular.ibuf = specular_ibuf;
if (specular_ibuf != NULL) {
@@ -1192,7 +1192,7 @@ static void studiolight_add_files_from_datafolder(const int folder_id,
uint totfile = BLI_filelist_dir_contents(folder, &dir);
int i;
for (i = 0; i < totfile; i++) {
- if ((dir[i].type & S_IFREG)) {
+ if (dir[i].type & S_IFREG) {
studiolight_add_file(dir[i].path, flag);
}
}
@@ -1473,7 +1473,7 @@ struct StudioLight *BKE_studiolight_find_default(int flag)
}
LISTBASE_FOREACH (StudioLight *, sl, &studiolights) {
- if ((sl->flag & flag)) {
+ if (sl->flag & flag) {
return sl;
}
}
@@ -1484,7 +1484,7 @@ struct StudioLight *BKE_studiolight_find(const char *name, int flag)
{
LISTBASE_FOREACH (StudioLight *, sl, &studiolights) {
if (STREQLEN(sl->name, name, FILE_MAXFILE)) {
- if ((sl->flag & flag)) {
+ if (sl->flag & flag) {
return sl;
}
@@ -1542,32 +1542,32 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
return;
}
- if ((flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED)) {
+ if (flag & STUDIOLIGHT_EXTERNAL_IMAGE_LOADED) {
studiolight_load_equirect_image(sl);
}
- if ((flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED)) {
+ if (flag & STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED) {
studiolight_calculate_radiance_cubemap_buffers(sl);
}
- if ((flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED)) {
+ if (flag & STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED) {
if (!studiolight_load_spherical_harmonics_coefficients(sl)) {
studiolight_calculate_diffuse_light(sl);
}
}
- if ((flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE)) {
+ if (flag & STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE) {
studiolight_create_equirect_radiance_gputexture(sl);
}
- if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE)) {
+ if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE) {
studiolight_create_equirect_irradiance_gputexture(sl);
}
- if ((flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED)) {
+ if (flag & STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED) {
if (!studiolight_load_irradiance_equirect_image(sl)) {
studiolight_calculate_irradiance_equirect_image(sl);
}
}
- if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) {
+ if (flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE) {
studiolight_create_matcap_diffuse_gputexture(sl);
}
- if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) {
+ if (flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE) {
studiolight_create_matcap_specular_gputexture(sl);
}
}
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 80ff8ce9162..275cf0d4c38 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -171,9 +171,6 @@ static void text_free_data(ID *id)
static void text_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
- if (id->us < 1 && !BLO_write_is_undo(writer)) {
- return;
- }
Text *text = (Text *)id;
/* NOTE: we are clearing local temp data here, *not* the flag in the actual 'real' ID. */
@@ -2331,7 +2328,7 @@ int txt_setcurr_tab_spaces(Text *text, int space)
}
while (text->curl->line[i] == indent) {
- // we only count those tabs/spaces that are before any text or before the curs;
+ /* We only count those tabs/spaces that are before any text or before the curs; */
if (i == text->curc) {
return i;
}
diff --git a/source/blender/blenkernel/intern/text_suggestions.c b/source/blender/blenkernel/intern/text_suggestions.c
index d717b88e8ca..e93e969cb33 100644
--- a/source/blender/blenkernel/intern/text_suggestions.c
+++ b/source/blender/blenkernel/intern/text_suggestions.c
@@ -57,10 +57,7 @@ static void txttl_free_suggest(void)
static void txttl_free_docs(void)
{
- if (documentation) {
- MEM_freeN(documentation);
- documentation = NULL;
- }
+ MEM_SAFE_FREE(documentation);
}
/**************************/
@@ -240,10 +237,7 @@ void texttool_docs_show(const char *docs)
len = strlen(docs);
- if (documentation) {
- MEM_freeN(documentation);
- documentation = NULL;
- }
+ MEM_SAFE_FREE(documentation);
/* Ensure documentation ends with a '\n' */
if (docs[len - 1] != '\n') {
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 29c41b88135..228e6fffdf7 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -150,28 +150,27 @@ static void texture_foreach_id(ID *id, LibraryForeachIDData *data)
static void texture_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Tex *tex = (Tex *)id;
- if (tex->id.us > 0 || BLO_write_is_undo(writer)) {
- /* write LibData */
- BLO_write_id_struct(writer, Tex, id_address, &tex->id);
- BKE_id_blend_write(writer, &tex->id);
- if (tex->adt) {
- BKE_animdata_blend_write(writer, tex->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Tex, id_address, &tex->id);
+ BKE_id_blend_write(writer, &tex->id);
- /* direct data */
- if (tex->coba) {
- BLO_write_struct(writer, ColorBand, tex->coba);
- }
+ if (tex->adt) {
+ BKE_animdata_blend_write(writer, tex->adt);
+ }
- /* nodetree is integral part of texture, no libdata */
- if (tex->nodetree) {
- BLO_write_struct(writer, bNodeTree, tex->nodetree);
- ntreeBlendWrite(writer, tex->nodetree);
- }
+ /* direct data */
+ if (tex->coba) {
+ BLO_write_struct(writer, ColorBand, tex->coba);
+ }
- BKE_previewimg_blend_write(writer, tex->preview);
+ /* nodetree is integral part of texture, no libdata */
+ if (tex->nodetree) {
+ BLO_write_struct(writer, bNodeTree, tex->nodetree);
+ ntreeBlendWrite(writer, tex->nodetree);
}
+
+ BKE_previewimg_blend_write(writer, tex->preview);
}
static void texture_blend_read_data(BlendDataReader *reader, ID *id)
@@ -490,9 +489,8 @@ void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex)
linestyle->mtex[act]->tex = newtex;
id_us_plus(&newtex->id);
}
- else if (linestyle->mtex[act]) {
- MEM_freeN(linestyle->mtex[act]);
- linestyle->mtex[act] = NULL;
+ else {
+ MEM_SAFE_FREE(linestyle->mtex[act]);
}
}
@@ -595,9 +593,8 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex)
part->mtex[act]->tex = newtex;
id_us_plus(&newtex->id);
}
- else if (part->mtex[act]) {
- MEM_freeN(part->mtex[act]);
- part->mtex[act] = NULL;
+ else {
+ MEM_SAFE_FREE(part->mtex[act]);
}
}
@@ -660,14 +657,8 @@ void BKE_texture_pointdensity_free_data(PointDensity *pd)
BLI_bvhtree_free(pd->point_tree);
pd->point_tree = NULL;
}
- if (pd->point_data) {
- MEM_freeN(pd->point_data);
- pd->point_data = NULL;
- }
- if (pd->coba) {
- MEM_freeN(pd->coba);
- pd->coba = NULL;
- }
+ MEM_SAFE_FREE(pd->point_data);
+ MEM_SAFE_FREE(pd->coba);
BKE_curvemapping_free(pd->falloff_curve); /* can be NULL */
}
diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c
index f107fc4d6bc..92ff0911cf3 100644
--- a/source/blender/blenkernel/intern/tracking_auto.c
+++ b/source/blender/blenkernel/intern/tracking_auto.c
@@ -322,7 +322,7 @@ static bool tracking_check_marker_margin(const libmv_Marker *libmv_marker,
static bool autotrack_is_marker_usable(const MovieTrackingMarker *marker)
{
- if ((marker->flag & MARKER_DISABLED)) {
+ if (marker->flag & MARKER_DISABLED) {
return false;
}
return true;
@@ -797,7 +797,7 @@ void BKE_autotrack_context_finish(AutoTrackContext *context)
clip, context->start_scene_frame);
LISTBASE_FOREACH (MovieTrackingPlaneTrack *, plane_track, plane_tracks_base) {
- if ((plane_track->flag & PLANE_TRACK_AUTOKEY)) {
+ if (plane_track->flag & PLANE_TRACK_AUTOKEY) {
continue;
}
for (int track_index = 0; track_index < context->num_all_tracks; track_index++) {
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index b28d17df814..69452d6896f 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -578,27 +578,26 @@ static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_addre
{
Volume *volume = (Volume *)id;
const bool is_undo = BLO_write_is_undo(writer);
- if (volume->id.us > 0 || is_undo) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- volume->runtime.grids = nullptr;
- /* Do not store packed files in case this is a library override ID. */
- if (ID_IS_OVERRIDE_LIBRARY(volume) && !is_undo) {
- volume->packedfile = nullptr;
- }
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ volume->runtime.grids = nullptr;
- /* write LibData */
- BLO_write_id_struct(writer, Volume, id_address, &volume->id);
- BKE_id_blend_write(writer, &volume->id);
+ /* Do not store packed files in case this is a library override ID. */
+ if (ID_IS_OVERRIDE_LIBRARY(volume) && !is_undo) {
+ volume->packedfile = nullptr;
+ }
- /* direct data */
- BLO_write_pointer_array(writer, volume->totcol, volume->mat);
- if (volume->adt) {
- BKE_animdata_blend_write(writer, volume->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, Volume, id_address, &volume->id);
+ BKE_id_blend_write(writer, &volume->id);
- BKE_packedfile_blend_write(writer, volume->packedfile);
+ /* direct data */
+ BLO_write_pointer_array(writer, volume->totcol, volume->mat);
+ if (volume->adt) {
+ BKE_animdata_blend_write(writer, volume->adt);
}
+
+ BKE_packedfile_blend_write(writer, volume->packedfile);
}
static void volume_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/volume_to_mesh.cc b/source/blender/blenkernel/intern/volume_to_mesh.cc
index 7ab67516242..e9d6eea4614 100644
--- a/source/blender/blenkernel/intern/volume_to_mesh.cc
+++ b/source/blender/blenkernel/intern/volume_to_mesh.cc
@@ -159,7 +159,7 @@ static Mesh *new_mesh_from_openvdb_data(Span<openvdb::Vec3s> verts,
}
BKE_mesh_calc_edges(mesh, false, false);
- BKE_mesh_calc_normals(mesh);
+ BKE_mesh_normals_tag_dirty(mesh);
return mesh;
}
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 059dc68b1dc..329633c6759 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -58,7 +58,7 @@ static void workspace_init_data(ID *id)
{
WorkSpace *workspace = (WorkSpace *)id;
- BKE_asset_library_reference_init_default(&workspace->asset_library);
+ BKE_asset_library_reference_init_default(&workspace->asset_library_ref);
}
static void workspace_free_data(ID *id)
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index e889d8af1d5..4abe1ff0f20 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -138,26 +138,25 @@ static void world_foreach_id(ID *id, LibraryForeachIDData *data)
static void world_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
World *wrld = (World *)id;
- if (wrld->id.us > 0 || BLO_write_is_undo(writer)) {
- /* Clean up, important in undo case to reduce false detection of changed datablocks. */
- BLI_listbase_clear(&wrld->gpumaterial);
- /* write LibData */
- BLO_write_id_struct(writer, World, id_address, &wrld->id);
- BKE_id_blend_write(writer, &wrld->id);
+ /* Clean up, important in undo case to reduce false detection of changed datablocks. */
+ BLI_listbase_clear(&wrld->gpumaterial);
- if (wrld->adt) {
- BKE_animdata_blend_write(writer, wrld->adt);
- }
+ /* write LibData */
+ BLO_write_id_struct(writer, World, id_address, &wrld->id);
+ BKE_id_blend_write(writer, &wrld->id);
- /* nodetree is integral part of world, no libdata */
- if (wrld->nodetree) {
- BLO_write_struct(writer, bNodeTree, wrld->nodetree);
- ntreeBlendWrite(writer, wrld->nodetree);
- }
+ if (wrld->adt) {
+ BKE_animdata_blend_write(writer, wrld->adt);
+ }
- BKE_previewimg_blend_write(writer, wrld->preview);
+ /* nodetree is integral part of world, no libdata */
+ if (wrld->nodetree) {
+ BLO_write_struct(writer, bNodeTree, wrld->nodetree);
+ ntreeBlendWrite(writer, wrld->nodetree);
}
+
+ BKE_previewimg_blend_write(writer, wrld->preview);
}
static void world_blend_read_data(BlendDataReader *reader, ID *id)
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 9b3103a638b..323da7473b5 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -149,7 +149,6 @@ static int write_audio_frame(FFMpegContext *context)
AUD_Device_read(
context->audio_mixdown_device, context->audio_input_buffer, context->audio_input_samples);
- context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
frame = av_frame_alloc();
frame->pts = context->audio_time / av_q2d(c->time_base);
@@ -184,7 +183,7 @@ static int write_audio_frame(FFMpegContext *context)
context->audio_input_samples * c->channels * context->audio_sample_size,
1);
- int success = 0;
+ int success = 1;
int ret = avcodec_send_frame(c, frame);
if (ret < 0) {
@@ -369,7 +368,7 @@ static int write_video_frame(FFMpegContext *context, int cfra, AVFrame *frame, R
return success;
}
-/* read and encode a frame of audio from the buffer */
+/* read and encode a frame of video from the buffer */
static AVFrame *generate_video_frame(FFMpegContext *context, const uint8_t *pixels)
{
AVCodecParameters *codec = context->video_stream->codecpar;
@@ -741,7 +740,7 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
}
}
- if ((of->oformat->flags & AVFMT_GLOBALHEADER)) {
+ if (of->oformat->flags & AVFMT_GLOBALHEADER) {
PRINT("Using global header\n");
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
@@ -1226,9 +1225,8 @@ fail:
* parameter.
* </p>
*/
-static void flush_ffmpeg(FFMpegContext *context)
+static void flush_ffmpeg(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
{
- AVCodecContext *c = context->video_codec;
AVPacket *packet = av_packet_alloc();
avcodec_send_frame(c, NULL);
@@ -1247,13 +1245,13 @@ static void flush_ffmpeg(FFMpegContext *context)
break;
}
- packet->stream_index = context->video_stream->index;
- av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
+ packet->stream_index = stream->index;
+ av_packet_rescale_ts(packet, c->time_base, stream->time_base);
# ifdef FFMPEG_USE_DURATION_WORKAROUND
- my_guess_pkt_duration(context->outfile, context->video_stream, packet);
+ my_guess_pkt_duration(context->outfile, stream, packet);
# endif
- int write_ret = av_interleaved_write_frame(context->outfile, packet);
+ int write_ret = av_interleaved_write_frame(outfile, packet);
if (write_ret != 0) {
fprintf(stderr, "Error writing delayed frame: %s\n", av_err2str(write_ret));
break;
@@ -1396,12 +1394,13 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit);
# ifdef WITH_AUDASPACE
static void write_audio_frames(FFMpegContext *context, double to_pts)
{
- int finished = 0;
+ AVCodecContext *c = context->audio_codec;
- while (context->audio_stream && !finished) {
- if ((context->audio_time >= to_pts) || (write_audio_frame(context))) {
- finished = 1;
+ while (context->audio_stream) {
+ if ((context->audio_time >= to_pts) || !write_audio_frame(context)) {
+ break;
}
+ context->audio_time += (double)context->audio_input_samples / (double)c->sample_rate;
}
}
# endif
@@ -1422,9 +1421,6 @@ int BKE_ffmpeg_append(void *context_v,
PRINT("Writing frame %i, render width=%d, render height=%d\n", frame, rectx, recty);
- /* why is this done before writing the video frame and again at end_ffmpeg? */
- // write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
-
if (context->video_stream) {
avframe = generate_video_frame(context, (unsigned char *)pixels);
success = (avframe && write_video_frame(context, frame - start_frame, avframe, reports));
@@ -1439,8 +1435,9 @@ int BKE_ffmpeg_append(void *context_v,
}
# ifdef WITH_AUDASPACE
- write_audio_frames(context,
- (frame - start_frame) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
+ /* Add +1 frame because we want to encode audio up until the next video frame. */
+ write_audio_frames(
+ context, (frame - start_frame + 1) / (((double)rd->frs_sec) / (double)rd->frs_sec_base));
# endif
return success;
}
@@ -1461,8 +1458,13 @@ static void end_ffmpeg_impl(FFMpegContext *context, int is_autosplit)
# endif
if (context->video_stream) {
- PRINT("Flushing delayed frames...\n");
- flush_ffmpeg(context);
+ PRINT("Flushing delayed video frames...\n");
+ flush_ffmpeg(context->video_codec, context->video_stream, context->outfile);
+ }
+
+ if (context->audio_stream) {
+ PRINT("Flushing delayed audio frames...\n");
+ flush_ffmpeg(context->audio_codec, context->audio_stream, context->outfile);
}
if (context->outfile) {