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:
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h22
-rw-r--r--source/blender/blenkernel/intern/lib_override.c56
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.cc1
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc166
-rw-r--r--source/blender/makesrna/intern/rna_ID.c12
5 files changed, 208 insertions, 49 deletions
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index daa94031489..2447208b49d 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -70,6 +70,14 @@ bool BKE_lib_override_library_is_user_edited(struct ID *id);
bool BKE_lib_override_library_is_system_defined(struct Main *bmain, struct ID *id);
/**
+ * Check if given ID is a leaf in its liboverride hierarchy (i.e. if it does not use any other
+ * override ID).
+ *
+ * NOTE: Embedded IDs of override IDs are not considered as leaves.
+ */
+bool BKE_lib_override_library_is_hierarchy_leaf(struct Main *bmain, struct ID *id);
+
+/**
* Create an overridden local copy of linked reference.
*
* \note This function is very basic, low-level. It does not consider any hierarchical dependency,
@@ -374,12 +382,22 @@ bool BKE_lib_override_library_main_operations_create(struct Main *bmain, bool fo
/**
* Reset all overrides in given \a id_root, while preserving ID relations.
+ *
+ * \param do_reset_system_override If \a true, reset the given ID as a system override one (i.e.
+ * non-editable).
*/
-void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root);
+void BKE_lib_override_library_id_reset(struct Main *bmain,
+ struct ID *id_root,
+ bool do_reset_system_override);
/**
* Reset all overrides in given \a id_root and its dependencies, while preserving ID relations.
+ *
+ * \param do_reset_system_override If \a true, reset the given ID and all of its descendants in the
+ * override hierarchy as system override ones (i.e. non-editable).
*/
-void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root);
+void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain,
+ struct ID *id_root,
+ bool do_reset_system_override);
/**
* Set or clear given tag in all operations in that override property data.
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index edb23f51308..eb6d9fe358e 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -291,6 +291,32 @@ bool BKE_lib_override_library_is_system_defined(Main *bmain, ID *id)
return false;
}
+static int foreachid_is_hierarchy_leaf_fn(LibraryIDLinkCallbackData *cb_data)
+{
+ ID *id_owner = cb_data->id_owner;
+ ID *id = *cb_data->id_pointer;
+ bool *is_leaf = cb_data->user_data;
+
+ if (id != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(id) &&
+ id->override_library->hierarchy_root == id_owner->override_library->hierarchy_root) {
+ *is_leaf = false;
+ return IDWALK_RET_STOP_ITER;
+ }
+ return IDWALK_RET_NOP;
+}
+
+bool BKE_lib_override_library_is_hierarchy_leaf(Main *bmain, ID *id)
+{
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ bool is_leaf = true;
+ BKE_library_foreach_ID_link(
+ bmain, id, foreachid_is_hierarchy_leaf_fn, &is_leaf, IDWALK_READONLY);
+ return is_leaf;
+ }
+
+ return false;
+}
+
ID *BKE_lib_override_library_create_from_id(Main *bmain,
ID *reference_id,
const bool do_tagged_remap)
@@ -3058,10 +3084,16 @@ bool BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
return create_pool_data.changed;
}
-static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
+static bool lib_override_library_id_reset_do(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
bool was_op_deleted = false;
+ if (do_reset_system_override) {
+ id_root->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
+ }
+
LISTBASE_FOREACH_MUTABLE (
IDOverrideLibraryProperty *, op, &id_root->override_library->properties) {
bool do_op_delete = true;
@@ -3117,13 +3149,15 @@ static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
return was_op_deleted;
}
-void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
+void BKE_lib_override_library_id_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
return;
}
- if (lib_override_library_id_reset_do(bmain, id_root)) {
+ if (lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override)) {
if (id_root->override_library->runtime != NULL &&
(id_root->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) !=
0) {
@@ -3133,7 +3167,9 @@ void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
}
}
-static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root)
+static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
return;
@@ -3142,7 +3178,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
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);
+ lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
return;
}
@@ -3152,7 +3188,7 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
return;
}
- lib_override_library_id_reset_do(bmain, id_root);
+ lib_override_library_id_reset_do(bmain, id_root, do_reset_system_override);
/* This way we won't process again that ID, should we encounter it again through another
* relationship hierarchy. */
@@ -3169,17 +3205,19 @@ static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *i
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);
+ lib_override_library_id_hierarchy_recursive_reset(bmain, to_id, do_reset_system_override);
}
}
}
}
-void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root)
+void BKE_lib_override_library_id_hierarchy_reset(Main *bmain,
+ ID *id_root,
+ const bool do_reset_system_override)
{
BKE_main_relations_create(bmain, 0);
- lib_override_library_id_hierarchy_recursive_reset(bmain, id_root);
+ lib_override_library_id_hierarchy_recursive_reset(bmain, id_root, do_reset_system_override);
BKE_main_relations_free(bmain);
diff --git a/source/blender/editors/space_outliner/outliner_edit.cc b/source/blender/editors/space_outliner/outliner_edit.cc
index ae67e7108bf..d6c5901b546 100644
--- a/source/blender/editors/space_outliner/outliner_edit.cc
+++ b/source/blender/editors/space_outliner/outliner_edit.cc
@@ -30,6 +30,7 @@
#include "BKE_context.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 6593fb9b6af..22e42c762ca 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -47,6 +47,7 @@
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -1008,6 +1009,23 @@ static void id_override_library_create_hierarchy_post_process(bContext *C,
FOREACH_MAIN_ID_END;
}
+static void id_override_library_toggle_flag_fn(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *user_data)
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ ID *id = tselem->id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ const uint flag = POINTER_AS_UINT(user_data);
+ id->override_library->flag ^= flag;
+ }
+}
+
static void id_override_library_reset_fn(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
@@ -1025,10 +1043,10 @@ static void id_override_library_reset_fn(bContext *C,
Main *bmain = CTX_data_main(C);
if (do_hierarchy) {
- BKE_lib_override_library_id_hierarchy_reset(bmain, id_root);
+ BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false);
}
else {
- BKE_lib_override_library_id_reset(bmain, id_root);
+ BKE_lib_override_library_id_reset(bmain, id_root, false);
}
WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, nullptr);
@@ -1080,40 +1098,76 @@ static void id_override_library_resync_fn(bContext *C,
}
}
-static void id_override_library_delete_fn(bContext *C,
- ReportList *UNUSED(reports),
- Scene *UNUSED(scene),
- TreeElement *te,
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+static void id_override_library_clear_hierarchy_fn(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
BLI_assert(TSE_IS_REAL_ID(tselem));
ID *id_root = tselem->id;
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
- Main *bmain = CTX_data_main(C);
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
+ CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ return;
+ }
- id_root->tag |= LIB_TAG_DOIT;
+ Main *bmain = CTX_data_main(C);
- /* Tag all linked parents in tree hierarchy to be also overridden. */
- while ((te = te->parent) != nullptr) {
- if (!TSE_IS_REAL_ID(te->store_elem)) {
- continue;
- }
- if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
- break;
- }
- te->store_elem->id->tag |= LIB_TAG_DOIT;
+ id_root->tag |= LIB_TAG_DOIT;
+
+ /* Tag all override parents in tree hierarchy to be also processed. */
+ while ((te = te->parent) != nullptr) {
+ if (!TSE_IS_REAL_ID(te->store_elem)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
+ break;
}
+ te->store_elem->id->tag |= LIB_TAG_DOIT;
+ }
- BKE_lib_override_library_delete(bmain, id_root);
+ BKE_lib_override_library_delete(bmain, id_root);
- WM_event_add_notifier(C, NC_WINDOW, nullptr);
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
+}
+
+static void id_override_library_clear_single_fn(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ Main *bmain = CTX_data_main(C);
+ ID *id = tselem->id;
+
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot clear embedded library override id '%s', only overrides of real "
+ "data-blocks can be directly deleted",
+ id->name);
+ return;
+ }
+
+ /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy),
+ * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system
+ * override. */
+ if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) {
+ BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE);
+ BKE_id_delete(bmain, id);
}
else {
- CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ BKE_lib_override_library_id_reset(bmain, id, true);
}
+
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
+ return;
}
static void id_fake_user_set_fn(bContext *UNUSED(C),
@@ -1911,11 +1965,13 @@ enum eOutlinerIdOpTypes {
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE,
- OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
OUTLINER_IDOP_SINGLE,
OUTLINER_IDOP_DELETE,
OUTLINER_IDOP_REMAP,
@@ -1954,6 +2010,11 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Make Library Override Hierarchy",
"Make a local override of this linked data-block, and its hierarchy of dependencies - only "
"applies to active Outliner item"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
+ "OVERRIDE_LIBRARY_MAKE_EDITABLE",
+ 0,
+ "Make Library Override Editable",
+ "Make the library override data-block editable"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
"OVERRIDE_LIBRARY_RESET",
0,
@@ -1977,12 +2038,18 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Rebuild this local override from its linked reference, as well as its hierarchy of "
"dependencies, enforcing that hierarchy to match the linked data (i.e. ignoring exiting "
"overrides on data-blocks pointer properties)"},
- {OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
- "OVERRIDE_LIBRARY_DELETE_HIERARCHY",
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ "OVERRIDE_LIBRARY_CLEAR_HIERARCHY",
0,
- "Delete Library Override Hierarchy",
+ "Clear Library Override Hierarchy",
"Delete this local override (including its hierarchy of override dependencies) and relink "
"its usages to the linked data-blocks"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
+ "OVERRIDE_LIBRARY_CLEAR_SINGLE",
+ 0,
+ "Clear Single Library Override",
+ "Delete this local override if possible, else reset it and mark it as non editable, and "
+ "relink its usages to the linked data-blocks"},
{0, "", 0, nullptr, nullptr},
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
@@ -2026,11 +2093,19 @@ static bool outliner_id_operation_item_poll(bContext *C,
return true;
}
return false;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE:
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
+ if (tselem->id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) {
+ return true;
+ }
+ }
+ return false;
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE:
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE:
if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
return true;
}
@@ -2211,6 +2286,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Overridden Data Hierarchy");
break;
}
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_toggle_flag_fn,
+ POINTER_FROM_UINT(IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED));
+
+ ED_undo_push(C, "Make Overridden Data Editable");
+ break;
+ }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
OutlinerLibOverrideData override_data{};
outliner_do_libdata_operation(C,
@@ -2263,17 +2350,26 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Resync Overridden Data Hierarchy");
break;
}
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: {
- OutlinerLibOverrideData override_data{};
- override_data.do_hierarchy = true;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: {
outliner_do_libdata_operation(C,
op->reports,
scene,
space_outliner,
&space_outliner->tree,
- id_override_library_delete_fn,
- &override_data);
- ED_undo_push(C, "Delete Overridden Data Hierarchy");
+ id_override_library_clear_hierarchy_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
+ break;
+ }
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_clear_single_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
break;
}
case OUTLINER_IDOP_SINGLE: {
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 5f264a19d47..d3b7e380afa 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -762,7 +762,8 @@ static void rna_ID_override_library_reset(ID *id,
IDOverrideLibrary *UNUSED(override_library),
Main *bmain,
ReportList *reports,
- bool do_hierarchy)
+ bool do_hierarchy,
+ bool set_system_override)
{
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
BKE_reportf(reports, RPT_ERROR, "ID '%s' isn't an override", id->name);
@@ -770,10 +771,10 @@ static void rna_ID_override_library_reset(ID *id,
}
if (do_hierarchy) {
- BKE_lib_override_library_id_hierarchy_reset(bmain, id);
+ BKE_lib_override_library_id_hierarchy_reset(bmain, id, set_system_override);
}
else {
- BKE_lib_override_library_id_reset(bmain, id);
+ BKE_lib_override_library_id_reset(bmain, id, set_system_override);
}
WM_main_add_notifier(NC_WM | ND_LIB_OVERRIDE_CHANGED, NULL);
@@ -1869,6 +1870,11 @@ static void rna_def_ID_override_library(BlenderRNA *brna)
true,
"",
"Also reset all the dependencies of this override to match their reference linked IDs");
+ RNA_def_boolean(func,
+ "set_system_override",
+ false,
+ "",
+ "Reset all user-editable overrides as (non-editable) system overrides");
func = RNA_def_function(srna, "destroy", "rna_ID_override_library_destroy");
RNA_def_function_ui_description(