Merge branch 'blender-v2.90-release'
This commit is contained in:
commit
6596891121
|
@ -119,6 +119,9 @@ bool BKE_lib_override_library_status_check_reference(struct Main *bmain, struct
|
|||
bool BKE_lib_override_library_operations_create(struct Main *bmain, struct ID *local);
|
||||
void BKE_lib_override_library_main_operations_create(struct Main *bmain, const bool force_auto);
|
||||
|
||||
void BKE_lib_override_library_id_reset(struct Main *bmain, struct ID *id_root);
|
||||
void BKE_lib_override_library_id_hierarchy_reset(struct Main *bmain, struct ID *id_root);
|
||||
|
||||
void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property,
|
||||
const short tag,
|
||||
const bool do_set);
|
||||
|
|
|
@ -155,8 +155,8 @@ void BKE_lib_override_library_clear(IDOverrideLibrary *override, const bool do_i
|
|||
{
|
||||
BLI_assert(override != NULL);
|
||||
|
||||
if (override->runtime != NULL) {
|
||||
BLI_ghash_clear(override->runtime, NULL, NULL);
|
||||
if (!ELEM(NULL, override->runtime, override->runtime->rna_path_to_override_properties)) {
|
||||
BLI_ghash_clear(override->runtime->rna_path_to_override_properties, NULL, NULL);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &override->properties) {
|
||||
|
@ -176,8 +176,10 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bo
|
|||
BLI_assert(*override != NULL);
|
||||
|
||||
if ((*override)->runtime != NULL) {
|
||||
BLI_ghash_free((*override)->runtime, NULL, NULL);
|
||||
(*override)->runtime = NULL;
|
||||
if ((*override)->runtime->rna_path_to_override_properties != NULL) {
|
||||
BLI_ghash_free((*override)->runtime->rna_path_to_override_properties, NULL, NULL);
|
||||
}
|
||||
MEM_SAFE_FREE((*override)->runtime);
|
||||
}
|
||||
|
||||
BKE_lib_override_library_clear(*override, do_id_user);
|
||||
|
@ -362,7 +364,11 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain)
|
|||
|
||||
static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint tag)
|
||||
{
|
||||
MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->id_user_to_used, id);
|
||||
void **entry_vp = BLI_ghash_lookup_p(bmain->relations->id_user_to_used, id);
|
||||
if (entry_vp == NULL) {
|
||||
/* Already processed. */
|
||||
return (id->tag & tag) != 0;
|
||||
}
|
||||
|
||||
/* This way we won't process again that ID should we encounter it again through another
|
||||
* relationship hierarchy.
|
||||
|
@ -370,7 +376,12 @@ static bool lib_override_hierarchy_recursive_tag(Main *bmain, ID *id, const uint
|
|||
*/
|
||||
BKE_main_relations_ID_remove(bmain, id);
|
||||
|
||||
for (; entry != NULL; entry = entry->next) {
|
||||
for (MainIDRelationsEntry *entry = *entry_vp; entry != NULL; entry = entry->next) {
|
||||
if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
|
||||
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
|
||||
* actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
/* We only consider IDs from the same library. */
|
||||
if (entry->id_pointer != NULL && (*entry->id_pointer)->lib == id->lib) {
|
||||
if (lib_override_hierarchy_recursive_tag(bmain, *entry->id_pointer, tag)) {
|
||||
|
@ -606,19 +617,28 @@ bool BKE_lib_override_library_create(
|
|||
return success;
|
||||
}
|
||||
|
||||
/* We only build override GHash on request. */
|
||||
BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure(
|
||||
BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_runtime_ensure(
|
||||
IDOverrideLibrary *override)
|
||||
{
|
||||
if (override->runtime == NULL) {
|
||||
override->runtime = BLI_ghash_new(
|
||||
override->runtime = MEM_callocN(sizeof(*override->runtime), __func__);
|
||||
}
|
||||
return override->runtime;
|
||||
}
|
||||
|
||||
/* We only build override GHash on request. */
|
||||
BLI_INLINE GHash *override_library_rna_path_mapping_ensure(IDOverrideLibrary *override)
|
||||
{
|
||||
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_runtime_ensure(override);
|
||||
if (override_runtime->rna_path_to_override_properties == NULL) {
|
||||
override_runtime->rna_path_to_override_properties = BLI_ghash_new(
|
||||
BLI_ghashutil_strhash_p_murmur, BLI_ghashutil_strcmp, __func__);
|
||||
for (IDOverrideLibraryProperty *op = override->properties.first; op != NULL; op = op->next) {
|
||||
BLI_ghash_insert(override->runtime, op->rna_path, op);
|
||||
BLI_ghash_insert(override_runtime->rna_path_to_override_properties, op->rna_path, op);
|
||||
}
|
||||
}
|
||||
|
||||
return override->runtime;
|
||||
return override_runtime->rna_path_to_override_properties;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -627,7 +647,7 @@ BLI_INLINE IDOverrideLibraryRuntime *override_library_rna_path_mapping_ensure(
|
|||
IDOverrideLibraryProperty *BKE_lib_override_library_property_find(IDOverrideLibrary *override,
|
||||
const char *rna_path)
|
||||
{
|
||||
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(override);
|
||||
GHash *override_runtime = override_library_rna_path_mapping_ensure(override);
|
||||
return BLI_ghash_lookup(override_runtime, rna_path);
|
||||
}
|
||||
|
||||
|
@ -645,8 +665,7 @@ IDOverrideLibraryProperty *BKE_lib_override_library_property_get(IDOverrideLibra
|
|||
op->rna_path = BLI_strdup(rna_path);
|
||||
BLI_addtail(&override->properties, op);
|
||||
|
||||
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_mapping_ensure(
|
||||
override);
|
||||
GHash *override_runtime = override_library_rna_path_mapping_ensure(override);
|
||||
BLI_ghash_insert(override_runtime, op->rna_path, op);
|
||||
|
||||
if (r_created) {
|
||||
|
@ -692,8 +711,11 @@ void lib_override_library_property_clear(IDOverrideLibraryProperty *op)
|
|||
void BKE_lib_override_library_property_delete(IDOverrideLibrary *override,
|
||||
IDOverrideLibraryProperty *override_property)
|
||||
{
|
||||
if (override->runtime != NULL) {
|
||||
BLI_ghash_remove(override->runtime, override_property->rna_path, NULL, NULL);
|
||||
if (!ELEM(NULL, override->runtime, override->runtime->rna_path_to_override_properties)) {
|
||||
BLI_ghash_remove(override->runtime->rna_path_to_override_properties,
|
||||
override_property->rna_path,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
lib_override_library_property_clear(override_property);
|
||||
BLI_freelinkN(&override->properties, override_property);
|
||||
|
@ -1143,6 +1165,137 @@ void BKE_lib_override_library_main_operations_create(Main *bmain, const bool for
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool lib_override_library_id_reset_do(Main *bmain, ID *id_root)
|
||||
{
|
||||
bool was_property_deleted = false;
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (
|
||||
IDOverrideLibraryProperty *, op, &id_root->override_library->properties) {
|
||||
bool do_op_delete = true;
|
||||
const bool is_collection = op->rna_prop_type == PROP_COLLECTION;
|
||||
if (is_collection || op->rna_prop_type == PROP_POINTER) {
|
||||
PointerRNA ptr_root, ptr_root_lib, ptr, ptr_lib;
|
||||
PropertyRNA *prop, *prop_lib;
|
||||
|
||||
RNA_pointer_create(id_root, &RNA_ID, id_root, &ptr_root);
|
||||
RNA_pointer_create(id_root->override_library->reference,
|
||||
&RNA_ID,
|
||||
id_root->override_library->reference,
|
||||
&ptr_root_lib);
|
||||
|
||||
bool prop_exists = RNA_path_resolve_property(&ptr_root, op->rna_path, &ptr, &prop);
|
||||
BLI_assert(prop_exists);
|
||||
prop_exists = RNA_path_resolve_property(&ptr_root_lib, op->rna_path, &ptr_lib, &prop_lib);
|
||||
|
||||
if (prop_exists) {
|
||||
BLI_assert(ELEM(RNA_property_type(prop), PROP_POINTER, PROP_COLLECTION));
|
||||
BLI_assert(RNA_property_type(prop) == RNA_property_type(prop_lib));
|
||||
if (is_collection) {
|
||||
ptr.type = RNA_property_pointer_type(&ptr, prop);
|
||||
ptr_lib.type = RNA_property_pointer_type(&ptr_lib, prop_lib);
|
||||
}
|
||||
else {
|
||||
ptr = RNA_property_pointer_get(&ptr, prop);
|
||||
ptr_lib = RNA_property_pointer_get(&ptr_lib, prop_lib);
|
||||
}
|
||||
if (ptr.owner_id != NULL && ptr_lib.owner_id != NULL) {
|
||||
BLI_assert(ptr.type == ptr_lib.type);
|
||||
do_op_delete = !(RNA_struct_is_ID(ptr.type) && ptr.owner_id->override_library != NULL &&
|
||||
ptr.owner_id->override_library->reference == ptr_lib.owner_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_op_delete) {
|
||||
BKE_lib_override_library_property_delete(id_root->override_library, op);
|
||||
was_property_deleted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (was_property_deleted) {
|
||||
DEG_id_tag_update_ex(bmain, id_root, ID_RECALC_COPY_ON_WRITE);
|
||||
IDOverrideLibraryRuntime *override_runtime = override_library_rna_path_runtime_ensure(
|
||||
id_root->override_library);
|
||||
override_runtime->tag |= IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD;
|
||||
}
|
||||
|
||||
return was_property_deleted;
|
||||
}
|
||||
|
||||
/** Reset all overrides in given \a id_root, while preserving ID relations. */
|
||||
void BKE_lib_override_library_id_reset(Main *bmain, ID *id_root)
|
||||
{
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lib_override_library_id_reset_do(bmain, id_root)) {
|
||||
if (id_root->override_library->runtime != NULL &&
|
||||
(id_root->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) !=
|
||||
0) {
|
||||
BKE_lib_override_library_update(bmain, id_root);
|
||||
id_root->override_library->runtime->tag &= ~IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lib_override_library_id_hierarchy_recursive_reset(Main *bmain, ID *id_root)
|
||||
{
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
|
||||
return;
|
||||
}
|
||||
|
||||
void **entry_pp = BLI_ghash_lookup(bmain->relations->id_user_to_used, id_root);
|
||||
if (entry_pp == NULL) {
|
||||
/* Already processed. */
|
||||
return;
|
||||
}
|
||||
|
||||
lib_override_library_id_reset_do(bmain, id_root);
|
||||
|
||||
/* This way we won't process again that ID should we encounter it again through another
|
||||
* relationship hierarchy.
|
||||
* Note that this does not free any memory from relations, so we can still use the entries.
|
||||
*/
|
||||
BKE_main_relations_ID_remove(bmain, id_root);
|
||||
|
||||
for (MainIDRelationsEntry *entry = *entry_pp; entry != NULL; entry = entry->next) {
|
||||
if ((entry->usage_flag & IDWALK_CB_LOOPBACK) != 0) {
|
||||
/* Never consider 'loop back' relationships ('from', 'parents', 'owner' etc. pointers) as
|
||||
* actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
/* We only consider IDs from the same library. */
|
||||
if (entry->id_pointer != NULL) {
|
||||
ID *id_entry = *entry->id_pointer;
|
||||
if (id_entry->override_library != NULL) {
|
||||
lib_override_library_id_hierarchy_recursive_reset(bmain, id_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Reset all overrides in given \a id_root and its dependencies, while preserving ID relations. */
|
||||
void BKE_lib_override_library_id_hierarchy_reset(Main *bmain, ID *id_root)
|
||||
{
|
||||
BKE_main_relations_create(bmain, 0);
|
||||
|
||||
lib_override_library_id_hierarchy_recursive_reset(bmain, id_root);
|
||||
|
||||
BKE_main_relations_free(bmain);
|
||||
|
||||
ID *id;
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) || id->override_library->runtime == NULL ||
|
||||
(id->override_library->runtime->tag & IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD) == 0) {
|
||||
continue;
|
||||
}
|
||||
BKE_lib_override_library_update(bmain, id);
|
||||
id->override_library->runtime->tag &= ~IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD;
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
}
|
||||
|
||||
/** Set or clear given tag in all operations as unused in that override property data. */
|
||||
void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property,
|
||||
const short tag,
|
||||
|
@ -1320,6 +1473,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
|
|||
/* Full rebuild of Depsgraph! */
|
||||
/* Note: this is really brute force, in theory updates from RNA should have handle this already,
|
||||
* but for now let's play it safe. */
|
||||
DEG_id_tag_update_ex(bmain, local, ID_RECALC_ALL);
|
||||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
||||
|
|
|
@ -744,22 +744,21 @@ typedef struct OutlinerLibOverrideData {
|
|||
bool do_hierarchy;
|
||||
} OutlinerLibOverrideData;
|
||||
|
||||
static void id_override_library_cb(bContext *C,
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
TreeElement *te,
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
TreeStoreElem *tselem,
|
||||
void *user_data)
|
||||
static void id_override_library_create_cb(bContext *C,
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
TreeElement *te,
|
||||
TreeStoreElem *UNUSED(tsep),
|
||||
TreeStoreElem *tselem,
|
||||
void *user_data)
|
||||
{
|
||||
BLI_assert(TSE_IS_REAL_ID(tselem));
|
||||
ID *id_root = tselem->id;
|
||||
OutlinerLibOverrideData *data = user_data;
|
||||
const bool do_hierarchy = data->do_hierarchy;
|
||||
|
||||
if (ID_IS_LINKED(id_root) &&
|
||||
(BKE_idtype_get_info_from_id(id_root)->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0) {
|
||||
if (ID_IS_OVERRIDABLE_LIBRARY(id_root) || (ID_IS_LINKED(id_root) && do_hierarchy)) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
OutlinerLibOverrideData *data = user_data;
|
||||
const bool do_hierarchy = data->do_hierarchy;
|
||||
|
||||
id_root->tag |= LIB_TAG_DOIT;
|
||||
|
||||
|
@ -798,6 +797,34 @@ static void id_override_library_cb(bContext *C,
|
|||
}
|
||||
}
|
||||
|
||||
static void id_override_library_reset_cb(bContext *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_root = tselem->id;
|
||||
OutlinerLibOverrideData *data = user_data;
|
||||
const bool do_hierarchy = data->do_hierarchy;
|
||||
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
||||
if (do_hierarchy) {
|
||||
BKE_lib_override_library_id_hierarchy_reset(bmain, id_root);
|
||||
}
|
||||
else {
|
||||
BKE_lib_override_library_id_reset(bmain, id_root);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL);
|
||||
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void id_fake_user_set_cb(bContext *UNUSED(C),
|
||||
ReportList *UNUSED(reports),
|
||||
Scene *UNUSED(scene),
|
||||
|
@ -1546,8 +1573,10 @@ typedef enum eOutlinerIdOpTypes {
|
|||
|
||||
OUTLINER_IDOP_UNLINK,
|
||||
OUTLINER_IDOP_LOCAL,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
|
||||
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
|
||||
OUTLINER_IDOP_SINGLE,
|
||||
OUTLINER_IDOP_DELETE,
|
||||
OUTLINER_IDOP_REMAP,
|
||||
|
@ -1566,16 +1595,6 @@ typedef enum eOutlinerIdOpTypes {
|
|||
static const EnumPropertyItem prop_id_op_types[] = {
|
||||
{OUTLINER_IDOP_UNLINK, "UNLINK", 0, "Unlink", ""},
|
||||
{OUTLINER_IDOP_LOCAL, "LOCAL", 0, "Make Local", ""},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY,
|
||||
"OVERRIDE_LIBRARY",
|
||||
0,
|
||||
"Add Library Override",
|
||||
"Add a local override of this linked data-block"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY,
|
||||
"OVERRIDE_LIBRARY_HIERARCHY",
|
||||
0,
|
||||
"Add Library Override Hierarchy",
|
||||
"Add a local override of this linked data-block, and its hierarchy of dependencies"},
|
||||
{OUTLINER_IDOP_SINGLE, "SINGLE", 0, "Make Single User", ""},
|
||||
{OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
|
||||
{OUTLINER_IDOP_REMAP,
|
||||
|
@ -1584,6 +1603,27 @@ static const EnumPropertyItem prop_id_op_types[] = {
|
|||
"Remap Users",
|
||||
"Make all users of selected data-blocks to use instead current (clicked) one"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
|
||||
"OVERRIDE_LIBRARY_CREATE",
|
||||
0,
|
||||
"Add Library Override",
|
||||
"Add a local override of this linked data-block"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
|
||||
"OVERRIDE_LIBRARY_CREATE_HIERARCHY",
|
||||
0,
|
||||
"Add Library Override Hierarchy",
|
||||
"Add a local override of this linked data-block, and its hierarchy of dependencies"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
|
||||
"OVERRIDE_LIBRARY_RESET",
|
||||
0,
|
||||
"Reset Library Override",
|
||||
"Reset this local override to its linked values"},
|
||||
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
|
||||
"OVERRIDE_LIBRARY_RESET_HIERARCHY",
|
||||
0,
|
||||
"Reset Library Override Hierarchy",
|
||||
"Reset this local override to its linked values, as well as its hierarchy of dependencies"},
|
||||
{0, "", 0, NULL, NULL},
|
||||
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
|
||||
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
|
||||
{0, "", 0, NULL, NULL},
|
||||
|
@ -1607,7 +1647,11 @@ static bool outliner_id_operation_item_poll(bContext *C,
|
|||
SpaceOutliner *soops = CTX_wm_space_outliner(C);
|
||||
|
||||
switch (enum_value) {
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY:
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE:
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY:
|
||||
return true;
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET:
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY:
|
||||
return true;
|
||||
case OUTLINER_IDOP_SINGLE:
|
||||
if (!soops || ELEM(soops->outlinevis, SO_SCENES, SO_VIEW_LAYER)) {
|
||||
|
@ -1721,28 +1765,52 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
|
|||
ED_undo_push(C, "Localized Data");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY: {
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
soops,
|
||||
&soops->tree,
|
||||
id_override_library_cb,
|
||||
id_override_library_create_cb,
|
||||
&(OutlinerLibOverrideData){.do_hierarchy = false});
|
||||
ED_undo_push(C, "Overridden Data");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_HIERARCHY: {
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
soops,
|
||||
&soops->tree,
|
||||
id_override_library_cb,
|
||||
id_override_library_create_cb,
|
||||
&(OutlinerLibOverrideData){.do_hierarchy = true});
|
||||
ED_undo_push(C, "Overridden Data");
|
||||
ED_undo_push(C, "Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
soops,
|
||||
&soops->tree,
|
||||
id_override_library_reset_cb,
|
||||
&(OutlinerLibOverrideData){.do_hierarchy = false});
|
||||
ED_undo_push(C, "Reset Overridden Data");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY: {
|
||||
/* make local */
|
||||
outliner_do_libdata_operation(C,
|
||||
op->reports,
|
||||
scene,
|
||||
soops,
|
||||
&soops->tree,
|
||||
id_override_library_reset_cb,
|
||||
&(OutlinerLibOverrideData){.do_hierarchy = true});
|
||||
ED_undo_push(C, "Reset Overridden Data Hierarchy");
|
||||
break;
|
||||
}
|
||||
case OUTLINER_IDOP_SINGLE: {
|
||||
|
|
|
@ -206,7 +206,10 @@ typedef struct IDOverrideLibraryProperty {
|
|||
|
||||
/** Runtime, tags are common to both IDOverrideProperty and IDOverridePropertyOperation. */
|
||||
short tag;
|
||||
char _pad0[6];
|
||||
char _pad[2];
|
||||
|
||||
/** The property type matching the rna_path. */
|
||||
unsigned int rna_prop_type;
|
||||
} IDOverrideLibraryProperty;
|
||||
|
||||
/* IDOverrideProperty->tag and IDOverridePropertyOperation->tag. */
|
||||
|
@ -215,8 +218,18 @@ enum {
|
|||
IDOVERRIDE_LIBRARY_TAG_UNUSED = 1 << 0,
|
||||
};
|
||||
|
||||
/* We do not need a full struct for that currently, just a GHash. */
|
||||
typedef struct GHash IDOverrideLibraryRuntime;
|
||||
#
|
||||
#
|
||||
typedef struct IDOverrideLibraryRuntime {
|
||||
struct GHash *rna_path_to_override_properties;
|
||||
uint tag;
|
||||
} IDOverrideLibraryRuntime;
|
||||
|
||||
/* IDOverrideLibraryRuntime->tag. */
|
||||
enum {
|
||||
/** This override needs to be reloaded. */
|
||||
IDOVERRIDE_LIBRARY_RUNTIME_TAG_NEEDS_RELOAD = 1 << 0,
|
||||
};
|
||||
|
||||
/* Main container for all overriding data info of a data-block. */
|
||||
typedef struct IDOverrideLibrary {
|
||||
|
@ -468,7 +481,8 @@ typedef enum ID_Type {
|
|||
/* Note that this is a fairly high-level check, should be used at user interaction level, not in
|
||||
* BKE_library_override typically (especially due to the check on LIB_TAG_EXTERN). */
|
||||
#define ID_IS_OVERRIDABLE_LIBRARY(_id) \
|
||||
(ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0)
|
||||
(ID_IS_LINKED(_id) && !ID_MISSING(_id) && (((const ID *)(_id))->tag & LIB_TAG_EXTERN) != 0 && \
|
||||
(BKE_idtype_get_info_from_id((const ID *)(_id))->flags & IDTYPE_FLAGS_NO_LIBLINKING) == 0)
|
||||
|
||||
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id) \
|
||||
(((const ID *)(_id))->override_library != NULL && \
|
||||
|
|
|
@ -96,6 +96,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
|
|||
# include "BKE_font.h"
|
||||
# include "BKE_global.h" /* XXX, remove me */
|
||||
# include "BKE_idprop.h"
|
||||
# include "BKE_idtype.h"
|
||||
# include "BKE_lib_override.h"
|
||||
# include "BKE_lib_query.h"
|
||||
# include "BKE_lib_remap.h"
|
||||
|
|
|
@ -1250,6 +1250,7 @@ static int rna_property_override_diff_propptr(Main *bmain,
|
|||
IDOverrideLibrary *override,
|
||||
const char *rna_path,
|
||||
size_t rna_path_len,
|
||||
const uint property_type,
|
||||
const char *rna_itemname_a,
|
||||
const char *rna_itemname_b,
|
||||
const int rna_itemindex_a,
|
||||
|
@ -1257,6 +1258,8 @@ static int rna_property_override_diff_propptr(Main *bmain,
|
|||
const int flags,
|
||||
bool *r_override_changed)
|
||||
{
|
||||
BLI_assert(ELEM(property_type, PROP_POINTER, PROP_COLLECTION));
|
||||
|
||||
const bool do_create = override != NULL && (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0 &&
|
||||
rna_path != NULL;
|
||||
|
||||
|
@ -1300,6 +1303,13 @@ static int rna_property_override_diff_propptr(Main *bmain,
|
|||
if (op != NULL) {
|
||||
BKE_lib_override_library_operations_tag(op, IDOVERRIDE_LIBRARY_TAG_UNUSED, false);
|
||||
|
||||
if (created || op->rna_prop_type == 0) {
|
||||
op->rna_prop_type = property_type;
|
||||
}
|
||||
else {
|
||||
BLI_assert(op->rna_prop_type == property_type);
|
||||
}
|
||||
|
||||
if (created || rna_itemname_a != NULL || rna_itemname_b != NULL ||
|
||||
rna_itemindex_a != -1 || rna_itemindex_b != -1) {
|
||||
BKE_lib_override_library_property_operation_get(op,
|
||||
|
@ -1464,7 +1474,11 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
PROPOVERRIDE_LIBRARY_INSERTION) &&
|
||||
do_create;
|
||||
|
||||
switch (RNA_property_type(prop_a->rnaprop)) {
|
||||
const uint rna_prop_type = RNA_property_type(prop_a->rnaprop);
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = NULL;
|
||||
|
||||
switch (rna_prop_type) {
|
||||
case PROP_BOOLEAN: {
|
||||
if (len_a) {
|
||||
bool array_stack_a[RNA_STACK_ARRAY], array_stack_b[RNA_STACK_ARRAY];
|
||||
|
@ -1482,9 +1496,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
|
||||
if (do_create && comp != 0) {
|
||||
/* XXX TODO this will have to be refined to handle array items */
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) {
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1513,9 +1525,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
|
||||
|
||||
if (do_create && comp != 0) {
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) { /* If not yet overridden... */
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1547,9 +1557,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
|
||||
if (do_create && comp != 0) {
|
||||
/* XXX TODO this will have to be refined to handle array items */
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) {
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1578,9 +1586,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
|
||||
|
||||
if (do_create && comp != 0) {
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) { /* If not yet overridden... */
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1612,9 +1618,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
|
||||
if (do_create && comp != 0) {
|
||||
/* XXX TODO this will have to be refined to handle array items */
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) {
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1643,9 +1647,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
const int comp = (value_a < value_b) ? -1 : (value_a > value_b) ? 1 : 0;
|
||||
|
||||
if (do_create && comp != 0) {
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) { /* If not yet overridden... */
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1666,9 +1668,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
const int comp = value_a != value_b;
|
||||
|
||||
if (do_create && comp != 0) {
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) { /* If not yet overridden... */
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1700,9 +1700,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
const int comp = strcmp(value_a, value_b);
|
||||
|
||||
if (do_create && comp != 0) {
|
||||
bool created = false;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (op != NULL && created) { /* If not yet overridden... */
|
||||
BKE_lib_override_library_property_operation_get(
|
||||
|
@ -1740,6 +1738,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
override,
|
||||
rna_path,
|
||||
rna_path_len,
|
||||
PROP_POINTER,
|
||||
NULL,
|
||||
NULL,
|
||||
-1,
|
||||
|
@ -1848,9 +1847,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
* pointers), since they do not support removing, only in *some* cases, insertion. We
|
||||
* also assume then that _a data is the one where things are inserted. */
|
||||
if (is_valid_for_insertion && use_collection_insertion) {
|
||||
bool created;
|
||||
IDOverrideLibraryProperty *op = BKE_lib_override_library_property_get(
|
||||
override, rna_path, &created);
|
||||
op = BKE_lib_override_library_property_get(override, rna_path, &created);
|
||||
|
||||
if (is_first_insert) {
|
||||
/* We need to clean up all possible existing insertion operations,
|
||||
|
@ -1883,6 +1880,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
prev_propname_a,
|
||||
idx_a - 1);
|
||||
# endif
|
||||
op = NULL;
|
||||
}
|
||||
else if (is_id || is_valid_for_diffing) {
|
||||
if (equals || do_create) {
|
||||
|
@ -1895,6 +1893,7 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
override,
|
||||
rna_path,
|
||||
rna_path_len,
|
||||
PROP_COLLECTION,
|
||||
propname_a,
|
||||
propname_b,
|
||||
idx_a,
|
||||
|
@ -1963,6 +1962,15 @@ int rna_property_override_diff_default(Main *bmain,
|
|||
break;
|
||||
}
|
||||
|
||||
if (op != NULL) {
|
||||
if (created || op->rna_prop_type == 0) {
|
||||
op->rna_prop_type = rna_prop_type;
|
||||
}
|
||||
else {
|
||||
BLI_assert(op->rna_prop_type == rna_prop_type);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue