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:
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tools.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c555
1 files changed, 300 insertions, 255 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 80a63af3f42..dae2ba32f09 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -44,6 +44,7 @@
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
@@ -53,6 +54,7 @@
#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
+#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
@@ -541,7 +543,7 @@ static void merged_element_search_cb_recursive(
/* Don't allow duplicate named items */
if (UI_search_items_find_index(items, name) == -1) {
- if (!UI_search_item_add(items, name, te, iconid, 0)) {
+ if (!UI_search_item_add(items, name, te, iconid, 0, 0)) {
break;
}
}
@@ -573,8 +575,7 @@ static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1)
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = (TreeElement *)element;
- outliner_item_select(soops, te, false, false);
- outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE);
ED_outliner_select_sync_from_outliner(C, soops);
}
@@ -664,12 +665,13 @@ static void object_select_hierarchy_cb(bContext *C,
Scene *UNUSED(scene),
TreeElement *te,
TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
+ TreeStoreElem *UNUSED(tselem),
void *UNUSED(user_data))
{
/* Don't extend because this toggles, which is nice for Ctrl-Click but not for a menu item.
* it's especially confusing when multiple items are selected since some toggle on/off. */
- outliner_item_do_activate_from_tree_element(C, te, tselem, false, true);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ outliner_item_select(C, soops, te, OL_ITEM_SELECT | OL_ITEM_ACTIVATE | OL_ITEM_RECURSIVE);
}
static void object_deselect_cb(bContext *C,
@@ -689,12 +691,8 @@ static void object_deselect_cb(bContext *C,
}
}
-static void outliner_object_delete(bContext *C,
- ReportList *reports,
- Scene *scene,
- TreeStoreElem *tselem)
+static void outliner_object_delete_fn(bContext *C, ReportList *reports, Scene *scene, Object *ob)
{
- Object *ob = (Object *)tselem->id;
if (ob) {
Main *bmain = CTX_data_main(C);
if (ob->id.tag & LIB_TAG_INDIRECT) {
@@ -702,8 +700,8 @@ static void outliner_object_delete(bContext *C,
reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2);
return;
}
- else if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
- ID_EXTRA_USERS(ob) == 0) {
+ if (BKE_library_ID_is_indirectly_used(bmain, ob) && ID_REAL_USERS(ob) <= 1 &&
+ ID_EXTRA_USERS(ob) == 0) {
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at "
@@ -742,26 +740,91 @@ static void id_local_cb(bContext *C,
}
}
-static void id_override_library_cb(bContext *C,
- ReportList *UNUSED(reports),
- Scene *UNUSED(scene),
- TreeElement *UNUSED(te),
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+typedef struct OutlinerLibOverrideData {
+ bool do_hierarchy;
+} OutlinerLibOverrideData;
+
+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)
{
- if (ID_IS_OVERRIDABLE_LIBRARY(tselem->id)) {
+ 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_OVERRIDABLE_LIBRARY(id_root) || (ID_IS_LINKED(id_root) && do_hierarchy)) {
Main *bmain = CTX_data_main(C);
+
+ id_root->tag |= LIB_TAG_DOIT;
+
/* For now, remapp all local usages of linked ID to local override one here. */
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, true);
- ID *override_id = BKE_lib_override_library_create_from_id(bmain, tselem->id, true);
- if (override_id != NULL) {
- BKE_main_id_clear_newpoins(bmain);
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (ID_IS_LINKED(id_iter)) {
+ id_iter->tag &= ~LIB_TAG_DOIT;
+ }
+ else {
+ id_iter->tag |= LIB_TAG_DOIT;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ if (do_hierarchy) {
+ /* Tag all linked parents in tree hierarchy to be also overridden. */
+ while ((te = te->parent) != NULL) {
+ if (!TSE_IS_REAL_ID(te->store_elem)) {
+ continue;
+ }
+ if (!ID_IS_LINKED(te->store_elem->id)) {
+ break;
+ }
+ te->store_elem->id->tag |= LIB_TAG_DOIT;
+ }
+ BKE_lib_override_library_create(
+ bmain, CTX_data_scene(C), CTX_data_view_layer(C), id_root, NULL);
+ }
+ else if (ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
+ BKE_lib_override_library_create_from_id(bmain, id_root, true);
}
+
+ BKE_main_id_clear_newpoins(bmain);
BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
}
+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),
@@ -804,11 +867,17 @@ static void id_select_linked_cb(bContext *C,
static void singleuser_action_cb(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
- TreeElement *UNUSED(te),
+ TreeElement *te,
TreeStoreElem *tsep,
TreeStoreElem *tselem,
void *UNUSED(user_data))
{
+ /* This callback runs for all selected elements, some of which may not be actions which results
+ * in a crash. */
+ if (te->idcode != ID_AC) {
+ return;
+ }
+
ID *id = tselem->id;
if (id) {
@@ -860,18 +929,17 @@ void outliner_do_object_operation_ex(bContext *C,
bool select_recurse)
{
TreeElement *te;
-
for (te = lb->first; te; te = te->next) {
TreeStoreElem *tselem = TREESTORE(te);
bool select_handled = false;
if (tselem->flag & TSE_SELECTED) {
if (tselem->type == 0 && te->idcode == ID_OB) {
- // when objects selected in other scenes... dunno if that should be allowed
+ /* When objects selected in other scenes... dunno if that should be allowed. */
Scene *scene_owner = (Scene *)outliner_search_back(te, ID_SCE);
if (scene_owner && scene_act != scene_owner) {
WM_window_set_active_scene(CTX_data_main(C), C, CTX_wm_window(C), scene_owner);
}
- /* important to use 'scene_owner' not scene_act else deleting objects can crash.
+ /* Important to use 'scene_owner' not scene_act else deleting objects can crash.
* only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
* outliner isn't showing scenes: Visible Layer draw mode for eg. */
operation_cb(
@@ -1051,10 +1119,10 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void
(void)tselem;
}
-static void gp_layer_cb(int event,
- TreeElement *te,
- TreeStoreElem *UNUSED(tselem),
- void *UNUSED(arg))
+static void gpencil_layer_cb(int event,
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tselem),
+ void *UNUSED(arg))
{
bGPDlayer *gpl = (bGPDlayer *)te->directdata;
@@ -1131,6 +1199,7 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
{
bContext *C = (bContext *)Carg;
Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
ModifierData *md = (ModifierData *)te->directdata;
Object *ob = (Object *)outliner_search_back(te, ID_OB);
@@ -1145,7 +1214,7 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
}
else if (event == OL_MODIFIER_OP_DELETE) {
- ED_object_modifier_remove(NULL, bmain, ob, md);
+ ED_object_modifier_remove(NULL, bmain, scene, ob, md);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER | NA_REMOVED, ob);
te->store_elem->flag &= ~TSE_SELECTED;
}
@@ -1175,82 +1244,6 @@ static void outliner_do_data_operation(
}
}
-static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *scene, Base *base)
-{
- Base *child_base, *base_next;
- Object *parent;
- ViewLayer *view_layer = CTX_data_view_layer(C);
-
- if (!base) {
- return NULL;
- }
-
- for (child_base = view_layer->object_bases.first; child_base; child_base = base_next) {
- base_next = child_base->next;
- for (parent = child_base->object->parent; parent && (parent != base->object);
- parent = parent->parent) {
- /* pass */
- }
- if (parent) {
- base_next = outline_delete_hierarchy(C, reports, scene, child_base);
- }
- }
-
- base_next = base->next;
-
- Main *bmain = CTX_data_main(C);
- if (base->object->id.tag & LIB_TAG_INDIRECT) {
- BKE_reportf(reports,
- RPT_WARNING,
- "Cannot delete indirectly linked object '%s'",
- base->object->id.name + 2);
- return base_next;
- }
- else if (BKE_library_ID_is_indirectly_used(bmain, base->object) &&
- ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) {
- BKE_reportf(reports,
- RPT_WARNING,
- "Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
- "one user",
- base->object->id.name + 2,
- scene->id.name + 2);
- return base_next;
- }
- ED_object_base_free_and_unlink(CTX_data_main(C), scene, base->object);
- return base_next;
-}
-
-static void object_delete_hierarchy_cb(bContext *C,
- ReportList *reports,
- Scene *scene,
- TreeElement *te,
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
-{
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = (Base *)te->directdata;
- Object *obedit = CTX_data_edit_object(C);
-
- if (!base) {
- base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
- }
- if (base) {
- /* Check also library later. */
- for (; obedit && (obedit != base->object); obedit = obedit->parent) {
- /* pass */
- }
- if (obedit == base->object) {
- ED_object_editmode_exit(C, EM_FREEDATA);
- }
-
- outline_delete_hierarchy(C, reports, scene, base);
- }
-
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
-}
-
static Base *outline_batch_delete_hierarchy(
ReportList *reports, Main *bmain, ViewLayer *view_layer, Scene *scene, Base *base)
{
@@ -1282,8 +1275,8 @@ static Base *outline_batch_delete_hierarchy(
base->object->id.name + 2);
return base_next;
}
- else if (BKE_library_ID_is_indirectly_used(bmain, object) && ID_REAL_USERS(object) <= 1 &&
- ID_EXTRA_USERS(object) == 0) {
+ if (BKE_library_ID_is_indirectly_used(bmain, object) && ID_REAL_USERS(object) <= 1 &&
+ ID_EXTRA_USERS(object) == 0) {
BKE_reportf(reports,
RPT_WARNING,
"Cannot delete object '%s' from scene '%s', indirectly used objects need at least "
@@ -1303,21 +1296,16 @@ static Base *outline_batch_delete_hierarchy(
return base_next;
}
-static void object_batch_delete_hierarchy_cb(bContext *C,
+static void object_batch_delete_hierarchy_fn(bContext *C,
ReportList *reports,
Scene *scene,
- TreeElement *te,
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+ Object *ob)
{
ViewLayer *view_layer = CTX_data_view_layer(C);
- Base *base = (Base *)te->directdata;
Object *obedit = CTX_data_edit_object(C);
- if (!base) {
- base = BKE_view_layer_base_find(view_layer, (Object *)tselem->id);
- }
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+
if (base) {
/* Check also library later. */
for (; obedit && (obedit != base->object); obedit = obedit->parent) {
@@ -1341,7 +1329,6 @@ enum {
OL_OP_SELECT = 1,
OL_OP_DESELECT,
OL_OP_SELECT_HIERARCHY,
- OL_OP_DELETE_HIERARCHY,
OL_OP_REMAP,
OL_OP_LOCALIZED, /* disabled, see below */
OL_OP_TOGVIS,
@@ -1356,7 +1343,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
{OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""},
{OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""},
{OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""},
- {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""},
{OL_OP_REMAP,
"REMAP",
0,
@@ -1370,7 +1356,6 @@ static const EnumPropertyItem prop_object_op_types[] = {
static int outliner_object_operation_exec(bContext *C, wmOperator *op)
{
- struct wmMsgBus *mbus = CTX_wm_message_bus(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
wmWindow *win = CTX_wm_window(C);
@@ -1387,7 +1372,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
event = RNA_enum_get(op->ptr, "type");
if (event == OL_OP_SELECT) {
- Scene *sce = scene; // to be able to delete, scenes are set...
+ Scene *sce = scene; /* To be able to delete, scenes are set... */
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_select_cb);
if (scene != sce) {
WM_window_set_active_scene(bmain, C, win, sce);
@@ -1397,7 +1382,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
selection_changed = true;
}
else if (event == OL_OP_SELECT_HIERARCHY) {
- Scene *sce = scene; // to be able to delete, scenes are set...
+ Scene *sce = scene; /* To be able to delete, scenes are set... */
outliner_do_object_operation_ex(
C, op->reports, scene, soops, &soops->tree, object_select_hierarchy_cb, NULL, false);
if (scene != sce) {
@@ -1411,47 +1396,10 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
str = "Deselect Objects";
selection_changed = true;
}
- else if (event == OL_OP_DELETE_HIERARCHY) {
- ViewLayer *view_layer = CTX_data_view_layer(C);
- const Base *basact_prev = BASACT(view_layer);
-
- /* Keeping old 'safe and slow' code for a bit (new one enabled on 28/01/2019). */
- if (G.debug_value == 666) {
- outliner_do_object_operation_ex(
- C, op->reports, scene, soops, &soops->tree, object_delete_hierarchy_cb, NULL, false);
- }
- else {
- BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-
- outliner_do_object_operation_ex(C,
- op->reports,
- scene,
- soops,
- &soops->tree,
- object_batch_delete_hierarchy_cb,
- NULL,
- false);
-
- BKE_id_multi_tagged_delete(bmain);
- }
-
- /* XXX: See outliner_delete_exec comment below. */
- outliner_cleanup_tree(soops);
-
- DEG_relations_tag_update(bmain);
- str = "Delete Object Hierarchy";
- DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
- if (basact_prev != BASACT(view_layer)) {
- WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
- WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active);
- }
- selection_changed = true;
- }
else if (event == OL_OP_REMAP) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
- /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth trick
- * does not work here). */
+ /* No undo push here, operator does it itself (since it's a modal one, the op_undo_depth
+ * trick does not work here). */
}
else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */
outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb);
@@ -1511,22 +1459,38 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
/** \name Delete Object/Collection Operator
* \{ */
-static void outliner_objects_delete(
- bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb)
+typedef void (*OutlinerDeleteFunc)(bContext *C, ReportList *reports, Scene *scene, Object *ob);
+
+static void outliner_do_object_delete(bContext *C,
+ ReportList *reports,
+ Scene *scene,
+ GSet *objects_to_delete,
+ OutlinerDeleteFunc delete_fn)
{
- LISTBASE_FOREACH (TreeElement *, te, lb) {
- TreeStoreElem *tselem = TREESTORE(te);
+ GSetIterator objects_to_delete_iter;
+ GSET_ITER (objects_to_delete_iter, objects_to_delete) {
+ Object *ob = (Object *)BLI_gsetIterator_getKey(&objects_to_delete_iter);
- if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == 0 && te->idcode == ID_OB) {
- outliner_object_delete(C, reports, scene, tselem);
- }
- }
+ delete_fn(C, reports, scene, ob);
+ }
+}
- if (TSELEM_OPEN(tselem, soops)) {
- outliner_objects_delete(C, scene, soops, reports, &te->subtree);
- }
+static TreeTraversalAction outliner_find_objects_to_delete(TreeElement *te, void *customdata)
+{
+ GSet *objects_to_delete = (GSet *)customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (outliner_is_collection_tree_element(te)) {
+ return TRAVERSE_CONTINUE;
+ }
+
+ if (tselem->type || (tselem->id == NULL) || (GS(tselem->id->name) != ID_OB)) {
+ return TRAVERSE_SKIP_CHILDS;
}
+
+ BLI_gset_add(objects_to_delete, tselem->id);
+
+ return TRAVERSE_CONTINUE;
}
static int outliner_delete_exec(bContext *C, wmOperator *op)
@@ -1535,12 +1499,32 @@ static int outliner_delete_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
-
ViewLayer *view_layer = CTX_data_view_layer(C);
const Base *basact_prev = BASACT(view_layer);
- outliner_collection_delete(C, bmain, scene, op->reports, false);
- outliner_objects_delete(C, scene, soops, op->reports, &soops->tree);
+ const bool delete_hierarchy = RNA_boolean_get(op->ptr, "hierarchy");
+
+ /* Get selected objects skipping duplicates to prevent deleting objects linked to multiple
+ * collections twice */
+ GSet *objects_to_delete = BLI_gset_ptr_new(__func__);
+ outliner_tree_traverse(
+ soops, &soops->tree, 0, TSE_SELECTED, outliner_find_objects_to_delete, objects_to_delete);
+
+ if (delete_hierarchy) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
+ outliner_do_object_delete(
+ C, op->reports, scene, objects_to_delete, object_batch_delete_hierarchy_fn);
+
+ BKE_id_multi_tagged_delete(bmain);
+ }
+ else {
+ outliner_do_object_delete(C, op->reports, scene, objects_to_delete, outliner_object_delete_fn);
+ }
+
+ BLI_gset_free(objects_to_delete, NULL);
+
+ outliner_collection_delete(C, bmain, scene, op->reports, delete_hierarchy);
/* Tree management normally happens from draw_outliner(), but when
* you're clicking too fast on Delete object from context menu in
@@ -1577,6 +1561,11 @@ void OUTLINER_OT_delete(wmOperatorType *ot)
/* flags */
ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(
+ ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/** \} */
@@ -1590,7 +1579,10 @@ typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_UNLINK,
OUTLINER_IDOP_LOCAL,
- OUTLINER_IDOP_OVERRIDE_LIBRARY,
+ 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,
@@ -1605,15 +1597,10 @@ typedef enum eOutlinerIdOpTypes {
OUTLINER_IDOP_SELECT_LINKED,
} eOutlinerIdOpTypes;
-// TODO: implement support for changing the ID-block used
+/* TODO: implement support for changing the ID-block used. */
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_SINGLE, "SINGLE", 0, "Make Single User", ""},
{OUTLINER_IDOP_DELETE, "DELETE", ICON_X, "Delete", ""},
{OUTLINER_IDOP_REMAP,
@@ -1622,6 +1609,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},
@@ -1645,8 +1653,12 @@ static bool outliner_id_operation_item_poll(bContext *C,
SpaceOutliner *soops = CTX_wm_space_outliner(C);
switch (enum_value) {
- case OUTLINER_IDOP_OVERRIDE_LIBRARY:
- return BKE_lib_override_library_is_enabled();
+ 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)) {
return true;
@@ -1759,13 +1771,52 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Localized Data");
break;
}
- case OUTLINER_IDOP_OVERRIDE_LIBRARY: {
- if (BKE_lib_override_library_is_enabled()) {
- /* make local */
- outliner_do_libdata_operation(
- C, op->reports, scene, soops, &soops->tree, id_override_library_cb, NULL);
- ED_undo_push(C, "Overridden Data");
- }
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE: {
+ /* make local */
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ soops,
+ &soops->tree,
+ id_override_library_create_cb,
+ &(OutlinerLibOverrideData){.do_hierarchy = false});
+ ED_undo_push(C, "Overridden Data");
+ break;
+ }
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY: {
+ /* make local */
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ soops,
+ &soops->tree,
+ id_override_library_create_cb,
+ &(OutlinerLibOverrideData){.do_hierarchy = true});
+ 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: {
@@ -1860,14 +1911,14 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
break;
default:
- // invalid - unhandled
+ /* Invalid - unhandled. */
break;
}
/* wrong notifier still... */
WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- // XXX: this is just so that outliner is always up to date
+ /* XXX: this is just so that outliner is always up to date. */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_OUTLINER, NULL);
return OPERATOR_FINISHED;
@@ -2043,7 +2094,7 @@ static void actionset_id_cb(TreeElement *UNUSED(te),
/* "animation" entries case again */
BKE_animdata_set_action(NULL, tsep->id, act);
}
- // TODO: other cases not supported yet
+ /* TODO: other cases not supported yet. */
}
static int outliner_action_set_exec(bContext *C, wmOperator *op)
@@ -2067,7 +2118,7 @@ static int outliner_action_set_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No valid action to add");
return OPERATOR_CANCELLED;
}
- else if (act->idroot == 0) {
+ if (act->idroot == 0) {
/* Hopefully in this case (i.e. library of userless actions),
* the user knows what they're doing. */
BKE_reportf(op->reports,
@@ -2115,7 +2166,7 @@ void OUTLINER_OT_action_set(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
- // TODO: this would be nicer as an ID-pointer...
+ /* TODO: this would be nicer as an ID-pointer... */
prop = RNA_def_enum(ot->srna, "action", DummyRNA_NULL_items, 0, "Action", "");
RNA_def_enum_funcs(prop, RNA_action_itemf);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
@@ -2139,8 +2190,8 @@ typedef enum eOutliner_AnimDataOps {
OUTLINER_ANIMOP_REFRESH_DRV,
OUTLINER_ANIMOP_CLEAR_DRV
- // OUTLINER_ANIMOP_COPY_DRIVERS,
- // OUTLINER_ANIMOP_PASTE_DRIVERS
+ /* OUTLINER_ANIMOP_COPY_DRIVERS, */
+ /* OUTLINER_ANIMOP_PASTE_DRIVERS */
} eOutliner_AnimDataOps;
static const EnumPropertyItem prop_animdata_op_types[] = {
@@ -2152,8 +2203,8 @@ static const EnumPropertyItem prop_animdata_op_types[] = {
{OUTLINER_ANIMOP_SET_ACT, "SET_ACT", 0, "Set Action", ""},
{OUTLINER_ANIMOP_CLEAR_ACT, "CLEAR_ACT", 0, "Unlink Action", ""},
{OUTLINER_ANIMOP_REFRESH_DRV, "REFRESH_DRIVERS", 0, "Refresh Drivers", ""},
- //{OUTLINER_ANIMOP_COPY_DRIVERS, "COPY_DRIVERS", 0, "Copy Drivers", ""},
- //{OUTLINER_ANIMOP_PASTE_DRIVERS, "PASTE_DRIVERS", 0, "Paste Drivers", ""},
+ /* {OUTLINER_ANIMOP_COPY_DRIVERS, "COPY_DRIVERS", 0, "Copy Drivers", ""}, */
+ /* {OUTLINER_ANIMOP_PASTE_DRIVERS, "PASTE_DRIVERS", 0, "Paste Drivers", ""}, */
{OUTLINER_ANIMOP_CLEAR_DRV, "CLEAR_DRIVERS", 0, "Clear Drivers", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -2209,7 +2260,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
soops, datalevel, event, &soops->tree, refreshdrivers_animdata_cb, NULL);
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, NULL);
- // ED_undo_push(C, "Refresh Drivers"); /* no undo needed - shouldn't have any impact? */
+ /* ED_undo_push(C, "Refresh Drivers"); No undo needed - shouldn't have any impact? */
break;
case OUTLINER_ANIMOP_CLEAR_DRV:
@@ -2220,7 +2271,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Clear Drivers");
break;
- default: // invalid
+ default: /* Invalid. */
break;
}
@@ -2351,7 +2402,7 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/** \name Data Menu Operator
* \{ */
-// XXX: select linked is for RNA structs only
+/* XXX: select linked is for RNA structs only. */
static const EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
{OL_DOP_DESELECT, "DESELECT", 0, "Deselect", ""},
@@ -2404,7 +2455,7 @@ static int outliner_data_operation_exec(bContext *C, wmOperator *op)
break;
}
case TSE_GP_LAYER: {
- outliner_do_data_operation(soops, datalevel, event, &soops->tree, gp_layer_cb, NULL);
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, gpencil_layer_cb, NULL);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, NULL);
ED_undo_push(C, "Grease Pencil Layer operation");
@@ -2470,7 +2521,7 @@ static int outliner_operator_menu(bContext *C, const char *opname)
static int do_outliner_operation_event(
bContext *C, ARegion *region, SpaceOutliner *soops, TreeElement *te, const float mval[2])
{
- ReportList *reports = CTX_wm_reports(C); // XXX...
+ ReportList *reports = CTX_wm_reports(C); /* XXX... */
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
@@ -2498,32 +2549,29 @@ static int do_outliner_operation_event(
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
- else {
- return outliner_operator_menu(C, "OUTLINER_OT_scene_operation");
- }
+ return outliner_operator_menu(C, "OUTLINER_OT_scene_operation");
}
- else if (objectlevel) {
+ if (objectlevel) {
WM_menu_name_call(C, "OUTLINER_MT_object", WM_OP_INVOKE_REGION_WIN);
return OPERATOR_FINISHED;
}
- else if (idlevel) {
+ if (idlevel) {
if (idlevel == -1 || datalevel) {
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
- else {
- switch (idlevel) {
- case ID_GR:
- WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- break;
- case ID_LI:
- return outliner_operator_menu(C, "OUTLINER_OT_lib_operation");
- break;
- default:
- return outliner_operator_menu(C, "OUTLINER_OT_id_operation");
- break;
- }
+
+ switch (idlevel) {
+ case ID_GR:
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ break;
+ case ID_LI:
+ return outliner_operator_menu(C, "OUTLINER_OT_lib_operation");
+ break;
+ default:
+ return outliner_operator_menu(C, "OUTLINER_OT_id_operation");
+ break;
}
}
else if (datalevel) {
@@ -2531,35 +2579,32 @@ static int do_outliner_operation_event(
BKE_report(reports, RPT_WARNING, "Mixed selection");
return OPERATOR_CANCELLED;
}
- else {
- if (datalevel == TSE_ANIM_DATA) {
- return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation");
- }
- else if (datalevel == TSE_DRIVER_BASE) {
- /* do nothing... no special ops needed yet */
- return OPERATOR_CANCELLED;
- }
- else if (datalevel == TSE_LAYER_COLLECTION) {
- WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
- else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
- WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
- return OPERATOR_FINISHED;
- }
- else if (datalevel == TSE_ID_BASE) {
- /* do nothing... there are no ops needed here yet */
- }
- else if (datalevel == TSE_CONSTRAINT) {
- return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation");
- }
- else if (datalevel == TSE_MODIFIER) {
- return outliner_operator_menu(C, "OUTLINER_OT_modifier_operation");
- }
- else {
- return outliner_operator_menu(C, "OUTLINER_OT_data_operation");
- }
+ if (datalevel == TSE_ANIM_DATA) {
+ return outliner_operator_menu(C, "OUTLINER_OT_animdata_operation");
+ }
+ if (datalevel == TSE_DRIVER_BASE) {
+ /* do nothing... no special ops needed yet */
+ return OPERATOR_CANCELLED;
+ }
+ if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ }
+ if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
+ WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
+ return OPERATOR_FINISHED;
+ }
+ if (datalevel == TSE_ID_BASE) {
+ /* do nothing... there are no ops needed here yet */
+ return 0;
+ }
+ if (datalevel == TSE_CONSTRAINT) {
+ return outliner_operator_menu(C, "OUTLINER_OT_constraint_operation");
+ }
+ if (datalevel == TSE_MODIFIER) {
+ return outliner_operator_menu(C, "OUTLINER_OT_modifier_operation");
}
+ return outliner_operator_menu(C, "OUTLINER_OT_data_operation");
}
return 0;