diff --git a/source/blender/makesrna/intern/rna_collection.cc b/source/blender/makesrna/intern/rna_collection.cc index c24427a9f6a..23d13222a43 100644 --- a/source/blender/makesrna/intern/rna_collection.cc +++ b/source/blender/makesrna/intern/rna_collection.cc @@ -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) diff --git a/source/blender/makesrna/intern/rna_object.cc b/source/blender/makesrna/intern/rna_object.cc index 1ec06f8f854..248dfd12c87 100644 --- a/source/blender/makesrna/intern/rna_object.cc +++ b/source/blender/makesrna/intern/rna_object.cc @@ -2177,6 +2177,85 @@ static std::optional 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(ptr_dst->owner_id); + Object *ob_src = blender::id_cast(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(ob_dst->light_linking->receiver_collection)); + ob_dst->light_linking->receiver_collection = ob_src->light_linking->receiver_collection; + id_us_plus(blender::id_cast(ob_dst->light_linking->receiver_collection)); + } + if (ob_src->light_linking->blocker_collection != nullptr) { + id_us_min(blender::id_cast(ob_dst->light_linking->blocker_collection)); + ob_dst->light_linking->blocker_collection = ob_src->light_linking->blocker_collection; + id_us_plus(blender::id_cast(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(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)