diff options
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tools.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tools.c | 237 |
1 files changed, 167 insertions, 70 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 29dcf73109c..f2d73f40039 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -53,9 +53,9 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_constraint.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -64,8 +64,12 @@ #include "BKE_scene.h" #include "BKE_sequencer.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_armature.h" #include "ED_object.h" +#include "ED_scene.h" #include "ED_screen.h" #include "ED_sequencer.h" #include "ED_util.h" @@ -308,7 +312,7 @@ static bool scene_cb(bContext *C, eOutliner_PropSceneOps event, TreeElement *UNU Scene *scene = (Scene *)tselem->id; if (event == OL_SCENE_OP_DELETE) { - if (ED_screen_delete_scene(C, scene)) { + if (ED_scene_delete(C, CTX_data_main(C), CTX_wm_window(C), scene)) { WM_event_add_notifier(C, NC_SCENE | NA_REMOVED, scene); } else { @@ -359,15 +363,15 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) /* ******************************************** */ static void object_select_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base && ((base->object->restrictflag & OB_RESTRICT_VIEW) == 0)) { - base->flag |= SELECT; - base->object->flag |= SELECT; + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + + if (base && ((base->flag & BASE_VISIBLED) != 0)) { + base->flag |= BASE_SELECTED; } } @@ -379,20 +383,20 @@ static void object_select_hierarchy_cb( wmWindow *win = CTX_wm_window(C); int x = win->eventstate->mval[0]; int y = win->eventstate->mval[1]; - outliner_item_do_activate(C, x, y, true, true); + outliner_item_activate_or_toggle_closed(C, x, y, true, true); } static void object_deselect_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *te, + bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - Base *base = (Base *)te->directdata; - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); + SceneLayer *sl = CTX_data_scene_layer(C); + Object *ob = (Object *)tselem->id; + Base *base = BKE_scene_layer_base_find(sl, ob); + if (base) { - base->flag &= ~SELECT; - base->object->flag &= ~SELECT; + base->flag &= ~BASE_SELECTED; } } @@ -400,30 +404,27 @@ static void object_delete_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *tsep, TreeStoreElem *tselem, void *user_data) { - Base *base = (Base *)te->directdata; - - if (base == NULL) - base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { + Object *ob = (Object *)tselem->id; + if (ob) { 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); + if (ob->id.tag & LIB_TAG_INDIRECT) { + BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked object '%s'", ob->id.name + 2); return; } - else if (BKE_library_ID_is_indirectly_used(bmain, base->object) && - ID_REAL_USERS(base->object) <= 1 && ID_EXTRA_USERS(base->object) == 0) + else 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 least one user", - base->object->id.name + 2, scene->id.name + 2); + ob->id.name + 2, scene->id.name + 2); return; } // check also library later - if (scene->obedit == base->object) + if (scene->obedit == ob) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, ob); /* leave for ED_outliner_id_unref to handle */ #if 0 te->directdata = NULL; @@ -521,22 +522,25 @@ static void singleuser_world_cb( } static void group_linkobs2scene_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), + bContext *C, ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { + SceneLayer *sl = CTX_data_scene_layer(C); + SceneCollection *sc = CTX_data_scene_collection(C); Group *group = (Group *)tselem->id; GroupObject *gob; Base *base; for (gob = group->gobject.first; gob; gob = gob->next) { - base = BKE_scene_base_find(scene, gob->ob); + base = BKE_scene_layer_base_find(sl, gob->ob); if (!base) { /* link to scene */ - base = BKE_scene_base_add(scene, gob->ob); + BKE_collection_object_add(scene, sc, gob->ob); + base = BKE_scene_layer_base_find(sl, gob->ob); id_us_plus(&gob->ob->id); } - base->object->flag |= SELECT; - base->flag |= SELECT; + + base->flag |= BASE_SELECTED; } } @@ -569,7 +573,7 @@ void outliner_do_object_operation_ex( // when objects selected in other scenes... dunno if that should be allowed Scene *scene_owner = (Scene *)outliner_search_back(soops, te, ID_SCE); if (scene_owner && scene_act != scene_owner) { - ED_screen_set_scene(C, CTX_wm_screen(C), scene_owner); + WM_window_change_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. * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the @@ -656,6 +660,14 @@ typedef enum eOutliner_PropModifierOps { OL_MODIFIER_OP_DELETE } eOutliner_PropModifierOps; +typedef enum eOutliner_PropCollectionOps { + OL_COLLECTION_OP_OBJECTS_ADD = 1, + OL_COLLECTION_OP_OBJECTS_REMOVE, + OL_COLLECTION_OP_COLLECTION_NEW, + OL_COLLECTION_OP_COLLECTION_DEL, + OL_COLLECTION_OP_COLLECTION_UNLINK, +} eOutliner_PropCollectionOps; + static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg)) { bPoseChannel *pchan = (bPoseChannel *)te->directdata; @@ -791,12 +803,12 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem if (event == OL_MODIFIER_OP_TOGVIS) { md->mode ^= eModifierMode_Realtime; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else if (event == OL_MODIFIER_OP_TOGREN) { md->mode ^= eModifierMode_Render; - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); } else if (event == OL_MODIFIER_OP_DELETE) { @@ -806,6 +818,63 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem } } +static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg) +{ + bContext *C = (bContext *)Carg; + Scene *scene = CTX_data_scene(C); + LayerCollection *lc = te->directdata; + SceneCollection *sc = lc->scene_collection; + + if (event == OL_COLLECTION_OP_OBJECTS_ADD) { + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + BKE_collection_object_add(scene, sc, ob); + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) { + Main *bmain = CTX_data_main(C); + + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + BKE_collection_object_remove(bmain, scene, sc, ob, true); + } + CTX_DATA_END; + + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + te->store_elem->flag &= ~TSE_SELECTED; + } + else if (event == OL_COLLECTION_OP_COLLECTION_NEW) { + BKE_collection_add(scene, sc, NULL); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) { + SceneLayer *sl = CTX_data_scene_layer(C); + + if (BLI_findindex(&sl->layer_collections, lc) == -1) { + /* we can't unlink if the layer collection wasn't directly linked */ + TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */ + } + else { + BKE_collection_unlink(sl, lc); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + } + else if (event == OL_COLLECTION_OP_COLLECTION_DEL) { + if (BKE_collection_remove(scene, sc)) { + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } + else { + /* we can't remove the master collection */ + TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */ + } + } +} + static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb, void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *), void *arg) @@ -830,12 +899,13 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s { Base *child_base, *base_next; Object *parent; + SceneLayer *scene_layer = CTX_data_scene_layer(C); if (!base) { return NULL; } - for (child_base = scene->base.first; child_base; child_base = base_next) { + for (child_base = scene_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); if (parent) { @@ -858,7 +928,7 @@ static Base *outline_delete_hierarchy(bContext *C, ReportList *reports, Scene *s base->object->id.name + 2, scene->id.name + 2); return base_next; } - ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); + ED_base_object_free_and_unlink(CTX_data_main(C), scene, base->object); return base_next; } @@ -866,11 +936,12 @@ static void object_delete_hierarchy_cb( bContext *C, ReportList *reports, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { + SceneLayer *sl = CTX_data_scene_layer(C); Base *base = (Base *)te->directdata; Object *obedit = scene->obedit; if (!base) { - base = BKE_scene_base_find(scene, (Object *)tselem->id); + base = BKE_scene_layer_base_find(sl, (Object *)tselem->id); } if (base) { /* Check also library later. */ @@ -925,6 +996,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); + wmWindow *win = CTX_wm_window(C); SpaceOops *soops = CTX_wm_space_outliner(C); int event; const char *str = NULL; @@ -939,7 +1011,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) 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) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); + WM_window_change_active_scene(bmain, C, win, sce); } str = "Select Objects"; @@ -949,8 +1021,8 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) 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, false); if (scene != sce) { - ED_screen_set_scene(C, CTX_wm_screen(C), sce); - } + WM_window_change_active_scene(bmain, C, win, sce); + } str = "Select Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -969,7 +1041,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) * cleanup tree here to prevent such cases. */ outliner_cleanup_tree(soops); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); str = "Delete Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -979,7 +1051,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) /* XXX: See OL_OP_DELETE comment above. */ outliner_cleanup_tree(soops); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); str = "Delete Object Hierarchy"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } @@ -991,21 +1063,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } - else if (event == OL_OP_TOGVIS) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - str = "Toggle Visibility"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - } - else if (event == OL_OP_TOGSEL) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - str = "Toggle Selectability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - } - else if (event == OL_OP_TOGREN) { - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - str = "Toggle Renderability"; - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - } else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; @@ -1093,7 +1150,7 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_INSTANCE: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_instance_cb, NULL); /* works without this except if you try render right after, see: 22027 */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); break; case OL_GROUPOP_DELETE: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL); @@ -1101,15 +1158,6 @@ static int outliner_group_operation_exec(bContext *C, wmOperator *op) case OL_GROUPOP_REMAP: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL); break; - case OL_GROUPOP_TOGVIS: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_visibility_cb, NULL); - break; - case OL_GROUPOP_TOGSEL: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_selectability_cb, NULL); - break; - case OL_GROUPOP_TOGREN: - outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, group_toggle_renderability_cb, NULL); - break; case OL_GROUPOP_RENAME: outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL); break; @@ -1631,7 +1679,7 @@ static int outliner_animdata_operation_exec(bContext *C, wmOperator *op) /* update dependencies */ if (updateDeps) { /* rebuild depsgraph for the new deps */ - DAG_relations_tag_update(CTX_data_main(C)); + DEG_relations_tag_update(CTX_data_main(C)); } return OPERATOR_FINISHED; @@ -1749,6 +1797,52 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) /* ******************** */ +static EnumPropertyItem prop_collection_op_types[] = { + {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"}, + {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, + {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, + {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"}, + {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_NEW", ICON_X, "Delete Collection", "Delete the collection"}, + {0, NULL, 0, NULL, NULL} +}; + +static int outliner_collection_operation_exec(bContext *C, wmOperator *op) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; + eOutliner_PropCollectionOps event; + + event = RNA_enum_get(op->ptr, "type"); + set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel); + + outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C); + + outliner_cleanup_tree(soops); + + ED_undo_push(C, "Collection operation"); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_operation(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Outliner Collection Operation"; + ot->idname = "OUTLINER_OT_collection_operation"; + ot->description = ""; + + /* callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = outliner_collection_operation_exec; + ot->poll = ED_operator_outliner_active; + + ot->flag = 0; + + ot->prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, 0, "Collection Operation", ""); +} + +/* ******************** */ + // XXX: select linked is for RNA structs only static EnumPropertyItem prop_data_op_types[] = { {OL_DOP_SELECT, "SELECT", 0, "Select", ""}, @@ -1923,6 +2017,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop else if (datalevel == TSE_MODIFIER) { WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL); } + else if (datalevel == TSE_LAYER_COLLECTION) { + WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL); + } else { WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL); } |