Core: Add data-level support for new 'system IDprops' storage for Blender 4.5 forward compatibility with 5.0 blendfiles
This mainly adds DNA level IDProp storage for system properties, their handling in data management code, and the forward-versioning code copying back content from system properties into 'all-in-one' single IDProperties storage, for data types that will support both in Blender 5.0. There is no user-facing changes expected here. Part of #123232. Pull Request: https://projects.blender.org/blender/blender/pulls/139257
This commit is contained in:
committed by
Bastien Montagne
parent
6e70b755ce
commit
f6a9f082e9
@@ -63,8 +63,6 @@ BoneCollection *ANIM_bonecoll_new(const char *name)
|
||||
STRNCPY_UTF8(bcoll->name, name);
|
||||
bcoll->flags = default_flags;
|
||||
|
||||
bcoll->prop = nullptr;
|
||||
|
||||
return bcoll;
|
||||
}
|
||||
|
||||
@@ -76,6 +74,9 @@ void ANIM_bonecoll_free(BoneCollection *bcoll, const bool do_id_user_count)
|
||||
if (bcoll->prop) {
|
||||
IDP_FreeProperty_ex(bcoll->prop, do_id_user_count);
|
||||
}
|
||||
if (bcoll->system_properties) {
|
||||
IDP_FreeProperty_ex(bcoll->system_properties, do_id_user_count);
|
||||
}
|
||||
MEM_delete(bcoll);
|
||||
}
|
||||
|
||||
@@ -258,6 +259,10 @@ static BoneCollection *copy_and_update_ownership(const bArmature *armature_dst,
|
||||
bcoll->prop = IDP_CopyProperty_ex(bcoll_to_copy->prop,
|
||||
0 /*do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT*/);
|
||||
}
|
||||
if (bcoll->system_properties) {
|
||||
bcoll->system_properties = IDP_CopyProperty_ex(
|
||||
bcoll_to_copy->system_properties, 0 /*do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT*/);
|
||||
}
|
||||
|
||||
/* Remap the bone pointers to the given armature, as `bcoll_to_copy` is
|
||||
* assumed to be owned by another armature. */
|
||||
@@ -1406,6 +1411,10 @@ blender::Map<BoneCollection *, BoneCollection *> ANIM_bonecoll_array_copy_no_mem
|
||||
bcoll_dst->prop = IDP_CopyProperty_ex(bcoll_src->prop,
|
||||
do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
if (bcoll_src->system_properties) {
|
||||
bcoll_dst->system_properties = IDP_CopyProperty_ex(
|
||||
bcoll_src->system_properties, do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
|
||||
(*bcoll_array_dst)[i] = bcoll_dst;
|
||||
|
||||
@@ -1425,6 +1434,9 @@ void ANIM_bonecoll_array_free(BoneCollection ***bcoll_array,
|
||||
if (bcoll->prop) {
|
||||
IDP_FreeProperty_ex(bcoll->prop, do_id_user);
|
||||
}
|
||||
if (bcoll->system_properties) {
|
||||
IDP_FreeProperty_ex(bcoll->system_properties, do_id_user);
|
||||
}
|
||||
|
||||
/* This will usually already be empty, because the passed BoneCollection
|
||||
* list is usually from ANIM_bonecoll_listbase_copy_no_membership().
|
||||
|
||||
@@ -38,6 +38,13 @@ struct EditBone {
|
||||
EditBone *next, *prev;
|
||||
/** User-Defined Properties on this Bone */
|
||||
IDProperty *prop;
|
||||
/**
|
||||
* System-Defined Properties storage.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
IDProperty *system_properties;
|
||||
/**
|
||||
* Edit-bones have a one-way link (i.e. children refer
|
||||
* to parents. This is converted to a two-way link for
|
||||
|
||||
@@ -1340,6 +1340,9 @@ void BKE_pose_copy_data_ex(bPose **dst,
|
||||
if (pchan->prop) {
|
||||
pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag);
|
||||
}
|
||||
if (pchan->system_properties) {
|
||||
pchan->system_properties = IDP_CopyProperty_ex(pchan->system_properties, flag);
|
||||
}
|
||||
|
||||
pchan->draw_data = nullptr; /* Drawing cache, no need to copy. */
|
||||
|
||||
@@ -1537,6 +1540,10 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
|
||||
IDP_FreeProperty_ex(pchan->prop, do_id_user);
|
||||
pchan->prop = nullptr;
|
||||
}
|
||||
if (pchan->system_properties) {
|
||||
IDP_FreeProperty_ex(pchan->system_properties, do_id_user);
|
||||
pchan->system_properties = nullptr;
|
||||
}
|
||||
|
||||
/* Cached data, for new draw manager rendering code. */
|
||||
MEM_SAFE_FREE(pchan->draw_data);
|
||||
@@ -1664,13 +1671,21 @@ void BKE_pose_channel_copy_data(bPoseChannel *pchan, const bPoseChannel *pchan_f
|
||||
|
||||
/* id-properties */
|
||||
if (pchan->prop) {
|
||||
/* unlikely but possible it exists */
|
||||
/* Unlikely, but possible that it exists. */
|
||||
IDP_FreeProperty(pchan->prop);
|
||||
pchan->prop = nullptr;
|
||||
}
|
||||
if (pchan_from->prop) {
|
||||
pchan->prop = IDP_CopyProperty(pchan_from->prop);
|
||||
}
|
||||
if (pchan->system_properties) {
|
||||
/* Unlikely, but possible that it exists. */
|
||||
IDP_FreeProperty(pchan->system_properties);
|
||||
pchan->system_properties = nullptr;
|
||||
}
|
||||
if (pchan_from->system_properties) {
|
||||
pchan->system_properties = IDP_CopyProperty(pchan_from->system_properties);
|
||||
}
|
||||
|
||||
/* custom shape */
|
||||
pchan->custom = pchan_from->custom;
|
||||
@@ -2074,6 +2089,8 @@ void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm)
|
||||
if (chan->prop) {
|
||||
IDP_BlendWrite(writer, chan->prop);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
BKE_constraint_blend_write(writer, &chan->constraints);
|
||||
|
||||
@@ -2138,6 +2155,8 @@ void BKE_pose_blend_read_data(BlendDataReader *reader, ID *id_owner, bPose *pose
|
||||
|
||||
BLO_read_struct(reader, IDProperty, &pchan->prop);
|
||||
IDP_BlendDataRead(reader, &pchan->prop);
|
||||
BLO_read_struct(reader, IDProperty, &pchan->system_properties);
|
||||
IDP_BlendDataRead(reader, &pchan->system_properties);
|
||||
|
||||
BLO_read_struct(reader, bMotionPath, &pchan->mpath);
|
||||
if (pchan->mpath) {
|
||||
|
||||
@@ -109,6 +109,9 @@ static void copy_bone_collection(bArmature *armature_dst,
|
||||
if (bcoll_dst->prop) {
|
||||
bcoll_dst->prop = IDP_CopyProperty_ex(bcoll_dst->prop, lib_id_flag);
|
||||
}
|
||||
if (bcoll_dst->system_properties) {
|
||||
bcoll_dst->system_properties = IDP_CopyProperty_ex(bcoll_dst->system_properties, lib_id_flag);
|
||||
}
|
||||
|
||||
/* Bone references. */
|
||||
BLI_duplicatelist(&bcoll_dst->bones, &bcoll_dst->bones);
|
||||
@@ -226,6 +229,11 @@ static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data)
|
||||
data, IDP_foreach_property(bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(bone->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) {
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data, armature_foreach_id_bone(curbone, data));
|
||||
@@ -238,6 +246,12 @@ static void armature_foreach_id_editbone(EditBone *edit_bone, LibraryForeachIDDa
|
||||
data, IDP_foreach_property(edit_bone->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(
|
||||
edit_bone->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
}
|
||||
|
||||
static void armature_foreach_id_bone_collection(BoneCollection *bcoll, LibraryForeachIDData *data)
|
||||
@@ -246,6 +260,11 @@ static void armature_foreach_id_bone_collection(BoneCollection *bcoll, LibraryFo
|
||||
data, IDP_foreach_property(bcoll->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(bcoll->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
}
|
||||
|
||||
static void armature_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
@@ -283,6 +302,8 @@ static void write_bone(BlendWriter *writer, Bone *bone)
|
||||
if (bone->prop) {
|
||||
IDP_BlendWrite(writer, bone->prop);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
/* Write Children */
|
||||
LISTBASE_FOREACH (Bone *, cbone, &bone->childbase) {
|
||||
@@ -300,6 +321,8 @@ static void write_bone_collection(BlendWriter *writer, BoneCollection *bcoll)
|
||||
if (bcoll->prop) {
|
||||
IDP_BlendWrite(writer, bcoll->prop);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
BLO_write_struct_list(writer, BoneCollectionMember, &bcoll->bones);
|
||||
}
|
||||
@@ -356,8 +379,11 @@ static void armature_blend_write(BlendWriter *writer, ID *id, const void *id_add
|
||||
static void direct_link_bones(BlendDataReader *reader, Bone *bone)
|
||||
{
|
||||
BLO_read_struct(reader, Bone, &bone->parent);
|
||||
|
||||
BLO_read_struct(reader, IDProperty, &bone->prop);
|
||||
IDP_BlendDataRead(reader, &bone->prop);
|
||||
BLO_read_struct(reader, IDProperty, &bone->system_properties);
|
||||
IDP_BlendDataRead(reader, &bone->system_properties);
|
||||
|
||||
BLO_read_struct(reader, Bone, &bone->bbone_next);
|
||||
BLO_read_struct(reader, Bone, &bone->bbone_prev);
|
||||
@@ -377,6 +403,8 @@ static void direct_link_bone_collection(BlendDataReader *reader, BoneCollection
|
||||
{
|
||||
BLO_read_struct(reader, IDProperty, &bcoll->prop);
|
||||
IDP_BlendDataRead(reader, &bcoll->prop);
|
||||
BLO_read_struct(reader, IDProperty, &bcoll->system_properties);
|
||||
IDP_BlendDataRead(reader, &bcoll->system_properties);
|
||||
|
||||
BLO_read_struct_list(reader, BoneCollectionMember, &bcoll->bones);
|
||||
LISTBASE_FOREACH (BoneCollectionMember *, member, &bcoll->bones) {
|
||||
@@ -538,6 +566,9 @@ void BKE_armature_bonelist_free(ListBase *lb, const bool do_id_user)
|
||||
if (bone->prop) {
|
||||
IDP_FreeProperty_ex(bone->prop, do_id_user);
|
||||
}
|
||||
if (bone->system_properties) {
|
||||
IDP_FreeProperty_ex(bone->system_properties, do_id_user);
|
||||
}
|
||||
BLI_freelistN(&bone->runtime.collections);
|
||||
BKE_armature_bonelist_free(&bone->childbase, do_id_user);
|
||||
}
|
||||
@@ -551,6 +582,9 @@ void BKE_armature_editbonelist_free(ListBase *lb, const bool do_id_user)
|
||||
if (edit_bone->prop) {
|
||||
IDP_FreeProperty_ex(edit_bone->prop, do_id_user);
|
||||
}
|
||||
if (edit_bone->system_properties) {
|
||||
IDP_FreeProperty_ex(edit_bone->system_properties, do_id_user);
|
||||
}
|
||||
BLI_remlink_safe(lb, edit_bone);
|
||||
MEM_freeN(edit_bone);
|
||||
}
|
||||
@@ -571,6 +605,9 @@ static void copy_bonechildren(Bone *bone_dst,
|
||||
if (bone_src->prop) {
|
||||
bone_dst->prop = IDP_CopyProperty_ex(bone_src->prop, flag);
|
||||
}
|
||||
if (bone_src->system_properties) {
|
||||
bone_dst->system_properties = IDP_CopyProperty_ex(bone_src->system_properties, flag);
|
||||
}
|
||||
|
||||
/* Clear the runtime cache of the collection relations, these will be
|
||||
* reconstructed after the entire armature duplication is done. Don't free,
|
||||
|
||||
@@ -1036,6 +1036,7 @@ static void legacy_gpencil_to_grease_pencil(ConversionData &conversion_data,
|
||||
BLI_assert(!grease_pencil.id.properties);
|
||||
if (gpd.id.properties) {
|
||||
grease_pencil.id.properties = IDP_CopyProperty(gpd.id.properties);
|
||||
grease_pencil.id.system_properties = IDP_CopyProperty(gpd.id.properties);
|
||||
}
|
||||
|
||||
/** Convert Grease Pencil data flag. */
|
||||
|
||||
@@ -270,6 +270,9 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
|
||||
if (view_layer->id_properties) {
|
||||
IDP_FreeProperty_ex(view_layer->id_properties, do_id_user);
|
||||
}
|
||||
if (view_layer->system_properties) {
|
||||
IDP_FreeProperty_ex(view_layer->system_properties, do_id_user);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(view_layer->object_bases_array);
|
||||
|
||||
@@ -503,6 +506,10 @@ void BKE_view_layer_copy_data(Scene *scene_dst,
|
||||
if (view_layer_dst->id_properties != nullptr) {
|
||||
view_layer_dst->id_properties = IDP_CopyProperty_ex(view_layer_dst->id_properties, flag);
|
||||
}
|
||||
if (view_layer_dst->system_properties != nullptr) {
|
||||
view_layer_dst->system_properties = IDP_CopyProperty_ex(view_layer_dst->system_properties,
|
||||
flag);
|
||||
}
|
||||
BKE_freestyle_config_copy(
|
||||
&view_layer_dst->freestyle_config, &view_layer_src->freestyle_config, flag);
|
||||
|
||||
@@ -2395,6 +2402,8 @@ void BKE_view_layer_blend_write(BlendWriter *writer, const Scene *scene, ViewLay
|
||||
if (view_layer->id_properties) {
|
||||
IDP_BlendWrite(writer, view_layer->id_properties);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
LISTBASE_FOREACH (FreestyleModuleConfig *, fmc, &view_layer->freestyle_config.modules) {
|
||||
BLO_write_struct(writer, FreestyleModuleConfig, fmc);
|
||||
@@ -2454,6 +2463,8 @@ void BKE_view_layer_blend_read_data(BlendDataReader *reader, ViewLayer *view_lay
|
||||
|
||||
BLO_read_struct(reader, IDProperty, &view_layer->id_properties);
|
||||
IDP_BlendDataRead(reader, &view_layer->id_properties);
|
||||
BLO_read_struct(reader, IDProperty, &view_layer->system_properties);
|
||||
IDP_BlendDataRead(reader, &view_layer->system_properties);
|
||||
|
||||
BLO_read_struct_list(reader, FreestyleModuleConfig, &(view_layer->freestyle_config.modules));
|
||||
BLO_read_struct_list(reader, FreestyleLineSet, &(view_layer->freestyle_config.linesets));
|
||||
|
||||
@@ -943,6 +943,8 @@ static void id_swap(Main *bmain,
|
||||
/* Exception: IDProperties. */
|
||||
id_a->properties = id_b_back.properties;
|
||||
id_b->properties = id_a_back.properties;
|
||||
id_a->system_properties = id_b_back.system_properties;
|
||||
id_b->system_properties = id_a_back.system_properties;
|
||||
/* Exception: recalc flags. */
|
||||
id_a->recalc = id_b_back.recalc;
|
||||
id_b->recalc = id_a_back.recalc;
|
||||
@@ -1609,6 +1611,9 @@ void BKE_libblock_copy_in_lib(Main *bmain,
|
||||
if (id->properties) {
|
||||
new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
|
||||
}
|
||||
if (id->system_properties) {
|
||||
new_id->system_properties = IDP_CopyProperty_ex(id->system_properties, copy_data_flag);
|
||||
}
|
||||
|
||||
/* This is never duplicated, only one existing ID should have a given weak ref to library/ID. */
|
||||
new_id->library_weak_reference = nullptr;
|
||||
@@ -2617,6 +2622,8 @@ void BKE_id_blend_write(BlendWriter *writer, ID *id)
|
||||
if (id->properties && !ELEM(GS(id->name), ID_WM)) {
|
||||
IDP_BlendWrite(writer, id->properties);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
BKE_animdata_blend_write(writer, id);
|
||||
|
||||
|
||||
@@ -52,6 +52,11 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
|
||||
MEM_freeN(id->properties);
|
||||
id->properties = nullptr;
|
||||
}
|
||||
if (id->system_properties) {
|
||||
IDP_FreePropertyContent_ex(id->system_properties, do_id_user);
|
||||
MEM_freeN(id->system_properties);
|
||||
id->system_properties = nullptr;
|
||||
}
|
||||
|
||||
if (id->override_library) {
|
||||
BKE_lib_override_library_free(&id->override_library, do_id_user);
|
||||
|
||||
@@ -393,6 +393,14 @@ static bool library_foreach_ID_link(Main *bmain,
|
||||
return false;
|
||||
}
|
||||
|
||||
IDP_foreach_property(id->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
|
||||
});
|
||||
if (BKE_lib_query_foreachid_iter_stop(&data)) {
|
||||
library_foreach_ID_data_cleanup(&data);
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimData *adt = BKE_animdata_from_id(id);
|
||||
if (adt) {
|
||||
BKE_animdata_foreach_id(adt, &data);
|
||||
|
||||
@@ -428,6 +428,12 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
data, IDP_foreach_property(pchan->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(
|
||||
pchan->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, pchan->custom, IDWALK_CB_USER);
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
|
||||
@@ -135,6 +135,7 @@ static void palette_undo_preserve(BlendLibReader * /*reader*/, ID *id_new, ID *i
|
||||
* fairly delicate. */
|
||||
BKE_lib_id_swap(nullptr, id_new, id_old, false, 0);
|
||||
std::swap(id_new->properties, id_old->properties);
|
||||
std::swap(id_new->system_properties, id_old->system_properties);
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_PAL = {
|
||||
|
||||
@@ -36,7 +36,9 @@ struct PoseChannelBackup {
|
||||
|
||||
bPoseChannel olddata; /* Backup of pose channel. */
|
||||
IDProperty *oldprops; /* Backup copy (needs freeing) of pose channel's ID properties. */
|
||||
const Object *owner; /* The object to which this pose channel belongs. */
|
||||
/* Backup copy (needs freeing) of pose channel's system IDProperties. */
|
||||
IDProperty *old_system_properties;
|
||||
const Object *owner; /* The object to which this pose channel belongs. */
|
||||
};
|
||||
|
||||
struct PoseBackup {
|
||||
@@ -84,6 +86,9 @@ static void pose_backup_create(const Object *ob,
|
||||
if (pchan->prop) {
|
||||
chan_bak->oldprops = IDP_CopyProperty(pchan->prop);
|
||||
}
|
||||
if (pchan->system_properties) {
|
||||
chan_bak->old_system_properties = IDP_CopyProperty(pchan->system_properties);
|
||||
}
|
||||
|
||||
BLI_addtail(&pose_backup.backups, chan_bak);
|
||||
backed_up_bone_names.add_new(bone_name);
|
||||
@@ -163,6 +168,9 @@ void BKE_pose_backup_restore(const PoseBackup *pbd)
|
||||
if (chan_bak->oldprops) {
|
||||
IDP_SyncGroupValues(chan_bak->pchan->prop, chan_bak->oldprops);
|
||||
}
|
||||
if (chan_bak->old_system_properties) {
|
||||
IDP_SyncGroupValues(chan_bak->pchan->system_properties, chan_bak->old_system_properties);
|
||||
}
|
||||
|
||||
/* TODO: constraints settings aren't restored yet,
|
||||
* even though these could change (though not that likely) */
|
||||
@@ -179,6 +187,9 @@ void BKE_pose_backup_free(PoseBackup *pbd)
|
||||
if (chan_bak->oldprops) {
|
||||
IDP_FreeProperty(chan_bak->oldprops);
|
||||
}
|
||||
if (chan_bak->old_system_properties) {
|
||||
IDP_FreeProperty(chan_bak->old_system_properties);
|
||||
}
|
||||
BLI_freelinkN(&pbd->backups, chan_bak);
|
||||
}
|
||||
MEM_freeN(pbd);
|
||||
|
||||
@@ -815,6 +815,9 @@ static bool strip_foreach_member_id_cb(Strip *strip, void *user_data)
|
||||
IDP_foreach_property(strip->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
});
|
||||
IDP_foreach_property(strip->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
});
|
||||
LISTBASE_FOREACH (StripModifierData *, smd, &strip->modifiers) {
|
||||
FOREACHID_PROCESS_IDSUPER(data, smd->mask_id, IDWALK_CB_USER);
|
||||
}
|
||||
@@ -873,6 +876,12 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
IDP_foreach_property(view_layer->id_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
|
||||
data,
|
||||
IDP_foreach_property(
|
||||
view_layer->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
|
||||
BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
|
||||
}));
|
||||
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(view_layer)) {
|
||||
@@ -1834,6 +1843,9 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
|
||||
if (sce->id.properties) {
|
||||
sce_copy->id.properties = IDP_CopyProperty(sce->id.properties);
|
||||
}
|
||||
if (sce->id.system_properties) {
|
||||
sce_copy->id.system_properties = IDP_CopyProperty(sce->id.system_properties);
|
||||
}
|
||||
|
||||
BKE_sound_destroy_scene(sce_copy);
|
||||
|
||||
|
||||
@@ -2118,6 +2118,11 @@ static void direct_link_id_common(BlendDataReader *reader,
|
||||
IDP_BlendDataRead(reader, &id->properties);
|
||||
}
|
||||
|
||||
if (id->system_properties) {
|
||||
BLO_read_struct(reader, IDProperty, &id->system_properties);
|
||||
IDP_BlendDataRead(reader, &id->system_properties);
|
||||
}
|
||||
|
||||
id->flag &= ~ID_FLAG_INDIRECT_WEAK_LINK;
|
||||
|
||||
/* NOTE: It is important to not clear the recalc flags for undo/redo.
|
||||
@@ -3089,6 +3094,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
/* Don't allow versioning to create new data-blocks. */
|
||||
main->is_locked_for_linking = true;
|
||||
|
||||
/* Code ensuring conversion from new 'system IDProperties' in 5.0. This needs to run before any
|
||||
* other data versioning. Otherwise, things like Cycles versioning code cannot work as expected.
|
||||
*
|
||||
* Merge (with overwrite) future system properties storage into current IDProperties. */
|
||||
version_forward_compat_system_idprops(main);
|
||||
|
||||
if (G.debug & G_DEBUG) {
|
||||
char build_commit_datetime[32];
|
||||
time_t temp_time = main->build_commit_timestamp;
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
#include "BKE_customdata.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_idprop.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_mesh_legacy_convert.hh"
|
||||
#include "BKE_node.hh"
|
||||
@@ -55,6 +58,60 @@
|
||||
|
||||
// static CLG_LogRef LOG = {"blo.readfile.doversion"};
|
||||
|
||||
void version_forward_compat_system_idprops(Main *bmain)
|
||||
{
|
||||
auto idprops_process = [](IDProperty **idprops, IDProperty *system_idprops) -> void {
|
||||
if (system_idprops) {
|
||||
/* Other ID pointers have not yet been relinked, do not try to access them for refcounting.
|
||||
*/
|
||||
if (*idprops) {
|
||||
IDP_MergeGroup_ex(*idprops, system_idprops, true, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
else {
|
||||
*idprops = IDP_CopyProperty_ex(system_idprops, LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ID *id_iter;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
|
||||
idprops_process(&id_iter->properties, id_iter->system_properties);
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
|
||||
idprops_process(&view_layer->id_properties, view_layer->system_properties);
|
||||
}
|
||||
|
||||
if (scene->ed != nullptr) {
|
||||
blender::seq::for_each_callback(&scene->ed->seqbase,
|
||||
[&idprops_process](Strip *strip) -> bool {
|
||||
idprops_process(&strip->prop, strip->system_properties);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
|
||||
if (!object->pose) {
|
||||
continue;
|
||||
}
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
|
||||
idprops_process(&pchan->prop, pchan->system_properties);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bArmature *, armature, &bmain->armatures) {
|
||||
for (BoneCollection *bcoll : armature->collections_span()) {
|
||||
idprops_process(&bcoll->prop, bcoll->system_properties);
|
||||
}
|
||||
LISTBASE_FOREACH (Bone *, bone, &armature->bonebase) {
|
||||
idprops_process(&bone->prop, bone->system_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void version_fix_fcurve_noise_offset(FCurve &fcurve)
|
||||
{
|
||||
LISTBASE_FOREACH (FModifier *, fcurve_modifier, &fcurve.modifiers) {
|
||||
|
||||
@@ -194,6 +194,10 @@ void version_update_node_input(
|
||||
FunctionRef<void(bNode *, bNodeSocket *, bNode *, bNodeSocket *)> update_input_link);
|
||||
|
||||
bNode *version_eevee_output_node_get(bNodeTree *ntree, int16_t node_type);
|
||||
|
||||
/* Allow 4.5 to open 5.0+ files and recover their system-defined ID properties. */
|
||||
void version_forward_compat_system_idprops(Main *bmain);
|
||||
|
||||
bool all_scenes_use(Main *bmain, const blender::Span<const char *> engines);
|
||||
|
||||
/* Adjust the values of the given FCurve key frames by applying the given function. The function is
|
||||
|
||||
@@ -1048,6 +1048,9 @@ static void copy_pchan(EditBone *src_bone, EditBone *dst_bone, Object *src_ob, O
|
||||
if (src_bone->prop) {
|
||||
dst_bone->prop = IDP_CopyProperty(src_bone->prop);
|
||||
}
|
||||
if (src_bone->system_properties) {
|
||||
dst_bone->system_properties = IDP_CopyProperty(src_bone->system_properties);
|
||||
}
|
||||
|
||||
/* Lets duplicate the list of constraints that the
|
||||
* current bone has.
|
||||
@@ -1909,6 +1912,7 @@ static wmOperatorStatus armature_subdivide_exec(bContext *C, wmOperator *op)
|
||||
|
||||
newbone->flag |= BONE_CONNECTED;
|
||||
newbone->prop = nullptr;
|
||||
newbone->system_properties = nullptr;
|
||||
|
||||
/* correct parent bones */
|
||||
LISTBASE_FOREACH (EditBone *, tbone, arm->edbo) {
|
||||
|
||||
@@ -164,6 +164,7 @@ struct tPChanFCurveLink {
|
||||
|
||||
/** copy of custom properties at start of operator (to be restored before each modal step) */
|
||||
IDProperty *oldprops;
|
||||
IDProperty *old_system_properties;
|
||||
};
|
||||
|
||||
/* ----------- */
|
||||
|
||||
@@ -291,6 +291,9 @@ static BoneCollection *join_armature_remap_collection(
|
||||
if (bcoll->prop) {
|
||||
new_bcoll->prop = IDP_CopyProperty_ex(bcoll->prop, 0);
|
||||
}
|
||||
if (bcoll->system_properties) {
|
||||
new_bcoll->system_properties = IDP_CopyProperty_ex(bcoll->system_properties, 0);
|
||||
}
|
||||
|
||||
bone_collection_by_name.add(bcoll->name, new_bcoll);
|
||||
return new_bcoll;
|
||||
|
||||
@@ -109,6 +109,9 @@ void bone_free(bArmature *arm, EditBone *bone)
|
||||
if (bone->prop) {
|
||||
IDP_FreeProperty(bone->prop);
|
||||
}
|
||||
if (bone->system_properties) {
|
||||
IDP_FreeProperty(bone->system_properties);
|
||||
}
|
||||
|
||||
/* Clear references from other edit bones. */
|
||||
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
|
||||
@@ -523,6 +526,9 @@ static EditBone *make_boneList_recursive(ListBase *edbo,
|
||||
if (curBone->prop) {
|
||||
eBone->prop = IDP_CopyProperty(curBone->prop);
|
||||
}
|
||||
if (curBone->system_properties) {
|
||||
eBone->system_properties = IDP_CopyProperty(curBone->system_properties);
|
||||
}
|
||||
|
||||
BLI_addtail(edbo, eBone);
|
||||
|
||||
@@ -744,6 +750,9 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm)
|
||||
if (eBone->prop) {
|
||||
newBone->prop = IDP_CopyProperty(eBone->prop);
|
||||
}
|
||||
if (eBone->system_properties) {
|
||||
newBone->system_properties = IDP_CopyProperty(eBone->system_properties);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix parenting in a separate pass to ensure ebone->bone connections are valid at this point.
|
||||
@@ -797,6 +806,9 @@ void ED_armature_edit_free(bArmature *arm)
|
||||
if (eBone->prop) {
|
||||
IDP_FreeProperty(eBone->prop);
|
||||
}
|
||||
if (eBone->system_properties) {
|
||||
IDP_FreeProperty(eBone->system_properties);
|
||||
}
|
||||
BLI_freelistN(&eBone->bone_collections);
|
||||
}
|
||||
|
||||
@@ -831,6 +843,9 @@ void ED_armature_ebone_listbase_free(ListBase *lb, const bool do_id_user)
|
||||
if (ebone->prop) {
|
||||
IDP_FreeProperty_ex(ebone->prop, do_id_user);
|
||||
}
|
||||
if (ebone->system_properties) {
|
||||
IDP_FreeProperty_ex(ebone->system_properties, do_id_user);
|
||||
}
|
||||
|
||||
BLI_freelistN(&ebone->bone_collections);
|
||||
|
||||
@@ -850,6 +865,10 @@ void ED_armature_ebone_listbase_copy(ListBase *lb_dst, ListBase *lb_src, const b
|
||||
ebone_dst->prop = IDP_CopyProperty_ex(ebone_dst->prop,
|
||||
do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
if (ebone_dst->system_properties) {
|
||||
ebone_dst->system_properties = IDP_CopyProperty_ex(
|
||||
ebone_dst->system_properties, do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT);
|
||||
}
|
||||
ebone_src->temp.ebone = ebone_dst;
|
||||
BLI_addtail(lb_dst, ebone_dst);
|
||||
}
|
||||
|
||||
@@ -767,6 +767,15 @@ static bPoseChannel *pose_bone_do_paste(Object *ob,
|
||||
pchan->prop = IDP_CopyProperty(chan->prop);
|
||||
}
|
||||
}
|
||||
if (chan->system_properties) {
|
||||
/* Same logic as above for system IDProperties, for now. */
|
||||
if (pchan->system_properties) {
|
||||
IDP_SyncGroupValues(pchan->system_properties, chan->system_properties);
|
||||
}
|
||||
else {
|
||||
pchan->system_properties = IDP_CopyProperty(chan->system_properties);
|
||||
}
|
||||
}
|
||||
|
||||
return pchan;
|
||||
}
|
||||
@@ -1397,6 +1406,9 @@ static wmOperatorStatus pose_clear_user_transforms_exec(bContext *C, wmOperator
|
||||
if (pchan->prop) {
|
||||
IDP_FreeProperty(pchan->prop);
|
||||
}
|
||||
if (pchan->system_properties) {
|
||||
IDP_FreeProperty(pchan->system_properties);
|
||||
}
|
||||
}
|
||||
|
||||
/* was copied without constraints */
|
||||
|
||||
@@ -226,6 +226,7 @@ static void fcurves_to_pchan_links_get(ListBase &pfLinks, Object &ob, bPoseChann
|
||||
/* Make copy of custom properties. */
|
||||
if (pchan.prop && (transFlags & ACT_TRANS_PROP)) {
|
||||
pfl->oldprops = IDP_CopyProperty(pchan.prop);
|
||||
pfl->old_system_properties = IDP_CopyProperty(pchan.system_properties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,6 +363,9 @@ void poseAnim_mapping_reset(ListBase *pfLinks)
|
||||
if (pfl->oldprops) {
|
||||
IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
|
||||
}
|
||||
if (pfl->old_system_properties) {
|
||||
IDP_SyncGroupValues(pfl->pchan->system_properties, pfl->old_system_properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,10 @@ BlenderStrokeRenderer::BlenderStrokeRenderer(Render *re, int render_count)
|
||||
if (old_scene->id.properties) {
|
||||
freestyle_scene->id.properties = IDP_CopyProperty_ex(old_scene->id.properties, 0);
|
||||
}
|
||||
if (old_scene->id.system_properties) {
|
||||
freestyle_scene->id.system_properties = IDP_CopyProperty_ex(old_scene->id.system_properties,
|
||||
0);
|
||||
}
|
||||
// Copy eevee render settings.
|
||||
BKE_scene_copy_data_eevee(freestyle_scene, old_scene);
|
||||
|
||||
|
||||
@@ -442,6 +442,16 @@ typedef struct ID {
|
||||
|
||||
IDProperty *properties;
|
||||
|
||||
/**
|
||||
* System-defined custom properties storage.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
IDProperty *system_properties;
|
||||
|
||||
void *_pad1;
|
||||
|
||||
/** Reference linked ID which this one overrides. */
|
||||
IDOverrideLibrary *override_library;
|
||||
|
||||
|
||||
@@ -287,6 +287,14 @@ typedef struct bPoseChannel {
|
||||
/** User-Defined Properties on this PoseChannel. */
|
||||
IDProperty *prop;
|
||||
|
||||
/**
|
||||
* System-defined custom properties storage.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
IDProperty *system_properties;
|
||||
|
||||
/** Constraints that act on this PoseChannel. */
|
||||
ListBase constraints;
|
||||
char name[/*MAXBONENAME*/ 64];
|
||||
@@ -421,6 +429,8 @@ typedef struct bPoseChannel {
|
||||
|
||||
BoneColor color; /* MUST be named the same as in Bone and EditBone structs. */
|
||||
|
||||
void *_pad2;
|
||||
|
||||
/** Runtime data (keep last). */
|
||||
struct bPoseChannel_Runtime runtime;
|
||||
} bPoseChannel;
|
||||
|
||||
@@ -61,6 +61,14 @@ typedef struct Bone {
|
||||
struct Bone *next, *prev;
|
||||
/** User-Defined Properties on this Bone. */
|
||||
IDProperty *prop;
|
||||
/**
|
||||
* System-Defined Properties storage.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
IDProperty *system_properties;
|
||||
void *_pad0;
|
||||
/** Parent (IK parent if appropriate flag is set). */
|
||||
struct Bone *parent;
|
||||
/** Children. */
|
||||
@@ -276,6 +284,13 @@ typedef struct BoneCollection {
|
||||
|
||||
/** Custom properties. */
|
||||
struct IDProperty *prop;
|
||||
/**
|
||||
* Custom system IDProperties.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
struct IDProperty *system_properties;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/**
|
||||
|
||||
@@ -178,6 +178,13 @@ typedef struct ViewLayer {
|
||||
struct World *world_override;
|
||||
/** Equivalent to datablocks ID properties. */
|
||||
struct IDProperty *id_properties;
|
||||
/**
|
||||
* Equivalent to datablocks system-defined ID properties.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
struct IDProperty *system_properties;
|
||||
|
||||
struct FreestyleConfig freestyle_config;
|
||||
struct ViewLayerEEVEE eevee;
|
||||
|
||||
@@ -296,6 +296,13 @@ typedef struct Strip {
|
||||
struct Stereo3dFormat *stereo3d_format;
|
||||
|
||||
struct IDProperty *prop;
|
||||
/**
|
||||
* System-defined custom properties storage.
|
||||
*
|
||||
* In Blender 4.5, only used to ensure forward compatibility with 5.x blendfiles, and data
|
||||
* management consistency.
|
||||
*/
|
||||
struct IDProperty *system_properties;
|
||||
|
||||
/* modifiers */
|
||||
ListBase modifiers;
|
||||
@@ -305,7 +312,6 @@ typedef struct Strip {
|
||||
float speed_factor;
|
||||
|
||||
struct SeqRetimingKey *retiming_keys;
|
||||
void *_pad5;
|
||||
int retiming_keys_num;
|
||||
char _pad6[4];
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* \ingroup sequencer
|
||||
*/
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
struct ListBase;
|
||||
@@ -32,6 +33,9 @@ using ForEachFunc = bool (*)(Strip *strip, void *user_data);
|
||||
*/
|
||||
void for_each_callback(ListBase *seqbase, ForEachFunc callback, void *user_data);
|
||||
|
||||
/** Same as above, but using a more modern FunctionRef as callback. */
|
||||
void for_each_callback(ListBase *seqbase, blender::FunctionRef<bool(Strip *)> callback);
|
||||
|
||||
/**
|
||||
* Expand set by running `strip_query_func()` for each strip, which will be used as reference.
|
||||
* Results of these queries will be merged into provided collection.
|
||||
|
||||
@@ -39,11 +39,33 @@ static bool strip_for_each_recursive(ListBase *seqbase, ForEachFunc callback, vo
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool strip_for_each_recursive(ListBase *seqbase,
|
||||
blender::FunctionRef<bool(Strip *)> callback)
|
||||
{
|
||||
LISTBASE_FOREACH (Strip *, strip, seqbase) {
|
||||
if (!callback(strip)) {
|
||||
/* Callback signaled stop, return. */
|
||||
return false;
|
||||
}
|
||||
if (strip->type == STRIP_TYPE_META) {
|
||||
if (!strip_for_each_recursive(&strip->seqbase, callback)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void for_each_callback(ListBase *seqbase, ForEachFunc callback, void *user_data)
|
||||
{
|
||||
strip_for_each_recursive(seqbase, callback, user_data);
|
||||
}
|
||||
|
||||
void for_each_callback(ListBase *seqbase, blender::FunctionRef<bool(Strip *)> callback)
|
||||
{
|
||||
strip_for_each_recursive(seqbase, callback);
|
||||
}
|
||||
|
||||
VectorSet<Strip *> query_by_reference(Strip *strip_reference,
|
||||
const Scene *scene,
|
||||
ListBase *seqbase,
|
||||
|
||||
@@ -214,6 +214,10 @@ static void seq_strip_free_ex(Scene *scene,
|
||||
IDP_FreePropertyContent_ex(strip->prop, do_id_user);
|
||||
MEM_freeN(strip->prop);
|
||||
}
|
||||
if (strip->system_properties) {
|
||||
IDP_FreePropertyContent_ex(strip->system_properties, do_id_user);
|
||||
MEM_freeN(strip->system_properties);
|
||||
}
|
||||
|
||||
/* free modifiers */
|
||||
modifier_clear(strip);
|
||||
@@ -534,6 +538,9 @@ static Strip *strip_duplicate(const Scene *scene_src,
|
||||
if (strip->prop) {
|
||||
strip_new->prop = IDP_CopyProperty_ex(strip->prop, flag);
|
||||
}
|
||||
if (strip->system_properties) {
|
||||
strip_new->system_properties = IDP_CopyProperty_ex(strip->system_properties, flag);
|
||||
}
|
||||
|
||||
if (strip_new->modifiers.first) {
|
||||
BLI_listbase_clear(&strip_new->modifiers);
|
||||
@@ -791,6 +798,8 @@ static bool strip_write_data_cb(Strip *strip, void *userdata)
|
||||
if (strip->prop) {
|
||||
IDP_BlendWrite(writer, strip->prop);
|
||||
}
|
||||
/* Never write system_properties in Blender 4.5, will be reset to `nullptr` by reading code (by
|
||||
* the matching call to #BLO_read_struct). */
|
||||
|
||||
modifier_blend_write(writer, &strip->modifiers);
|
||||
|
||||
@@ -879,6 +888,8 @@ static bool strip_read_data_cb(Strip *strip, void *user_data)
|
||||
|
||||
BLO_read_struct(reader, IDProperty, &strip->prop);
|
||||
IDP_BlendDataRead(reader, &strip->prop);
|
||||
BLO_read_struct(reader, IDProperty, &strip->system_properties);
|
||||
IDP_BlendDataRead(reader, &strip->system_properties);
|
||||
|
||||
BLO_read_struct(reader, StripData, &strip->data);
|
||||
if (strip->data && strip->data->done == 0) {
|
||||
|
||||
Reference in New Issue
Block a user