Merge branch 'blender-v4.5-release'
This commit is contained in:
@@ -17,6 +17,13 @@ The following updates do **not** trigger message bus notifications:
|
||||
- Moving objects in the 3D Viewport.
|
||||
- Changes performed by the animation system.
|
||||
|
||||
Changes done from ``msgbus`` callbacks are not included in related undo steps,
|
||||
so users can easily skip their effects by using Undo followed by Redo.
|
||||
|
||||
Unlike properties ``update`` callbacks, message bus update callbacks are postponed
|
||||
until all operators have finished executing.
|
||||
Additionally, for each property the callback is only triggered once per update cycle,
|
||||
even if the property was changed multiple times during that period.
|
||||
|
||||
Example Use
|
||||
-----------
|
||||
|
||||
@@ -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,6 +36,8 @@ struct PoseChannelBackup {
|
||||
|
||||
bPoseChannel olddata; /* Backup of pose channel. */
|
||||
IDProperty *oldprops; /* Backup copy (needs freeing) of pose channel's ID properties. */
|
||||
/* 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. */
|
||||
};
|
||||
|
||||
@@ -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)) {
|
||||
@@ -1840,6 +1849,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