Fix #146995: Liboverride: Add support for LightLinking data.

Collection side is trivial, Object one is a bit more intricate, as
its LightLinking data behave similar to AnimData of IDs, which requires
a custom liboverride `apply` callback.

Pull Request: https://projects.blender.org/blender/blender/pulls/147039
This commit is contained in:
Bastien Montagne
2025-10-01 18:11:19 +02:00
committed by Bastien Montagne
parent 9f755b6b01
commit ead0af6ef7
2 changed files with 98 additions and 0 deletions

View File

@@ -713,6 +713,8 @@ static void rna_def_collection_light_linking(BlenderRNA *brna)
{0, nullptr, 0, nullptr, nullptr},
};
RNA_define_lib_overridable(true);
srna = RNA_def_struct(brna, "CollectionLightLinking", nullptr);
RNA_def_struct_sdna(srna, "CollectionLightLinking");
RNA_def_struct_ui_text(
@@ -728,6 +730,8 @@ static void rna_def_collection_light_linking(BlenderRNA *brna)
prop, "Link State", "Light or shadow receiving state of the object or collection");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_CollectionLightLinking_update");
RNA_define_lib_overridable(false);
}
static void rna_def_collection_object(BlenderRNA *brna)
@@ -740,11 +744,15 @@ static void rna_def_collection_object(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Collection Object", "Object of a collection with its collection related settings");
RNA_define_lib_overridable(true);
/* Light Linking. */
prop = RNA_def_property(srna, "light_linking", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "CollectionLightLinking");
RNA_def_property_ui_text(prop, "Light Linking", "Light linking settings of the collection");
RNA_define_lib_overridable(false);
}
static void rna_def_collection_child(BlenderRNA *brna)
@@ -757,12 +765,16 @@ static void rna_def_collection_child(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Collection Child", "Child collection with its collection related settings");
RNA_define_lib_overridable(true);
/* Light Linking. */
prop = RNA_def_property(srna, "light_linking", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "CollectionLightLinking");
RNA_def_property_ui_text(
prop, "Light Linking", "Light linking settings of the collection object");
RNA_define_lib_overridable(false);
}
static void rna_def_collection_exporter_data(BlenderRNA *brna)

View File

@@ -2177,6 +2177,85 @@ static std::optional<std::string> rna_ObjectLightLinking_path(const PointerRNA *
return "light_linking";
}
bool rna_Object_light_linking_override_apply(Main *bmain,
RNAPropertyOverrideApplyContext &rnaapply_ctx)
{
/* NOTE: Here:
* - `dst` is the new, being updated liboverride data, which is a clean copy from the linked
* reference data.
* - `src` is the old, stored liboverride data, which is the source to copy overridden data
* from.
*/
PointerRNA *ptr_dst = &rnaapply_ctx.ptr_dst;
PointerRNA *ptr_src = &rnaapply_ctx.ptr_src;
PointerRNA *ptr_storage = &rnaapply_ctx.ptr_storage;
const int len_dst = rnaapply_ctx.len_src;
const int len_src = rnaapply_ctx.len_src;
const int len_storage = rnaapply_ctx.len_storage;
IDOverrideLibraryPropertyOperation *opop = rnaapply_ctx.liboverride_operation;
BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0);
BLI_assert_msg(opop->operation == LIBOVERRIDE_OP_REPLACE,
"Unsupported RNA override operation on object light linking pointer");
UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop);
/* LightLinking is a special case, since you cannot edit/replace it, it's either existent or not.
* Further more, when a lightlinking is added to the linked reference later on, the one created
* for the liboverride needs to be 'merged', such that its overridable data is kept. */
Object *ob_dst = blender::id_cast<Object *>(ptr_dst->owner_id);
Object *ob_src = blender::id_cast<Object *>(ptr_src->owner_id);
if (ob_dst->light_linking == nullptr && ob_src->light_linking == nullptr) {
/* Nothing to do. */
return false;
}
if (ob_dst->light_linking == nullptr && ob_src->light_linking != nullptr) {
/* Copy light linking data from previous liboverride data into final liboverride one. */
BKE_light_linking_copy(ob_dst, ob_src, 0);
return true;
}
else if (ob_dst->light_linking != nullptr && ob_src->light_linking == nullptr) {
/* Override has cleared/removed light linking data from its reference. */
BKE_light_linking_delete(ob_dst, 0);
return true;
}
else {
BLI_assert(ob_dst->light_linking != nullptr && ob_src->light_linking != nullptr);
/* Override had to create a light linking data, but now its reference also has one, need to
* merge them by keeping the overridable data from the liboverride, while using the light
* linking of the reference.
*
* Note that this case will not be encountered when the linked reference data already had
* light linking data, since there will be no operation for the light linking pointer itself
* then, only potentially for its internal overridable data (collections...). */
/* For these collections, only replace linked data with previously defined liboverride data if
* the latter is non-null. Otherwise, assume that the previously defined liboverride data
* property was 'unset', and can be replaced by the linked reference value. */
if (ob_src->light_linking->receiver_collection != nullptr) {
id_us_min(blender::id_cast<ID *>(ob_dst->light_linking->receiver_collection));
ob_dst->light_linking->receiver_collection = ob_src->light_linking->receiver_collection;
id_us_plus(blender::id_cast<ID *>(ob_dst->light_linking->receiver_collection));
}
if (ob_src->light_linking->blocker_collection != nullptr) {
id_us_min(blender::id_cast<ID *>(ob_dst->light_linking->blocker_collection));
ob_dst->light_linking->blocker_collection = ob_src->light_linking->blocker_collection;
id_us_plus(blender::id_cast<ID *>(ob_dst->light_linking->blocker_collection));
}
/* Note: LightLinking runtime data is currently set by depsgraph evaluation, so no need to
* handle them here. */
}
DEG_id_tag_update(&ob_dst->id, ID_RECALC_SHADING);
DEG_relations_tag_update(bmain);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, &ob_dst->id);
return true;
}
static PointerRNA rna_LightLinking_receiver_collection_get(PointerRNA *ptr)
{
Object *object = reinterpret_cast<Object *>(ptr->owner_id);
@@ -3642,6 +3721,9 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_struct_type(prop, "ObjectLightLinking");
RNA_def_property_pointer_funcs(prop, "rna_Object_light_linking_get", nullptr, nullptr, nullptr);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_override_funcs(
prop, nullptr, nullptr, "rna_Object_light_linking_override_apply");
RNA_def_property_ui_text(prop, "Light Linking", "Light linking settings");
/* Shadow terminator. */
@@ -3696,6 +3778,8 @@ static void rna_def_object_light_linking(BlenderRNA *brna)
RNA_def_struct_nested(brna, srna, "Object");
RNA_def_struct_path_func(srna, "rna_ObjectLightLinking_path");
RNA_define_lib_overridable(true);
prop = RNA_def_property(srna, "receiver_collection", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
@@ -3721,6 +3805,8 @@ static void rna_def_object_light_linking(BlenderRNA *brna)
"Blocker Collection",
"Collection which defines objects which block light from this emitter");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_LightLinking_collection_update");
RNA_define_lib_overridable(false);
}
void RNA_def_object(BlenderRNA *brna)