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/action.c2
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c528
-rw-r--r--source/blender/blenkernel/intern/armature.c2
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc17
-rw-r--r--source/blender/blenkernel/intern/blendfile.c4
-rw-r--r--source/blender/blenkernel/intern/bpath.c2
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/cachefile.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c2
-rw-r--r--source/blender/blenkernel/intern/cloth.c2
-rw-r--r--source/blender/blenkernel/intern/collection.c10
-rw-r--r--source/blender/blenkernel/intern/context.c2
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/curve_deform.c2
-rw-r--r--source/blender/blenkernel/intern/customdata.c140
-rw-r--r--source/blender/blenkernel/intern/displist.c5
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c3
-rw-r--r--source/blender/blenkernel/intern/effect.c81
-rw-r--r--source/blender/blenkernel/intern/fluid.c2
-rw-r--r--source/blender/blenkernel/intern/font.c2
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc103
-rw-r--r--source/blender/blenkernel/intern/gpencil.c157
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c9
-rw-r--r--source/blender/blenkernel/intern/hair.c2
-rw-r--r--source/blender/blenkernel/intern/idprop.c104
-rw-r--r--source/blender/blenkernel/intern/image.c2
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/key.c2
-rw-r--r--source/blender/blenkernel/intern/lattice.c2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c29
-rw-r--r--source/blender/blenkernel/intern/lib_override.c334
-rw-r--r--source/blender/blenkernel/intern/lib_query.c9
-rw-r--r--source/blender/blenkernel/intern/library.c2
-rw-r--r--source/blender/blenkernel/intern/light.c2
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c2
-rw-r--r--source/blender/blenkernel/intern/linestyle.c2
-rw-r--r--source/blender/blenkernel/intern/main.c124
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/material.c2
-rw-r--r--source/blender/blenkernel/intern/mball.c2
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c2
-rw-r--r--source/blender/blenkernel/intern/mesh.c4
-rw-r--r--source/blender/blenkernel/intern/movieclip.c2
-rw-r--r--source/blender/blenkernel/intern/multires.c2
-rw-r--r--source/blender/blenkernel/intern/node.cc (renamed from source/blender/blenkernel/intern/node.c)717
-rw-r--r--source/blender/blenkernel/intern/object.c25
-rw-r--r--source/blender/blenkernel/intern/object_update.c2
-rw-r--r--source/blender/blenkernel/intern/ocean.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c4
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c3
-rw-r--r--source/blender/blenkernel/intern/pointcloud.cc2
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c15
-rw-r--r--source/blender/blenkernel/intern/screen.c5
-rw-r--r--source/blender/blenkernel/intern/simulation.cc2
-rw-r--r--source/blender/blenkernel/intern/softbody.c5
-rw-r--r--source/blender/blenkernel/intern/sound.c2
-rw-r--r--source/blender/blenkernel/intern/speaker.c2
-rw-r--r--source/blender/blenkernel/intern/text.c2
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenkernel/intern/tracking.c345
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c6
-rw-r--r--source/blender/blenkernel/intern/tracking_test.cc170
-rw-r--r--source/blender/blenkernel/intern/undo_system.c363
-rw-r--r--source/blender/blenkernel/intern/unit.c3
-rw-r--r--source/blender/blenkernel/intern/volume.cc32
-rw-r--r--source/blender/blenkernel/intern/workspace.c2
-rw-r--r--source/blender/blenkernel/intern/world.c2
69 files changed, 2207 insertions, 1229 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index ccb077d6b82..db8fe75b6d1 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -298,6 +298,8 @@ IDTypeInfo IDType_ID_AC = {
.blend_read_expand = action_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* ***************** Library data level operations on action ************** */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 20956d6eb18..da874539232 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -362,6 +362,20 @@ void BKE_keyingsets_blend_read_expand(BlendExpander *expander, ListBase *list)
/* ***************************************** */
/* Evaluation Data-Setting Backend */
+static bool is_fcurve_evaluatable(FCurve *fcu)
+{
+ if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
+ return false;
+ }
+ if (fcu->grp != NULL && (fcu->grp->flag & AGRP_MUTED)) {
+ return false;
+ }
+ if (BKE_fcurve_is_empty(fcu)) {
+ return false;
+ }
+ return true;
+}
+
bool BKE_animsys_store_rna_setting(PointerRNA *ptr,
/* typically 'fcu->rna_path', 'fcu->array_index' */
const char *rna_path,
@@ -594,18 +608,11 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr,
{
/* Calculate then execute each curve. */
LISTBASE_FOREACH (FCurve *, fcu, list) {
- /* Check if this F-Curve doesn't belong to a muted group. */
- if ((fcu->grp != NULL) && (fcu->grp->flag & AGRP_MUTED)) {
- continue;
- }
- /* Check if this curve should be skipped. */
- if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED))) {
- continue;
- }
- /* Skip empty curves, as if muted. */
- if (BKE_fcurve_is_empty(fcu)) {
+
+ if (!is_fcurve_evaluatable(fcu)) {
continue;
}
+
PathResolvedRNA anim_rna;
if (BKE_animsys_store_rna_setting(ptr, fcu->rna_path, fcu->array_index, &anim_rna)) {
const float curval = calculate_fcurve(&anim_rna, fcu, anim_eval_context);
@@ -979,6 +986,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
return nes;
}
+static NlaEvalStrip *nlastrips_ctime_get_strip_single(
+ ListBase *dst_list,
+ NlaStrip *single_strip,
+ const AnimationEvalContext *anim_eval_context,
+ const bool flush_to_original)
+{
+ ListBase single_tracks_list;
+ single_tracks_list.first = single_tracks_list.last = single_strip;
+
+ return nlastrips_ctime_get_strip(
+ dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original);
+}
+
/* ---------------------- */
/* Initialize a valid mask, allocating memory if necessary. */
@@ -1152,7 +1172,7 @@ static void nlaeval_snapshot_free_data(NlaEvalSnapshot *snapshot)
/* Free memory owned by this evaluation channel. */
static void nlaevalchan_free_data(NlaEvalChannel *nec)
{
- nlavalidmask_free(&nec->valid);
+ nlavalidmask_free(&nec->domain);
if (nec->blend_snapshot != NULL) {
nlaevalchan_snapshot_free(nec->blend_snapshot);
@@ -1353,7 +1373,7 @@ static NlaEvalChannel *nlaevalchan_verify_key(NlaEvalData *nlaeval,
nec->mix_mode = nlaevalchan_detect_mix_mode(key, length);
- nlavalidmask_init(&nec->valid, length);
+ nlavalidmask_init(&nec->domain, length);
nec->base_snapshot.channel = nec;
nec->base_snapshot.length = length;
@@ -1682,14 +1702,6 @@ static bool nlaeval_blend_value(NlaBlendData *blend,
return false;
}
- if (nec->mix_mode == NEC_MIX_QUATERNION) {
- /* For quaternion properties, always output all sub-channels. */
- BLI_bitmap_set_all(nec->valid.ptr, true, 4);
- }
- else {
- BLI_BITMAP_ENABLE(nec->valid.ptr, array_index);
- }
-
NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_ensure_channel(blend->snapshot, nec);
float *p_value = &nec_snapshot->values[array_index];
@@ -1889,16 +1901,8 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
/* Evaluate all the F-Curves in the action,
* saving the relevant pointers to data that will need to be used. */
for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
- float value = 0.0f;
- /* check if this curve should be skipped */
- if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
- continue;
- }
- if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
- continue;
- }
- if (BKE_fcurve_is_empty(fcu)) {
+ if (!is_fcurve_evaluatable(fcu)) {
continue;
}
@@ -1906,7 +1910,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
* NOTE: we use the modified time here, since strip's F-Curve Modifiers
* are applied on top of this.
*/
- value = evaluate_fcurve(fcu, evaltime);
+ float value = evaluate_fcurve(fcu, evaltime);
/* apply strip's F-Curve Modifiers on this value
* NOTE: we apply the strip's original evaluation time not the modified one
@@ -2099,12 +2103,21 @@ void nladata_flush_channels(PointerRNA *ptr,
/* for each channel with accumulated values, write its value on the property it affects */
LISTBASE_FOREACH (NlaEvalChannel *, nec, &channels->channels) {
+ /**
+ * The bitmask is set for all channels touched by NLA due to the domain() function.
+ * Channels touched by current set of evaluated strips will have a snapshot channel directly
+ * from the evaluation snapshot.
+ *
+ * This function falls back to the default value if the snapshot channel doesn't exist.
+ * Thus channels, touched by NLA but not by the current set of evaluated strips, will be
+ * reset to default. If channel not touched by NLA then it's value is unchanged.
+ */
NlaEvalChannelSnapshot *nec_snapshot = nlaeval_snapshot_find_channel(snapshot, nec);
PathResolvedRNA rna = {nec->key.ptr, nec->key.prop, -1};
for (int i = 0; i < nec_snapshot->length; i++) {
- if (BLI_BITMAP_TEST(nec->valid.ptr, i)) {
+ if (BLI_BITMAP_TEST(nec->domain.ptr, i)) {
float value = nec_snapshot->values[i];
if (nec->is_array) {
rna.prop_index = i;
@@ -2131,13 +2144,7 @@ static void nla_eval_domain_action(PointerRNA *ptr,
LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
/* check if this curve should be skipped */
- if (fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) {
- continue;
- }
- if ((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) {
- continue;
- }
- if (BKE_fcurve_is_empty(fcu)) {
+ if (!is_fcurve_evaluatable(fcu)) {
continue;
}
@@ -2146,14 +2153,14 @@ static void nla_eval_domain_action(PointerRNA *ptr,
if (nec != NULL) {
/* For quaternion properties, enable all sub-channels. */
if (nec->mix_mode == NEC_MIX_QUATERNION) {
- BLI_bitmap_set_all(nec->valid.ptr, true, 4);
+ BLI_bitmap_set_all(nec->domain.ptr, true, 4);
continue;
}
int idx = nlaevalchan_validate_index(nec, fcu->array_index);
if (idx >= 0) {
- BLI_BITMAP_ENABLE(nec->valid.ptr, idx);
+ BLI_BITMAP_ENABLE(nec->domain.ptr, idx);
}
}
}
@@ -2212,190 +2219,345 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels,
/* ---------------------- */
+/** Tweaked strip is evaluated differently from other strips. Adjacent strips are ignored
+ * and includes a workaround for when user is not editing in place. */
+static void animsys_create_tweak_strip(const AnimData *adt,
+ const bool keyframing_to_strip,
+ NlaStrip *r_tweak_strip)
+
+{
+ /* Copy active strip so we can modify how it evaluates without affecting user data. */
+ memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip));
+ r_tweak_strip->next = r_tweak_strip->prev = NULL;
+
+ /* If tweaked strip is syncing action length, then evaluate using action length. */
+ if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
+ BKE_nlastrip_recalculate_bounds_sync_action(r_tweak_strip);
+ }
+
+ /* Strips with a user-defined time curve don't get properly remapped for editing
+ * at the moment, so mapping them just for display may be confusing. */
+ const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
+ !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
+
+ if (!is_inplace_tweak) {
+ /* Use Hold due to no proper remapping yet (the note above). */
+ r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD;
+
+ /* Disable range. */
+ r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
+ }
+
+ /** Controls whether able to keyframe outside range of tweaked strip. */
+ if (keyframing_to_strip) {
+ r_tweak_strip->extendmode = (is_inplace_tweak &&
+ !(r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
+ NLASTRIP_EXTEND_NOTHING :
+ NLASTRIP_EXTEND_HOLD;
+ }
+}
+
+/** Action track and strip are associated with the non-pushed action. */
+static void animsys_create_action_track_strip(const AnimData *adt,
+ const bool keyframing_to_strip,
+ NlaStrip *r_action_strip)
+{
+ memset(r_action_strip, 0, sizeof(NlaStrip));
+
+ bAction *action = adt->action;
+
+ if ((adt->flag & ADT_NLA_EDIT_ON)) {
+ action = adt->tmpact;
+ }
+
+ /* Set settings of dummy NLA strip from AnimData settings. */
+ r_action_strip->act = action;
+
+ /* Action range is calculated taking F-Modifiers into account
+ * (which making new strips doesn't do due to the troublesome nature of that). */
+ calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1);
+ r_action_strip->start = r_action_strip->actstart;
+ r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ?
+ (r_action_strip->actstart + 1.0f) :
+ (r_action_strip->actend);
+
+ r_action_strip->blendmode = adt->act_blendmode;
+ r_action_strip->extendmode = adt->act_extendmode;
+ r_action_strip->influence = adt->act_influence;
+
+ /* NOTE: must set this, or else the default setting overrides,
+ * and this setting doesn't work. */
+ r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+
+ /* Unless extendmode is Nothing (might be useful for flattening NLA evaluation), disable range.
+ * Extendmode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold.
+ */
+ if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
+ r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
+ }
+
+ const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0;
+ const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0;
+ const bool actionstrip_evaluated = r_action_strip->act && !soloing && !tweaking;
+ if (!actionstrip_evaluated) {
+ r_action_strip->flag |= NLASTRIP_FLAG_MUTED;
+ }
+
+ /** If we're keyframing, then we must allow keyframing outside fcurve bounds. */
+ if (keyframing_to_strip) {
+ r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD;
+ }
+}
+
+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) &&
+ (nlt->index == adt->act_track->index);
+ if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
+ return false;
+ }
+
+ /* Solo and muting are mutually exclusive. */
+ if (adt->flag & ADT_NLA_SOLO_TRACK) {
+ /* Skip if there is a solo track, but this isn't it. */
+ if ((nlt->flag & NLATRACK_SOLO) == 0) {
+ return false;
+ }
+ }
+ else {
+ /* Skip track if muted. */
+ if (nlt->flag & NLATRACK_MUTED) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/** Check for special case of non-pushed action being evaluated with no NLA influence (off and no
+ * strips evaluated) nor NLA interference (ensure NLA not soloing). */
+static bool is_action_track_evaluated_without_nla(const AnimData *adt,
+ const bool any_strip_evaluated)
+{
+ if (adt->action == NULL) {
+ return false;
+ }
+
+ if (any_strip_evaluated) {
+ return false;
+ }
+
+ /** NLA settings interference. */
+ if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) == 0) {
+ return false;
+ }
+
+ /** Allow action track to evaluate as if there isn't any NLA data. */
+ return true;
+}
+
/**
- * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels"
+ * XXX(Wayde Moss): #BKE_nlatrack_find_tweaked() exists within nla.c, but it doesn't appear to
+ * work as expected. From #animsys_evaluate_nla_for_flush(), it returns NULL in tweak mode. I'm not
+ * sure why. Preferably, it would be as simple as checking for `(adt->act_Track == nlt)` but that
+ * doesn't work either, neither does comparing indices.
*
+ * This function is a temporary work around. The first disabled track is always the tweaked track.
+ */
+static NlaTrack *nlatrack_find_tweaked(const AnimData *adt)
+{
+ NlaTrack *nlt;
+
+ if (adt == NULL) {
+ return NULL;
+ }
+
+ /* Since the track itself gets disabled, we want the first disabled. */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
+ if (nlt->flag & NLATRACK_DISABLED) {
+ return nlt;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels"
* \param[out] echannels: Evaluation channels with calculated values
- * \param[out] r_context: If not NULL,
- * data about the currently edited strip is stored here and excluded from value calculation.
- * \return false if NLA evaluation isn't actually applicable.
*/
-static bool animsys_evaluate_nla(NlaEvalData *echannels,
- PointerRNA *ptr,
- AnimData *adt,
- const AnimationEvalContext *anim_eval_context,
- const bool flush_to_original,
- NlaKeyframingContext *r_context)
+static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels,
+ PointerRNA *ptr,
+ const AnimData *adt,
+ const AnimationEvalContext *anim_eval_context,
+ const bool flush_to_original)
{
NlaTrack *nlt;
short track_index = 0;
bool has_strips = false;
-
ListBase estrips = {NULL, NULL};
NlaEvalStrip *nes;
- NlaStrip dummy_strip_buf;
- /* dummy strip for active action */
- NlaStrip *dummy_strip = r_context ? &r_context->strip : &dummy_strip_buf;
+ NlaStrip tweak_strip;
- memset(dummy_strip, 0, sizeof(*dummy_strip));
+ NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
- /* 1. get the stack of strips to evaluate at current time (influence calculated here) */
+ /* Get the stack of strips to evaluate at current time (influence calculated here). */
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
- /* stop here if tweaking is on and this strip is the tweaking track
- * (it will be the first one that's 'disabled')... */
- if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) {
- break;
+
+ if (!is_nlatrack_evaluatable(adt, nlt)) {
+ continue;
}
- /* solo and muting are mutually exclusive... */
- if (adt->flag & ADT_NLA_SOLO_TRACK) {
- /* skip if there is a solo track, but this isn't it */
- if ((nlt->flag & NLATRACK_SOLO) == 0) {
- continue;
- }
- /* else - mute doesn't matter */
+ if (nlt->strips.first) {
+ has_strips = true;
+ }
+
+ /** Append strip to evaluate for this track. */
+ if (nlt == tweaked_track) {
+ /** Tweaked strip is evaluated differently. */
+ animsys_create_tweak_strip(adt, false, &tweak_strip);
+ nes = nlastrips_ctime_get_strip_single(
+ &estrips, &tweak_strip, anim_eval_context, flush_to_original);
}
else {
- /* no solo tracks - skip track if muted */
- if (nlt->flag & NLATRACK_MUTED) {
- continue;
- }
+ nes = nlastrips_ctime_get_strip(
+ &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
+ }
+ if (nes) {
+ nes->track = nlt;
+ }
+ }
+
+ if (is_action_track_evaluated_without_nla(adt, has_strips)) {
+ BLI_freelistN(&estrips);
+ return false;
+ }
+
+ NlaStrip action_strip = {0};
+ animsys_create_action_track_strip(adt, false, &action_strip);
+ nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original);
+
+ /* Per strip, evaluate and accumulate on top of existing channels. */
+ for (nes = estrips.first; nes; nes = nes->next) {
+ nlastrip_evaluate(ptr,
+ echannels,
+ NULL,
+ nes,
+ &echannels->eval_snapshot,
+ anim_eval_context,
+ flush_to_original);
+ }
+
+ /* Free temporary evaluation data that's not used elsewhere. */
+ BLI_freelistN(&estrips);
+ return true;
+}
+
+/** Lower blended values are calculated and accumulated into r_context->lower_eval_data. */
+static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr,
+ const AnimData *adt,
+ const AnimationEvalContext *anim_eval_context,
+ NlaKeyframingContext *r_context)
+{
+ if (!r_context) {
+ return;
+ }
+
+ /* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe
+ * insertion. */
+ if (adt->flag & ADT_NLA_SOLO_TRACK) {
+ if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) {
+ r_context->eval_strip = NULL;
+ return;
+ }
+ }
+
+ NlaTrack *nlt;
+ short track_index = 0;
+ bool has_strips = false;
+
+ ListBase lower_estrips = {NULL, NULL};
+ NlaEvalStrip *nes;
+
+ NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
+
+ /* Get the lower stack of strips to evaluate at current time (influence calculated here). */
+ for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
+
+ if (!is_nlatrack_evaluatable(adt, nlt)) {
+ continue;
+ }
+
+ /* Tweaked strip effect should not be stored in any snapshot. */
+ if (nlt == tweaked_track) {
+ break;
}
- /* if this track has strips (but maybe they won't be suitable), set has_strips
- * - used for mainly for still allowing normal action evaluation...
- */
if (nlt->strips.first) {
has_strips = true;
}
- /* otherwise, get strip to evaluate for this channel */
+ /* Get strip to evaluate for this channel. */
nes = nlastrips_ctime_get_strip(
- &estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
+ &lower_estrips, &nlt->strips, track_index, anim_eval_context, false);
if (nes) {
nes->track = nlt;
}
}
- /* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack
- * - only do this if we're not exclusively evaluating the 'solo' NLA-track
- * - however, if the 'solo' track houses the current 'tweaking' strip,
- * then we should allow this to play, otherwise nothing happens
+ /** Note: Although we early out, we can still keyframe to the non-pushed action since the
+ * keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without
+ * remapping.
*/
- if ((adt->action) && ((adt->flag & ADT_NLA_SOLO_TRACK) == 0 || (adt->flag & ADT_NLA_EDIT_ON))) {
- /* if there are strips, evaluate action as per NLA rules */
- if ((has_strips) || (adt->actstrip)) {
- /* make dummy NLA strip, and add that to the stack */
- ListBase dummy_trackslist;
-
- dummy_trackslist.first = dummy_trackslist.last = dummy_strip;
-
- /* Strips with a user-defined time curve don't get properly remapped for editing
- * at the moment, so mapping them just for display may be confusing. */
- bool is_inplace_tweak = (nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
- !(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
-
- if (is_inplace_tweak) {
- /* edit active action in-place according to its active strip, so copy the data */
- memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip));
- /* Prevents nla eval from considering active strip's adj strips.
- * For user, this means entering tweak mode on a strip ignores evaluating adjacent strips
- * in the same track. */
- dummy_strip->next = dummy_strip->prev = NULL;
-
- /* If tweaked strip is syncing action length, then evaluate using action length. */
- if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
- BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip);
- }
- }
- else {
- /* set settings of dummy NLA strip from AnimData settings */
- dummy_strip->act = adt->action;
-
- /* action range is calculated taking F-Modifiers into account
- * (which making new strips doesn't do due to the troublesome nature of that) */
- calc_action_range(dummy_strip->act, &dummy_strip->actstart, &dummy_strip->actend, 1);
- dummy_strip->start = dummy_strip->actstart;
- dummy_strip->end = (IS_EQF(dummy_strip->actstart, dummy_strip->actend)) ?
- (dummy_strip->actstart + 1.0f) :
- (dummy_strip->actend);
-
- /* Always use the blend mode of the strip in tweak mode, even if not in-place. */
- if (nlt && adt->actstrip) {
- dummy_strip->blendmode = adt->actstrip->blendmode;
- dummy_strip->extendmode = NLASTRIP_EXTEND_HOLD;
- }
- else {
- dummy_strip->blendmode = adt->act_blendmode;
- dummy_strip->extendmode = adt->act_extendmode;
- }
+ if (is_action_track_evaluated_without_nla(adt, has_strips)) {
+ BLI_freelistN(&lower_estrips);
+ return;
+ }
- /* Unless extend-mode is Nothing (might be useful for flattening NLA evaluation),
- * disable range. */
- if (dummy_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
- dummy_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
- }
+ /* Write r_context->eval_strip. */
+ if (adt->flag & ADT_NLA_EDIT_ON) {
- dummy_strip->influence = adt->act_influence;
+ NlaStrip *tweak_strip = &r_context->strip;
+ animsys_create_tweak_strip(adt, true, tweak_strip);
+ r_context->eval_strip = nlastrips_ctime_get_strip_single(
+ NULL, tweak_strip, anim_eval_context, false);
+ }
+ else {
- /* NOTE: must set this, or else the default setting overrides,
- * and this setting doesn't work. */
- dummy_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
- }
+ NlaStrip *action_strip = &r_context->strip;
+ animsys_create_action_track_strip(adt, true, action_strip);
+ r_context->eval_strip = nlastrips_ctime_get_strip_single(
+ NULL, action_strip, anim_eval_context, false);
+ }
- /* add this to our list of evaluation strips */
- if (r_context == NULL) {
- nlastrips_ctime_get_strip(
- &estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
- }
- /* If computing the context for keyframing, store data there instead of the list. */
- else {
- /* The extend mode here effectively controls
- * whether it is possible to key-frame beyond the ends.*/
- dummy_strip->extendmode = (is_inplace_tweak &&
- !(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
- NLASTRIP_EXTEND_NOTHING :
- NLASTRIP_EXTEND_HOLD;
-
- r_context->eval_strip = nes = nlastrips_ctime_get_strip(
- NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
-
- /* These setting combinations require no data from strips below, so exit immediately. */
- if ((nes == NULL) ||
- (dummy_strip->blendmode == NLASTRIP_MODE_REPLACE && dummy_strip->influence == 1.0f)) {
- BLI_freelistN(&estrips);
- return true;
- }
- }
- }
- else {
- /* special case - evaluate as if there isn't any NLA data */
- BLI_freelistN(&estrips);
- return false;
- }
+ /* If NULL, then keyframing will fail. No need to do any more processing. */
+ if (!r_context->eval_strip) {
+ BLI_freelistN(&lower_estrips);
+ return;
}
- /* only continue if there are strips to evaluate */
- if (BLI_listbase_is_empty(&estrips)) {
- return true;
+ /* If tweak strip is full REPLACE, then lower strips not needed. */
+ if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE &&
+ IS_EQF(r_context->strip.influence, 1.0f)) {
+ BLI_freelistN(&lower_estrips);
+ return;
}
- /* 2. for each strip, evaluate then accumulate on top of existing channels,
- * but don't set values yet. */
- for (nes = estrips.first; nes; nes = nes->next) {
+ /* For each strip, evaluate then accumulate on top of existing channels. */
+ for (nes = lower_estrips.first; nes; nes = nes->next) {
nlastrip_evaluate(ptr,
- echannels,
+ &r_context->lower_eval_data,
NULL,
nes,
- &echannels->eval_snapshot,
+ &r_context->lower_eval_data.eval_snapshot,
anim_eval_context,
- flush_to_original);
+ false);
}
- /* 3. free temporary evaluation data that's not used elsewhere */
- BLI_freelistN(&estrips);
- return true;
+ /* Free temporary evaluation data that's not used elsewhere. */
+ BLI_freelistN(&lower_estrips);
}
/* NLA Evaluation function (mostly for use through do_animdata)
@@ -2412,7 +2574,7 @@ static void animsys_calculate_nla(PointerRNA *ptr,
nlaeval_init(&echannels);
/* evaluate the NLA stack, obtaining a set of values to flush */
- if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) {
+ if (animsys_evaluate_nla_for_flush(&echannels, ptr, adt, anim_eval_context, flush_to_original)) {
/* reset any channels touched by currently inactive actions to default value */
animsys_evaluate_nla_domain(ptr, &echannels, adt);
@@ -2448,8 +2610,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
struct ListBase *cache,
struct PointerRNA *ptr,
struct AnimData *adt,
- const AnimationEvalContext *anim_eval_context,
- const bool flush_to_original)
+ const AnimationEvalContext *anim_eval_context)
{
/* No remapping needed if NLA is off or no action. */
if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) ||
@@ -2472,8 +2633,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
ctx->adt = adt;
nlaeval_init(&ctx->lower_eval_data);
- animsys_evaluate_nla(
- &ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx);
+ animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx);
BLI_assert(ELEM(ctx->strip.act, NULL, adt->action));
BLI_addtail(cache, ctx);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 4c9fb4b191a..b8a0ed087e0 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -331,6 +331,8 @@ IDTypeInfo IDType_ID_AR = {
.blend_read_expand = armature_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/** \} */
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index e1e8d06b9ec..85dabe4490c 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -526,6 +526,10 @@ static ReadAttributePtr read_attribute_from_custom_data(const CustomData &custom
case CD_PROP_BOOL:
return std::make_unique<ArrayReadAttribute<bool>>(
domain, Span(static_cast<bool *>(layer.data), size));
+ case CD_MLOOPUV:
+ auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
+ return std::make_unique<DerivedArrayReadAttribute<MLoopUV, float2, decltype(get_uv)>>(
+ domain, Span(static_cast<MLoopUV *>(layer.data), size), get_uv);
}
}
}
@@ -570,6 +574,12 @@ static WriteAttributePtr write_attribute_from_custom_data(
case CD_PROP_BOOL:
return std::make_unique<ArrayWriteAttribute<bool>>(
domain, MutableSpan(static_cast<bool *>(layer.data), size));
+ case CD_MLOOPUV:
+ auto get_uv = [](const MLoopUV &uv) { return float2(uv.uv); };
+ auto set_uv = [](MLoopUV &uv, const float2 value) { copy_v2_v2(uv.uv, value); };
+ return std::make_unique<
+ DerivedArrayWriteAttribute<MLoopUV, float2, decltype(get_uv), decltype(set_uv)>>(
+ domain, MutableSpan(static_cast<MLoopUV *>(layer.data), size), get_uv, set_uv);
}
}
}
@@ -597,8 +607,9 @@ static void get_custom_data_layer_attribute_names(const CustomData &custom_data,
Set<std::string> &r_names)
{
for (const CustomDataLayer &layer : blender::Span(custom_data.layers, custom_data.totlayer)) {
- if (component.attribute_domain_with_type_supported(domain,
- static_cast<CustomDataType>(layer.type))) {
+ const CustomDataType data_type = static_cast<CustomDataType>(layer.type);
+ if (component.attribute_domain_with_type_supported(domain, data_type) ||
+ ELEM(data_type, CD_MLOOPUV)) {
r_names.add(layer.name);
}
}
@@ -1327,7 +1338,7 @@ Set<std::string> MeshComponent::attribute_names() const
for (StringRef name : vertex_group_names_.keys()) {
names.add(name);
}
- get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_CORNER, names);
+ get_custom_data_layer_attribute_names(mesh_->ldata, *this, ATTR_DOMAIN_CORNER, names);
get_custom_data_layer_attribute_names(mesh_->vdata, *this, ATTR_DOMAIN_POINT, names);
get_custom_data_layer_attribute_names(mesh_->edata, *this, ATTR_DOMAIN_EDGE, names);
get_custom_data_layer_attribute_names(mesh_->pdata, *this, ATTR_DOMAIN_POLYGON, names);
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 0855db1a943..49475c014cd 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -647,6 +647,10 @@ 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/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 762ced7dc5f..2ad0ac950d0 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -23,7 +23,7 @@
* - passing output paths to the visitor?, like render out.
* - passing sequence strips with many images.
* - passing directory paths - visitors don't know which path is a dir or a file.
- * */
+ */
#include <sys/stat.h>
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 9a954a89cad..28c8ae3e416 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -410,6 +410,8 @@ IDTypeInfo IDType_ID_BR = {
.blend_read_expand = brush_blend_read_expand,
.blend_read_undo_preserve = brush_undo_preserve,
+
+ .lib_override_apply_post = NULL,
};
static RNG *brush_rng;
@@ -978,7 +980,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
brush->gpencil_settings->fill_leak = 3;
brush->gpencil_settings->fill_threshold = 0.1f;
brush->gpencil_settings->fill_simplylvl = 1;
- brush->gpencil_settings->fill_factor = 1;
+ brush->gpencil_settings->fill_factor = 1.0f;
brush->gpencil_settings->draw_strength = 1.0f;
brush->gpencil_settings->hardeness = 1.0f;
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index d6c31809a2e..1e2139522f1 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -142,6 +142,8 @@ IDTypeInfo IDType_ID_CF = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* TODO: make this per cache file to avoid global locks. */
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 0ca22e34973..b0e3743add1 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -203,6 +203,8 @@ IDTypeInfo IDType_ID_CA = {
.blend_read_expand = camera_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/** \} */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index c2d6d5c7594..09bd397cc78 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -285,7 +285,7 @@ static int do_step_cloth(
mul_m4_v3(ob->obmat, verts->xconst);
}
- effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights);
+ effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights, false);
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) {
cloth_update_verts(ob, clmd, result);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 58ce7227398..601ee57fc89 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -362,6 +362,8 @@ IDTypeInfo IDType_ID_GR = {
.blend_read_expand = collection_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/** \} */
@@ -1941,9 +1943,6 @@ static void scene_collections_build_array(Collection *collection, void *data)
static void scene_collections_array(Scene *scene, Collection ***collections_array, int *tot)
{
- Collection *collection;
- Collection **array;
-
*collections_array = NULL;
*tot = 0;
@@ -1951,7 +1950,7 @@ static void scene_collections_array(Scene *scene, Collection ***collections_arra
return;
}
- collection = scene->master_collection;
+ Collection *collection = scene->master_collection;
BLI_assert(collection != NULL);
scene_collection_callback(collection, scene_collections_count, tot);
@@ -1959,7 +1958,8 @@ static void scene_collections_array(Scene *scene, Collection ***collections_arra
return;
}
- *collections_array = array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray");
+ Collection **array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray");
+ *collections_array = array;
scene_collection_callback(collection, scene_collections_build_array, &array);
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 65accc66084..6bc385ecd31 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -318,7 +318,7 @@ static eContextResult ctx_data_get(bContext *C, const char *member, bContextData
*
* Values in order of importance
* (0, -1, 1) - Where 1 is highest priority
- * */
+ */
if (done != 1 && recursion < 1 && C->wm.store) {
C->data.recursion = 1;
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index ebce28c4e23..5632ae28960 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -327,6 +327,8 @@ IDTypeInfo IDType_ID_CU = {
.blend_read_expand = curve_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
static int cu_isectLL(const float v1[3],
@@ -2373,7 +2375,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
* 0,1,2,3,4 --> 1,2,3,4,0
*
* this is why we compare last with second last
- * */
+ */
float vec_1[3] = {0, 1, 0}, vec_2[3] = {0, 1, 0}, angle, ang_fac, cross_tmp[3];
BevPoint *bevp_first;
diff --git a/source/blender/blenkernel/intern/curve_deform.c b/source/blender/blenkernel/intern/curve_deform.c
index 4725be6d302..63da7c1dd11 100644
--- a/source/blender/blenkernel/intern/curve_deform.c
+++ b/source/blender/blenkernel/intern/curve_deform.c
@@ -233,7 +233,7 @@ static bool calc_curve_deform(
* Now for Neg Up XYZ, the colors are all dark, and ordered clockwise - Campbell
*
* note: moved functions into quat_apply_track/vec_apply_track
- * */
+ */
copy_qt_qt(quat, new_quat);
copy_v3_v3(cent, co);
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index b0994fb683a..37e9c810123 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -212,9 +212,9 @@ static void layerFree_mdeformvert(void *data, int count, int size)
/* copy just zeros in this case */
static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, int count)
{
- int i, size = sizeof(void *);
+ const int size = sizeof(void *);
- for (i = 0; i < count; i++) {
+ for (int i = 0; i < count; i++) {
void **ptr = POINTER_OFFSET(dest, i * size);
*ptr = NULL;
}
@@ -253,15 +253,14 @@ static void layerInterp_mdeformvert(const void **sources,
MDeformVert *dvert = dest;
struct MDeformWeight_Link *dest_dwlink = NULL;
struct MDeformWeight_Link *node;
- int i, j, totweight;
/* build a list of unique def_nrs for dest */
- totweight = 0;
- for (i = 0; i < count; i++) {
+ int totweight = 0;
+ for (int i = 0; i < count; i++) {
const MDeformVert *source = sources[i];
float interp_weight = weights[i];
- for (j = 0; j < source->totweight; j++) {
+ for (int j = 0; j < source->totweight; j++) {
MDeformWeight *dw = &source->dw[j];
float weight = dw->weight * interp_weight;
@@ -311,7 +310,8 @@ static void layerInterp_mdeformvert(const void **sources,
if (totweight) {
dvert->totweight = totweight;
- for (i = 0, node = dest_dwlink; node; node = node->next, i++) {
+ int i = 0;
+ for (node = dest_dwlink; node; node = node->next, i++) {
if (node->dw.weight > 1.0f) {
node->dw.weight = 1.0f;
}
@@ -416,18 +416,16 @@ static void layerInterp_tface(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
MTFace *tf = dest;
- int i, j, k;
float uv[4][2] = {{0.0f}};
- const float *sub_weight;
- sub_weight = sub_weights;
- for (i = 0; i < count; i++) {
+ const float *sub_weight = sub_weights;
+ for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MTFace *src = sources[i];
- for (j = 0; j < 4; j++) {
+ for (int j = 0; j < 4; j++) {
if (sub_weights) {
- for (k = 0; k < 4; k++, sub_weight++) {
+ for (int k = 0; k < 4; k++, sub_weight++) {
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
}
}
@@ -446,9 +444,8 @@ static void layerSwap_tface(void *data, const int *corner_indices)
{
MTFace *tf = data;
float uv[4][2];
- int j;
- for (j = 0; j < 4; j++) {
+ for (int j = 0; j < 4; j++) {
const int source_index = corner_indices[j];
copy_v2_v2(uv[j], tf->uv[source_index]);
}
@@ -517,18 +514,16 @@ static void layerInterp_origspace_face(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
OrigSpaceFace *osf = dest;
- int i, j, k;
float uv[4][2] = {{0.0f}};
- const float *sub_weight;
- sub_weight = sub_weights;
- for (i = 0; i < count; i++) {
+ const float *sub_weight = sub_weights;
+ for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const OrigSpaceFace *src = sources[i];
- for (j = 0; j < 4; j++) {
+ for (int j = 0; j < 4; j++) {
if (sub_weights) {
- for (k = 0; k < 4; k++, sub_weight++) {
+ for (int k = 0; k < 4; k++, sub_weight++) {
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
}
}
@@ -546,9 +541,8 @@ static void layerSwap_origspace_face(void *data, const int *corner_indices)
{
OrigSpaceFace *osf = data;
float uv[4][2];
- int j;
- for (j = 0; j < 4; j++) {
+ for (int j = 0; j < 4; j++) {
copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
}
memcpy(osf->uv, uv, sizeof(osf->uv));
@@ -567,13 +561,11 @@ static void layerDefault_origspace_face(void *data, int count)
static void layerSwap_mdisps(void *data, const int *ci)
{
MDisps *s = data;
- float(*d)[3] = NULL;
- int corners, cornersize, S;
if (s->disps) {
int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
- corners = multires_mdisp_corners(s);
- cornersize = s->totdisp / corners;
+ int corners = multires_mdisp_corners(s);
+ int cornersize = s->totdisp / corners;
if (corners != nverts) {
/* happens when face changed vertex count in edit mode
@@ -585,9 +577,9 @@ static void layerSwap_mdisps(void *data, const int *ci)
return;
}
- d = MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
+ float(*d)[3] = MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
- for (S = 0; S < corners; S++) {
+ for (int S = 0; S < corners; S++) {
memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize);
}
@@ -1128,9 +1120,8 @@ static void layerSwap_mcol(void *data, const int *corner_indices)
{
MCol *mcol = data;
MCol col[4];
- int j;
- for (j = 0; j < 4; j++) {
+ for (int j = 0; j < 4; j++) {
col[j] = mcol[corner_indices[j]];
}
@@ -2064,13 +2055,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
void CustomData_update_typemap(CustomData *data)
{
- int i, lasttype = -1;
+ int lasttype = -1;
- for (i = 0; i < CD_NUMTYPES; i++) {
+ for (int i = 0; i < CD_NUMTYPES; i++) {
data->typemap[i] = -1;
}
- for (i = 0; i < data->totlayer; i++) {
+ for (int i = 0; i < data->totlayer; i++) {
const int type = data->layers[i].type;
if (type != lasttype) {
data->typemap[type] = i;
@@ -2097,18 +2088,16 @@ bool CustomData_merge(const struct CustomData *source,
{
/*const LayerTypeInfo *typeInfo;*/
CustomDataLayer *layer, *newlayer;
- void *data;
- int i, type, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0,
- flag = 0;
+ int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
int number = 0, maxnumber = -1;
bool changed = false;
- for (i = 0; i < source->totlayer; i++) {
+ for (int i = 0; i < source->totlayer; i++) {
layer = &source->layers[i];
/*typeInfo = layerType_getInfo(layer->type);*/ /*UNUSED*/
- type = layer->type;
- flag = layer->flag;
+ int type = layer->type;
+ int flag = layer->flag;
if (type != lasttype) {
number = 0;
@@ -2136,6 +2125,7 @@ bool CustomData_merge(const struct CustomData *source,
continue;
}
+ void *data;
switch (alloctype) {
case CD_ASSIGN:
case CD_REFERENCE:
@@ -2518,8 +2508,7 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
/* Passing a layer-data to copy from with an alloctype that won't copy is
* most likely a bug */
- BLI_assert(!layerdata || (alloctype == CD_ASSIGN) || (alloctype == CD_DUPLICATE) ||
- (alloctype == CD_REFERENCE));
+ BLI_assert(!layerdata || ELEM(alloctype, CD_ASSIGN, CD_DUPLICATE, CD_REFERENCE));
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
return &data->layers[CustomData_get_layer_index(data, type)];
@@ -2616,10 +2605,9 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
void *CustomData_add_layer(
CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem)
{
- CustomDataLayer *layer;
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
- layer = customData_add_layer__internal(
+ CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
@@ -2638,9 +2626,8 @@ void *CustomData_add_layer_named(CustomData *data,
int totelem,
const char *name)
{
- CustomDataLayer *layer;
-
- layer = customData_add_layer__internal(data, type, alloctype, layerdata, totelem, name);
+ CustomDataLayer *layer = customData_add_layer__internal(
+ data, type, alloctype, layerdata, totelem, name);
CustomData_update_typemap(data);
if (layer) {
@@ -2828,12 +2815,10 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type)
void CustomData_free_temporary(CustomData *data, int totelem)
{
- CustomDataLayer *layer;
int i, j;
bool changed = false;
-
for (i = 0, j = 0; i < data->totlayer; i++) {
- layer = &data->layers[i];
+ CustomDataLayer *layer = &data->layers[i];
if (i != j) {
data->layers[j] = data->layers[i];
@@ -3681,10 +3666,8 @@ void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
{
- const LayerTypeInfo *typeInfo;
int offset = data->layers[n].offset;
-
- typeInfo = layerType_getInfo(data->layers[n].type);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if (typeInfo->set_default) {
typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
@@ -4050,7 +4033,6 @@ void CustomData_bmesh_interp(CustomData *data,
return;
}
- int i, j;
void *source_buf[SOURCE_BUF_SIZE];
const void **sources = (const void **)source_buf;
@@ -4071,11 +4053,11 @@ void CustomData_bmesh_interp(CustomData *data,
}
/* interpolates a layer at a time */
- for (i = 0; i < data->totlayer; i++) {
+ for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->interp) {
- for (j = 0; j < count; j++) {
+ for (int j = 0; j < count; j++) {
sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
}
CustomData_bmesh_interp_n(
@@ -4453,7 +4435,6 @@ bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, cons
void CustomData_layers__print(CustomData *data)
{
-
printf("{\n");
int i;
@@ -4508,10 +4489,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
{
CustomDataExternal *external = data->external;
CustomDataLayer *layer;
- CDataFile *cdf;
- CDataFileLayer *blay;
char filename[FILE_MAX];
- const LayerTypeInfo *typeInfo;
int update = 0;
if (!external) {
@@ -4520,7 +4498,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
for (int i = 0; i < data->totlayer; i++) {
layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
@@ -4539,7 +4517,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
customdata_external_filename(filename, id, external);
- cdf = cdf_create(CDF_TYPE_MESH);
+ CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
if (!cdf_read_open(cdf, filename)) {
cdf_free(cdf);
CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filename);
@@ -4548,7 +4526,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
for (int i = 0; i < data->totlayer; i++) {
layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
@@ -4557,7 +4535,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
- blay = cdf_layer_find(cdf, layer->type, layer->name);
+ CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
if (blay) {
if (cdf_read_layer(cdf, blay)) {
@@ -4584,10 +4562,6 @@ void CustomData_external_write(
CustomData *data, ID *id, CustomDataMask mask, int totelem, int free)
{
CustomDataExternal *external = data->external;
- CustomDataLayer *layer;
- CDataFile *cdf;
- CDataFileLayer *blay;
- const LayerTypeInfo *typeInfo;
int update = 0;
char filename[FILE_MAX];
@@ -4597,8 +4571,8 @@ void CustomData_external_write(
/* test if there is anything to write */
for (int i = 0; i < data->totlayer; i++) {
- layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
@@ -4616,11 +4590,11 @@ void CustomData_external_write(
CustomData_external_read(data, id, mask, totelem);
customdata_external_filename(filename, id, external);
- cdf = cdf_create(CDF_TYPE_MESH);
+ CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
for (int i = 0; i < data->totlayer; i++) {
- layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
if (layer->flag & CD_FLAG_IN_MEMORY) {
@@ -4642,11 +4616,11 @@ void CustomData_external_write(
int i;
for (i = 0; i < data->totlayer; i++) {
- layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
- blay = cdf_layer_find(cdf, layer->type, layer->name);
+ CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
if (cdf_write_layer(cdf, blay)) {
if (typeInfo->write(cdf, layer->data, totelem)) {
@@ -4670,8 +4644,8 @@ void CustomData_external_write(
}
for (i = 0; i < data->totlayer; i++) {
- layer = &data->layers[i];
- typeInfo = layerType_getInfo(layer->type);
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
if (free) {
@@ -4691,15 +4665,13 @@ void CustomData_external_add(
CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename)
{
CustomDataExternal *external = data->external;
- CustomDataLayer *layer;
- int layer_index;
- layer_index = CustomData_get_active_layer_index(data, type);
+ int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return;
}
- layer = &data->layers[layer_index];
+ CustomDataLayer *layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_EXTERNAL) {
return;
@@ -4823,8 +4795,6 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
cd_interp interp_cd = NULL;
cd_copy copy_cd = NULL;
- void *tmp_dst;
-
if (!sources) {
/* Not supported here, abort. */
return;
@@ -4841,7 +4811,7 @@ static void customdata_data_transfer_interp_generic(const CustomDataTransferLaye
copy_cd = type_info->copy;
}
- tmp_dst = MEM_mallocN(data_size, __func__);
+ void *tmp_dst = MEM_mallocN(data_size, __func__);
if (count > 1 && !interp_cd) {
if (data_flag) {
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 375792a02c2..58c050493c9 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -488,6 +488,7 @@ void BKE_displist_fill(ListBase *dispbase,
while (cont) {
int dl_flag_accum = 0;
+ int dl_rt_accum = 0;
cont = 0;
totvert = 0;
nextcol = 0;
@@ -535,6 +536,7 @@ void BKE_displist_fill(ListBase *dispbase,
}
}
dl_flag_accum |= dl->flag;
+ dl_rt_accum |= dl->rt;
}
}
@@ -544,6 +546,7 @@ void BKE_displist_fill(ListBase *dispbase,
dlnew = MEM_callocN(sizeof(DispList), "filldisplist");
dlnew->type = DL_INDEX3;
dlnew->flag = (dl_flag_accum & (DL_BACK_CURVE | DL_FRONT_CURVE));
+ dlnew->rt = (dl_rt_accum & CU_SMOOTH);
dlnew->col = colnr;
dlnew->nr = totvert;
dlnew->parts = tot;
@@ -1129,7 +1132,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
*
* The right solution would be to COW the Curve data block at the input of the modifier
* stack just like what the mesh modifier does.
- * */
+ */
modified = BKE_mesh_new_nomain_from_curve_displist(ob, dispbase);
}
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 811a27c9f3f..31860bbe0b4 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -5156,7 +5156,8 @@ static int dynamicPaint_prepareEffectStep(struct Depsgraph *depsgraph,
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, surface->effector_weights);
+ ListBase *effectors = BKE_effectors_create(
+ depsgraph, ob, NULL, surface->effector_weights, false);
/* allocate memory for force data (dir vector + strength) */
*force = MEM_mallocN(sizeof(float[4]) * sData->total_points, "PaintEffectForces");
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 13e9bb1bf24..4104b6080c5 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -270,11 +270,71 @@ void BKE_effector_relations_free(ListBase *lb)
}
}
+/* Check that the force field isn't disabled via its flags. */
+static bool is_effector_enabled(PartDeflect *pd, bool use_rotation)
+{
+ switch (pd->forcefield) {
+ case PFIELD_BOID:
+ case PFIELD_GUIDE:
+ return true;
+
+ case PFIELD_TEXTURE:
+ return (pd->flag & PFIELD_DO_LOCATION) != 0 && pd->tex != NULL;
+
+ default:
+ if (use_rotation) {
+ return (pd->flag & (PFIELD_DO_LOCATION | PFIELD_DO_ROTATION)) != 0;
+ }
+ else {
+ return (pd->flag & PFIELD_DO_LOCATION) != 0;
+ }
+ }
+}
+
+/* Check that the force field won't have zero effect due to strength settings. */
+static bool is_effector_nonzero_strength(PartDeflect *pd)
+{
+ if (pd->f_strength != 0.0f) {
+ return true;
+ }
+
+ if (pd->forcefield == PFIELD_TEXTURE) {
+ return false;
+ }
+
+ if (pd->f_noise > 0.0f || pd->f_flow != 0.0f) {
+ return true;
+ }
+
+ switch (pd->forcefield) {
+ case PFIELD_BOID:
+ case PFIELD_GUIDE:
+ return true;
+
+ case PFIELD_VORTEX:
+ return pd->shape != PFIELD_SHAPE_POINT;
+
+ case PFIELD_DRAG:
+ return pd->f_damp != 0.0f;
+
+ default:
+ return false;
+ }
+}
+
+/* Check if the force field will affect its user. */
+static bool is_effector_relevant(PartDeflect *pd, EffectorWeights *weights, bool use_rotation)
+{
+ return (weights->weight[pd->forcefield] != 0.0f) && is_effector_enabled(pd, use_rotation) &&
+ is_effector_nonzero_strength(pd);
+}
+
/* Create effective list of effectors from relations built beforehand. */
ListBase *BKE_effectors_create(Depsgraph *depsgraph,
Object *ob_src,
ParticleSystem *psys_src,
- EffectorWeights *weights)
+ EffectorWeights *weights,
+ bool use_rotation)
{
Scene *scene = DEG_get_evaluated_scene(depsgraph);
ListBase *relations = DEG_get_effector_relations(depsgraph, weights->group);
@@ -299,7 +359,8 @@ ListBase *BKE_effectors_create(Depsgraph *depsgraph,
}
PartDeflect *pd = (relation->pd == relation->psys->part->pd) ? part->pd : part->pd2;
- if (weights->weight[pd->forcefield] == 0.0f) {
+
+ if (!is_effector_relevant(pd, weights, use_rotation)) {
continue;
}
@@ -310,7 +371,7 @@ ListBase *BKE_effectors_create(Depsgraph *depsgraph,
if (ob == ob_src) {
continue;
}
- if (weights->weight[ob->pd->forcefield] == 0.0f) {
+ if (!is_effector_relevant(ob->pd, weights, use_rotation)) {
continue;
}
if (ob->pd->shape == PFIELD_SHAPE_POINTS && BKE_object_get_evaluated_mesh(ob) == NULL) {
@@ -903,7 +964,9 @@ static void do_texture_effector(EffectorCache *eff,
madd_v3_v3fl(force, efd->nor, fac);
}
- add_v3_v3(total_force, force);
+ if (eff->pd->flag & PFIELD_DO_LOCATION) {
+ add_v3_v3(total_force, force);
+ }
}
static void do_physical_effector(EffectorCache *eff,
EffectorData *efd,
@@ -918,6 +981,7 @@ static void do_physical_effector(EffectorCache *eff,
float strength = pd->f_strength;
float damp = pd->f_damp;
float noise_factor = pd->f_noise;
+ float flow_falloff = efd->falloff;
if (noise_factor > 0.0f) {
strength += wind_func(rng, noise_factor);
@@ -1027,6 +1091,7 @@ static void do_physical_effector(EffectorCache *eff,
break;
case PFIELD_FLUIDFLOW:
zero_v3(force);
+ flow_falloff = 0;
#ifdef WITH_FLUID
if (pd->f_source) {
float density;
@@ -1036,8 +1101,7 @@ static void do_physical_effector(EffectorCache *eff,
influence *= density;
}
mul_v3_fl(force, influence);
- /* apply flow */
- madd_v3_v3fl(total_force, point->vel, -pd->f_flow * influence);
+ flow_falloff = influence;
}
}
#endif
@@ -1047,9 +1111,8 @@ static void do_physical_effector(EffectorCache *eff,
if (pd->flag & PFIELD_DO_LOCATION) {
madd_v3_v3fl(total_force, force, 1.0f / point->vel_to_sec);
- if (ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG, PFIELD_FLUIDFLOW) == 0 &&
- pd->f_flow != 0.0f) {
- madd_v3_v3fl(total_force, point->vel, -pd->f_flow * efd->falloff);
+ if (!ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG) && pd->f_flow != 0.0f) {
+ madd_v3_v3fl(total_force, point->vel, -pd->f_flow * flow_falloff);
}
}
diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c
index 59248e5f9f8..7fe009d51ca 100644
--- a/source/blender/blenkernel/intern/fluid.c
+++ b/source/blender/blenkernel/intern/fluid.c
@@ -3225,7 +3225,7 @@ static void update_effectors(
ListBase *effectors;
/* make sure smoke flow influence is 0.0f */
fds->effector_weights->weight[PFIELD_FLUIDFLOW] = 0.0f;
- effectors = BKE_effectors_create(depsgraph, ob, NULL, fds->effector_weights);
+ effectors = BKE_effectors_create(depsgraph, ob, NULL, fds->effector_weights, false);
if (effectors) {
/* Precalculate wind forces. */
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index df1dbaa905f..25a0259abe3 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -176,6 +176,8 @@ IDTypeInfo IDType_ID_VF = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/***************************** VFont *******************************/
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index a47a3dbc872..dae0b757df0 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -19,6 +19,7 @@
#include "BKE_mesh.h"
#include "BKE_mesh_wrapper.h"
#include "BKE_pointcloud.h"
+#include "BKE_volume.h"
#include "DNA_object_types.h"
@@ -52,6 +53,8 @@ GeometryComponent *GeometryComponent::create(GeometryComponentType component_typ
return new PointCloudComponent();
case GeometryComponentType::Instances:
return new InstancesComponent();
+ case GeometryComponentType::Volume:
+ return new VolumeComponent();
}
BLI_assert(false);
return nullptr;
@@ -202,6 +205,13 @@ const PointCloud *GeometrySet::get_pointcloud_for_read() const
return (component == nullptr) ? nullptr : component->get_for_read();
}
+/* Returns a read-only volume or null. */
+const Volume *GeometrySet::get_volume_for_read() const
+{
+ const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
+ return (component == nullptr) ? nullptr : component->get_for_read();
+}
+
/* Returns true when the geometry set has a point cloud component that has a point cloud. */
bool GeometrySet::has_pointcloud() const
{
@@ -216,6 +226,13 @@ bool GeometrySet::has_instances() const
return component != nullptr && component->instances_amount() >= 1;
}
+/* Returns true when the geometry set has a volume component that has a volume. */
+bool GeometrySet::has_volume() const
+{
+ const VolumeComponent *component = this->get_component_for_read<VolumeComponent>();
+ return component != nullptr && component->has_volume();
+}
+
/* Create a new geometry set that only contains the given mesh. */
GeometrySet GeometrySet::create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership)
{
@@ -263,6 +280,13 @@ PointCloud *GeometrySet::get_pointcloud_for_write()
return component.get_for_write();
}
+/* Returns a mutable volume or null. No ownership is transferred. */
+Volume *GeometrySet::get_volume_for_write()
+{
+ VolumeComponent &component = this->get_component_for_write<VolumeComponent>();
+ return component.get_for_write();
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -545,6 +569,85 @@ bool InstancesComponent::is_empty() const
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Volume Component
+ * \{ */
+
+VolumeComponent::VolumeComponent() : GeometryComponent(GeometryComponentType::Volume)
+{
+}
+
+VolumeComponent::~VolumeComponent()
+{
+ this->clear();
+}
+
+GeometryComponent *VolumeComponent::copy() const
+{
+ VolumeComponent *new_component = new VolumeComponent();
+ if (volume_ != nullptr) {
+ new_component->volume_ = BKE_volume_copy_for_eval(volume_, false);
+ new_component->ownership_ = GeometryOwnershipType::Owned;
+ }
+ return new_component;
+}
+
+void VolumeComponent::clear()
+{
+ BLI_assert(this->is_mutable());
+ if (volume_ != nullptr) {
+ if (ownership_ == GeometryOwnershipType::Owned) {
+ BKE_id_free(nullptr, volume_);
+ }
+ volume_ = nullptr;
+ }
+}
+
+bool VolumeComponent::has_volume() const
+{
+ return volume_ != nullptr;
+}
+
+/* Clear the component and replace it with the new volume. */
+void VolumeComponent::replace(Volume *volume, GeometryOwnershipType ownership)
+{
+ BLI_assert(this->is_mutable());
+ this->clear();
+ volume_ = volume;
+ ownership_ = ownership;
+}
+
+/* Return the volume and clear the component. The caller takes over responsibility for freeing the
+ * volume (if the component was responsible before). */
+Volume *VolumeComponent::release()
+{
+ BLI_assert(this->is_mutable());
+ Volume *volume = volume_;
+ volume_ = nullptr;
+ return volume;
+}
+
+/* Get the volume from this component. This method can be used by multiple threads at the same
+ * time. Therefore, the returned volume should not be modified. No ownership is transferred. */
+const Volume *VolumeComponent::get_for_read() const
+{
+ return volume_;
+}
+
+/* Get the volume from this component. This method can only be used when the component is mutable,
+ * i.e. it is not shared. The returned volume can be modified. No ownership is transferred. */
+Volume *VolumeComponent::get_for_write()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ == GeometryOwnershipType::ReadOnly) {
+ volume_ = BKE_volume_copy_for_eval(volume_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+ return volume_;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name C API
* \{ */
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index f68a390db64..0c813c170ad 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -93,7 +93,33 @@ static void greasepencil_copy_data(Main *UNUSED(bmain),
/* make a copy of source layer and its data */
/* TODO here too could add unused flags... */
- bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src);
+ bGPDlayer *gpl_dst = BKE_gpencil_layer_duplicate(gpl_src, true, true);
+
+ /* Apply local layer transform to all frames. Calc the active frame is not enough
+ * because onion skin can use more frames. This is more slow but required here. */
+ if (gpl_dst->actframe != NULL) {
+ bool transfomed = ((!is_zero_v3(gpl_dst->location)) || (!is_zero_v3(gpl_dst->rotation)) ||
+ (!is_one_v3(gpl_dst->scale)));
+ if (transfomed) {
+ loc_eul_size_to_mat4(
+ gpl_dst->layer_mat, gpl_dst->location, gpl_dst->rotation, gpl_dst->scale);
+ bool do_onion = ((gpl_dst->onion_flag & GP_LAYER_ONIONSKIN) != 0);
+ bGPDframe *init_gpf = (do_onion) ? gpl_dst->frames.first : gpl_dst->actframe;
+ for (bGPDframe *gpf = init_gpf; gpf; gpf = gpf->next) {
+ LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) {
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(gpl_dst->layer_mat, &pt->x);
+ }
+ }
+ /* if not onion, exit loop. */
+ if (!do_onion) {
+ break;
+ }
+ }
+ }
+ }
BLI_addtail(&gpd_dst->layers, gpl_dst);
}
@@ -303,6 +329,8 @@ IDTypeInfo IDType_ID_GD = {
.blend_read_expand = greasepencil_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* ************************************************** */
@@ -581,7 +609,7 @@ bGPDframe *BKE_gpencil_frame_addcopy(bGPDlayer *gpl, int cframe)
}
/* Create a copy of the frame */
- new_frame = BKE_gpencil_frame_duplicate(gpl->actframe);
+ new_frame = BKE_gpencil_frame_duplicate(gpl->actframe, true);
/* Find frame to insert it before */
LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) {
@@ -686,6 +714,14 @@ bGPDlayer *BKE_gpencil_layer_addnew(bGPdata *gpd, const char *name, bool setacti
/* Enable always affected by scene lights. */
gpl->flag |= GP_LAYER_USE_LIGHTS;
+
+ /* Init transform. */
+ zero_v3(gpl->location);
+ zero_v3(gpl->rotation);
+ copy_v3_fl(gpl->scale, 1.0f);
+ loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
+ invert_m4_m4(gpl->layer_invmat, gpl->layer_mat);
+
/* make this one the active one */
if (setactive) {
BKE_gpencil_layer_active_set(gpd, gpl);
@@ -957,7 +993,7 @@ bGPDstroke *BKE_gpencil_stroke_duplicate(bGPDstroke *gps_src,
* \param gpf_src: Source grease pencil frame
* \return Pointer to new frame
*/
-bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
+bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src, const bool dup_strokes)
{
bGPDstroke *gps_dst = NULL;
bGPDframe *gpf_dst;
@@ -971,12 +1007,14 @@ bGPDframe *BKE_gpencil_frame_duplicate(const bGPDframe *gpf_src)
gpf_dst = MEM_dupallocN(gpf_src);
gpf_dst->prev = gpf_dst->next = NULL;
- /* copy strokes */
+ /* Copy strokes. */
BLI_listbase_clear(&gpf_dst->strokes);
- LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
- /* make copy of source stroke */
- gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
- BLI_addtail(&gpf_dst->strokes, gps_dst);
+ if (dup_strokes) {
+ LISTBASE_FOREACH (bGPDstroke *, gps_src, &gpf_src->strokes) {
+ /* make copy of source stroke */
+ gps_dst = BKE_gpencil_stroke_duplicate(gps_src, true, true);
+ BLI_addtail(&gpf_dst->strokes, gps_dst);
+ }
}
/* return new frame */
@@ -1010,7 +1048,9 @@ void BKE_gpencil_frame_copy_strokes(bGPDframe *gpf_src, struct bGPDframe *gpf_ds
* \param gpl_src: Source grease pencil layer
* \return Pointer to new layer
*/
-bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
+bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src,
+ const bool dup_frames,
+ const bool dup_strokes)
{
const bGPDframe *gpf_src;
bGPDframe *gpf_dst;
@@ -1035,14 +1075,16 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src)
/* copy frames */
BLI_listbase_clear(&gpl_dst->frames);
- for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
- /* make a copy of source frame */
- gpf_dst = BKE_gpencil_frame_duplicate(gpf_src);
- BLI_addtail(&gpl_dst->frames, gpf_dst);
-
- /* if source frame was the current layer's 'active' frame, reassign that too */
- if (gpf_src == gpl_dst->actframe) {
- gpl_dst->actframe = gpf_dst;
+ if (dup_frames) {
+ for (gpf_src = gpl_src->frames.first; gpf_src; gpf_src = gpf_src->next) {
+ /* make a copy of source frame */
+ gpf_dst = BKE_gpencil_frame_duplicate(gpf_src, dup_strokes);
+ BLI_addtail(&gpl_dst->frames, gpf_dst);
+
+ /* if source frame was the current layer's 'active' frame, reassign that too */
+ if (gpf_src == gpl_dst->actframe) {
+ gpl_dst->actframe = gpf_dst;
+ }
}
}
@@ -2519,7 +2561,7 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
- const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+ const bool is_multiedit = ((GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) && (!GPENCIL_PLAY_ON(gpd)));
const bool is_onion = do_onion && ((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0);
const bool is_drawing = (gpd->runtime.sbuffer_used > 0);
@@ -2541,6 +2583,11 @@ void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
continue;
}
+ /* If scale to 0 the layer must be invisible. */
+ if (is_zero_v3(gpl->scale)) {
+ continue;
+ }
+
/* Hide the layer if it's defined a view layer filter. This is used to
* generate renders, putting only selected GP layers for each View Layer.
* This is used only in final render and never in Viewport. */
@@ -2759,10 +2806,10 @@ void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_ev
* \param gpl: Grease pencil layer
* \param diff_mat: Result parent matrix
*/
-void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
- Object *obact,
- bGPDlayer *gpl,
- float diff_mat[4][4])
+void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
+ Object *obact,
+ bGPDlayer *gpl,
+ float diff_mat[4][4])
{
Object *ob_eval = depsgraph != NULL ? DEG_get_evaluated_object(depsgraph, obact) : obact;
Object *obparent = gpl->parent;
@@ -2771,11 +2818,10 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
/* if not layer parented, try with object parented */
if (obparent_eval == NULL) {
- if (ob_eval != NULL) {
- if (ob_eval->type == OB_GPENCIL) {
- copy_m4_m4(diff_mat, ob_eval->obmat);
- return;
- }
+ if ((ob_eval != NULL) && (ob_eval->type == OB_GPENCIL)) {
+ copy_m4_m4(diff_mat, ob_eval->obmat);
+ mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
+ return;
}
/* not gpencil object */
unit_m4(diff_mat);
@@ -2785,6 +2831,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
+ mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
return;
}
if (gpl->partype == PARBONE) {
@@ -2800,6 +2847,7 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
mul_m4_m4m4(diff_mat, obparent_eval->obmat, gpl->inverse);
add_v3_v3(diff_mat[3], ob_eval->obmat[3]);
}
+ mul_m4_m4m4(diff_mat, diff_mat, gpl->layer_mat);
return;
}
@@ -2807,11 +2855,11 @@ void BKE_gpencil_parent_matrix_get(const Depsgraph *depsgraph,
}
/**
- * Update parent matrix.
+ * Update parent matrix and local transforms.
* \param depsgraph: Depsgraph
* \param ob: Grease pencil object
*/
-void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob)
+void BKE_gpencil_update_layer_transforms(const Depsgraph *depsgraph, Object *ob)
{
if (ob->type != OB_GPENCIL) {
return;
@@ -2820,31 +2868,50 @@ void BKE_gpencil_update_layer_parent(const Depsgraph *depsgraph, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
float cur_mat[4][4];
+ bool changed = false;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) {
- if ((gpl->parent != NULL) && (gpl->actframe != NULL)) {
- Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
- /* calculate new matrix */
- if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
- copy_m4_m4(cur_mat, ob_parent->obmat);
- }
- else if (gpl->partype == PARBONE) {
- bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
- if (pchan != NULL) {
- copy_m4_m4(cur_mat, ob->imat);
- mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat);
+ unit_m4(cur_mat);
+ if (gpl->actframe != NULL) {
+ if (gpl->parent != NULL) {
+ Object *ob_parent = DEG_get_evaluated_object(depsgraph, gpl->parent);
+ /* calculate new matrix */
+ if (ELEM(gpl->partype, PAROBJECT, PARSKEL)) {
+ copy_m4_m4(cur_mat, ob_parent->obmat);
}
- else {
- unit_m4(cur_mat);
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_parent->pose, gpl->parsubstr);
+ if (pchan != NULL) {
+ copy_m4_m4(cur_mat, ob->imat);
+ mul_m4_m4m4(cur_mat, ob_parent->obmat, pchan->pose_mat);
+ }
+ else {
+ unit_m4(cur_mat);
+ }
}
+ changed = !equals_m4m4(gpl->inverse, cur_mat);
+ }
+
+ /* Calc local layer transform. */
+ bool transfomed = ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) ||
+ (!is_one_v3(gpl->scale)));
+ if (transfomed) {
+ loc_eul_size_to_mat4(gpl->layer_mat, gpl->location, gpl->rotation, gpl->scale);
}
+
/* only redo if any change */
- if (!equals_m4m4(gpl->inverse, cur_mat)) {
+ if (changed || transfomed) {
LISTBASE_FOREACH (bGPDstroke *, gps, &gpl->actframe->strokes) {
bGPDspoint *pt;
int i;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- mul_m4_v3(gpl->inverse, &pt->x);
- mul_m4_v3(cur_mat, &pt->x);
+ if (changed) {
+ mul_m4_v3(gpl->inverse, &pt->x);
+ mul_m4_v3(cur_mat, &pt->x);
+ }
+
+ if (transfomed) {
+ mul_m4_v3(gpl->layer_mat, &pt->x);
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 1be2cba31b5..8b12e1b5fca 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -701,13 +701,18 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
Object *ob_orig = (Object *)DEG_get_original_id(&ob->id);
bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
- /* Need check if some layer is parented. */
+ /* Need check if some layer is parented or transformed. */
bool do_parent = false;
+ bool do_transform = false;
LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
if (gpl->parent != NULL) {
do_parent = true;
break;
}
+ if ((!is_zero_v3(gpl->location)) || (!is_zero_v3(gpl->rotation)) || (!is_one_v3(gpl->scale))) {
+ do_transform = true;
+ break;
+ }
}
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_eval);
@@ -715,7 +720,7 @@ void BKE_gpencil_prepare_eval_data(Depsgraph *depsgraph, Scene *scene, Object *o
const bool do_modifiers = (bool)((!is_multiedit) && (!is_curve_edit) &&
(ob->greasepencil_modifiers.first != NULL) &&
(!GPENCIL_SIMPLIFY_MODIF(scene)));
- if ((!do_modifiers) && (!do_parent)) {
+ if ((!do_modifiers) && (!do_parent) && (!do_transform)) {
return;
}
DEG_debug_print_eval(depsgraph, __func__, gpd_eval->id.name, gpd_eval);
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index a44b054e366..f76e5a73478 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -197,6 +197,8 @@ IDTypeInfo IDType_ID_HA = {
.blend_read_expand = hair_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
static void hair_random(Hair *hair)
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index b0991f1d343..6b164e6bc50 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -92,11 +92,9 @@ IDProperty *IDP_NewIDPArray(const char *name)
IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag)
{
/* don't use MEM_dupallocN because this may be part of an array */
- IDProperty *narray, *tmp;
-
BLI_assert(array->type == IDP_IDPARRAY);
- narray = MEM_mallocN(sizeof(IDProperty), __func__);
+ IDProperty *narray = MEM_mallocN(sizeof(IDProperty), __func__);
*narray = *array;
narray->data.pointer = MEM_dupallocN(array->data.pointer);
@@ -107,7 +105,7 @@ IDProperty *IDP_CopyIDPArray(const IDProperty *array, const int flag)
* then free it. this makes for more maintainable
* code than simply re-implementing the copy functions
* in this loop.*/
- tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag);
+ IDProperty *tmp = IDP_CopyProperty_ex(GETPROP(narray, i), flag);
memcpy(GETPROP(narray, i), tmp, sizeof(IDProperty));
MEM_freeN(tmp);
}
@@ -131,15 +129,13 @@ static void IDP_FreeIDPArray(IDProperty *prop, const bool do_id_user)
/* shallow copies item */
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
- IDProperty *old;
-
BLI_assert(prop->type == IDP_IDPARRAY);
if (index >= prop->len || index < 0) {
return;
}
- old = GETPROP(prop, index);
+ IDProperty *old = GETPROP(prop, index);
if (item != old) {
IDP_FreePropertyContent(old);
@@ -164,8 +160,6 @@ void IDP_AppendArray(IDProperty *prop, IDProperty *item)
void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
{
- int newsize;
-
BLI_assert(prop->type == IDP_IDPARRAY);
/* first check if the array buffer size has room */
@@ -200,7 +194,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen)
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
- newsize = newlen;
+ int newsize = newlen;
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize);
prop->len = newlen;
@@ -218,9 +212,8 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
/* bigger */
IDProperty **array = newarr;
IDPropertyTemplate val;
- int a;
- for (a = prop->len; a < newlen; a++) {
+ for (int a = prop->len; a < newlen; a++) {
val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
array[a] = IDP_New(IDP_GROUP, &val, "IDP_ResizeArray group");
}
@@ -228,9 +221,8 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
else {
/* smaller */
IDProperty **array = prop->data.pointer;
- int a;
- for (a = newlen; a < prop->len; a++) {
+ for (int a = newlen; a < prop->len; a++) {
IDP_FreeProperty(array[a]);
}
}
@@ -239,7 +231,6 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr)
/*this function works for strings too!*/
void IDP_ResizeArray(IDProperty *prop, int newlen)
{
- int newsize;
const bool is_grow = newlen >= prop->len;
/* first check if the array buffer size has room */
@@ -257,7 +248,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen)
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
*/
- newsize = newlen;
+ int newsize = newlen;
newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
if (is_grow == false) {
@@ -362,10 +353,8 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen)
static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag)
{
- IDProperty *newp;
-
BLI_assert(prop->type == IDP_STRING);
- newp = idp_generic_copy(prop, flag);
+ IDProperty *newp = idp_generic_copy(prop, flag);
if (prop->data.pointer) {
newp->data.pointer = MEM_dupallocN(prop->data.pointer);
@@ -379,10 +368,8 @@ static IDProperty *IDP_CopyString(const IDProperty *prop, const int flag)
void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
{
- int stlen;
-
BLI_assert(prop->type == IDP_STRING);
- stlen = (int)strlen(st);
+ int stlen = (int)strlen(st);
if (maxlen > 0 && maxlen < stlen) {
stlen = maxlen;
}
@@ -400,11 +387,9 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen)
void IDP_ConcatStringC(IDProperty *prop, const char *st)
{
- int newlen;
-
BLI_assert(prop->type == IDP_STRING);
- newlen = prop->len + (int)strlen(st);
+ int newlen = prop->len + (int)strlen(st);
/* we have to remember that prop->len includes the null byte for strings.
* so there's no need to add +1 to the resize function.*/
IDP_ResizeArray(prop, newlen);
@@ -413,13 +398,11 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st)
void IDP_ConcatString(IDProperty *str1, IDProperty *append)
{
- int newlen;
-
BLI_assert(append->type == IDP_STRING);
/* since ->len for strings includes the NULL byte, we have to subtract one or
* we'll get an extra null byte after each concatenation operation.*/
- newlen = str1->len + append->len - 1;
+ int newlen = str1->len + append->len - 1;
IDP_ResizeArray(str1, newlen);
strcat(str1->data.pointer, append->data.pointer);
}
@@ -440,10 +423,8 @@ void IDP_FreeString(IDProperty *prop)
static IDProperty *IDP_CopyID(const IDProperty *prop, const int flag)
{
- IDProperty *newp;
-
BLI_assert(prop->type == IDP_ID);
- newp = idp_generic_copy(prop, flag);
+ IDProperty *newp = idp_generic_copy(prop, flag);
newp->data.pointer = prop->data.pointer;
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
@@ -479,14 +460,12 @@ void IDP_AssignID(IDProperty *prop, ID *id, const int flag)
*/
static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
{
- IDProperty *newp, *link;
-
BLI_assert(prop->type == IDP_GROUP);
- newp = idp_generic_copy(prop, flag);
+ IDProperty *newp = idp_generic_copy(prop, flag);
newp->len = prop->len;
newp->subtype = prop->subtype;
- for (link = prop->data.group.first; link; link = link->next) {
+ LISTBASE_FOREACH (IDProperty *, link, &prop->data.group) {
BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag));
}
@@ -497,13 +476,11 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag)
* When values name and types match, copy the values, else ignore */
void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
{
- IDProperty *other, *prop;
-
BLI_assert(dest->type == IDP_GROUP);
BLI_assert(src->type == IDP_GROUP);
- for (prop = src->data.group.first; prop; prop = prop->next) {
- other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name));
+ LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
+ IDProperty *other = BLI_findstring(&dest->data.group, prop->name, offsetof(IDProperty, name));
if (other && prop->type == other->type) {
switch (prop->type) {
case IDP_INT:
@@ -526,12 +503,9 @@ void IDP_SyncGroupValues(IDProperty *dest, const IDProperty *src)
void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_arraylen)
{
- IDProperty *prop_dst, *prop_dst_next;
- const IDProperty *prop_src;
-
- for (prop_dst = dest->data.group.first; prop_dst; prop_dst = prop_dst_next) {
- prop_dst_next = prop_dst->next;
- if ((prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name))) {
+ LISTBASE_FOREACH_MUTABLE (IDProperty *, prop_dst, &src->data.group) {
+ const IDProperty *prop_src = IDP_GetPropertyFromGroup((IDProperty *)src, prop_dst->name);
+ if (prop_src != NULL) {
/* check of we should replace? */
if ((prop_dst->type != prop_src->type || prop_dst->subtype != prop_src->subtype) ||
(do_arraylen && ELEM(prop_dst->type, IDP_ARRAY, IDP_IDPARRAY) &&
@@ -554,12 +528,11 @@ void IDP_SyncGroupTypes(IDProperty *dest, const IDProperty *src, const bool do_a
*/
void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src)
{
- IDProperty *loop, *prop;
-
BLI_assert(dest->type == IDP_GROUP);
BLI_assert(src->type == IDP_GROUP);
- for (prop = src->data.group.first; prop; prop = prop->next) {
+ LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
+ IDProperty *loop;
for (loop = dest->data.group.first; loop; loop = loop->next) {
if (STREQ(loop->name, prop->name)) {
BLI_insertlinkreplace(&dest->data.group, loop, IDP_CopyProperty(prop));
@@ -612,13 +585,11 @@ void IDP_MergeGroup_ex(IDProperty *dest,
const bool do_overwrite,
const int flag)
{
- IDProperty *prop;
-
BLI_assert(dest->type == IDP_GROUP);
BLI_assert(src->type == IDP_GROUP);
if (do_overwrite) {
- for (prop = src->data.group.first; prop; prop = prop->next) {
+ LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
if (prop->type == IDP_GROUP) {
IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
@@ -633,7 +604,7 @@ void IDP_MergeGroup_ex(IDProperty *dest,
}
}
else {
- for (prop = src->data.group.first; prop; prop = prop->next) {
+ LISTBASE_FOREACH (IDProperty *, prop, &src->data.group) {
IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name);
if (prop_exist != NULL) {
if (prop->type == IDP_GROUP) {
@@ -741,10 +712,9 @@ IDProperty *IDP_GetPropertyTypeFromGroup(const IDProperty *prop, const char *nam
* direct data. */
static void IDP_FreeGroup(IDProperty *prop, const bool do_id_user)
{
- IDProperty *loop;
-
BLI_assert(prop->type == IDP_GROUP);
- for (loop = prop->data.group.first; loop; loop = loop->next) {
+
+ LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
IDP_FreePropertyContent_ex(loop, do_id_user);
}
BLI_freelistN(&prop->data.group);
@@ -863,14 +833,12 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
}
return false;
case IDP_GROUP: {
- IDProperty *link1, *link2;
-
if (is_strict && prop1->len != prop2->len) {
return false;
}
- for (link1 = prop1->data.group.first; link1; link1 = link1->next) {
- link2 = IDP_GetPropertyFromGroup(prop2, link1->name);
+ LISTBASE_FOREACH (IDProperty *, link1, &prop1->data.group) {
+ IDProperty *link2 = IDP_GetPropertyFromGroup(prop2, link1->name);
if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) {
return false;
@@ -1158,11 +1126,10 @@ static void IDP_WriteIDPArray(const IDProperty *prop, BlendWriter *writer)
/*REMEMBER to set totalen to len in the linking code!!*/
if (prop->data.pointer) {
const IDProperty *array = prop->data.pointer;
- int a;
BLO_write_struct_array(writer, IDProperty, prop->len, array);
- for (a = 0; a < prop->len; a++) {
+ for (int a = 0; a < prop->len; a++) {
IDP_WriteProperty_OnlyData(&array[a], writer);
}
}
@@ -1176,9 +1143,7 @@ static void IDP_WriteString(const IDProperty *prop, BlendWriter *writer)
static void IDP_WriteGroup(const IDProperty *prop, BlendWriter *writer)
{
- IDProperty *loop;
-
- for (loop = prop->data.group.first; loop; loop = loop->next) {
+ LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
IDP_BlendWrite(writer, loop);
}
}
@@ -1212,13 +1177,11 @@ static void IDP_DirectLinkProperty(IDProperty *prop, BlendDataReader *reader);
static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader)
{
- IDProperty *array;
-
/* since we didn't save the extra buffer, set totallen to len */
prop->totallen = prop->len;
BLO_read_data_address(reader, &prop->data.pointer);
- array = (IDProperty *)prop->data.pointer;
+ IDProperty *array = (IDProperty *)prop->data.pointer;
/* note!, idp-arrays didn't exist in 2.4x, so the pointer will be cleared
* there's not really anything we can do to correct this, at least don't crash */
@@ -1234,14 +1197,12 @@ static void IDP_DirectLinkIDPArray(IDProperty *prop, BlendDataReader *reader)
static void IDP_DirectLinkArray(IDProperty *prop, BlendDataReader *reader)
{
- IDProperty **array;
-
/* since we didn't save the extra buffer, set totallen to len */
prop->totallen = prop->len;
if (prop->subtype == IDP_GROUP) {
BLO_read_pointer_array(reader, &prop->data.pointer);
- array = prop->data.pointer;
+ IDProperty **array = prop->data.pointer;
for (int i = 0; i < prop->len; i++) {
IDP_DirectLinkProperty(array[i], reader);
@@ -1266,12 +1227,11 @@ static void IDP_DirectLinkString(IDProperty *prop, BlendDataReader *reader)
static void IDP_DirectLinkGroup(IDProperty *prop, BlendDataReader *reader)
{
ListBase *lb = &prop->data.group;
- IDProperty *loop;
BLO_read_list(reader, lb);
/*Link child id properties now*/
- for (loop = prop->data.group.first; loop; loop = loop->next) {
+ LISTBASE_FOREACH (IDProperty *, loop, &prop->data.group) {
IDP_DirectLinkProperty(loop, reader);
}
}
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index ab57d14d2cf..10f15519ea4 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -338,6 +338,8 @@ IDTypeInfo IDType_ID_IM = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* prototypes */
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 1ab6e61e20e..d43a0cb3813 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -200,6 +200,8 @@ IDTypeInfo IDType_ID_IP = {
.blend_read_expand = ipo_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* *************************************************** */
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 433d64a5927..540337b84b3 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -223,6 +223,8 @@ IDTypeInfo IDType_ID_KE = {
.blend_read_expand = shapekey_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 74f78106be5..3d3ade1a529 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -205,6 +205,8 @@ IDTypeInfo IDType_ID_LT = {
.blend_read_expand = lattice_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w)
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 13f76b46570..54c2f5f5565 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -112,6 +112,8 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* GS reads the memory pointed at in a specific ordering.
@@ -1793,32 +1795,31 @@ static void library_make_local_copying_check(ID *id,
return; /* Already checked, nothing else to do. */
}
- MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->id_used_to_user, id);
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(id_relations->relations_from_pointers, id);
BLI_gset_insert(loop_tags, id);
- for (; entry != NULL; entry = entry->next) {
-
- /* Used_to_user stores ID pointer, not pointer to ID pointer. */
- ID *par_id = (ID *)entry->id_pointer;
-
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
/* Our oh-so-beloved 'from' pointers... Those should always be ignored here, since the actual
* relation we want to check is in the other way around. */
- if (entry->usage_flag & IDWALK_CB_LOOPBACK) {
+ if (from_id_entry->usage_flag & IDWALK_CB_LOOPBACK) {
continue;
}
+ ID *from_id = from_id_entry->id_pointer.from;
+
/* Shape-keys are considered 'private' to their owner ID here, and never tagged
* (since they cannot be linked), so we have to switch effective parent to their owner.
*/
- if (GS(par_id->name) == ID_KE) {
- par_id = ((Key *)par_id)->from;
+ if (GS(from_id->name) == ID_KE) {
+ from_id = ((Key *)from_id)->from;
}
- if (par_id->lib == NULL) {
+ if (from_id->lib == NULL) {
/* Local user, early out to avoid some gset querying... */
continue;
}
- if (!BLI_gset_haskey(done_ids, par_id)) {
- if (BLI_gset_haskey(loop_tags, par_id)) {
+ if (!BLI_gset_haskey(done_ids, from_id)) {
+ if (BLI_gset_haskey(loop_tags, from_id)) {
/* We are in a 'dependency loop' of IDs, this does not say us anything, skip it.
* Note that this is the situation that can lead to archipelagoes of linked data-blocks
* (since all of them have non-local users, they would all be duplicated,
@@ -1827,10 +1828,10 @@ static void library_make_local_copying_check(ID *id,
continue;
}
/* Else, recursively check that user ID. */
- library_make_local_copying_check(par_id, loop_tags, id_relations, done_ids);
+ library_make_local_copying_check(from_id, loop_tags, id_relations, done_ids);
}
- if (par_id->tag & LIB_TAG_DOIT) {
+ if (from_id->tag & LIB_TAG_DOIT) {
/* This user will be fully local in future, so far so good,
* nothing to do here but check next user. */
}
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index e4094c48368..9e8e515e1a3 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -368,118 +368,154 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain)
return success;
}
-static bool lib_override_hierarchy_recursive_tag(Main *bmain,
- ID *id,
- const uint tag,
- const uint missing_tag,
- Library *override_group_lib_reference)
+/* Tag all IDs in dependency relationships within an override hierarchy/group.
+ *
+ * Note: this is typically called to complete `lib_override_linked_group_tag()`.
+ * Note: BMain's relations mapping won't be valid anymore after that call.
+ */
+static bool lib_override_hierarchy_dependencies_recursive_tag(Main *bmain,
+ ID *id,
+ const uint tag,
+ const uint missing_tag)
{
- void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id);
- if (entry_vp == NULL) {
- /* Already processed. */
- return (id->tag & tag) != 0;
- }
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+ BLI_assert(entry != NULL);
- /* Note: in case some reference ID is missing from linked data (and therefore its override uses
- * a placeholder as reference), use `missing_tag` instead of `tag` for this override. */
- if (override_group_lib_reference != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
- id->override_library->reference->lib == override_group_lib_reference) {
- if (id->override_library->reference->tag & LIB_TAG_MISSING) {
- id->tag |= missing_tag;
- }
- else {
- id->tag |= tag;
- }
+ if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+ /* This ID has already been processed. */
+ return (*(uint *)&id->tag & tag) != 0;
}
-
/* This way we won't process again that ID, should we encounter it again through another
- * relationship hierarchy.
- * Note that this does not free any memory from relations, so we can still use the entries.
- */
- BKE_main_relations_ID_remove(bmain, id);
+ * relationship hierarchy. */
+ entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
- for (MainIDRelationsEntry *entry = *entry_vp; entry != NULL; entry = entry->next) {
- if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
* actual dependencies. */
continue;
}
/* We only consider IDs from the same library. */
- if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) {
- if (lib_override_hierarchy_recursive_tag(
- bmain, *entry->id_pointer, tag, missing_tag, override_group_lib_reference) &&
- override_group_lib_reference == NULL) {
+ ID *to_id = *to_id_entry->id_pointer.to;
+ if (to_id != NULL && to_id->lib == id->lib) {
+ if (lib_override_hierarchy_dependencies_recursive_tag(bmain, to_id, tag, missing_tag)) {
id->tag |= tag;
}
}
}
- return (id->tag & tag) != 0;
+ return (*(uint *)&id->tag & tag) != 0;
}
-/**
- * Tag all IDs in given \a bmain that are being used by given \a id_root ID or its dependencies,
- * recursively.
- * It detects and tag only chains of dependencies marked at both ends by given tag.
- *
- * This will include all local IDs, and all IDs from the same library as the \a id_root.
- *
- * \param id_root: The root of the hierarchy of dependencies to be tagged.
- * \param do_create_main_relashionships: Whether main relations needs to be created or already
- * exist (in any case, they will be freed by this function).
- */
-void BKE_lib_override_library_dependencies_tag(Main *bmain,
- ID *id_root,
- const uint tag,
- const bool do_create_main_relashionships)
+typedef struct LibOverrideGroupTagData {
+ ID *id_root;
+ uint tag;
+ uint missing_tag;
+} LibOverrideGroupTagData;
+
+static int lib_override_linked_group_tag_cb(LibraryIDLinkCallbackData *cb_data)
{
- if (do_create_main_relashionships) {
- BKE_main_relations_create(bmain, 0);
+ if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) {
+ return IDWALK_RET_STOP_RECURSION;
}
- /* We tag all intermediary data-blocks in-between two overridden ones (e.g. if a shape-key
- * has a driver using an armature object's bone, we need to override the shape-key/obdata,
- * the objects using them, etc.) */
- lib_override_hierarchy_recursive_tag(bmain, id_root, tag, 0, NULL);
+ LibOverrideGroupTagData *data = cb_data->user_data;
+ const uint tag = data->tag;
+ const uint missing_tag = data->missing_tag;
- BKE_main_relations_free(bmain);
+ ID *id_root = data->id_root;
+ Library *library_root = id_root->lib;
+ ID *id = *cb_data->id_pointer;
+ ID *id_owner = cb_data->id_owner;
+
+ BLI_assert(id_owner == cb_data->id_self);
+
+ if (ELEM(id, NULL, id_owner)) {
+ return IDWALK_RET_NOP;
+ }
+
+ BLI_assert(id_owner->lib == library_root);
+
+ if (*(uint *)&id->tag & (tag | missing_tag)) {
+ /* Already processed and tagged, nothing else to do here. */
+ return IDWALK_RET_STOP_RECURSION;
+ }
+
+ if (id->lib != library_root) {
+ /* We do not override data-blocks from other libraries, nor do we process them. */
+ return IDWALK_RET_STOP_RECURSION;
+ }
+
+ /* We tag all collections and objects for override. And we also tag all other data-blocks which
+ * would use one of those.
+ * Note: missing IDs (aka placeholders) are never overridden. */
+ if (ELEM(GS(id->name), ID_OB, ID_GR)) {
+ if ((id->tag & LIB_TAG_MISSING)) {
+ id->tag |= missing_tag;
+ }
+ else {
+ id->tag |= tag;
+ }
+ }
+
+ return IDWALK_RET_NOP;
}
-/**
- * Tag all IDs in given \a bmain that are part of the same \a id_root liboverride ID group.
- * That is, all other liboverride IDs (in)directly used by \a is_root one, and sharing the same
- * library for their reference IDs.
+/* This will tag at least all 'boundary' linked IDs for a potential override group.
*
- * \param id_root: The root of the hierarchy of liboverride dependencies to be tagged.
- * \param do_create_main_relashionships: Whether main relations needs to be created or already
- * exist (in any case, they will be freed by this function).
+ * Note that you will then need to call #lib_override_hierarchy_dependencies_recursive_tag to
+ * complete tagging of all dependencies within the override group.
+ *
+ * We currently only consider Collections and Objects (that are not used as bone shapes) as valid
+ * boundary IDs to define an override group.
*/
-void BKE_lib_override_library_override_group_tag(Main *bmain,
- ID *id_root,
- const uint tag,
- const uint missing_tag,
- const bool do_create_main_relashionships)
+static void lib_override_linked_group_tag(
+ Main *bmain, ID *id, const uint tag, const uint missing_tag, const bool create_bmain_relations)
{
- if (do_create_main_relashionships) {
+ if (create_bmain_relations) {
BKE_main_relations_create(bmain, 0);
}
- /* We tag all liboverride data-blocks from the same library as reference one,
- * being used by the root ID. */
- lib_override_hierarchy_recursive_tag(
- bmain, id_root, tag, missing_tag, id_root->override_library->reference->lib);
+ if (ELEM(GS(id->name), ID_OB, ID_GR)) {
+ LibOverrideGroupTagData data = {.id_root = id, .tag = tag, .missing_tag = missing_tag};
+ /* Tag all collections and objects. */
+ BKE_library_foreach_ID_link(
+ bmain, id, lib_override_linked_group_tag_cb, &data, IDWALK_READONLY | IDWALK_RECURSE);
- BKE_main_relations_free(bmain);
+ /* Then, we remove (untag) bone shape objects, you shall never want to directly/explicitly
+ * override those. */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & tag)) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ if (pchan->custom != NULL) {
+ pchan->custom->id.tag &= ~(tag | missing_tag);
+ }
+ }
+ }
+ }
+ }
+
+ lib_override_hierarchy_dependencies_recursive_tag(bmain, id, tag, missing_tag);
+
+ if (create_bmain_relations) {
+ BKE_main_relations_free(bmain);
+ }
}
-static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_data)
+static int lib_override_local_group_tag_cb(LibraryIDLinkCallbackData *cb_data)
{
- if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK)) {
+ if (cb_data->cb_flag &
+ (IDWALK_CB_EMBEDDED | IDWALK_CB_LOOPBACK | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE)) {
return IDWALK_RET_STOP_RECURSION;
}
- ID *id_root = cb_data->user_data;
- Library *library_root = id_root->lib;
+ LibOverrideGroupTagData *data = cb_data->user_data;
+ const uint tag = data->tag;
+ const uint missing_tag = data->missing_tag;
+
+ ID *id_root = data->id_root;
+ Library *library_reference_root = id_root->override_library->reference->lib;
ID *id = *cb_data->id_pointer;
ID *id_owner = cb_data->id_owner;
@@ -489,62 +525,69 @@ static int lib_override_library_make_tag_ids_cb(LibraryIDLinkCallbackData *cb_da
return IDWALK_RET_NOP;
}
- BLI_assert(id->lib != NULL);
- BLI_assert(id_owner->lib == library_root);
-
- if (id->tag & LIB_TAG_DOIT) {
+ if (*(uint *)&id->tag & (tag | missing_tag)) {
/* Already processed and tagged, nothing else to do here. */
return IDWALK_RET_STOP_RECURSION;
}
- if (id->lib != library_root) {
+ if (!ID_IS_OVERRIDE_LIBRARY(id) || ID_IS_LINKED(id)) {
+ /* Fully local, or linked ID, those are never part of a local override group. */
+ return IDWALK_RET_STOP_RECURSION;
+ }
+
+ /* NOTE: Since we rejected embedded data too at the beginning of this function, id should only be
+ * a real override now.
+ *
+ * However, our usual trouble maker, Key, is not considered as an embedded ID currently, yet it
+ * is never a real override either. Enjoy. */
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ return IDWALK_RET_NOP;
+ }
+
+ if (id->override_library->reference->lib != library_reference_root) {
/* We do not override data-blocks from other libraries, nor do we process them. */
return IDWALK_RET_STOP_RECURSION;
}
- /* We tag all collections and objects for override. And we also tag all other data-blocks which
- * would use one of those.
- * Note: missing IDs (aka placeholders) are never overridden. */
- if (ELEM(GS(id->name), ID_OB, ID_GR) && !(id->tag & LIB_TAG_MISSING)) {
- id->tag |= LIB_TAG_DOIT;
+ if (id->override_library->reference->tag & LIB_TAG_MISSING) {
+ id->tag |= missing_tag;
+ }
+ else {
+ id->tag |= tag;
}
return IDWALK_RET_NOP;
}
+/* This will tag at least all 'boundary' linked IDs for a potential override group.
+ *
+ * Note that you will then need to call #lib_override_hierarchy_dependencies_recursive_tag to
+ * complete tagging of all dependencies within the override group.
+ *
+ * We currently only consider Collections and Objects (that are not used as bone shapes) as valid
+ * boundary IDs to define an override group.
+ */
+static void lib_override_local_group_tag(Main *bmain,
+ ID *id,
+ const uint tag,
+ const uint missing_tag)
+{
+ LibOverrideGroupTagData data = {.id_root = id, .tag = tag, .missing_tag = missing_tag};
+ /* Tag all local overrides in id_root's group. */
+ BKE_library_foreach_ID_link(
+ bmain, id, lib_override_local_group_tag_cb, &data, IDWALK_READONLY | IDWALK_RECURSE);
+}
+
static bool lib_override_library_create_do(Main *bmain, ID *id_root)
{
id_root->tag |= LIB_TAG_DOIT;
BKE_main_relations_create(bmain, 0);
- if (ELEM(GS(id_root->name), ID_OB, ID_GR)) {
- /* Tag all collections and objects. */
- BKE_library_foreach_ID_link(bmain,
- id_root,
- lib_override_library_make_tag_ids_cb,
- id_root,
- IDWALK_READONLY | IDWALK_RECURSE);
-
- /* Then, we remove (untag) bone shape objects, you shall never want to override those
- * (hopefully). */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- if (ob->type == OB_ARMATURE && ob->pose != NULL && (ob->id.tag & LIB_TAG_DOIT)) {
- for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
- if (pchan->custom != NULL) {
- pchan->custom->id.tag &= ~LIB_TAG_DOIT;
- }
- }
- }
- }
- }
+ lib_override_linked_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING, false);
+ lib_override_hierarchy_dependencies_recursive_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING);
- /* Now tag all non-object/collection IDs 'in-between' two tagged ones, as those are part of an
- * override chain and therefore also need to be overridden.
- * One very common cases are e.g. drivers on geometry or materials of an overridden object, that
- * are using another overridden object as parameter. */
- /* Note that this call will also free the main relations data we created above. */
- BKE_lib_override_library_dependencies_tag(bmain, id_root, LIB_TAG_DOIT, false);
+ BKE_main_relations_free(bmain);
return BKE_lib_override_library_create_from_tag(bmain);
}
@@ -737,14 +780,14 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_
{
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
- /* Tag all collections and objects, as well as other IDs using them. */
id_root->tag |= LIB_TAG_DOIT;
ID *id_root_reference = id_root->override_library->reference;
- /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides, and tag
- * linked reference ones to be overridden again. */
- BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING, true);
+ lib_override_local_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_MISSING);
+
+ lib_override_linked_group_tag(bmain, id_root_reference, LIB_TAG_DOIT, LIB_TAG_MISSING, true);
+ /* Make a mapping 'linked reference IDs' -> 'Local override IDs' of existing overrides. */
GHash *linkedref_to_old_override = BLI_ghash_new(
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
ID *id;
@@ -755,7 +798,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_
* same linked ID in a same hierarchy. */
if (!BLI_ghash_haskey(linkedref_to_old_override, id->override_library->reference)) {
BLI_ghash_insert(linkedref_to_old_override, id->override_library->reference, id);
- id->override_library->reference->tag |= LIB_TAG_DOIT;
+ BLI_assert(id->override_library->reference->tag & LIB_TAG_DOIT);
}
}
}
@@ -765,7 +808,7 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_
/* Note that this call also remaps all pointers of tagged IDs from old override IDs to new
* override IDs (including within the old overrides themselves, since those are tagged too
* above). */
- const bool success = lib_override_library_create_do(bmain, id_root_reference);
+ const bool success = BKE_lib_override_library_create_from_tag(bmain);
if (!success) {
return success;
@@ -828,6 +871,23 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_
RNA_id_pointer_create(id_override_old, &rnaptr_src);
RNA_id_pointer_create(id_override_new, &rnaptr_dst);
+ /* We remove any operation tagged with `IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE`,
+ * that way the potentially new pointer will be properly kept, when old one is still valid
+ * too (typical case: assigning new ID to some usage, while old one remains used elsewhere
+ * in the override hierarchy). */
+ LISTBASE_FOREACH_MUTABLE (
+ IDOverrideLibraryProperty *, op, &id_override_new->override_library->properties) {
+ LISTBASE_FOREACH_MUTABLE (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
+ if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) {
+ lib_override_library_property_operation_clear(opop);
+ BLI_freelinkN(&op->operations, opop);
+ }
+ }
+ if (BLI_listbase_is_empty(&op->operations)) {
+ BKE_lib_override_library_property_delete(id_override_new->override_library, op);
+ }
+ }
+
RNA_struct_override_apply(
bmain, &rnaptr_dst, &rnaptr_src, NULL, id_override_new->override_library);
}
@@ -900,7 +960,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
id_root->tag |= LIB_TAG_DOIT;
/* Tag all library overrides in the chains of dependencies from the given root one. */
- BKE_lib_override_library_override_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_DOIT, true);
+ lib_override_local_group_tag(bmain, id_root, LIB_TAG_DOIT, LIB_TAG_DOIT);
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
@@ -1619,31 +1679,37 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
return;
}
- void **entry_pp = BLI_ghash_lookup(bmain->relations->id_user_to_used, id_root);
- if (entry_pp == NULL) {
- /* Already processed. */
+ void **entry_vp = BLI_ghash_lookup_p(bmain->relations->relations_from_pointers, id_root);
+ if (entry_vp == NULL) {
+ /* This ID is not used by nor using any other ID. */
+ lib_override_library_id_reset_do(bmain, id_root);
+ return;
+ }
+
+ MainIDRelationsEntry *entry = *entry_vp;
+ if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) {
+ /* This ID has already been processed. */
return;
}
lib_override_library_id_reset_do(bmain, id_root);
/* This way we won't process again that ID, should we encounter it again through another
- * relationship hierarchy.
- * Note that this does not free any memory from relations, so we can still use the entries.
- */
- BKE_main_relations_ID_remove(bmain, id_root);
+ * relationship hierarchy. */
+ entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED;
- for (MainIDRelationsEntry *entry = *entry_pp; entry != NULL; entry = entry->next) {
- if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
* actual dependencies. */
continue;
}
/* We only consider IDs from the same library. */
- if (entry->id_pointer != NULL) {
- ID *id_entry = *entry->id_pointer;
- if (id_entry->override_library != NULL) {
- lib_override_library_id_hierarchy_recursive_reset(bmain, id_entry);
+ if (*to_id_entry->id_pointer.to != NULL) {
+ ID *to_id = *to_id_entry->id_pointer.to;
+ if (to_id->override_library != NULL) {
+ lib_override_library_id_hierarchy_recursive_reset(bmain, to_id);
}
}
}
@@ -1922,7 +1988,9 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
ID *local)
{
if (ID_IS_OVERRIDE_LIBRARY_TEMPLATE(local) || ID_IS_OVERRIDE_LIBRARY_VIRTUAL(local)) {
- /* This is actually purely local data with an override template, nothing to do here! */
+ /* This is actually purely local data with an override template, or one of those embedded IDs
+ * (root node trees, master collections or shapekeys) that cannot have their own override.
+ * Nothing to do here! */
return NULL;
}
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index e687e94073d..8be26fc8547 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -237,9 +237,12 @@ static void library_foreach_ID_link(Main *bmain,
* but we might as well use it (Main->relations is always assumed valid,
* it's responsibility of code creating it to free it,
* especially if/when it starts modifying Main database). */
- MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
- for (; entry != NULL; entry = entry->next) {
- BKE_lib_query_foreachid_process(&data, entry->id_pointer, entry->usage_flag);
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers,
+ id);
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ BKE_lib_query_foreachid_process(
+ &data, to_id_entry->id_pointer.to, to_id_entry->usage_flag);
}
continue;
}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 6a560d51362..d2f1196d804 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -84,6 +84,8 @@ IDTypeInfo IDType_ID_LI = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index a47a0c043ff..4a2afb7f5e6 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -209,6 +209,8 @@ IDTypeInfo IDType_ID_LA = {
.blend_read_expand = light_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
Light *BKE_light_add(Main *bmain, const char *name)
diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c
index 0553c070fdf..4ef3b8c3237 100644
--- a/source/blender/blenkernel/intern/lightprobe.c
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -107,6 +107,8 @@ IDTypeInfo IDType_ID_LP = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type)
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 8542959d4b0..283e2a94732 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -767,6 +767,8 @@ IDTypeInfo IDType_ID_LS = {
.blend_read_expand = linestyle_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
static const char *modifier_name[LS_MODIFIER_NUM] = {
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index 4b577ccec2c..d5cbcb62af2 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -211,35 +211,51 @@ void BKE_main_unlock(struct Main *bmain)
static int main_relations_create_idlink_cb(LibraryIDLinkCallbackData *cb_data)
{
- MainIDRelations *rel = cb_data->user_data;
+ MainIDRelations *bmain_relations = cb_data->user_data;
ID *id_self = cb_data->id_self;
ID **id_pointer = cb_data->id_pointer;
const int cb_flag = cb_data->cb_flag;
if (*id_pointer) {
- MainIDRelationsEntry *entry, **entry_p;
-
- entry = BLI_mempool_alloc(rel->entry_pool);
- if (BLI_ghash_ensure_p(rel->id_user_to_used, id_self, (void ***)&entry_p)) {
- entry->next = *entry_p;
- }
- else {
- entry->next = NULL;
+ MainIDRelationsEntry **entry_p;
+
+ /* Add `id_pointer` as child of `id_self`. */
+ {
+ if (!BLI_ghash_ensure_p(
+ bmain_relations->relations_from_pointers, id_self, (void ***)&entry_p)) {
+ *entry_p = MEM_callocN(sizeof(**entry_p), __func__);
+ (*entry_p)->session_uuid = id_self->session_uuid;
+ }
+ else {
+ BLI_assert((*entry_p)->session_uuid == id_self->session_uuid);
+ }
+ MainIDRelationsEntryItem *to_id_entry = BLI_mempool_alloc(bmain_relations->entry_items_pool);
+ to_id_entry->next = (*entry_p)->to_ids;
+ to_id_entry->id_pointer.to = id_pointer;
+ to_id_entry->session_uuid = (*id_pointer != NULL) ? (*id_pointer)->session_uuid :
+ MAIN_ID_SESSION_UUID_UNSET;
+ to_id_entry->usage_flag = cb_flag;
+ (*entry_p)->to_ids = to_id_entry;
}
- entry->id_pointer = id_pointer;
- entry->usage_flag = cb_flag;
- *entry_p = entry;
- entry = BLI_mempool_alloc(rel->entry_pool);
- if (BLI_ghash_ensure_p(rel->id_used_to_user, *id_pointer, (void ***)&entry_p)) {
- entry->next = *entry_p;
- }
- else {
- entry->next = NULL;
+ /* Add `id_self` as parent of `id_pointer`. */
+ if (*id_pointer != NULL) {
+ if (!BLI_ghash_ensure_p(
+ bmain_relations->relations_from_pointers, *id_pointer, (void ***)&entry_p)) {
+ *entry_p = MEM_callocN(sizeof(**entry_p), __func__);
+ (*entry_p)->session_uuid = (*id_pointer)->session_uuid;
+ }
+ else {
+ BLI_assert((*entry_p)->session_uuid == (*id_pointer)->session_uuid);
+ }
+ MainIDRelationsEntryItem *from_id_entry = BLI_mempool_alloc(
+ bmain_relations->entry_items_pool);
+ from_id_entry->next = (*entry_p)->from_ids;
+ from_id_entry->id_pointer.from = id_self;
+ from_id_entry->session_uuid = id_self->session_uuid;
+ from_id_entry->usage_flag = cb_flag;
+ (*entry_p)->from_ids = from_id_entry;
}
- entry->id_pointer = (ID **)id_self;
- entry->usage_flag = cb_flag;
- *entry_p = entry;
}
return IDWALK_RET_NOP;
@@ -253,59 +269,63 @@ void BKE_main_relations_create(Main *bmain, const short flag)
}
bmain->relations = MEM_mallocN(sizeof(*bmain->relations), __func__);
- bmain->relations->id_used_to_user = BLI_ghash_new(
- BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- bmain->relations->id_user_to_used = BLI_ghash_new(
+ bmain->relations->relations_from_pointers = BLI_ghash_new(
BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- bmain->relations->entry_pool = BLI_mempool_create(
- sizeof(MainIDRelationsEntry), 128, 128, BLI_MEMPOOL_NOP);
+ bmain->relations->entry_items_pool = BLI_mempool_create(
+ sizeof(MainIDRelationsEntryItem), 128, 128, BLI_MEMPOOL_NOP);
+
+ bmain->relations->flag = flag;
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
const int idwalk_flag = IDWALK_READONLY |
((flag & MAINIDRELATIONS_INCLUDE_UI) != 0 ? IDWALK_INCLUDE_UI : 0);
+
+ /* Ensure all IDs do have an entry, even if they are not connected to any other. */
+ MainIDRelationsEntry **entry_p;
+ if (!BLI_ghash_ensure_p(bmain->relations->relations_from_pointers, id, (void ***)&entry_p)) {
+ *entry_p = MEM_callocN(sizeof(**entry_p), __func__);
+ (*entry_p)->session_uuid = id->session_uuid;
+ }
+ else {
+ BLI_assert((*entry_p)->session_uuid == id->session_uuid);
+ }
+
BKE_library_foreach_ID_link(
NULL, id, main_relations_create_idlink_cb, bmain->relations, idwalk_flag);
}
FOREACH_MAIN_ID_END;
-
- bmain->relations->flag = flag;
}
void BKE_main_relations_free(Main *bmain)
{
- if (bmain->relations) {
- if (bmain->relations->id_used_to_user) {
- BLI_ghash_free(bmain->relations->id_used_to_user, NULL, NULL);
- }
- if (bmain->relations->id_user_to_used) {
- BLI_ghash_free(bmain->relations->id_user_to_used, NULL, NULL);
+ if (bmain->relations != NULL) {
+ if (bmain->relations->relations_from_pointers != NULL) {
+ BLI_ghash_free(bmain->relations->relations_from_pointers, NULL, MEM_freeN);
}
- BLI_mempool_destroy(bmain->relations->entry_pool);
+ BLI_mempool_destroy(bmain->relations->entry_items_pool);
MEM_freeN(bmain->relations);
bmain->relations = NULL;
}
}
-/**
- * Remove an ID from the relations (the two entries for that ID, not the ID from entries in other
- * IDs' relationships).
- *
- * Does not free any allocated memory.
- * Allows to use those relations as a way to mark an ID as already processed, without requiring any
- * additional tagging or GSet.
- * Obviously, relations should be freed after use then, since this will make them fully invalid.
- */
-void BKE_main_relations_ID_remove(Main *bmain, ID *id)
+/** Set or clear given `tag` in all relation entries of given `bmain`. */
+void BKE_main_relations_tag_set(struct Main *bmain,
+ const MainIDRelationsEntryTags tag,
+ const bool value)
{
- if (bmain->relations) {
- /* Note: we do not free the entries from the mempool, those will be dealt with when finally
- * freeing the whole relations. */
- if (bmain->relations->id_used_to_user) {
- BLI_ghash_remove(bmain->relations->id_used_to_user, id, NULL, NULL);
+ if (bmain->relations == NULL) {
+ return;
+ }
+ for (GHashIterator *gh_iter = BLI_ghashIterator_new(bmain->relations->relations_from_pointers);
+ !BLI_ghashIterator_done(gh_iter);
+ BLI_ghashIterator_step(gh_iter)) {
+ MainIDRelationsEntry *entry = BLI_ghashIterator_getValue(gh_iter);
+ if (value) {
+ entry->tags |= tag;
}
- if (bmain->relations->id_user_to_used) {
- BLI_ghash_remove(bmain->relations->id_user_to_used, id, NULL, NULL);
+ else {
+ entry->tags &= ~tag;
}
}
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 04fec1e57c4..83d9449934c 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -270,6 +270,8 @@ IDTypeInfo IDType_ID_MSK = {
.blend_read_expand = mask_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
static struct {
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index e892a3f4d53..70906065347 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -274,6 +274,8 @@ IDTypeInfo IDType_ID_MA = {
.blend_read_expand = material_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
void BKE_gpencil_material_attr_init(Material *ma)
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 65ec91c57cf..849c7ef57fb 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -204,6 +204,8 @@ IDTypeInfo IDType_ID_MB = {
.blend_read_expand = metaball_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* Functions */
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 051c7e56ef9..1550401cc9c 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -263,7 +263,7 @@ static void build_bvh_spatial(PROCESS *process,
* BASED AT CODE (but mostly rewritten) :
* C code from the article
* "An Implicit Surface Polygonizer"
- * by Jules Bloomenthal, jbloom@beauty.gmu.edu
+ * by Jules Bloomenthal <jbloom@beauty.gmu.edu>
* in "Graphics Gems IV", Academic Press, 1994
*
* Authored by Jules Bloomenthal, Xerox PARC.
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 950885d2114..622f6d7a7b8 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -364,6 +364,8 @@ IDTypeInfo IDType_ID_ME = {
.blend_read_expand = mesh_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
enum {
@@ -939,7 +941,7 @@ Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
Mesh *me_dst = BKE_id_new_nomain(ID_ME, NULL);
- me_dst->mselect = MEM_dupallocN(me_dst->mselect);
+ me_dst->mselect = MEM_dupallocN(me_src->mselect);
me_dst->totvert = verts_len;
me_dst->totedge = edges_len;
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index b872c91cc29..175caf85b49 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -362,6 +362,8 @@ IDTypeInfo IDType_ID_MC = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/*********************** movieclip buffer loaders *************************/
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 441da8b134a..45ac20ef154 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -781,7 +781,7 @@ static DerivedMesh *subsurf_dm_create_local(Scene *scene,
smd.levels = smd.renderLevels = lvl;
smd.quality = 3;
if (!is_plain_uv) {
- smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_CORNERS;
+ smd.uv_smooth = SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES;
}
else {
smd.uv_smooth = SUBSURF_UV_SMOOTH_NONE;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.cc
index 76885eadaae..2dbfa85b8e1 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.cc
@@ -25,10 +25,10 @@
#include "MEM_guardedalloc.h"
-#include <limits.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
+#include <climits>
+#include <cstddef>
+#include <cstdlib>
+#include <cstring>
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
@@ -109,7 +109,7 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree),
static void ntree_init_data(ID *id)
{
bNodeTree *ntree = (bNodeTree *)id;
- ntree_set_typeinfo(ntree, NULL);
+ ntree_set_typeinfo(ntree, nullptr);
}
static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
@@ -121,7 +121,7 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* in case a running nodetree is copied */
- ntree_dst->execdata = NULL;
+ ntree_dst->execdata = nullptr;
BLI_listbase_clear(&ntree_dst->nodes);
BLI_listbase_clear(&ntree_dst->links);
@@ -133,17 +133,17 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
bNode *new_node = BKE_node_copy_ex(ntree_dst, node_src, flag_subdata, true);
BLI_ghash_insert(new_pointers, (void *)node_src, new_node);
/* Store mapping to inputs. */
- bNodeSocket *new_input_sock = new_node->inputs.first;
- const bNodeSocket *input_sock_src = node_src->inputs.first;
- while (new_input_sock != NULL) {
+ bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first;
+ const bNodeSocket *input_sock_src = (const bNodeSocket *)node_src->inputs.first;
+ while (new_input_sock != nullptr) {
BLI_ghash_insert(new_pointers, (void *)input_sock_src, new_input_sock);
new_input_sock = new_input_sock->next;
input_sock_src = input_sock_src->next;
}
/* Store mapping to outputs. */
- bNodeSocket *new_output_sock = new_node->outputs.first;
- const bNodeSocket *output_sock_src = node_src->outputs.first;
- while (new_output_sock != NULL) {
+ bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first;
+ const bNodeSocket *output_sock_src = (const bNodeSocket *)node_src->outputs.first;
+ while (new_output_sock != nullptr) {
BLI_ghash_insert(new_pointers, (void *)output_sock_src, new_output_sock);
new_output_sock = new_output_sock->next;
output_sock_src = output_sock_src->next;
@@ -153,10 +153,13 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
/* copy links */
BLI_duplicatelist(&ntree_dst->links, &ntree_src->links);
LISTBASE_FOREACH (bNodeLink *, link_dst, &ntree_dst->links) {
- link_dst->fromnode = BLI_ghash_lookup_default(new_pointers, link_dst->fromnode, NULL);
- link_dst->fromsock = BLI_ghash_lookup_default(new_pointers, link_dst->fromsock, NULL);
- link_dst->tonode = BLI_ghash_lookup_default(new_pointers, link_dst->tonode, NULL);
- link_dst->tosock = BLI_ghash_lookup_default(new_pointers, link_dst->tosock, NULL);
+ link_dst->fromnode = (bNode *)BLI_ghash_lookup_default(
+ new_pointers, link_dst->fromnode, nullptr);
+ link_dst->fromsock = (bNodeSocket *)BLI_ghash_lookup_default(
+ new_pointers, link_dst->fromsock, nullptr);
+ link_dst->tonode = (bNode *)BLI_ghash_lookup_default(new_pointers, link_dst->tonode, nullptr);
+ link_dst->tosock = (bNodeSocket *)BLI_ghash_lookup_default(
+ new_pointers, link_dst->tosock, nullptr);
/* update the link socket's pointer */
if (link_dst->tosock) {
link_dst->tosock->link = link_dst;
@@ -166,14 +169,18 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
/* copy interface sockets */
BLI_duplicatelist(&ntree_dst->inputs, &ntree_src->inputs);
bNodeSocket *sock_dst, *sock_src;
- for (sock_dst = ntree_dst->inputs.first, sock_src = ntree_src->inputs.first; sock_dst != NULL;
- sock_dst = sock_dst->next, sock_src = sock_src->next) {
+ for (sock_dst = (bNodeSocket *)ntree_dst->inputs.first,
+ sock_src = (bNodeSocket *)ntree_src->inputs.first;
+ sock_dst != nullptr;
+ sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) {
node_socket_copy(sock_dst, sock_src, flag_subdata);
}
BLI_duplicatelist(&ntree_dst->outputs, &ntree_src->outputs);
- for (sock_dst = ntree_dst->outputs.first, sock_src = ntree_src->outputs.first; sock_dst != NULL;
- sock_dst = sock_dst->next, sock_src = sock_src->next) {
+ for (sock_dst = (bNodeSocket *)ntree_dst->outputs.first,
+ sock_src = (bNodeSocket *)ntree_src->outputs.first;
+ sock_dst != nullptr;
+ sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) {
node_socket_copy(sock_dst, sock_src, flag_subdata);
}
@@ -185,26 +192,29 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
NODE_INSTANCE_HASH_ITER (iter, ntree_src->previews) {
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
- bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
BKE_node_instance_hash_insert(ntree_dst->previews, key, BKE_node_preview_copy(preview));
}
}
else {
- ntree_dst->previews = NULL;
+ ntree_dst->previews = nullptr;
}
/* update node->parent pointers */
- for (bNode *node_dst = ntree_dst->nodes.first, *node_src = ntree_src->nodes.first; node_dst;
- node_dst = node_dst->next, node_src = node_src->next) {
+ for (bNode *node_dst = (bNode *)ntree_dst->nodes.first,
+ *node_src = (bNode *)ntree_src->nodes.first;
+ node_dst;
+ node_dst = (bNode *)node_dst->next, node_src = (bNode *)node_src->next) {
if (node_dst->parent) {
- node_dst->parent = BLI_ghash_lookup_default(new_pointers, node_dst->parent, NULL);
+ node_dst->parent = (bNode *)BLI_ghash_lookup_default(
+ new_pointers, node_dst->parent, nullptr);
}
}
- BLI_ghash_free(new_pointers, NULL, NULL);
+ BLI_ghash_free(new_pointers, nullptr, nullptr);
/* node tree will generate its own interface type */
- ntree_dst->interface_type = NULL;
+ ntree_dst->interface_type = nullptr;
}
static void ntree_free_data(ID *id)
@@ -223,7 +233,7 @@ static void ntree_free_data(ID *id)
break;
case NTREE_TEXTURE:
ntreeTexEndExecTree(ntree->execdata);
- ntree->execdata = NULL;
+ ntree->execdata = nullptr;
break;
}
}
@@ -267,17 +277,18 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
- bNodeSocketValueObject *default_value = sock->default_value;
+ bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER);
break;
}
case SOCK_IMAGE: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER);
break;
}
case SOCK_COLLECTION: {
- bNodeSocketValueCollection *default_value = sock->default_value;
+ bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
+ sock->default_value;
BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER);
break;
}
@@ -327,11 +338,10 @@ static void node_foreach_cache(ID *id,
void *user_data)
{
bNodeTree *nodetree = (bNodeTree *)id;
- IDCacheKey key = {
- .id_session_uuid = id->session_uuid,
- .offset_in_ID = offsetof(bNodeTree, previews),
- .cache_v = nodetree->previews,
- };
+ IDCacheKey key = {0};
+ key.id_session_uuid = id->session_uuid;
+ key.offset_in_ID = offsetof(bNodeTree, previews);
+ key.cache_v = nodetree->previews;
/* TODO, see also `direct_link_nodetree()` in readfile.c. */
#if 0
@@ -351,7 +361,7 @@ static void node_foreach_cache(ID *id,
static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock)
{
- if (sock->default_value == NULL) {
+ if (sock->default_value == nullptr) {
return;
}
@@ -448,7 +458,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
/* could be handlerized at some point, now only 1 exception still */
if ((ntree->type == NTREE_SHADER) &&
ELEM(node->type, SH_NODE_CURVE_VEC, SH_NODE_CURVE_RGB)) {
- BKE_curvemapping_blend_write(writer, node->storage);
+ BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
else if (ntree->type == NTREE_SHADER && (node->type == SH_NODE_SCRIPT)) {
NodeShaderScript *nss = (NodeShaderScript *)node->storage;
@@ -462,11 +472,11 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
CMP_NODE_CURVE_VEC,
CMP_NODE_CURVE_RGB,
CMP_NODE_HUECORRECT)) {
- BKE_curvemapping_blend_write(writer, node->storage);
+ BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
else if ((ntree->type == NTREE_TEXTURE) &&
(node->type == TEX_NODE_CURVE_RGB || node->type == TEX_NODE_CURVE_TIME)) {
- BKE_curvemapping_blend_write(writer, node->storage);
+ BKE_curvemapping_blend_write(writer, (const CurveMapping *)node->storage);
}
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_MOVIEDISTORTION)) {
/* pass */
@@ -474,7 +484,7 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
/* Simple forward compatibility for fix for T50736.
* Not ideal (there is no ideal solution here), but should do for now. */
- NodeGlare *ndg = node->storage;
+ NodeGlare *ndg = (NodeGlare *)node->storage;
/* Not in undo case. */
if (!BLO_write_is_undo(writer)) {
switch (ndg->type) {
@@ -543,10 +553,10 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
/* 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 = NULL;
- ntree->interface_type = NULL;
- ntree->progress = NULL;
- ntree->execdata = NULL;
+ ntree->typeinfo = nullptr;
+ ntree->interface_type = nullptr;
+ ntree->progress = nullptr;
+ ntree->execdata = nullptr;
BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
@@ -560,10 +570,10 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
IDP_BlendDataRead(reader, &sock->prop);
BLO_read_data_address(reader, &sock->link);
- sock->typeinfo = NULL;
+ sock->typeinfo = nullptr;
BLO_read_data_address(reader, &sock->storage);
BLO_read_data_address(reader, &sock->default_value);
- sock->cache = NULL;
+ sock->cache = nullptr;
}
/* ntree itself has been read! */
@@ -572,18 +582,18 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
/* note: writing and reading goes in sync, for speed */
ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
- ntree->typeinfo = NULL;
- ntree->interface_type = NULL;
+ ntree->typeinfo = nullptr;
+ ntree->interface_type = nullptr;
- ntree->progress = NULL;
- ntree->execdata = NULL;
+ ntree->progress = nullptr;
+ ntree->execdata = nullptr;
BLO_read_data_address(reader, &ntree->adt);
BKE_animdata_blend_read_data(reader, ntree->adt);
BLO_read_list(reader, &ntree->nodes);
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- node->typeinfo = NULL;
+ node->typeinfo = nullptr;
BLO_read_list(reader, &node->inputs);
BLO_read_list(reader, &node->outputs);
@@ -618,7 +628,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
case CMP_NODE_HUECORRECT:
case TEX_NODE_CURVE_RGB:
case TEX_NODE_CURVE_TIME: {
- BKE_curvemapping_blend_read(reader, node->storage);
+ BKE_curvemapping_blend_read(reader, (CurveMapping *)node->storage);
break;
}
case SH_NODE_SCRIPT: {
@@ -634,22 +644,22 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
case SH_NODE_TEX_IMAGE: {
NodeTexImage *tex = (NodeTexImage *)node->storage;
tex->iuser.ok = 1;
- tex->iuser.scene = NULL;
+ tex->iuser.scene = nullptr;
break;
}
case SH_NODE_TEX_ENVIRONMENT: {
NodeTexEnvironment *tex = (NodeTexEnvironment *)node->storage;
tex->iuser.ok = 1;
- tex->iuser.scene = NULL;
+ tex->iuser.scene = nullptr;
break;
}
case CMP_NODE_IMAGE:
case CMP_NODE_R_LAYERS:
case CMP_NODE_VIEWER:
case CMP_NODE_SPLITVIEWER: {
- ImageUser *iuser = node->storage;
+ ImageUser *iuser = (ImageUser *)node->storage;
iuser->ok = 1;
- iuser->scene = NULL;
+ iuser->scene = nullptr;
break;
}
case CMP_NODE_CRYPTOMATTE: {
@@ -659,9 +669,9 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
break;
}
case TEX_NODE_IMAGE: {
- ImageUser *iuser = node->storage;
+ ImageUser *iuser = (ImageUser *)node->storage;
iuser->ok = 1;
- iuser->scene = NULL;
+ iuser->scene = nullptr;
break;
}
default:
@@ -701,7 +711,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
}
/* TODO, should be dealt by new generic cache handling of IDs... */
- ntree->previews = NULL;
+ ntree->previews = nullptr;
/* type verification is in lib-link */
}
@@ -718,17 +728,18 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
- bNodeSocketValueObject *default_value = sock->default_value;
+ bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
BLO_read_id_address(reader, lib, &default_value->value);
break;
}
case SOCK_IMAGE: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
BLO_read_id_address(reader, lib, &default_value->value);
break;
}
case SOCK_COLLECTION: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
+ sock->default_value;
BLO_read_id_address(reader, lib, &default_value->value);
break;
}
@@ -777,7 +788,7 @@ void ntreeBlendReadLib(struct BlendLibReader *reader, struct bNodeTree *ntree)
* first versioning that can change types still without functions that
* update the typeinfo pointers. Versioning after lib linking needs
* these top be valid. */
- ntreeSetTypes(NULL, ntree);
+ ntreeSetTypes(nullptr, ntree);
/* For nodes with static socket layout, add/remove sockets as needed
* to match the static layout. */
@@ -798,21 +809,22 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
{
IDP_BlendReadExpand(expander, sock->prop);
- if (sock->default_value != NULL) {
+ if (sock->default_value != nullptr) {
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
- bNodeSocketValueObject *default_value = sock->default_value;
+ bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
BLO_expand(expander, default_value->value);
break;
}
case SOCK_IMAGE: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
BLO_expand(expander, default_value->value);
break;
}
case SOCK_COLLECTION: {
- bNodeSocketValueCollection *default_value = sock->default_value;
+ bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
+ sock->default_value;
BLO_expand(expander, default_value->value);
break;
}
@@ -866,28 +878,30 @@ static void ntree_blend_read_expand(BlendExpander *expander, ID *id)
}
IDTypeInfo IDType_ID_NT = {
- .id_code = ID_NT,
- .id_filter = FILTER_ID_NT,
- .main_listbase_index = INDEX_ID_NT,
- .struct_size = sizeof(bNodeTree),
- .name = "NodeTree",
- .name_plural = "node_groups",
- .translation_context = BLT_I18NCONTEXT_ID_NODETREE,
- .flags = 0,
-
- .init_data = ntree_init_data,
- .copy_data = ntree_copy_data,
- .free_data = ntree_free_data,
- .make_local = NULL,
- .foreach_id = node_foreach_id,
- .foreach_cache = node_foreach_cache,
-
- .blend_write = ntree_blend_write,
- .blend_read_data = ntree_blend_read_data,
- .blend_read_lib = ntree_blend_read_lib,
- .blend_read_expand = ntree_blend_read_expand,
-
- .blend_read_undo_preserve = NULL,
+ /* id_code */ ID_NT,
+ /* id_filter */ FILTER_ID_NT,
+ /* main_listbase_index */ INDEX_ID_NT,
+ /* struct_size */ sizeof(bNodeTree),
+ /* name */ "NodeTree",
+ /* name_plural */ "node_groups",
+ /* translation_context */ BLT_I18NCONTEXT_ID_NODETREE,
+ /* flags */ 0,
+
+ /* init_data */ ntree_init_data,
+ /* copy_data */ ntree_copy_data,
+ /* free_data */ ntree_free_data,
+ /* make_local */ nullptr,
+ /* foreach_id */ node_foreach_id,
+ /* foreach_cache */ node_foreach_cache,
+
+ /* blend_write */ ntree_blend_write,
+ /* blend_read_data */ ntree_blend_read_data,
+ /* blend_read_lib */ ntree_blend_read_lib,
+ /* blend_read_expand */ ntree_blend_read_expand,
+
+ /* blend_read_undo_preserve */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
@@ -947,11 +961,11 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
node_add_sockets_from_type(ntree, node, ntype);
- if (ntype->initfunc != NULL) {
+ if (ntype->initfunc != nullptr) {
ntype->initfunc(ntree, node);
}
- if (ntree->typeinfo->node_add_init != NULL) {
+ if (ntree->typeinfo->node_add_init != nullptr) {
ntree->typeinfo->node_add_init(ntree, node);
}
@@ -964,10 +978,10 @@ static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
PointerRNA ptr;
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
- /* XXX Warning: context can be NULL in case nodes are added in do_versions.
+ /* XXX Warning: context can be nullptr in case nodes are added in do_versions.
* Delayed init is not supported for nodes with context-based initfunc_api atm.
*/
- BLI_assert(C != NULL);
+ BLI_assert(C != nullptr);
ntype->initfunc_api(C, &ptr);
}
@@ -997,7 +1011,7 @@ static void node_set_typeinfo(const struct bContext *C,
/* for nodes saved in older versions storage can get lost, make undefined then */
if (node->flag & NODE_INIT) {
if (typeinfo && typeinfo->storagename[0] && !node->storage) {
- typeinfo = NULL;
+ typeinfo = nullptr;
}
}
@@ -1027,7 +1041,7 @@ static void node_socket_set_typeinfo(bNodeTree *ntree,
/* deprecated integer type */
sock->type = typeinfo->type;
- if (sock->default_value == NULL) {
+ if (sock->default_value == nullptr) {
/* initialize the default_value pointer used by standard socket types */
node_socket_init_default_value(sock);
}
@@ -1055,24 +1069,24 @@ static void update_typeinfo(Main *bmain,
ntree->init |= NTREE_TYPE_INIT;
if (treetype && STREQ(ntree->idname, treetype->idname)) {
- ntree_set_typeinfo(ntree, unregister ? NULL : treetype);
+ ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
}
/* initialize nodes */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (nodetype && STREQ(node->idname, nodetype->idname)) {
- node_set_typeinfo(C, ntree, node, unregister ? NULL : nodetype);
+ node_set_typeinfo(C, ntree, node, unregister ? nullptr : nodetype);
}
/* initialize node sockets */
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
if (socktype && STREQ(sock->idname, socktype->idname)) {
- node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
if (socktype && STREQ(sock->idname, socktype->idname)) {
- node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
}
@@ -1080,12 +1094,12 @@ static void update_typeinfo(Main *bmain,
/* initialize tree sockets */
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) {
if (socktype && STREQ(sock->idname, socktype->idname)) {
- node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) {
if (socktype && STREQ(sock->idname, socktype->idname)) {
- node_socket_set_typeinfo(ntree, sock, unregister ? NULL : socktype);
+ node_socket_set_typeinfo(ntree, sock, unregister ? nullptr : socktype);
}
}
}
@@ -1123,22 +1137,20 @@ void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
}
}
-static GHash *nodetreetypes_hash = NULL;
-static GHash *nodetypes_hash = NULL;
-static GHash *nodesockettypes_hash = NULL;
+static GHash *nodetreetypes_hash = nullptr;
+static GHash *nodetypes_hash = nullptr;
+static GHash *nodesockettypes_hash = nullptr;
bNodeTreeType *ntreeTypeFind(const char *idname)
{
- bNodeTreeType *nt;
-
if (idname[0]) {
- nt = BLI_ghash_lookup(nodetreetypes_hash, idname);
+ bNodeTreeType *nt = (bNodeTreeType *)BLI_ghash_lookup(nodetreetypes_hash, idname);
if (nt) {
return nt;
}
}
- return NULL;
+ return nullptr;
}
void ntreeTypeAdd(bNodeTreeType *nt)
@@ -1147,23 +1159,23 @@ void ntreeTypeAdd(bNodeTreeType *nt)
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, nt, NULL, NULL, false);
+ update_typeinfo(G_MAIN, nullptr, nt, nullptr, nullptr, false);
}
/* callback for hash value free function */
static void ntree_free_type(void *treetype_v)
{
- bNodeTreeType *treetype = treetype_v;
+ bNodeTreeType *treetype = (bNodeTreeType *)treetype_v;
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, treetype, NULL, NULL, true);
+ update_typeinfo(G_MAIN, nullptr, treetype, nullptr, nullptr, true);
MEM_freeN(treetype);
}
void ntreeTypeFreeLink(const bNodeTreeType *nt)
{
- BLI_ghash_remove(nodetreetypes_hash, nt->idname, NULL, ntree_free_type);
+ BLI_ghash_remove(nodetreetypes_hash, nt->idname, nullptr, ntree_free_type);
}
bool ntreeIsRegistered(bNodeTree *ntree)
@@ -1179,13 +1191,13 @@ GHashIterator *ntreeTypeGetIterator(void)
bNodeType *nodeTypeFind(const char *idname)
{
if (idname[0]) {
- bNodeType *nt = BLI_ghash_lookup(nodetypes_hash, idname);
+ bNodeType *nt = (bNodeType *)BLI_ghash_lookup(nodetypes_hash, idname);
if (nt) {
return nt;
}
}
- return NULL;
+ return nullptr;
}
static void free_dynamic_typeinfo(bNodeType *ntype)
@@ -1203,18 +1215,18 @@ static void free_dynamic_typeinfo(bNodeType *ntype)
/* callback for hash value free function */
static void node_free_type(void *nodetype_v)
{
- bNodeType *nodetype = nodetype_v;
+ bNodeType *nodetype = (bNodeType *)nodetype_v;
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, NULL, nodetype, NULL, true);
+ update_typeinfo(G_MAIN, nullptr, nullptr, nodetype, nullptr, true);
/* XXX deprecated */
if (nodetype->type == NODE_DYNAMIC) {
free_dynamic_typeinfo(nodetype);
}
- /* Can be NULL when the type is not dynamically allocated. */
+ /* Can be null when the type is not dynamically allocated. */
if (nodetype->free_self) {
nodetype->free_self(nodetype);
}
@@ -1224,18 +1236,18 @@ void nodeRegisterType(bNodeType *nt)
{
/* debug only: basic verification of registered types */
BLI_assert(nt->idname[0] != '\0');
- BLI_assert(nt->poll != NULL);
+ BLI_assert(nt->poll != nullptr);
BLI_ghash_insert(nodetypes_hash, nt->idname, nt);
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, NULL, nt, NULL, false);
+ update_typeinfo(G_MAIN, nullptr, nullptr, nt, nullptr, false);
}
void nodeUnregisterType(bNodeType *nt)
{
- BLI_ghash_remove(nodetypes_hash, nt->idname, NULL, node_free_type);
+ BLI_ghash_remove(nodetypes_hash, nt->idname, nullptr, node_free_type);
}
bool nodeTypeUndefined(bNode *node)
@@ -1253,23 +1265,23 @@ GHashIterator *nodeTypeGetIterator(void)
bNodeSocketType *nodeSocketTypeFind(const char *idname)
{
if (idname[0]) {
- bNodeSocketType *st = BLI_ghash_lookup(nodesockettypes_hash, idname);
+ bNodeSocketType *st = (bNodeSocketType *)BLI_ghash_lookup(nodesockettypes_hash, idname);
if (st) {
return st;
}
}
- return NULL;
+ return nullptr;
}
/* callback for hash value free function */
static void node_free_socket_type(void *socktype_v)
{
- bNodeSocketType *socktype = socktype_v;
+ bNodeSocketType *socktype = (bNodeSocketType *)socktype_v;
/* XXX pass Main to unregister function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, NULL, NULL, socktype, true);
+ update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, socktype, true);
socktype->free_self(socktype);
}
@@ -1280,12 +1292,12 @@ void nodeRegisterSocketType(bNodeSocketType *st)
/* XXX pass Main to register function? */
/* Probably not. It is pretty much expected we want to update G_MAIN here I think -
* or we'd want to update *all* active Mains, which we cannot do anyway currently. */
- update_typeinfo(G_MAIN, NULL, NULL, NULL, st, false);
+ update_typeinfo(G_MAIN, nullptr, nullptr, nullptr, st, false);
}
void nodeUnregisterSocketType(bNodeSocketType *st)
{
- BLI_ghash_remove(nodesockettypes_hash, st->idname, NULL, node_free_socket_type);
+ BLI_ghash_remove(nodesockettypes_hash, st->idname, nullptr, node_free_socket_type);
}
bool nodeSocketIsRegistered(bNodeSocket *sock)
@@ -1306,13 +1318,13 @@ struct bNodeSocket *nodeFindSocket(const bNode *node, int in_out, const char *id
return sock;
}
}
- return NULL;
+ return nullptr;
}
/* find unique socket identifier */
static bool unique_identifier_check(void *arg, const char *identifier)
{
- struct ListBase *lb = arg;
+ const ListBase *lb = (const ListBase *)arg;
LISTBASE_FOREACH (bNodeSocket *, sock, lb) {
if (STREQ(sock->identifier, identifier)) {
return true;
@@ -1343,14 +1355,14 @@ static bNodeSocket *make_socket(bNodeTree *ntree,
BLI_uniquename_cb(
unique_identifier_check, lb, "socket", '.', auto_identifier, sizeof(auto_identifier));
- bNodeSocket *sock = MEM_callocN(sizeof(bNodeSocket), "sock");
+ bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "sock");
sock->in_out = in_out;
BLI_strncpy(sock->identifier, auto_identifier, NODE_MAXSTR);
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
BLI_strncpy(sock->name, name, NODE_MAXSTR);
- sock->storage = NULL;
+ sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
sock->type = SOCK_CUSTOM; /* int type undefined by default */
@@ -1364,17 +1376,18 @@ static void socket_id_user_increment(bNodeSocket *sock)
{
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
- bNodeSocketValueObject *default_value = sock->default_value;
+ bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
id_us_plus((ID *)default_value->value);
break;
}
case SOCK_IMAGE: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
id_us_plus((ID *)default_value->value);
break;
}
case SOCK_COLLECTION: {
- bNodeSocketValueCollection *default_value = sock->default_value;
+ bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
+ sock->default_value;
id_us_plus((ID *)default_value->value);
break;
}
@@ -1396,17 +1409,18 @@ static void socket_id_user_decrement(bNodeSocket *sock)
{
switch ((eNodeSocketDatatype)sock->type) {
case SOCK_OBJECT: {
- bNodeSocketValueObject *default_value = sock->default_value;
+ bNodeSocketValueObject *default_value = (bNodeSocketValueObject *)sock->default_value;
id_us_min(&default_value->value->id);
break;
}
case SOCK_IMAGE: {
- bNodeSocketValueImage *default_value = sock->default_value;
+ bNodeSocketValueImage *default_value = (bNodeSocketValueImage *)sock->default_value;
id_us_min(&default_value->value->id);
break;
}
case SOCK_COLLECTION: {
- bNodeSocketValueCollection *default_value = sock->default_value;
+ bNodeSocketValueCollection *default_value = (bNodeSocketValueCollection *)
+ sock->default_value;
id_us_min(&default_value->value->id);
break;
}
@@ -1437,7 +1451,7 @@ void nodeModifySocketType(
if (sock->default_value) {
socket_id_user_decrement(sock);
MEM_freeN(sock->default_value);
- sock->default_value = NULL;
+ sock->default_value = nullptr;
}
sock->type = type;
@@ -1552,7 +1566,7 @@ const char *nodeStaticSocketType(int type, int subtype)
case SOCK_COLLECTION:
return "NodeSocketCollection";
}
- return NULL;
+ return nullptr;
}
const char *nodeStaticSocketInterfaceType(int type, int subtype)
@@ -1621,7 +1635,7 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype)
case SOCK_COLLECTION:
return "NodeSocketInterfaceCollection";
}
- return NULL;
+ return nullptr;
}
bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
@@ -1636,7 +1650,7 @@ bNodeSocket *nodeAddStaticSocket(bNodeTree *ntree,
if (!idname) {
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
- return NULL;
+ return nullptr;
}
bNodeSocket *sock = nodeAddSocket(ntree, node, in_out, idname, identifier, name);
@@ -1657,7 +1671,7 @@ bNodeSocket *nodeInsertStaticSocket(bNodeTree *ntree,
if (!idname) {
CLOG_ERROR(&LOG, "static node socket type %d undefined", type);
- return NULL;
+ return nullptr;
}
bNodeSocket *sock = nodeInsertSocket(ntree, node, in_out, idname, next_sock, identifier, name);
@@ -1727,23 +1741,23 @@ void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
/* finds a node based on its name */
bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
{
- return BLI_findstring(&ntree->nodes, name, offsetof(bNode, name));
+ return (bNode *)BLI_findstring(&ntree->nodes, name, offsetof(bNode, name));
}
/* Finds a node based on given socket and returns true on success. */
bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
{
- *r_node = NULL;
+ *r_node = nullptr;
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
int index = 0;
LISTBASE_FOREACH (bNodeSocket *, tsock, sockets) {
if (sock == tsock) {
- if (r_node != NULL) {
+ if (r_node != nullptr) {
*r_node = node;
}
- if (r_sockindex != NULL) {
+ if (r_sockindex != nullptr) {
*r_sockindex = index;
}
return true;
@@ -1762,7 +1776,7 @@ bNode *nodeFindRootParent(bNode *node)
if (node->parent) {
return nodeFindRootParent(node->parent);
}
- return node->type == NODE_FRAME ? node : NULL;
+ return node->type == NODE_FRAME ? node : nullptr;
}
/**
@@ -1821,7 +1835,7 @@ static void iter_backwards_ex(const bNodeTree *ntree,
{
LISTBASE_FOREACH (bNodeSocket *, sock, &node_start->inputs) {
bNodeLink *link = sock->link;
- if (link == NULL) {
+ if (link == nullptr) {
continue;
}
if ((link->flag & NODE_LINK_VALID) == 0) {
@@ -1901,7 +1915,7 @@ void nodeUniqueName(bNodeTree *ntree, bNode *node)
bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idname)
{
- bNode *node = MEM_callocN(sizeof(bNode), "new node");
+ bNode *node = (bNode *)MEM_callocN(sizeof(bNode), "new node");
BLI_addtail(&ntree->nodes, node);
BLI_strncpy(node->idname, idname, sizeof(node->idname));
@@ -1914,7 +1928,7 @@ bNode *nodeAddNode(const struct bContext *C, bNodeTree *ntree, const char *idnam
bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
{
- const char *idname = NULL;
+ const char *idname = nullptr;
NODE_TYPES_BEGIN (ntype) {
/* do an extra poll here, because some int types are used
@@ -1928,7 +1942,7 @@ bNode *nodeAddStaticNode(const struct bContext *C, bNodeTree *ntree, int type)
NODE_TYPES_END;
if (!idname) {
CLOG_ERROR(&LOG, "static node type %d undefined", type);
- return NULL;
+ return nullptr;
}
return nodeAddNode(C, ntree, idname);
}
@@ -1951,7 +1965,7 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src,
/* XXX some compositor node (e.g. image, render layers) still store
* some persistent buffer data here, need to clear this to avoid dangling pointers.
*/
- sock_dst->cache = NULL;
+ sock_dst->cache = nullptr;
}
/* keep socket listorder identical, for copying links */
@@ -1962,7 +1976,7 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
const int flag,
const bool unique_name)
{
- bNode *node_dst = MEM_callocN(sizeof(bNode), "dupli node");
+ bNode *node_dst = (bNode *)MEM_callocN(sizeof(bNode), "dupli node");
bNodeSocket *sock_dst, *sock_src;
bNodeLink *link_dst, *link_src;
@@ -1977,14 +1991,18 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
}
BLI_duplicatelist(&node_dst->inputs, &node_src->inputs);
- for (sock_dst = node_dst->inputs.first, sock_src = node_src->inputs.first; sock_dst != NULL;
- sock_dst = sock_dst->next, sock_src = sock_src->next) {
+ for (sock_dst = (bNodeSocket *)node_dst->inputs.first,
+ sock_src = (bNodeSocket *)node_src->inputs.first;
+ sock_dst != nullptr;
+ sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) {
node_socket_copy(sock_dst, sock_src, flag);
}
BLI_duplicatelist(&node_dst->outputs, &node_src->outputs);
- for (sock_dst = node_dst->outputs.first, sock_src = node_src->outputs.first; sock_dst != NULL;
- sock_dst = sock_dst->next, sock_src = sock_src->next) {
+ for (sock_dst = (bNodeSocket *)node_dst->outputs.first,
+ sock_src = (bNodeSocket *)node_src->outputs.first;
+ sock_dst != nullptr;
+ sock_dst = (bNodeSocket *)sock_dst->next, sock_src = (bNodeSocket *)sock_src->next) {
node_socket_copy(sock_dst, sock_src, flag);
}
@@ -1993,9 +2011,10 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
}
BLI_duplicatelist(&node_dst->internal_links, &node_src->internal_links);
- for (link_dst = node_dst->internal_links.first, link_src = node_src->internal_links.first;
- link_dst != NULL;
- link_dst = link_dst->next, link_src = link_src->next) {
+ for (link_dst = (bNodeLink *)node_dst->internal_links.first,
+ link_src = (bNodeLink *)node_src->internal_links.first;
+ link_dst != nullptr;
+ link_dst = (bNodeLink *)link_dst->next, link_src = (bNodeLink *)link_src->next) {
/* This is a bit annoying to do index lookups in a list, but is likely to be faster than
* trying to create a hash-map. At least for usual nodes, which only have so much sockets
* and internal links. */
@@ -2005,8 +2024,8 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
BLI_assert(to_sock_index != -1);
link_dst->fromnode = node_dst;
link_dst->tonode = node_dst;
- link_dst->fromsock = BLI_findlink(&node_dst->inputs, from_sock_index);
- link_dst->tosock = BLI_findlink(&node_dst->outputs, to_sock_index);
+ link_dst->fromsock = (bNodeSocket *)BLI_findlink(&node_dst->inputs, from_sock_index);
+ link_dst->tosock = (bNodeSocket *)BLI_findlink(&node_dst->outputs, to_sock_index);
}
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
@@ -2017,7 +2036,7 @@ bNode *BKE_node_copy_ex(bNodeTree *ntree,
node_src->typeinfo->copyfunc(ntree, node_dst, node_src);
}
- node_dst->new_node = NULL;
+ node_dst->new_node = nullptr;
/* Only call copy function when a copy is made for the main database, not
* for cases like the dependency graph and localization. */
@@ -2040,17 +2059,17 @@ static void node_set_new_pointers(bNode *node_src, bNode *new_node)
/* Store mapping to the node itself. */
node_src->new_node = new_node;
/* Store mapping to inputs. */
- bNodeSocket *new_input_sock = new_node->inputs.first;
- bNodeSocket *input_sock_src = node_src->inputs.first;
- while (new_input_sock != NULL) {
+ bNodeSocket *new_input_sock = (bNodeSocket *)new_node->inputs.first;
+ bNodeSocket *input_sock_src = (bNodeSocket *)node_src->inputs.first;
+ while (new_input_sock != nullptr) {
input_sock_src->new_sock = new_input_sock;
new_input_sock = new_input_sock->next;
input_sock_src = input_sock_src->next;
}
/* Store mapping to outputs. */
- bNodeSocket *new_output_sock = new_node->outputs.first;
- bNodeSocket *output_sock_src = node_src->outputs.first;
- while (new_output_sock != NULL) {
+ bNodeSocket *new_output_sock = (bNodeSocket *)new_node->outputs.first;
+ bNodeSocket *output_sock_src = (bNodeSocket *)node_src->outputs.first;
+ while (new_output_sock != nullptr) {
output_sock_src->new_sock = new_output_sock;
new_output_sock = new_output_sock->next;
output_sock_src = output_sock_src->next;
@@ -2069,9 +2088,9 @@ bNodeTree *ntreeCopyTree_ex_new_pointers(const bNodeTree *ntree,
const bool do_id_user)
{
bNodeTree *new_ntree = ntreeCopyTree_ex(ntree, bmain, do_id_user);
- bNode *new_node = new_ntree->nodes.first;
- bNode *node_src = ntree->nodes.first;
- while (new_node != NULL) {
+ bNode *new_node = (bNode *)new_ntree->nodes.first;
+ bNode *node_src = (bNode *)ntree->nodes.first;
+ while (new_node != nullptr) {
node_set_new_pointers(node_src, new_node);
new_node = new_node->next;
node_src = node_src->next;
@@ -2083,14 +2102,14 @@ bNodeTree *ntreeCopyTree_ex_new_pointers(const bNodeTree *ntree,
bNodeLink *nodeAddLink(
bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
{
- bNodeLink *link = NULL;
+ bNodeLink *link = nullptr;
/* test valid input */
BLI_assert(fromnode);
BLI_assert(tonode);
if (fromsock->in_out == SOCK_OUT && tosock->in_out == SOCK_IN) {
- link = MEM_callocN(sizeof(bNodeLink), "link");
+ link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "link");
if (ntree) {
BLI_addtail(&ntree->links, link);
}
@@ -2101,7 +2120,7 @@ bNodeLink *nodeAddLink(
}
else if (fromsock->in_out == SOCK_IN && tosock->in_out == SOCK_OUT) {
/* OK but flip */
- link = MEM_callocN(sizeof(bNodeLink), "link");
+ link = (bNodeLink *)MEM_callocN(sizeof(bNodeLink), "link");
if (ntree) {
BLI_addtail(&ntree->links, link);
}
@@ -2126,7 +2145,7 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
}
if (link->tosock) {
- link->tosock->link = NULL;
+ link->tosock->link = nullptr;
}
MEM_freeN(link);
@@ -2137,10 +2156,7 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
{
- bNodeLink *link, *next;
-
- for (link = ntree->links.first; link; link = next) {
- next = link->next;
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromsock == sock || link->tosock == sock) {
nodeRemLink(ntree, link);
}
@@ -2149,7 +2165,7 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
ntree->update |= NTREE_UPDATE_LINKS;
}
-bool nodeLinkIsHidden(bNodeLink *link)
+bool nodeLinkIsHidden(const bNodeLink *link)
{
return nodeSocketIsHidden(link->fromsock) || nodeSocketIsHidden(link->tosock);
}
@@ -2200,7 +2216,7 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node)
}
}
-void nodeToView(bNode *node, float x, float y, float *rx, float *ry)
+void nodeToView(const bNode *node, float x, float y, float *rx, float *ry)
{
if (node->parent) {
nodeToView(node->parent, x + node->locx, y + node->locy, rx, ry);
@@ -2211,7 +2227,7 @@ void nodeToView(bNode *node, float x, float y, float *rx, float *ry)
}
}
-void nodeFromView(bNode *node, float x, float y, float *rx, float *ry)
+void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry)
{
if (node->parent) {
nodeFromView(node->parent, x, y, rx, ry);
@@ -2224,10 +2240,10 @@ void nodeFromView(bNode *node, float x, float y, float *rx, float *ry)
}
}
-bool nodeAttachNodeCheck(bNode *node, bNode *parent)
+bool nodeAttachNodeCheck(const bNode *node, const bNode *parent)
{
- for (bNode *parent_recurse = node; parent_recurse; parent_recurse = parent_recurse->parent) {
- if (parent_recurse == parent) {
+ for (const bNode *parent_iter = node; parent_iter; parent_iter = parent_iter->parent) {
+ if (parent_iter == parent) {
return true;
}
}
@@ -2258,7 +2274,7 @@ void nodeDetachNode(struct bNode *node)
nodeToView(node, 0.0f, 0.0f, &locx, &locy);
node->locx = locx;
node->locy = locy;
- node->parent = NULL;
+ node->parent = nullptr;
}
}
@@ -2307,7 +2323,7 @@ void nodePositionRelative(bNode *from_node,
void nodePositionPropagate(bNode *node)
{
LISTBASE_FOREACH (bNodeSocket *, nsock, &node->inputs) {
- if (nsock->link != NULL) {
+ if (nsock->link != nullptr) {
bNodeLink *link = nsock->link;
nodePositionRelative(link->fromnode, link->tonode, link->fromsock, link->tosock);
nodePositionPropagate(link->fromnode);
@@ -2317,17 +2333,15 @@ void nodePositionPropagate(bNode *node)
bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
{
- bNodeTree *ntree;
-
/* trees are created as local trees for compositor, material or texture nodes,
* node groups and other tree types are created as library data.
*/
- const bool is_embedded = (bmain == NULL);
+ const bool is_embedded = (bmain == nullptr);
int flag = 0;
if (is_embedded) {
flag |= LIB_ID_CREATE_NO_MAIN;
}
- ntree = BKE_libblock_alloc(bmain, ID_NT, name, flag);
+ bNodeTree *ntree = (bNodeTree *)BKE_libblock_alloc(bmain, ID_NT, name, flag);
if (is_embedded) {
ntree->id.flag |= LIB_EMBEDDED_DATA;
}
@@ -2347,7 +2361,7 @@ bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_i
{
const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN;
- bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, NULL, flag);
+ bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, nullptr, flag);
return ntree_copy;
}
bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
@@ -2362,7 +2376,7 @@ bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree)
* using BKE_node_preview_init_tree to set up previews for a whole node tree in advance.
* This should be left more to the individual node tree implementations.
*/
-int BKE_node_preview_used(bNode *node)
+bool BKE_node_preview_used(const bNode *node)
{
/* XXX check for closed nodes? */
return (node->typeinfo->flag & NODE_PREVIEW) != 0;
@@ -2371,14 +2385,14 @@ int BKE_node_preview_used(bNode *node)
bNodePreview *BKE_node_preview_verify(
bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create)
{
- bNodePreview *preview = BKE_node_instance_hash_lookup(previews, key);
+ bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_lookup(previews, key);
if (!preview) {
if (create) {
- preview = MEM_callocN(sizeof(bNodePreview), "node preview");
+ preview = (bNodePreview *)MEM_callocN(sizeof(bNodePreview), "node preview");
BKE_node_instance_hash_insert(previews, key, preview);
}
else {
- return NULL;
+ return nullptr;
}
}
@@ -2391,12 +2405,13 @@ bNodePreview *BKE_node_preview_verify(
if (preview->rect) {
if (preview->xsize != xsize || preview->ysize != ysize) {
MEM_freeN(preview->rect);
- preview->rect = NULL;
+ preview->rect = nullptr;
}
}
- if (preview->rect == NULL) {
- preview->rect = MEM_callocN(4 * xsize + xsize * ysize * sizeof(char[4]), "node preview rect");
+ if (preview->rect == nullptr) {
+ preview->rect = (unsigned char *)MEM_callocN(4 * xsize + xsize * ysize * sizeof(char[4]),
+ "node preview rect");
preview->xsize = xsize;
preview->ysize = ysize;
}
@@ -2407,9 +2422,9 @@ bNodePreview *BKE_node_preview_verify(
bNodePreview *BKE_node_preview_copy(bNodePreview *preview)
{
- bNodePreview *new_preview = MEM_dupallocN(preview);
+ bNodePreview *new_preview = (bNodePreview *)MEM_dupallocN(preview);
if (preview->rect) {
- new_preview->rect = MEM_dupallocN(preview->rect);
+ new_preview->rect = (unsigned char *)MEM_dupallocN(preview->rect);
}
return new_preview;
}
@@ -2498,7 +2513,7 @@ void BKE_node_preview_free_tree(bNodeTree *ntree)
if (ntree->previews) {
BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)BKE_node_preview_free);
- ntree->previews = NULL;
+ ntree->previews = nullptr;
}
}
@@ -2517,7 +2532,7 @@ void BKE_node_preview_clear_tree(bNodeTree *ntree)
bNodeInstanceHashIterator iter;
NODE_INSTANCE_HASH_ITER (iter, ntree->previews) {
- bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
BKE_node_preview_clear(preview);
}
}
@@ -2547,8 +2562,8 @@ void BKE_node_preview_sync_tree(bNodeTree *to_ntree, bNodeTree *from_ntree)
bNodeInstanceHashIterator iter;
NODE_INSTANCE_HASH_ITER (iter, from_previews) {
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
- bNodePreview *from = BKE_node_instance_hash_iterator_get_value(&iter);
- bNodePreview *to = BKE_node_instance_hash_lookup(to_previews, key);
+ bNodePreview *from = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *to = (bNodePreview *)BKE_node_instance_hash_lookup(to_previews, key);
if (from && to) {
node_preview_sync(to, from);
@@ -2566,7 +2581,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo
/* transfer previews */
to_ntree->previews = from_ntree->previews;
- from_ntree->previews = NULL;
+ from_ntree->previews = nullptr;
/* clean up, in case any to_ntree nodes have been removed */
BKE_node_preview_remove_unused(to_ntree);
@@ -2576,7 +2591,7 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo
bNodeInstanceHashIterator iter;
NODE_INSTANCE_HASH_ITER (iter, from_ntree->previews) {
bNodeInstanceKey key = BKE_node_instance_hash_iterator_get_key(&iter);
- bNodePreview *preview = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodePreview *preview = (bNodePreview *)BKE_node_instance_hash_iterator_get_value(&iter);
/* replace existing previews */
BKE_node_instance_hash_remove(
@@ -2584,10 +2599,10 @@ void BKE_node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, boo
BKE_node_instance_hash_insert(to_ntree->previews, key, preview);
}
- /* Note: NULL free function here,
+ /* Note: null free function here,
* because pointers have already been moved over to to_ntree->previews! */
- BKE_node_instance_hash_free(from_ntree->previews, NULL);
- from_ntree->previews = NULL;
+ BKE_node_instance_hash_free(from_ntree->previews, nullptr);
+ from_ntree->previews = nullptr;
}
}
}
@@ -2633,7 +2648,7 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
lb = &node->inputs;
}
else {
- lb = NULL;
+ lb = nullptr;
}
if (lb) {
@@ -2677,7 +2692,7 @@ static void node_free_node(bNodeTree *ntree, bNode *node)
/* texture node has bad habit of keeping exec data around */
if (ntree->type == NTREE_TEXTURE && ntree->execdata) {
ntreeTexEndExecTree(ntree->execdata);
- ntree->execdata = NULL;
+ ntree->execdata = nullptr;
}
}
@@ -2754,7 +2769,7 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user)
BLI_snprintf(prefix, sizeof(prefix), "nodes[\"%s\"]", propname_esc);
if (BKE_animdata_fix_paths_remove((ID *)ntree, prefix)) {
- if (bmain != NULL) {
+ if (bmain != nullptr) {
DEG_relations_tag_update(bmain);
}
}
@@ -2826,7 +2841,7 @@ void ntreeFreeLocalTree(bNodeTree *ntree)
void ntreeFreeCache(bNodeTree *ntree)
{
- if (ntree == NULL) {
+ if (ntree == nullptr) {
return;
}
@@ -2925,7 +2940,7 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id)
case ID_SIM:
return &((Simulation *)id)->nodetree;
default:
- return NULL;
+ return nullptr;
}
}
@@ -2933,10 +2948,10 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id)
bNodeTree *ntreeFromID(ID *id)
{
bNodeTree **nodetree = BKE_ntree_ptr_from_id(id);
- return (nodetree != NULL) ? *nodetree : NULL;
+ return (nodetree != nullptr) ? *nodetree : nullptr;
}
-/* Finds and returns the datablock that privately owns the given tree, or NULL. */
+/* Finds and returns the datablock that privately owns the given tree, or null. */
ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
{
ListBase *lists[] = {&bmain->materials,
@@ -2946,9 +2961,9 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
&bmain->scenes,
&bmain->linestyles,
&bmain->simulations,
- NULL};
+ nullptr};
- for (int i = 0; lists[i] != NULL; i++) {
+ for (int i = 0; lists[i] != nullptr; i++) {
LISTBASE_FOREACH (ID *, id, lists[i]) {
if (ntreeFromID(id) == ntree) {
return id;
@@ -2956,12 +2971,12 @@ ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
}
}
- return NULL;
+ return nullptr;
}
-bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode)
+bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode)
{
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) {
if (node == testnode) {
return true;
}
@@ -2969,9 +2984,9 @@ bool ntreeNodeExists(bNodeTree *ntree, bNode *testnode)
return false;
}
-bool ntreeOutputExists(bNode *node, bNodeSocket *testsock)
+bool ntreeOutputExists(const bNode *node, const bNodeSocket *testsock)
{
- LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) {
+ LISTBASE_FOREACH (const bNodeSocket *, sock, &node->outputs) {
if (sock == testsock) {
return true;
}
@@ -2999,7 +3014,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
* Note: previews are not copied here.
*/
bNodeTree *ltree = (bNodeTree *)BKE_id_copy_ex(
- NULL, &ntree->id, NULL, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
+ nullptr, &ntree->id, nullptr, (LIB_ID_COPY_LOCALIZE | LIB_ID_COPY_NO_ANIMDATA));
ltree->id.tag |= LIB_TAG_LOCALIZED;
@@ -3012,9 +3027,9 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
/* ensures only a single output node is enabled */
ntreeSetOutput(ntree);
- bNode *node_src = ntree->nodes.first;
- bNode *node_local = ltree->nodes.first;
- while (node_src != NULL) {
+ bNode *node_src = (bNode *)ntree->nodes.first;
+ bNode *node_local = (bNode *)ltree->nodes.first;
+ while (node_src != nullptr) {
node_local->original = node_src;
node_src = node_src->next;
node_local = node_local->next;
@@ -3027,7 +3042,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
return ltree;
}
- return NULL;
+ return nullptr;
}
/* sync local composite with real tree */
@@ -3066,11 +3081,11 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
bNodeSocketType *stype = nodeSocketTypeFind(idname);
int own_index = ntree->cur_index++;
- if (stype == NULL) {
- return NULL;
+ if (stype == nullptr) {
+ return nullptr;
}
- bNodeSocket *sock = MEM_callocN(sizeof(bNodeSocket), "socket template");
+ bNodeSocket *sock = (bNodeSocket *)MEM_callocN(sizeof(bNodeSocket), "socket template");
BLI_strncpy(sock->idname, stype->idname, sizeof(sock->idname));
node_socket_set_typeinfo(ntree, sock, stype);
sock->in_out = in_out;
@@ -3089,7 +3104,7 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
sock->limit = (in_out == SOCK_IN ? 1 : 0xFFF);
BLI_strncpy(sock->name, name, NODE_MAXSTR);
- sock->storage = NULL;
+ sock->storage = nullptr;
sock->flag |= SOCK_COLLAPSED;
return sock;
@@ -3103,7 +3118,7 @@ bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree, int in_out, const char *
return iosock;
}
}
- return NULL;
+ return nullptr;
}
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
@@ -3190,7 +3205,7 @@ static void ntree_interface_identifier_base(bNodeTree *ntree, char *base)
/* check if the identifier is already in use */
static bool ntree_interface_unique_identifier_check(void *UNUSED(data), const char *identifier)
{
- return (RNA_struct_find(identifier) != NULL);
+ return (RNA_struct_find(identifier) != nullptr);
}
/* generates the actual unique identifier and ui name and description */
@@ -3206,7 +3221,8 @@ static void ntree_interface_identifier(bNodeTree *ntree,
* On top of the sanitized id string add a number suffix if necessary to avoid duplicates.
*/
identifier[0] = '\0';
- BLI_uniquename_cb(ntree_interface_unique_identifier_check, NULL, base, '_', identifier, maxlen);
+ BLI_uniquename_cb(
+ ntree_interface_unique_identifier_check, nullptr, base, '_', identifier, maxlen);
sprintf(name, "Node Tree %s Interface", ntree->id.name + 2);
sprintf(description, "Interface properties of node group %s", ntree->id.name + 2);
@@ -3246,7 +3262,7 @@ static void ntree_interface_type_create(bNodeTree *ntree)
}
}
-StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, int create)
+StructRNA *ntreeInterfaceTypeGet(bNodeTree *ntree, bool create)
{
if (ntree->interface_type) {
/* strings are generated from base string + ID name, sizes are sufficient */
@@ -3284,7 +3300,7 @@ void ntreeInterfaceTypeFree(bNodeTree *ntree)
{
if (ntree->interface_type) {
RNA_struct_free(&BLENDER_RNA, ntree->interface_type);
- ntree->interface_type = NULL;
+ ntree->interface_type = nullptr;
}
}
@@ -3310,12 +3326,12 @@ bNode *ntreeFindType(const bNodeTree *ntree, int type)
}
}
}
- return NULL;
+ return nullptr;
}
bool ntreeHasType(const bNodeTree *ntree, int type)
{
- return ntreeFindType(ntree, type) != NULL;
+ return ntreeFindType(ntree, type) != nullptr;
}
bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
@@ -3333,7 +3349,7 @@ bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup)
return false;
}
-bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
+bNodeLink *nodeFindLink(bNodeTree *ntree, const bNodeSocket *from, const bNodeSocket *to)
{
LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
if (link->fromsock == from && link->tosock == to) {
@@ -3343,13 +3359,13 @@ bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
return link;
}
}
- return NULL;
+ return nullptr;
}
-int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
+int nodeCountSocketLinks(const bNodeTree *ntree, const bNodeSocket *sock)
{
int tot = 0;
- LISTBASE_FOREACH (bNodeLink *, link, &ntree->links) {
+ LISTBASE_FOREACH (const bNodeLink *, link, &ntree->links) {
if (link->fromsock == sock || link->tosock == sock) {
tot++;
}
@@ -3359,8 +3375,8 @@ int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
bNode *nodeGetActive(bNodeTree *ntree)
{
- if (ntree == NULL) {
- return NULL;
+ if (ntree == nullptr) {
+ return nullptr;
}
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -3368,7 +3384,7 @@ bNode *nodeGetActive(bNodeTree *ntree)
return node;
}
}
- return NULL;
+ return nullptr;
}
static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key,
@@ -3400,7 +3416,7 @@ static bNode *node_get_active_id_recursive(bNodeInstanceKey active_key,
}
}
}
- return NULL;
+ return nullptr;
}
/* two active flags, ID nodes have special flag for buttons display */
@@ -3410,14 +3426,14 @@ bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
return node_get_active_id_recursive(
ntree->active_viewer_key, NODE_INSTANCE_KEY_BASE, ntree, idtype);
}
- return NULL;
+ return nullptr;
}
bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
{
bool ok = false;
- if (ntree == NULL) {
+ if (ntree == nullptr) {
return ok;
}
@@ -3435,11 +3451,11 @@ bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
/* update all groups linked from here
* if active ID node has been found already,
- * just pass NULL so other matching nodes are deactivated.
+ * just pass null so other matching nodes are deactivated.
*/
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->type == NODE_GROUP) {
- ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : NULL));
+ ok |= nodeSetActiveID((bNodeTree *)node->id, idtype, (ok == false ? id : nullptr));
}
}
@@ -3449,7 +3465,7 @@ bool nodeSetActiveID(bNodeTree *ntree, short idtype, ID *id)
/* two active flags, ID nodes have special flag for buttons display */
void nodeClearActiveID(bNodeTree *ntree, short idtype)
{
- if (ntree == NULL) {
+ if (ntree == nullptr) {
return;
}
@@ -3480,7 +3496,7 @@ void nodeSetSelected(bNode *node, bool select)
void nodeClearActive(bNodeTree *ntree)
{
- if (ntree == NULL) {
+ if (ntree == nullptr) {
return;
}
@@ -3515,7 +3531,7 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
}
}
-int nodeSocketIsHidden(bNodeSocket *sock)
+int nodeSocketIsHidden(const bNodeSocket *sock)
{
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
}
@@ -3530,10 +3546,13 @@ void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
}
}
-int nodeSocketLinkLimit(struct bNodeSocket *sock)
+int nodeSocketLinkLimit(const bNodeSocket *sock)
{
bNodeSocketType *stype = sock->typeinfo;
- if (stype != NULL && stype->use_link_limits_of_type) {
+ if (sock->flag & SOCK_MULTI_INPUT) {
+ return 4095;
+ }
+ if (stype != nullptr && stype->use_link_limits_of_type) {
int limit = (sock->in_out == SOCK_IN) ? stype->input_link_limit : stype->output_link_limit;
return limit;
}
@@ -3553,15 +3572,15 @@ int nodeSocketLinkLimit(struct bNodeSocket *sock)
* Currently its only used for ID's, but nodes may one day
* reference other pointers which need validation.
*/
-typedef struct bNodeClipboardExtraInfo {
+struct bNodeClipboardExtraInfo {
struct bNodeClipboardExtraInfo *next, *prev;
ID *id;
char id_name[MAX_ID_NAME];
char library_name[FILE_MAX];
-} bNodeClipboardExtraInfo;
+};
#endif /* USE_NODE_CB_VALIDATE */
-typedef struct bNodeClipboard {
+struct bNodeClipboard {
ListBase nodes;
#ifdef USE_NODE_CB_VALIDATE
@@ -3570,11 +3589,11 @@ typedef struct bNodeClipboard {
ListBase links;
int type;
-} bNodeClipboard;
+};
-static bNodeClipboard node_clipboard = {{NULL}};
+static bNodeClipboard node_clipboard = {{nullptr}};
-void BKE_node_clipboard_init(struct bNodeTree *ntree)
+void BKE_node_clipboard_init(const struct bNodeTree *ntree)
{
node_clipboard.type = ntree->type;
}
@@ -3582,12 +3601,12 @@ void BKE_node_clipboard_init(struct bNodeTree *ntree)
void BKE_node_clipboard_clear(void)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &node_clipboard.links) {
- nodeRemLink(NULL, link);
+ nodeRemLink(nullptr, link);
}
BLI_listbase_clear(&node_clipboard.links);
LISTBASE_FOREACH_MUTABLE (bNode *, node, &node_clipboard.nodes) {
- node_free_node(NULL, node);
+ node_free_node(nullptr, node);
}
BLI_listbase_clear(&node_clipboard.nodes);
@@ -3609,8 +3628,10 @@ bool BKE_node_clipboard_validate(void)
BLI_assert(BLI_listbase_count(&node_clipboard.nodes) ==
BLI_listbase_count(&node_clipboard.nodes_extra_info));
- for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first; node;
- node = node->next, node_info = node_info->next) {
+ for (node = (bNode *)node_clipboard.nodes.first,
+ node_info = (bNodeClipboardExtraInfo *)node_clipboard.nodes_extra_info.first;
+ node;
+ node = (bNode *)node->next, node_info = (bNodeClipboardExtraInfo *)node_info->next) {
/* validate the node against the stored node info */
/* re-assign each loop since we may clear,
@@ -3621,13 +3642,13 @@ bool BKE_node_clipboard_validate(void)
if (node->id) {
/* We want to search into current blend file, so using G_MAIN is valid here too. */
ListBase *lb = which_libbase(G_MAIN, GS(node_info->id_name));
- BLI_assert(lb != NULL);
+ BLI_assert(lb != nullptr);
if (BLI_findindex(lb, node_info->id) == -1) {
- /* may assign NULL */
- node->id = BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
+ /* May assign null. */
+ node->id = (ID *)BLI_findstring(lb, node_info->id_name + 2, offsetof(ID, name) + 2);
- if (node->id == NULL) {
+ if (node->id == nullptr) {
ok = false;
}
}
@@ -3642,8 +3663,8 @@ void BKE_node_clipboard_add_node(bNode *node)
{
#ifdef USE_NODE_CB_VALIDATE
/* add extra info */
- bNodeClipboardExtraInfo *node_info = MEM_mallocN(sizeof(bNodeClipboardExtraInfo),
- "bNodeClipboardExtraInfo");
+ bNodeClipboardExtraInfo *node_info = (bNodeClipboardExtraInfo *)MEM_mallocN(
+ sizeof(bNodeClipboardExtraInfo), __func__);
node_info->id = node->id;
if (node->id) {
@@ -3718,11 +3739,11 @@ static bNodeInstanceKey node_hash_int_str(bNodeInstanceKey hash, const char *str
return hash;
}
-bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key, bNodeTree *ntree, bNode *node)
+bNodeInstanceKey BKE_node_instance_key(bNodeInstanceKey parent_key,
+ const bNodeTree *ntree,
+ const bNode *node)
{
- bNodeInstanceKey key;
-
- key = node_hash_int_str(parent_key, ntree->id.name + 2);
+ bNodeInstanceKey key = node_hash_int_str(parent_key, ntree->id.name + 2);
if (node) {
key = node_hash_int_str(key, node->name);
@@ -3746,7 +3767,7 @@ static bool node_instance_hash_key_cmp(const void *a, const void *b)
bNodeInstanceHash *BKE_node_instance_hash_new(const char *info)
{
- bNodeInstanceHash *hash = MEM_mallocN(sizeof(bNodeInstanceHash), info);
+ bNodeInstanceHash *hash = (bNodeInstanceHash *)MEM_mallocN(sizeof(bNodeInstanceHash), info);
hash->ghash = BLI_ghash_new(
node_instance_hash_key, node_instance_hash_key_cmp, "node instance hash ghash");
return hash;
@@ -3754,13 +3775,13 @@ bNodeInstanceHash *BKE_node_instance_hash_new(const char *info)
void BKE_node_instance_hash_free(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
{
- BLI_ghash_free(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+ BLI_ghash_free(hash->ghash, nullptr, (GHashValFreeFP)valfreefp);
MEM_freeN(hash);
}
void BKE_node_instance_hash_insert(bNodeInstanceHash *hash, bNodeInstanceKey key, void *value)
{
- bNodeInstanceHashEntry *entry = value;
+ bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value;
entry->key = key;
entry->tag = 0;
BLI_ghash_insert(hash->ghash, &entry->key, value);
@@ -3775,17 +3796,17 @@ int BKE_node_instance_hash_remove(bNodeInstanceHash *hash,
bNodeInstanceKey key,
bNodeInstanceValueFP valfreefp)
{
- return BLI_ghash_remove(hash->ghash, &key, NULL, (GHashValFreeFP)valfreefp);
+ return BLI_ghash_remove(hash->ghash, &key, nullptr, (GHashValFreeFP)valfreefp);
}
void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP valfreefp)
{
- BLI_ghash_clear(hash->ghash, NULL, (GHashValFreeFP)valfreefp);
+ BLI_ghash_clear(hash->ghash, nullptr, (GHashValFreeFP)valfreefp);
}
void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key)
{
- return BLI_ghash_popkey(hash->ghash, &key, NULL);
+ return BLI_ghash_popkey(hash->ghash, &key, nullptr);
}
int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
@@ -3803,7 +3824,8 @@ void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
bNodeInstanceHashIterator iter;
NODE_INSTANCE_HASH_ITER (iter, hash) {
- bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *)
+ BKE_node_instance_hash_iterator_get_value(&iter);
value->tag = 0;
}
@@ -3811,13 +3833,14 @@ void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
void BKE_node_instance_hash_tag(bNodeInstanceHash *UNUSED(hash), void *value)
{
- bNodeInstanceHashEntry *entry = value;
+ bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)value;
entry->tag = 1;
}
bool BKE_node_instance_hash_tag_key(bNodeInstanceHash *hash, bNodeInstanceKey key)
{
- bNodeInstanceHashEntry *entry = BKE_node_instance_hash_lookup(hash, key);
+ bNodeInstanceHashEntry *entry = (bNodeInstanceHashEntry *)BKE_node_instance_hash_lookup(hash,
+ key);
if (entry) {
entry->tag = 1;
@@ -3833,13 +3856,14 @@ void BKE_node_instance_hash_remove_untagged(bNodeInstanceHash *hash,
/* NOTE: Hash must not be mutated during iterating!
* Store tagged entries in a separate list and remove items afterward.
*/
- bNodeInstanceKey *untagged = MEM_mallocN(sizeof(bNodeInstanceKey) *
- BKE_node_instance_hash_size(hash),
- "temporary node instance key list");
+ bNodeInstanceKey *untagged = (bNodeInstanceKey *)MEM_mallocN(
+ sizeof(bNodeInstanceKey) * BKE_node_instance_hash_size(hash),
+ "temporary node instance key list");
bNodeInstanceHashIterator iter;
int num_untagged = 0;
NODE_INSTANCE_HASH_ITER (iter, hash) {
- bNodeInstanceHashEntry *value = BKE_node_instance_hash_iterator_get_value(&iter);
+ bNodeInstanceHashEntry *value = (bNodeInstanceHashEntry *)
+ BKE_node_instance_hash_iterator_get_value(&iter);
if (!value->tag) {
untagged[num_untagged++] = BKE_node_instance_hash_iterator_get_key(&iter);
@@ -3903,12 +3927,12 @@ void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, in
(*totnodes)++;
}
if (*totnodes == 0) {
- *deplist = NULL;
+ *deplist = nullptr;
return;
}
bNode **nsort;
- nsort = *deplist = MEM_callocN((*totnodes) * sizeof(bNode *), "sorted node array");
+ nsort = *deplist = (bNode **)MEM_callocN((*totnodes) * sizeof(bNode *), "sorted node array");
/* recursive check */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -3929,7 +3953,7 @@ static void ntree_update_node_level(bNodeTree *ntree)
/* recursive check */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
if (node->done == 0) {
- node->level = node_get_deplist_recurs(ntree, node, NULL);
+ node->level = node_get_deplist_recurs(ntree, node, nullptr);
}
}
}
@@ -3957,7 +3981,7 @@ static void ntree_update_link_pointers(bNodeTree *ntree)
/* first clear data */
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) {
- sock->link = NULL;
+ sock->link = nullptr;
}
}
@@ -3996,7 +4020,7 @@ void ntreeUpdateAllNew(Main *main)
}
}
- ntreeUpdateTree(NULL, ntree);
+ ntreeUpdateTree(nullptr, ntree);
}
}
FOREACH_NODETREE_END;
@@ -4004,7 +4028,7 @@ void ntreeUpdateAllNew(Main *main)
void ntreeUpdateAllUsers(Main *main, ID *id)
{
- if (id == NULL) {
+ if (id == nullptr) {
return;
}
@@ -4023,7 +4047,7 @@ void ntreeUpdateAllUsers(Main *main, ID *id)
}
if (need_update) {
- ntreeUpdateTree(NULL, ntree);
+ ntreeUpdateTree(nullptr, ntree);
}
}
FOREACH_NODETREE_END;
@@ -4133,7 +4157,7 @@ bool nodeUpdateID(bNodeTree *ntree, ID *id)
{
bool changed = false;
- if (ELEM(NULL, id, ntree)) {
+ if (ELEM(nullptr, id, ntree)) {
return changed;
}
@@ -4237,7 +4261,7 @@ void node_type_base(bNodeType *ntype, int type, const char *name, short nclass,
case ID: \
BLI_strncpy(ntype->idname, #Category #StructName, sizeof(ntype->idname)); \
ntype->rna_ext.srna = RNA_struct_find(#Category #StructName); \
- BLI_assert(ntype->rna_ext.srna != NULL); \
+ BLI_assert(ntype->rna_ext.srna != nullptr); \
RNA_struct_blender_type_set(ntype->rna_ext.srna, ntype); \
break;
@@ -4271,15 +4295,16 @@ void node_type_base_custom(
node_type_base_defaults(ntype);
}
+struct SocketTemplateIdentifierCallbackData {
+ bNodeSocketTemplate *list;
+ bNodeSocketTemplate *ntemp;
+};
+
static bool unique_socket_template_identifier_check(void *arg, const char *name)
{
- bNodeSocketTemplate *ntemp;
- struct {
- bNodeSocketTemplate *list;
- bNodeSocketTemplate *ntemp;
- } *data = arg;
+ SocketTemplateIdentifierCallbackData *data = (SocketTemplateIdentifierCallbackData *)arg;
- for (ntemp = data->list; ntemp->type >= 0; ntemp++) {
+ for (bNodeSocketTemplate *ntemp = data->list; ntemp->type >= 0; ntemp++) {
if (ntemp != data->ntemp) {
if (STREQ(ntemp->identifier, name)) {
return true;
@@ -4295,10 +4320,7 @@ static void unique_socket_template_identifier(bNodeSocketTemplate *list,
const char defname[],
char delim)
{
- struct {
- bNodeSocketTemplate *list;
- bNodeSocketTemplate *ntemp;
- } data;
+ SocketTemplateIdentifierCallbackData data;
data.list = list;
data.ntemp = ntemp;
@@ -4448,7 +4470,7 @@ static bool node_undefined_poll(bNodeType *UNUSED(ntype), bNodeTree *UNUSED(node
}
/* register fallback types used for undefined tree, nodes, sockets */
-static void register_undefined_types(void)
+static void register_undefined_types()
{
/* Note: these types are not registered in the type hashes,
* they are just used as placeholders in case the actual types are not registered.
@@ -4473,7 +4495,7 @@ static void register_undefined_types(void)
NodeSocketTypeUndefined.output_link_limit = 0xFFF;
}
-static void registerCompositNodes(void)
+static void registerCompositNodes()
{
register_node_type_cmp_group();
@@ -4577,7 +4599,7 @@ static void registerCompositNodes(void)
register_node_type_cmp_cornerpin();
}
-static void registerShaderNodes(void)
+static void registerShaderNodes()
{
register_node_type_sh_group();
@@ -4674,7 +4696,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_white_noise();
}
-static void registerTextureNodes(void)
+static void registerTextureNodes()
{
register_node_type_tex_group();
@@ -4724,7 +4746,7 @@ static void registerTextureNodes(void)
register_node_type_tex_proc_distnoise();
}
-static void registerGeometryNodes(void)
+static void registerGeometryNodes()
{
register_node_type_geo_group();
@@ -4749,9 +4771,12 @@ static void registerGeometryNodes(void)
register_node_type_geo_attribute_color_ramp();
register_node_type_geo_point_rotate();
register_node_type_geo_align_rotation_to_vector();
+ register_node_type_geo_sample_texture();
+ register_node_type_geo_points_to_volume();
+ register_node_type_geo_collection_info();
}
-static void registerFunctionNodes(void)
+static void registerFunctionNodes()
{
register_node_type_fn_boolean_math();
register_node_type_fn_float_compare();
@@ -4800,8 +4825,8 @@ void BKE_node_system_exit(void)
}
NODE_TYPES_END;
- BLI_ghash_free(nodetypes_hash, NULL, node_free_type);
- nodetypes_hash = NULL;
+ BLI_ghash_free(nodetypes_hash, nullptr, node_free_type);
+ nodetypes_hash = nullptr;
}
if (nodesockettypes_hash) {
@@ -4815,8 +4840,8 @@ void BKE_node_system_exit(void)
}
NODE_SOCKET_TYPES_END;
- BLI_ghash_free(nodesockettypes_hash, NULL, node_free_socket_type);
- nodesockettypes_hash = NULL;
+ BLI_ghash_free(nodesockettypes_hash, nullptr, node_free_socket_type);
+ nodesockettypes_hash = nullptr;
}
if (nodetreetypes_hash) {
@@ -4827,8 +4852,8 @@ void BKE_node_system_exit(void)
}
NODE_TREE_TYPES_END;
- BLI_ghash_free(nodetreetypes_hash, NULL, ntree_free_type);
- nodetreetypes_hash = NULL;
+ BLI_ghash_free(nodetreetypes_hash, nullptr, ntree_free_type);
+ nodetreetypes_hash = nullptr;
}
}
@@ -4837,58 +4862,58 @@ void BKE_node_system_exit(void)
void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain)
{
- ntreeiter->ngroup = bmain->nodetrees.first;
- ntreeiter->scene = bmain->scenes.first;
- ntreeiter->mat = bmain->materials.first;
- ntreeiter->tex = bmain->textures.first;
- ntreeiter->light = bmain->lights.first;
- ntreeiter->world = bmain->worlds.first;
- ntreeiter->linestyle = bmain->linestyles.first;
- ntreeiter->simulation = bmain->simulations.first;
+ ntreeiter->ngroup = (bNodeTree *)bmain->nodetrees.first;
+ ntreeiter->scene = (Scene *)bmain->scenes.first;
+ ntreeiter->mat = (Material *)bmain->materials.first;
+ ntreeiter->tex = (Tex *)bmain->textures.first;
+ ntreeiter->light = (Light *)bmain->lights.first;
+ ntreeiter->world = (World *)bmain->worlds.first;
+ ntreeiter->linestyle = (FreestyleLineStyle *)bmain->linestyles.first;
+ ntreeiter->simulation = (Simulation *)bmain->simulations.first;
}
bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
bNodeTree **r_nodetree,
struct ID **r_id)
{
if (ntreeiter->ngroup) {
- *r_nodetree = ntreeiter->ngroup;
+ *r_nodetree = (bNodeTree *)ntreeiter->ngroup;
*r_id = (ID *)ntreeiter->ngroup;
- ntreeiter->ngroup = ntreeiter->ngroup->id.next;
+ ntreeiter->ngroup = (bNodeTree *)ntreeiter->ngroup->id.next;
}
else if (ntreeiter->scene) {
- *r_nodetree = ntreeiter->scene->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->scene->nodetree;
*r_id = (ID *)ntreeiter->scene;
- ntreeiter->scene = ntreeiter->scene->id.next;
+ ntreeiter->scene = (Scene *)ntreeiter->scene->id.next;
}
else if (ntreeiter->mat) {
- *r_nodetree = ntreeiter->mat->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->mat->nodetree;
*r_id = (ID *)ntreeiter->mat;
- ntreeiter->mat = ntreeiter->mat->id.next;
+ ntreeiter->mat = (Material *)ntreeiter->mat->id.next;
}
else if (ntreeiter->tex) {
- *r_nodetree = ntreeiter->tex->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->tex->nodetree;
*r_id = (ID *)ntreeiter->tex;
- ntreeiter->tex = ntreeiter->tex->id.next;
+ ntreeiter->tex = (Tex *)ntreeiter->tex->id.next;
}
else if (ntreeiter->light) {
- *r_nodetree = ntreeiter->light->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->light->nodetree;
*r_id = (ID *)ntreeiter->light;
- ntreeiter->light = ntreeiter->light->id.next;
+ ntreeiter->light = (Light *)ntreeiter->light->id.next;
}
else if (ntreeiter->world) {
- *r_nodetree = ntreeiter->world->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->world->nodetree;
*r_id = (ID *)ntreeiter->world;
- ntreeiter->world = ntreeiter->world->id.next;
+ ntreeiter->world = (World *)ntreeiter->world->id.next;
}
else if (ntreeiter->linestyle) {
- *r_nodetree = ntreeiter->linestyle->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->linestyle->nodetree;
*r_id = (ID *)ntreeiter->linestyle;
- ntreeiter->linestyle = ntreeiter->linestyle->id.next;
+ ntreeiter->linestyle = (FreestyleLineStyle *)ntreeiter->linestyle->id.next;
}
else if (ntreeiter->simulation) {
- *r_nodetree = ntreeiter->simulation->nodetree;
+ *r_nodetree = (bNodeTree *)ntreeiter->simulation->nodetree;
*r_id = (ID *)ntreeiter->simulation;
- ntreeiter->simulation = ntreeiter->simulation->id.next;
+ ntreeiter->simulation = (Simulation *)ntreeiter->simulation->id.next;
}
else {
return false;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 155508e9caa..381823754e9 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1118,6 +1118,20 @@ static void object_blend_read_expand(BlendExpander *expander, ID *id)
}
}
+static void object_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src))
+{
+ Object *object = (Object *)id_dst;
+
+ ListBase pidlist;
+ BKE_ptcache_ids_from_object(&pidlist, object, NULL, 0);
+ LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
+ LISTBASE_FOREACH (PointCache *, point_cache, pid->ptcaches) {
+ point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
+ }
+ }
+ BLI_freelistN(&pidlist);
+}
+
IDTypeInfo IDType_ID_OB = {
.id_code = ID_OB,
.id_filter = FILTER_ID_OB,
@@ -1141,6 +1155,8 @@ IDTypeInfo IDType_ID_OB = {
.blend_read_expand = object_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = object_lib_override_apply_post,
};
void BKE_object_workob_clear(Object *workob)
@@ -1506,11 +1522,11 @@ bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData
/**
* Copy the whole stack of modifiers from one object into another.
*
- * \warning **Does not** clear modifier stack and related data (particle systems, softbody,
+ * \warning **Does not** clear modifier stack and related data (particle systems, soft-body,
* etc.) in `ob_dst`, if needed calling code must do it.
*
- * @param do_copy_all If true, even modifiers that should not suport copying (like Hook one) will
- * be duplicated.
+ * \param do_copy_all: If true, even modifiers that should not support copying (like Hook one)
+ * will be duplicated.
*/
bool BKE_object_modifier_stack_copy(Object *ob_dst,
const Object *ob_src,
@@ -3527,9 +3543,6 @@ static void solve_parenting(
}
}
-/**
- * \note scene is the active scene while actual_scene is the scene the object resides in.
- */
static void object_where_is_calc_ex(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 1d79f871fa2..69442b7646c 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -225,7 +225,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
case OB_GPENCIL: {
BKE_gpencil_prepare_eval_data(depsgraph, scene, ob);
BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
- BKE_gpencil_update_layer_parent(depsgraph, ob);
+ BKE_gpencil_update_layer_transforms(depsgraph, ob);
break;
}
case OB_HAIR:
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 1d62a1cce2a..d2f4d0702ed 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -140,7 +140,7 @@ static void compute_eigenstuff(struct OceanResult *ocr, float jxx, float jzz, fl
* instead of Complex.h
* in fftw.h "fftw_complex" typedefed as double[2]
* below you can see functions are needed to work with such complex numbers.
- * */
+ */
static void init_complex(fftw_complex cmpl, float real, float image)
{
cmpl[0] = real;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 7c65f118cf4..13f4304f923 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -158,6 +158,8 @@ IDTypeInfo IDType_ID_PAL = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = palette_undo_preserve,
+
+ .lib_override_apply_post = NULL,
};
static void paint_curve_copy_data(Main *UNUSED(bmain),
@@ -221,6 +223,8 @@ IDTypeInfo IDType_ID_PC = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100};
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 335913c9b8e..ec3b6198d7c 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -511,6 +511,8 @@ IDTypeInfo IDType_ID_PA = {
.blend_read_expand = particle_settings_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 55d4043f96c..c727a144c87 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -1400,8 +1400,9 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra)
static void psys_update_effectors(ParticleSimulationData *sim)
{
BKE_effectors_free(sim->psys->effectors);
+ bool use_rotation = (sim->psys->part->flag & PART_ROT_DYN) != 0;
sim->psys->effectors = BKE_effectors_create(
- sim->depsgraph, sim->ob, sim->psys, sim->psys->part->effector_weights);
+ sim->depsgraph, sim->ob, sim->psys, sim->psys->part->effector_weights, use_rotation);
precalc_guides(sim, sim->psys->effectors);
}
diff --git a/source/blender/blenkernel/intern/pointcloud.cc b/source/blender/blenkernel/intern/pointcloud.cc
index 7bd14e80333..b9ff2a1179d 100644
--- a/source/blender/blenkernel/intern/pointcloud.cc
+++ b/source/blender/blenkernel/intern/pointcloud.cc
@@ -190,6 +190,8 @@ IDTypeInfo IDType_ID_PT = {
/* blend_read_expand */ pointcloud_blend_read_expand,
/* blend_read_undo_preserve */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
static void pointcloud_random(PointCloud *pointcloud)
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 586aeb274a5..19078446009 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1720,7 +1720,7 @@ static void rigidbody_update_sim_ob(
ListBase *effectors;
/* get effectors present in the group specified by effector_weights */
- effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights);
+ effectors = BKE_effectors_create(depsgraph, ob, NULL, effector_weights, false);
if (effectors) {
float eff_force[3] = {0.0f, 0.0f, 0.0f};
float eff_loc[3], eff_vel[3];
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index b19b0e684b2..0ce5240b17d 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -1689,6 +1689,19 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
}
}
+static void scene_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src))
+{
+ Scene *scene = (Scene *)id_dst;
+
+ if (scene->rigidbody_world != NULL) {
+ PTCacheID pid;
+ BKE_ptcache_id_from_rigidbody(&pid, NULL, scene->rigidbody_world);
+ LISTBASE_FOREACH (PointCache *, point_cache, pid.ptcaches) {
+ point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
+ }
+ }
+}
+
IDTypeInfo IDType_ID_SCE = {
.id_code = ID_SCE,
.id_filter = FILTER_ID_SCE,
@@ -1714,6 +1727,8 @@ IDTypeInfo IDType_ID_SCE = {
.blend_read_expand = scene_blend_read_expand,
.blend_read_undo_preserve = scene_undo_preserve,
+
+ .lib_override_apply_post = scene_lib_override_apply_post,
};
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 52c41c9fd05..80a83aecea8 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -315,6 +315,8 @@ IDTypeInfo IDType_ID_SCR = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* ************ Spacetype/regiontype handling ************** */
@@ -1599,8 +1601,7 @@ static void direct_link_area(BlendDataReader *reader, ScrArea *area)
BLO_read_list(reader, &snode->treepath);
snode->edittree = NULL;
- snode->iofsd = NULL;
- BLI_listbase_clear(&snode->linkdrag);
+ snode->runtime = NULL;
}
else if (sl->spacetype == SPACE_TEXT) {
SpaceText *st = (SpaceText *)sl;
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index 14e6ce63023..4e0a08455e6 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -173,6 +173,8 @@ IDTypeInfo IDType_ID_SIM = {
/* blend_read_expand */ simulation_blend_read_expand,
/* blend_read_undo_preserve */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
void *BKE_simulation_add(Main *bmain, const char *name)
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 736acd76dfd..de88e8a941c 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1539,7 +1539,8 @@ static void sb_sfesf_threads_run(struct Depsgraph *depsgraph,
* or even be UI option sb->spawn_cf_threads_nopts */
int lowsprings = 100;
- ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, ob->soft->effector_weights);
+ ListBase *effectors = BKE_effectors_create(
+ depsgraph, ob, NULL, ob->soft->effector_weights, false);
/* figure the number of threads while preventing pretty pointless threading overhead */
totthread = BKE_scene_num_threads(scene);
@@ -2300,7 +2301,7 @@ static void softbody_calc_forces(
}
/* after spring scan because it uses Effoctors too */
- ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights);
+ ListBase *effectors = BKE_effectors_create(depsgraph, ob, NULL, sb->effector_weights, false);
if (do_deflector) {
float defforce[3];
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 78729fb9261..0c917434bd1 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -221,6 +221,8 @@ IDTypeInfo IDType_ID_SO = {
.blend_read_expand = sound_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
#ifdef WITH_AUDASPACE
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index fabf0bb8971..9caeaf05e6a 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -114,6 +114,8 @@ IDTypeInfo IDType_ID_SPK = {
.blend_read_expand = speaker_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
void *BKE_speaker_add(Main *bmain, const char *name)
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 9ef2e818293..9bf215515f7 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -258,6 +258,8 @@ IDTypeInfo IDType_ID_TXT = {
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/** \} */
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 4c2e4a82acb..ce84bfcd95a 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -226,6 +226,8 @@ IDTypeInfo IDType_ID_TE = {
.blend_read_expand = texture_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* Utils for all IDs using those texture slots. */
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index e5f9d59270e..d124922acd1 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -587,15 +587,15 @@ MovieTrackingTrack *BKE_tracking_track_add(MovieTracking *tracking,
{
const MovieTrackingSettings *settings = &tracking->settings;
+ MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase);
+ MovieTrackingMarker marker;
+
const float half_pattern_px = settings->default_pattern_size / 2.0f;
const float half_search_px = settings->default_search_size / 2.0f;
const float pattern_size[2] = {half_pattern_px / width, half_pattern_px / height};
const float search_size[2] = {half_search_px / width, half_search_px / height};
- MovieTrackingTrack *track = BKE_tracking_track_add_empty(tracking, tracksbase);
-
- MovieTrackingMarker marker;
memset(&marker, 0, sizeof(marker));
marker.pos[0] = x;
marker.pos[1] = y;
@@ -665,6 +665,86 @@ void BKE_tracking_track_free(MovieTrackingTrack *track)
}
}
+/* Get frame numbers of the very first and last markers.
+ * There is no check on whether the marker is enabled or not. */
+void BKE_tracking_track_first_last_frame_get(const MovieTrackingTrack *track,
+ int *r_first_frame,
+ int *r_last_frame)
+{
+ BLI_assert(track->markersnr > 0);
+ const int last_marker_index = track->markersnr - 1;
+ *r_first_frame = track->markers[0].framenr;
+ *r_last_frame = track->markers[last_marker_index].framenr;
+}
+
+/* Find the minimum starting frame and maximum ending frame within given set of
+ * tracks.
+ */
+void BKE_tracking_tracks_first_last_frame_minmax(/*const*/ MovieTrackingTrack **tracks,
+ const int num_tracks,
+ int *r_first_frame,
+ int *r_last_frame)
+{
+ *r_first_frame = INT_MAX;
+ *r_last_frame = INT_MIN;
+ for (int i = 0; i < num_tracks; ++i) {
+ const struct MovieTrackingTrack *track = tracks[i];
+ int track_first_frame, track_last_frame;
+ BKE_tracking_track_first_last_frame_get(track, &track_first_frame, &track_last_frame);
+ *r_first_frame = min_ii(*r_first_frame, track_first_frame);
+ *r_last_frame = max_ii(*r_last_frame, track_last_frame);
+ }
+}
+
+int BKE_tracking_count_selected_tracks_in_list(const ListBase *tracks_list)
+{
+ int num_selected_tracks = 0;
+ LISTBASE_FOREACH (const MovieTrackingTrack *, track, tracks_list) {
+ if (TRACK_SELECTED(track)) {
+ ++num_selected_tracks;
+ }
+ }
+ return num_selected_tracks;
+}
+
+int BKE_tracking_count_selected_tracks_in_active_object(/*const*/ MovieTracking *tracking)
+{
+ ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking);
+ return BKE_tracking_count_selected_tracks_in_list(tracks_list);
+}
+
+MovieTrackingTrack **BKE_tracking_selected_tracks_in_active_object(MovieTracking *tracking,
+ int *r_num_tracks)
+{
+ *r_num_tracks = 0;
+
+ ListBase *tracks_list = BKE_tracking_get_active_tracks(tracking);
+ if (tracks_list == NULL) {
+ return NULL;
+ }
+
+ /* Initialize input. */
+ const int num_selected_tracks = BKE_tracking_count_selected_tracks_in_active_object(tracking);
+ if (num_selected_tracks == 0) {
+ return NULL;
+ }
+
+ MovieTrackingTrack **source_tracks = MEM_malloc_arrayN(
+ num_selected_tracks, sizeof(MovieTrackingTrack *), "selected tracks array");
+ int source_track_index = 0;
+ LISTBASE_FOREACH (MovieTrackingTrack *, track, tracks_list) {
+ if (!TRACK_SELECTED(track)) {
+ continue;
+ }
+ source_tracks[source_track_index] = track;
+ ++source_track_index;
+ }
+
+ *r_num_tracks = num_selected_tracks;
+
+ return source_tracks;
+}
+
/* Set flag for all specified track's areas.
*
* area - which part of marker should be selected. see TRACK_AREA_* constants.
@@ -918,6 +998,124 @@ void BKE_tracking_tracks_join(MovieTracking *tracking,
BKE_tracking_dopesheet_tag_update(tracking);
}
+static void accumulate_marker(MovieTrackingMarker *dst_marker,
+ const MovieTrackingMarker *src_marker)
+{
+ BLI_assert(dst_marker->framenr == src_marker->framenr);
+
+ if (src_marker->flag & MARKER_DISABLED) {
+ return;
+ }
+
+ add_v2_v2(dst_marker->pos, src_marker->pos);
+ for (int corner = 0; corner < 4; ++corner) {
+ add_v2_v2(dst_marker->pattern_corners[corner], src_marker->pattern_corners[corner]);
+ }
+ add_v2_v2(dst_marker->search_min, src_marker->search_min);
+ add_v2_v2(dst_marker->search_max, src_marker->search_max);
+
+ BLI_assert(is_finite_v2(src_marker->search_min));
+ BLI_assert(is_finite_v2(src_marker->search_max));
+
+ dst_marker->flag &= ~MARKER_DISABLED;
+ if ((src_marker->flag & MARKER_TRACKED) == 0) {
+ dst_marker->flag &= ~MARKER_TRACKED;
+ }
+}
+
+static void multiply_marker(MovieTrackingMarker *marker, const float multiplier)
+{
+ mul_v2_fl(marker->pos, multiplier);
+ for (int corner = 0; corner < 4; ++corner) {
+ mul_v2_fl(marker->pattern_corners[corner], multiplier);
+ }
+ mul_v2_fl(marker->search_min, multiplier);
+ mul_v2_fl(marker->search_max, multiplier);
+}
+
+/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of
+ * markers (position, patterns, ...). */
+static void tracking_average_markers(MovieTrackingTrack *dst_track,
+ /*const*/ MovieTrackingTrack **src_tracks,
+ const int num_src_tracks)
+{
+ /* Get global range of frames within which averaging would happen. */
+ int first_frame, last_frame;
+ BKE_tracking_tracks_first_last_frame_minmax(
+ src_tracks, num_src_tracks, &first_frame, &last_frame);
+ if (last_frame < first_frame) {
+ return;
+ }
+ const int num_frames = last_frame - first_frame + 1;
+
+ /* Allocate temporary array where averaging will happen into. */
+ MovieTrackingMarker *accumulator = MEM_calloc_arrayN(
+ num_frames, sizeof(MovieTrackingMarker), "tracks average accumulator");
+ int *counters = MEM_calloc_arrayN(num_frames, sizeof(int), "tracks accumulator counters");
+ for (int frame = first_frame; frame <= last_frame; ++frame) {
+ const int frame_index = frame - first_frame;
+ accumulator[frame_index].framenr = frame;
+ accumulator[frame_index].flag |= (MARKER_DISABLED | MARKER_TRACKED);
+ }
+
+ /* Accumulate track markers. */
+ for (int track_index = 0; track_index < num_src_tracks; ++track_index) {
+ /*const*/ MovieTrackingTrack *track = src_tracks[track_index];
+ for (int frame = first_frame; frame <= last_frame; ++frame) {
+ MovieTrackingMarker interpolated_marker;
+ if (!BKE_tracking_marker_get_interpolated(track, frame, &interpolated_marker)) {
+ continue;
+ }
+ const int frame_index = frame - first_frame;
+ accumulate_marker(&accumulator[frame_index], &interpolated_marker);
+ ++counters[frame_index];
+ }
+ }
+
+ /* Average and store the result. */
+ for (int frame = first_frame; frame <= last_frame; ++frame) {
+ /* Average. */
+ const int frame_index = frame - first_frame;
+ if (!counters[frame_index]) {
+ continue;
+ }
+ const float multiplier = 1.0f / (float)counters[frame_index];
+ multiply_marker(&accumulator[frame_index], multiplier);
+ /* Store the result. */
+ BKE_tracking_marker_insert(dst_track, &accumulator[frame_index]);
+ }
+
+ /* Free memory. */
+ MEM_freeN(accumulator);
+ MEM_freeN(counters);
+}
+
+/* Helper function for BKE_tracking_tracks_average which takes care of averaging fields of
+ * tracks (track for example, offset). */
+static void tracking_average_tracks(MovieTrackingTrack *dst_track,
+ /*const*/ MovieTrackingTrack **src_tracks,
+ const int num_src_tracks)
+{
+ /* TODO(sergey): Consider averaging weight, stabilization weight, maybe even bundle position. */
+ zero_v2(dst_track->offset);
+ for (int track_index = 0; track_index < num_src_tracks; track_index++) {
+ add_v2_v2(dst_track->offset, src_tracks[track_index]->offset);
+ }
+ mul_v2_fl(dst_track->offset, 1.0f / num_src_tracks);
+}
+
+void BKE_tracking_tracks_average(MovieTrackingTrack *dst_track,
+ /*const*/ MovieTrackingTrack **src_tracks,
+ const int num_src_tracks)
+{
+ if (num_src_tracks == 0) {
+ return;
+ }
+
+ tracking_average_markers(dst_track, src_tracks, num_src_tracks);
+ tracking_average_tracks(dst_track, src_tracks, num_src_tracks);
+}
+
MovieTrackingTrack *BKE_tracking_track_get_named(MovieTracking *tracking,
MovieTrackingObject *object,
const char *name)
@@ -1224,8 +1422,6 @@ MovieTrackingMarker *BKE_tracking_marker_insert(MovieTrackingTrack *track,
/* put new marker */
track->markers[a + 1] = *marker;
- track->last_marker = a + 1;
-
return &track->markers[a + 1];
}
@@ -1314,51 +1510,47 @@ void BKE_tracking_marker_clamp(MovieTrackingMarker *marker, int event)
}
}
+/**
+ * Get marker closest to the given frame number.
+ *
+ * If there is maker with exact frame number it returned.
+ * Otherwise, marker with highest frame number but lower than the requested
+ * frame is returned if such marker exists. Otherwise, the marker with lowest
+ * frame number greater than the requested frame number is returned.
+ *
+ * This function has complexity of `O(log number_of_markers)`.
+ */
MovieTrackingMarker *BKE_tracking_marker_get(MovieTrackingTrack *track, int framenr)
{
- int a = track->markersnr - 1;
+ const int num_markers = track->markersnr;
- if (!track->markersnr) {
+ if (num_markers == 0) {
+ BLI_assert(!"Detected degenerated track, should never happen.");
return NULL;
}
- /* approximate pre-first framenr marker with first marker */
- if (framenr < track->markers[0].framenr) {
- return &track->markers[0];
- }
+ int left_boundary = 0;
+ int right_boundary = num_markers;
+ while (left_boundary < right_boundary) {
+ const int median_index = (left_boundary + right_boundary) / 2;
+ MovieTrackingMarker *marker = &track->markers[median_index];
- if (track->last_marker < track->markersnr) {
- a = track->last_marker;
- }
-
- if (track->markers[a].framenr <= framenr) {
- while (a < track->markersnr && track->markers[a].framenr <= framenr) {
- if (track->markers[a].framenr == framenr) {
- track->last_marker = a;
-
- return &track->markers[a];
- }
- a++;
+ if (marker->framenr == framenr) {
+ return marker;
}
- /* if there's no marker for exact position, use nearest marker from left side */
- return &track->markers[a - 1];
- }
-
- while (a >= 0 && track->markers[a].framenr >= framenr) {
- if (track->markers[a].framenr == framenr) {
- track->last_marker = a;
-
- return &track->markers[a];
+ if (marker->framenr < framenr) {
+ left_boundary = median_index + 1;
+ }
+ else {
+ BLI_assert(marker->framenr > framenr);
+ right_boundary = median_index - 1;
}
-
- a--;
}
- /* if there's no marker for exact position, use nearest marker from left side */
- return &track->markers[a];
+ const int closest_index = clamp_i(right_boundary, 0, num_markers - 1);
- return NULL;
+ return &track->markers[closest_index];
}
MovieTrackingMarker *BKE_tracking_marker_get_exact(MovieTrackingTrack *track, int framenr)
@@ -1389,6 +1581,84 @@ MovieTrackingMarker *BKE_tracking_marker_ensure(MovieTrackingTrack *track, int f
return marker;
}
+static const MovieTrackingMarker *get_usable_marker_for_interpolation(
+ struct MovieTrackingTrack *track,
+ const MovieTrackingMarker *anchor_marker,
+ const int direction)
+{
+ BLI_assert(direction == -1 || direction == 1);
+
+ const MovieTrackingMarker *last_marker = track->markers + track->markersnr - 1;
+ const MovieTrackingMarker *current_marker = anchor_marker;
+
+ while (current_marker >= track->markers && current_marker <= last_marker) {
+ if ((current_marker->flag & MARKER_DISABLED) == 0) {
+ return current_marker;
+ }
+ current_marker += direction;
+ }
+
+ return NULL;
+}
+
+bool BKE_tracking_marker_get_interpolated(struct MovieTrackingTrack *track,
+ const int framenr,
+ struct MovieTrackingMarker *r_marker)
+{
+ const MovieTrackingMarker *closest_marker = BKE_tracking_marker_get(track, framenr);
+ if (closest_marker == NULL) {
+ return false;
+ }
+ if (closest_marker->framenr == framenr && (closest_marker->flag & MARKER_DISABLED) == 0) {
+ *r_marker = *closest_marker;
+ return true;
+ }
+
+ const MovieTrackingMarker *left_marker = get_usable_marker_for_interpolation(
+ track, closest_marker, -1);
+ if (left_marker == NULL) {
+ return false;
+ }
+
+ const MovieTrackingMarker *right_marker = get_usable_marker_for_interpolation(
+ track, closest_marker + 1, 1);
+ if (right_marker == NULL) {
+ return false;
+ }
+
+ if (left_marker == right_marker) {
+ *r_marker = *left_marker;
+ return true;
+ }
+
+ const float factor = (float)(framenr - left_marker->framenr) /
+ (right_marker->framenr - left_marker->framenr);
+
+ interp_v2_v2v2(r_marker->pos, left_marker->pos, right_marker->pos, factor);
+
+ for (int i = 0; i < 4; i++) {
+ interp_v2_v2v2(r_marker->pattern_corners[i],
+ left_marker->pattern_corners[i],
+ right_marker->pattern_corners[i],
+ factor);
+ }
+
+ interp_v2_v2v2(r_marker->search_min, left_marker->search_min, right_marker->search_min, factor);
+ interp_v2_v2v2(r_marker->search_max, left_marker->search_max, right_marker->search_max, factor);
+
+ r_marker->framenr = framenr;
+ r_marker->flag = 0;
+
+ if (framenr == left_marker->framenr) {
+ r_marker->flag = left_marker->flag;
+ }
+ else if (framenr == right_marker->framenr) {
+ r_marker->flag = right_marker->flag;
+ }
+
+ return true;
+}
+
void BKE_tracking_marker_pattern_minmax(const MovieTrackingMarker *marker,
float min[2],
float max[2])
@@ -1683,7 +1953,6 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_insert(MovieTrackingPlaneTra
/* Put new marker to an array. */
plane_track->markers[a + 1] = *plane_marker;
- plane_track->last_marker = a + 1;
return &plane_track->markers[a + 1];
}
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 6f58416924f..46589a578a8 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -311,11 +311,7 @@ static void retrieve_next_lower_usable_frame(
* translation stabilization, which has an enabled tracking marker at this very
* frame. We search both for the next lower and next higher position, to allow
* the caller to interpolate gaps and to extrapolate at the ends of the
- * definition range.
- *
- * NOTE: Regarding performance note that the individual tracks will cache the
- * last search position.
- */
+ * definition range. */
static void find_next_working_frames(StabContext *ctx,
int framenr,
int *next_lower,
diff --git a/source/blender/blenkernel/intern/tracking_test.cc b/source/blender/blenkernel/intern/tracking_test.cc
index 6afcf6872eb..2877d8db358 100644
--- a/source/blender/blenkernel/intern/tracking_test.cc
+++ b/source/blender/blenkernel/intern/tracking_test.cc
@@ -5,15 +5,23 @@
#include "DNA_tracking_types.h"
#include "BKE_tracking.h"
+#include "BLI_float2.hh"
+
+namespace blender {
namespace {
class TrackingTest : public ::testing::Test {
protected:
- MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track, int frame_number)
+ MovieTrackingMarker *addMarkerToTrack(MovieTrackingTrack *track,
+ int frame_number,
+ const float2 &position = float2(0.0f, 0.0f),
+ int flag = 0)
{
MovieTrackingMarker marker = {{0.0f}};
+ copy_v2_v2(marker.pos, position);
marker.framenr = frame_number;
+ marker.flag = flag;
return BKE_tracking_marker_insert(track, &marker);
}
};
@@ -22,24 +30,58 @@ class TrackingTest : public ::testing::Test {
TEST_F(TrackingTest, BKE_tracking_marker_get)
{
- MovieTrackingTrack track = {nullptr};
+ {
+ MovieTrackingTrack track = {nullptr};
- addMarkerToTrack(&track, 1);
- addMarkerToTrack(&track, 10);
+ addMarkerToTrack(&track, 10);
- {
- const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1);
- EXPECT_NE(marker, nullptr);
- EXPECT_EQ(marker->framenr, 1);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[0]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 20), &track.markers[0]);
+
+ BKE_tracking_track_free(&track);
}
{
- const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5);
- EXPECT_NE(marker, nullptr);
- EXPECT_EQ(marker->framenr, 1);
+ MovieTrackingTrack track = {nullptr};
+
+ addMarkerToTrack(&track, 1);
+ addMarkerToTrack(&track, 10);
+
+ {
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 1);
+ EXPECT_NE(marker, nullptr);
+ EXPECT_EQ(marker->framenr, 1);
+ }
+
+ {
+ const MovieTrackingMarker *marker = BKE_tracking_marker_get(&track, 5);
+ EXPECT_NE(marker, nullptr);
+ EXPECT_EQ(marker->framenr, 1);
+ }
+
+ BKE_tracking_track_free(&track);
}
- BKE_tracking_track_free(&track);
+ {
+ {
+ MovieTrackingTrack track = {nullptr};
+
+ addMarkerToTrack(&track, 1);
+ addMarkerToTrack(&track, 2);
+ addMarkerToTrack(&track, 10);
+
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 0), &track.markers[0]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 1), &track.markers[0]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 2), &track.markers[1]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 3), &track.markers[1]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 9), &track.markers[1]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 10), &track.markers[2]);
+ EXPECT_EQ(BKE_tracking_marker_get(&track, 11), &track.markers[2]);
+
+ BKE_tracking_track_free(&track);
+ }
+ }
}
TEST_F(TrackingTest, BKE_tracking_marker_get_exact)
@@ -62,3 +104,107 @@ TEST_F(TrackingTest, BKE_tracking_marker_get_exact)
BKE_tracking_track_free(&track);
}
+
+TEST_F(TrackingTest, BKE_tracking_marker_get_interpolated)
+{
+ /* Simple case, no disabled markers in a way. */
+ {
+ MovieTrackingTrack track = {nullptr};
+
+ addMarkerToTrack(&track, 1, float2(1.0f, 5.0f));
+ addMarkerToTrack(&track, 10, float2(2.0f, 1.0f));
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 1);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 10);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 4);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f);
+ }
+
+ BKE_tracking_track_free(&track);
+ }
+
+ /* More comprehensive test, which resembles real life trackign scenario better. */
+ {
+ MovieTrackingTrack track = {nullptr};
+
+ addMarkerToTrack(&track, 1, float2(1.0f, 5.0f));
+ addMarkerToTrack(&track, 2, float2(0.0f, 0.0f), MARKER_DISABLED);
+ addMarkerToTrack(&track, 9, float2(0.0f, 0.0f), MARKER_DISABLED);
+ addMarkerToTrack(&track, 10, float2(2.0f, 1.0f));
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 1);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.0f, 5.0f), 1e-6f);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 10);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(2.0f, 1.0f), 1e-6f);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 4);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.3333333f, 3.6666666f), 1e-6f);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 9, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.framenr, 9);
+ EXPECT_V2_NEAR(interpolated_marker.pos, float2(1.888888f, 1.4444444f), 1e-6f);
+ }
+
+ BKE_tracking_track_free(&track);
+ }
+
+ /* Tracked/keyframed flag check. */
+ {
+ MovieTrackingTrack track = {nullptr};
+
+ addMarkerToTrack(&track, 1, float2(1.0f, 5.0f), MARKER_TRACKED);
+ addMarkerToTrack(&track, 10, float2(2.0f, 1.0f), MARKER_TRACKED);
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 1, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 10, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.flag, MARKER_TRACKED);
+ }
+
+ {
+ MovieTrackingMarker interpolated_marker;
+ EXPECT_TRUE(BKE_tracking_marker_get_interpolated(&track, 4, &interpolated_marker));
+ EXPECT_EQ(interpolated_marker.flag, 0);
+ }
+
+ BKE_tracking_track_free(&track);
+ }
+}
+
+} // namespace blender
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index e78576206de..643510cf652 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -251,42 +251,10 @@ static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
BLI_assert(!BLI_listbase_is_empty(&ustack->steps));
}
}
-
-/* Return whether `us_item` is before (-1), after (1) or same as (0) `us_anchor` step. */
-static int undosys_stack_order(const UndoStack *ustack,
- const UndoStep *us_anchor,
- const UndoStep *us_item)
-{
- const int index_anchor = BLI_findindex(&ustack->steps, us_anchor);
- const int index_item = BLI_findindex(&ustack->steps, us_item);
- BLI_assert(index_anchor >= 0);
- BLI_assert(index_item >= 0);
-
- return (index_item == index_anchor) ? 0 : (index_item < index_anchor) ? -1 : 1;
-}
-
-# define ASSERT_VALID_UNDO_STEP(_ustack, _us_undo) \
- { \
- const UndoStep *_us_anchor = (_ustack)->step_active; \
- BLI_assert(_us_anchor == NULL || \
- (undosys_stack_order((_ustack), _us_anchor, (_us_undo)) <= 0)); \
- } \
- (void)0
-
-# define ASSERT_VALID_REDO_STEP(_ustack, _us_redo) \
- { \
- const UndoStep *_us_anchor = (_ustack)->step_active; \
- BLI_assert(_us_anchor == NULL || \
- (undosys_stack_order((_ustack), _us_anchor, (_us_redo)) >= 0)); \
- } \
- (void)0
-
#else
static void undosys_stack_validate(UndoStack *UNUSED(ustack), bool UNUSED(expect_non_empty))
{
}
-# define ASSERT_VALID_UNDO_STEP(_ustack, _us_undo)
-# define ASSERT_VALID_REDO_STEP(_ustack, _us_redo)
#endif
UndoStack *BKE_undosys_stack_create(void)
@@ -586,7 +554,7 @@ UndoPushReturn BKE_undosys_step_push_with_type(UndoStack *ustack,
BLI_strncpy(us->name, name, sizeof(us->name));
}
us->type = ut;
- /* True by default, code needs to explicitely set it to false if necessary. */
+ /* True by default, code needs to explicitly set it to false if necessary. */
us->use_old_bmain_data = true;
/* Initialized, not added yet. */
@@ -701,37 +669,91 @@ UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut)
return NULL;
}
-bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
- bContext *C,
- UndoStep *us,
- bool use_skip)
+/**
+ * Return direction of the undo/redo from `us_reference` (or `ustack->step_active` if NULL), and
+ * `us_target`.
+ *
+ * \note If `us_reference` and `us_target` are the same, we consider this is an undo.
+ *
+ * \return -1 for undo, 1 for redo, 0 in case of error.
+ */
+int BKE_undosys_step_calc_direction(const UndoStack *ustack,
+ const UndoStep *us_target,
+ const UndoStep *us_reference)
+{
+ if (us_reference == NULL) {
+ us_reference = ustack->step_active;
+ }
+
+ BLI_assert(us_reference != NULL);
+
+ /* Note that we use heuristics to make this lookup as fast as possible in most common cases,
+ * assuming that:
+ * - Most cases are just undo or redo of one step from active one.
+ * - Otherwise, it is typically faster to check future steps since active one is usually close
+ * to the end of the list, rather than its start. */
+ /* NOTE: in case target step is the active one, we assume we are in an undo case... */
+ if (ELEM(us_target, us_reference, us_reference->prev)) {
+ return -1;
+ }
+ if (us_target == us_reference->next) {
+ return 1;
+ }
+
+ /* Search forward, and then backward. */
+ for (UndoStep *us_iter = us_reference->next; us_iter != NULL; us_iter = us_iter->next) {
+ if (us_iter == us_target) {
+ return 1;
+ }
+ }
+ for (UndoStep *us_iter = us_reference->prev; us_iter != NULL; us_iter = us_iter->prev) {
+ if (us_iter == us_target) {
+ return -1;
+ }
+ }
+
+ BLI_assert(!"Target undo step not found, this should not happen and may indicate an undo stack corruption");
+ return 0;
+}
+
+/**
+ * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
+ * active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **beyond** the given one (if
+ * the given one has to be skipped).
+ *
+ * \param us_reference If NULL, will be set to current active step in the undo stack. Otherwise, it
+ * is assumed to match the current state, and will be used as basis for the
+ * undo/redo process (i.e. all steps in-between `us_reference` and `us_target`
+ * will be processed).
+ */
+bool BKE_undosys_step_load_data_ex(UndoStack *ustack,
+ bContext *C,
+ UndoStep *us_target,
+ UndoStep *us_reference,
+ const bool use_skip)
{
UNDO_NESTED_ASSERT(false);
- if (us == NULL) {
- CLOG_ERROR(&LOG, "called with a NULL step");
+ if (us_target == NULL) {
+ CLOG_ERROR(&LOG, "called with a NULL target step");
return false;
}
undosys_stack_validate(ustack, true);
- /* We expect to get next-from-actual-target step here (i.e. active step in case we only undo
- * once)?
- * FIXME: this is very confusing now that we may have to undo several steps anyway, this function
- * should just get the target final step, not assume that it is getting the active one by default
- * (or the step after the target one when undoing more than one step). */
- UndoStep *us_target = us->prev;
- if (us_target == NULL) {
- CLOG_ERROR(&LOG, "could not find a valid target step");
+ if (us_reference == NULL) {
+ us_reference = ustack->step_active;
+ }
+ if (us_reference == NULL) {
+ CLOG_ERROR(&LOG, "could not find a valid initial active target step as reference");
return false;
}
- ASSERT_VALID_UNDO_STEP(ustack, us_target);
- /* This will be active once complete. */
- UndoStep *us_active = us_target;
- if (use_skip) {
- while (us_active && us_active->skip) {
- us_active = us_active->prev;
- }
- }
+ /* This considers we are in undo case if both `us_target` and `us_reference` are the same. */
+ const int undo_dir = BKE_undosys_step_calc_direction(ustack, us_target, us_reference);
+ BLI_assert(undo_dir != 0);
/* This will be the active step once the undo process is complete.
*
@@ -740,7 +762,7 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
UndoStep *us_target_active = us_target;
if (use_skip) {
while (us_target_active != NULL && us_target_active->skip) {
- us_target_active = us_target_active->prev;
+ us_target_active = (undo_dir == -1) ? us_target_active->prev : us_target_active->next;
}
}
if (us_target_active == NULL) {
@@ -748,42 +770,47 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
return false;
}
- CLOG_INFO(
- &LOG, 1, "addr=%p, name='%s', type='%s'", us_target, us_target->name, us_target->type->name);
+ CLOG_INFO(&LOG,
+ 1,
+ "addr=%p, name='%s', type='%s', undo_dir=%d",
+ us_target,
+ us_target->name,
+ us_target->type->name,
+ undo_dir);
- /* Undo steps until we reach original given target, if we do have a current active step.
+ /* Undo/Redo steps until we reach given target step (or beyond if it has to be skipped), from
+ * given reference step.
*
* NOTE: Unlike with redo case, where we can expect current active step to fully reflect current
* data status, in undo case we also do reload the active step.
* FIXME: this feels weak, and should probably not be actually needed? Or should also be done in
* redo case? */
- if (ustack->step_active != NULL) {
- for (UndoStep *us_iter = ustack->step_active; us_iter != us_target; us_iter = us_iter->prev) {
- BLI_assert(us_iter != NULL);
- undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, false);
- ustack->step_active = us_iter;
- }
- }
+ bool is_processing_extra_skipped_steps = false;
+ for (UndoStep *us_iter = (undo_dir == -1) ? us_reference : us_reference->next; us_iter != NULL;
+ us_iter = (undo_dir == -1) ? us_iter->prev : us_iter->next) {
+ BLI_assert(us_iter != NULL);
- /* Undo target step, and all potential extra ones if some steps have to be 'skipped'. */
- for (UndoStep *us_iter = us_target; us_iter != NULL; us_iter = us_iter->prev) {
const bool is_final = (us_iter == us_target_active);
- if (!is_final) {
+ if (!is_final && is_processing_extra_skipped_steps) {
BLI_assert(us_iter->skip == true);
CLOG_INFO(&LOG,
2,
- "undo continue with skip addr=%p, name='%s', type='%s'",
+ "undo/redo continue with skip addr=%p, name='%s', type='%s'",
us_iter,
us_iter->name,
us_iter->type->name);
}
- undosys_step_decode(C, G_MAIN, ustack, us_iter, -1, is_final);
+ undosys_step_decode(C, G_MAIN, ustack, us_iter, undo_dir, is_final);
ustack->step_active = us_iter;
+ if (us_iter == us_target) {
+ is_processing_extra_skipped_steps = true;
+ }
+
if (is_final) {
- /* Undo process is finished and successful. */
+ /* Undo/Redo process is finished and successful. */
return true;
}
}
@@ -793,139 +820,117 @@ bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
return false;
}
-bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
-{
- return BKE_undosys_step_undo_with_data_ex(ustack, C, us, true);
-}
-
-bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
+/**
+ * Undo/Redo until the given `us_target` step becomes the active (currently loaded) one.
+ */
+bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
{
- return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ /* Note that here we do not skip 'skipped' steps by default. */
+ return BKE_undosys_step_load_data_ex(ustack, C, us_target, NULL, false);
}
-void BKE_undosys_step_undo_from_index(UndoStack *ustack, bContext *C, int index)
+/**
+ * Undo/Redo until the step matching given `index` in the undo stack becomes the active (currently
+ * loaded) one.
+ */
+void BKE_undosys_step_load_from_index(UndoStack *ustack, bContext *C, const int index)
{
- UndoStep *us = BLI_findlink(&ustack->steps, index);
- BLI_assert(us->skip == false);
- BKE_undosys_step_load_data(ustack, C, us);
+ UndoStep *us_target = BLI_findlink(&ustack->steps, index);
+ BLI_assert(us_target->skip == false);
+ BKE_undosys_step_load_data(ustack, C, us_target);
}
-bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
+/**
+ * Undo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \warning This function assumes that the given target step is _before_ current active one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
+ * active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **before** the given one (if
+ * the given one has to be skipped).
+ */
+bool BKE_undosys_step_undo_with_data_ex(UndoStack *ustack,
bContext *C,
- UndoStep *us,
+ UndoStep *us_target,
bool use_skip)
{
- UNDO_NESTED_ASSERT(false);
- if (us == NULL) {
- CLOG_ERROR(&LOG, "called with a NULL step");
- return false;
- }
- undosys_stack_validate(ustack, true);
+ /* In case there is no active step, we consider we just load given step, so reference must be
+ * itself (due to weird 'load current active step in undo case' thing, see comments in
+ * #BKE_undosys_step_load_data_ex). */
+ UndoStep *us_reference = ustack->step_active != NULL ? ustack->step_active : us_target;
- /* We expect to get previous-from-actual-target step here (i.e. active step in case we only redo
- * once)?
- * FIXME: this is very confusing now that we may have to redo several steps anyway, this function
- * should just get the target final step, not assume that it is getting the active one by default
- * (or the step before the target one when redoing more than one step). */
- UndoStep *us_target = us->next;
- if (us_target == NULL) {
- CLOG_ERROR(&LOG, "could not find a valid target step");
- return false;
- }
- ASSERT_VALID_REDO_STEP(ustack, us_target);
+ BLI_assert(BKE_undosys_step_calc_direction(ustack, us_target, us_reference) == -1);
- /* This will be the active step once the redo process is complete.
- *
- * In case we do skip 'skipped' steps, the final active step may be several steps forward the one
- * passed as parameter. */
- UndoStep *us_target_active = us_target;
- if (use_skip) {
- while (us_target_active != NULL && us_target_active->skip) {
- us_target_active = us_target_active->next;
- }
- }
- if (us_target_active == NULL) {
- CLOG_ERROR(&LOG, "could not find a valid final active target step");
- return false;
- }
+ return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip);
+}
- CLOG_INFO(
- &LOG, 1, "addr=%p, name='%s', type='%s'", us_target, us_target->name, us_target->type->name);
+/**
+ * Undo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note See #BKE_undosys_step_undo_with_data_ex for details.
+ */
+bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
+{
+ return BKE_undosys_step_undo_with_data_ex(ustack, C, us_target, true);
+}
- /* Redo steps until we reach original given target, if we do have a current active step. */
+/**
+ * Undo one step from current active (currently loaded) one.
+ */
+bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
+{
if (ustack->step_active != NULL) {
- for (UndoStep *us_iter = ustack->step_active->next; us_iter != us_target;
- us_iter = us_iter->next) {
- BLI_assert(us_iter != NULL);
- undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, false);
- ustack->step_active = us_iter;
- }
+ return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active->prev);
}
-
- /* Redo target step, and all potential extra ones if some steps have to be 'skipped'. */
- for (UndoStep *us_iter = us_target; us_iter != NULL; us_iter = us_iter->next) {
- const bool is_final = (us_iter == us_target_active);
-
- if (!is_final) {
- BLI_assert(us_iter->skip == true);
- CLOG_INFO(&LOG,
- 2,
- "redo continue with skip addr=%p, name='%s', type='%s'",
- us_iter,
- us_iter->name,
- us_iter->type->name);
- }
-
- undosys_step_decode(C, G_MAIN, ustack, us_iter, 1, is_final);
- ustack->step_active = us_iter;
-
- if (is_final) {
- /* Redo process is finished and successful. */
- return true;
- }
- }
-
- BLI_assert(
- !"This should never be reached, either undo stack is corrupted, or code above is buggy");
return false;
}
-bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
+/**
+ * Redo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \warning This function assumes that the given target step is _after_ current active one.
+ *
+ * \note Unless `us_target` is a 'skipped' one and `use_skip` is true, `us_target` will become the
+ * active step.
+ *
+ * \note In case `use_skip` is true, the final target will always be **after** the given one (if
+ * the given one has to be skipped).
+ */
+bool BKE_undosys_step_redo_with_data_ex(UndoStack *ustack,
+ bContext *C,
+ UndoStep *us_target,
+ bool use_skip)
{
- return BKE_undosys_step_redo_with_data_ex(ustack, C, us, true);
+ /* In case there is no active step, we consider we just load given step, so reference must be
+ * the previous one. */
+ UndoStep *us_reference = ustack->step_active != NULL ? ustack->step_active : us_target->prev;
+
+ BLI_assert(BKE_undosys_step_calc_direction(ustack, us_target, us_reference) == 1);
+
+ return BKE_undosys_step_load_data_ex(ustack, C, us_target, us_reference, use_skip);
}
-bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
+/**
+ * Redo until `us_target` step becomes the active (currently loaded) one.
+ *
+ * \note See #BKE_undosys_step_redo_with_data_ex for details.
+ */
+bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us_target)
{
- return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+ return BKE_undosys_step_redo_with_data_ex(ustack, C, us_target, true);
}
-bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us)
+/**
+ * Redo one step from current active one.
+ */
+bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
{
- UNDO_NESTED_ASSERT(false);
- const int index_active = BLI_findindex(&ustack->steps, ustack->step_active);
- const int index_target = BLI_findindex(&ustack->steps, us);
- BLI_assert(!ELEM(-1, index_active, index_target));
- bool ok = true;
-
- if (index_target < index_active) {
- uint i = index_active - index_target;
- while (i-- && ok) {
- ok = BKE_undosys_step_undo_with_data_ex(ustack, C, ustack->step_active, false);
- }
- }
- else if (index_target > index_active) {
- uint i = index_target - index_active;
- while (i-- && ok) {
- ok = BKE_undosys_step_redo_with_data_ex(ustack, C, ustack->step_active, false);
- }
- }
-
- if (ok) {
- BLI_assert(ustack->step_active == us);
+ if (ustack->step_active != NULL) {
+ return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active->next);
}
-
- return ok;
+ return false;
}
/**
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index b55f80c6473..e98fae9d92a 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -1167,8 +1167,7 @@ bool BKE_unit_replace_string(
/* Replace # with add sign when there is no operator between it and the next number.
*
* "1*1# 3*100# * 3" -> "1*1+ 3*100 * 3"
- *
- * */
+ */
{
char *str_found = str;
const char *ch = str;
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 9e7a3736141..77cfb3ffea5 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -128,7 +128,7 @@ static struct VolumeFileCache {
std::lock_guard<std::mutex> lock(mutex);
return simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
const float resolution_factor = 1.0f / (1 << simplify_level);
- const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid);
+ const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(*grid);
return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor);
});
}
@@ -523,6 +523,8 @@ static void volume_copy_data(Main *UNUSED(bmain),
volume_dst->runtime.grids = OBJECT_GUARDED_NEW(VolumeGridVector, grids_src);
}
#endif
+
+ volume_dst->batch_cache = nullptr;
}
static void volume_free_data(ID *id)
@@ -642,6 +644,8 @@ IDTypeInfo IDType_ID_VO = {
/* blend_read_expand */ volume_blend_read_expand,
/* blend_read_undo_preserve */ nullptr,
+
+ /* lib_override_apply_post */ nullptr,
};
void BKE_volume_init_grids(Volume *volume)
@@ -1233,39 +1237,39 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid)
}
#ifdef WITH_OPENVDB
-VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase::Ptr &grid)
+VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase &grid)
{
- if (grid->isType<openvdb::FloatGrid>()) {
+ if (grid.isType<openvdb::FloatGrid>()) {
return VOLUME_GRID_FLOAT;
}
- if (grid->isType<openvdb::Vec3fGrid>()) {
+ if (grid.isType<openvdb::Vec3fGrid>()) {
return VOLUME_GRID_VECTOR_FLOAT;
}
- if (grid->isType<openvdb::BoolGrid>()) {
+ if (grid.isType<openvdb::BoolGrid>()) {
return VOLUME_GRID_BOOLEAN;
}
- if (grid->isType<openvdb::DoubleGrid>()) {
+ if (grid.isType<openvdb::DoubleGrid>()) {
return VOLUME_GRID_DOUBLE;
}
- if (grid->isType<openvdb::Int32Grid>()) {
+ if (grid.isType<openvdb::Int32Grid>()) {
return VOLUME_GRID_INT;
}
- if (grid->isType<openvdb::Int64Grid>()) {
+ if (grid.isType<openvdb::Int64Grid>()) {
return VOLUME_GRID_INT64;
}
- if (grid->isType<openvdb::Vec3IGrid>()) {
+ if (grid.isType<openvdb::Vec3IGrid>()) {
return VOLUME_GRID_VECTOR_INT;
}
- if (grid->isType<openvdb::Vec3dGrid>()) {
+ if (grid.isType<openvdb::Vec3dGrid>()) {
return VOLUME_GRID_VECTOR_DOUBLE;
}
- if (grid->isType<openvdb::StringGrid>()) {
+ if (grid.isType<openvdb::StringGrid>()) {
return VOLUME_GRID_STRING;
}
- if (grid->isType<openvdb::MaskGrid>()) {
+ if (grid.isType<openvdb::MaskGrid>()) {
return VOLUME_GRID_MASK;
}
- if (grid->isType<openvdb::points::PointDataGrid>()) {
+ if (grid.isType<openvdb::points::PointDataGrid>()) {
return VOLUME_GRID_POINTS;
}
return VOLUME_GRID_UNKNOWN;
@@ -1276,7 +1280,7 @@ VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid)
{
#ifdef WITH_OPENVDB
const openvdb::GridBase::Ptr grid = volume_grid->grid();
- return BKE_volume_grid_type_openvdb(grid);
+ return BKE_volume_grid_type_openvdb(*grid);
#else
UNUSED_VARS(volume_grid);
#endif
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 291116556c3..5a101cf009b 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -192,6 +192,8 @@ IDTypeInfo IDType_ID_WS = {
.blend_read_expand = workspace_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
/* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 8fe7653fc25..a2ce37a5d90 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -206,6 +206,8 @@ IDTypeInfo IDType_ID_WO = {
.blend_read_expand = world_blend_read_expand,
.blend_read_undo_preserve = NULL,
+
+ .lib_override_apply_post = NULL,
};
World *BKE_world_add(Main *bmain, const char *name)