diff options
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_edit.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_edit.c | 873 |
1 files changed, 181 insertions, 692 deletions
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 51117eef1dc..ce89e7e6d66 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -34,7 +34,7 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" -#include "DNA_group_types.h" +#include "DNA_collection_types.h" #include "DNA_ID.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -50,24 +50,28 @@ #include "BLT_translation.h" #include "BKE_animsys.h" +#include "BKE_collection.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_idcode.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" #include "BKE_main.h" +#include "BKE_material.h" #include "BKE_outliner_treehash.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_material.h" -#include "BKE_group.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" #include "../blenloader/BLO_readfile.h" #include "ED_object.h" #include "ED_outliner.h" #include "ED_screen.h" +#include "ED_select_utils.h" #include "ED_keyframing.h" #include "ED_armature.h" @@ -87,68 +91,49 @@ #include "outliner_intern.h" /* ************************************************************** */ -/* Unused Utilities */ -// XXX: where to place these? -/* This is not used anywhere at the moment */ -#if 0 -static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *teFind, int *found) +/* Highlight --------------------------------------------------- */ + +static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { - TreeElement *te; - TreeStoreElem *tselem; + /* Drag and drop does own highlighting. */ + wmWindowManager *wm = CTX_wm_manager(C); + if (wm->drags.first) { + return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH); + } - for (te = lb->first; te; te = te->next) { - /* check if this tree-element was the one we're seeking */ - if (te == teFind) { - *found = 1; - return; - } + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]); + + TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my); + bool changed = false; - /* try to see if sub-tree contains it then */ - outliner_open_reveal(soops, &te->subtree, teFind, found); - if (*found) { - tselem = TREESTORE(te); - if (tselem->flag & TSE_CLOSED) - tselem->flag &= ~TSE_CLOSED; - return; + if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) { + changed = outliner_flag_set(&soops->tree, TSE_HIGHLIGHTED | TSE_DRAG_ANY, false); + if (hovered_te) { + hovered_te->store_elem->flag |= TSE_HIGHLIGHTED; + changed = true; } } -} -#endif -static TreeElement *outliner_dropzone_element(TreeElement *te, const float fmval[2], const bool children) -{ - if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) { - /* name and first icon */ - if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) - return te; + if (changed) { + ED_region_tag_redraw_no_rebuild(ar); } - /* Not it. Let's look at its children. */ - if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) { - for (te = te->subtree.first; te; te = te->next) { - TreeElement *te_valid = outliner_dropzone_element(te, fmval, children); - if (te_valid) - return te_valid; - } - } - return NULL; + + return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH); } -/* Used for drag and drop parenting */ -TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const bool children) +void OUTLINER_OT_highlight_update(wmOperatorType *ot) { - TreeElement *te; + ot->name = "Update Highlight"; + ot->idname = "OUTLINER_OT_highlight_update"; + ot->description = "Update the item highlight based on the current mouse position"; - for (te = soops->tree.first; te; te = te->next) { - TreeElement *te_valid = outliner_dropzone_element(te, fmval, children); - if (te_valid) - return te_valid; - } - return NULL; -} + ot->invoke = outliner_highlight_update; -/* ************************************************************** */ -/* Click Activated */ + ot->poll = ED_operator_outliner_active; +} /* Toggle Open/Closed ------------------------------------------- */ @@ -202,7 +187,7 @@ static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *e void OUTLINER_OT_item_openclose(wmOperatorType *ot) { - ot->name = "Open/Close Item"; + ot->name = "Open/Close"; ot->idname = "OUTLINER_OT_item_openclose"; ot->description = "Toggle whether item under cursor is enabled or closed"; @@ -213,22 +198,85 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items"); } +/* -------------------------------------------------------------------- */ +/** \name Object Mode Enter/Exit + * \{ */ + +static void item_object_mode_enter_exit( + bContext *C, ReportList *reports, Object *ob, + bool enter) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + + if ((ob->type != obact->type) || ID_IS_LINKED(ob->data)) { + return; + } + if (((ob->mode & obact->mode) != 0) == enter) { + return; + } + + if (ob == obact) { + BKE_report(reports, RPT_WARNING, "Active object mode not changed"); + return; + } + + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base == NULL) { + return; + } + Scene *scene = CTX_data_scene(C); + outliner_object_mode_toggle(C, scene, view_layer, base); +} + +void item_object_mode_enter_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, true); +} + +void item_object_mode_exit_cb( + bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) +{ + Object *ob = (Object *)tselem->id; + item_object_mode_enter_exit(C, reports, ob, false); +} + +/** \} */ + /* Rename --------------------------------------------------- */ -static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports) +static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, + ReportList *reports) { + bool add_textbut = false; + /* can't rename rna datablocks entries or listbases */ - if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) { + if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE, TSE_SCENE_OBJECTS_BASE)) { /* do nothing */; } else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE, - TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_R_PASS)) + TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE, + TSE_VIEW_COLLECTION_BASE)) { BKE_report(reports, RPT_WARNING, "Cannot edit builtin name"); } else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) { BKE_report(reports, RPT_WARNING, "Cannot edit sequence name"); } + else if (outliner_is_collection_tree_element(te)) { + Collection *collection = outliner_collection_from_tree_element(te); + + if (collection->flag & COLLECTION_IS_MASTER) { + BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection"); + } + else { + add_textbut = true; + } + } else if (ID_IS_LINKED(tselem->id)) { BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); } @@ -236,6 +284,10 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library"); } else { + add_textbut = true; + } + + if (add_textbut) { tselem->flag |= TSE_TEXTBUT; ED_region_tag_redraw(ar); } @@ -249,7 +301,8 @@ void item_rename_cb( do_item_rename(ar, te, tselem, reports); } -static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te, const float mval[2]) +static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te, + const float mval[2]) { if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { TreeStoreElem *tselem = TREESTORE(te); @@ -291,7 +344,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even void OUTLINER_OT_item_rename(wmOperatorType *ot) { - ot->name = "Rename Item"; + ot->name = "Rename"; ot->idname = "OUTLINER_OT_item_rename"; ot->description = "Rename item under cursor"; @@ -402,7 +455,6 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot) static int outliner_id_remap_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); const short id_type = (short)RNA_enum_get(op->ptr, "id_type"); @@ -432,7 +484,7 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op) BKE_main_lib_objects_recalc_all(bmain); /* recreate dependency graph to include new objects */ - DAG_scene_relations_rebuild(bmain, scene); + DEG_relations_tag_update(bmain); /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ GPU_materials_free(bmain); @@ -742,17 +794,49 @@ int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel) return 0; } -void outliner_flag_set(ListBase *lb, short flag, short set) +/** + * Set or unset \a flag for all outliner elements in \a lb and sub-trees. + * \return if any flag was modified. + */ +bool outliner_flag_set(ListBase *lb, short flag, short set) +{ + TreeElement *te; + TreeStoreElem *tselem; + bool changed = false; + bool has_flag; + + for (te = lb->first; te; te = te->next) { + tselem = TREESTORE(te); + has_flag = (tselem->flag & flag); + if (set == 0) { + if (has_flag) { + tselem->flag &= ~flag; + changed = true; + } + } + else if (!has_flag) { + tselem->flag |= flag; + changed = true; + } + changed |= outliner_flag_set(&te->subtree, flag, set); + } + + return changed; +} + +bool outliner_flag_flip(ListBase *lb, short flag) { TreeElement *te; TreeStoreElem *tselem; + bool changed = false; for (te = lb->first; te; te = te->next) { tselem = TREESTORE(te); - if (set == 0) tselem->flag &= ~flag; - else tselem->flag |= flag; - outliner_flag_set(&te->subtree, flag, set); + tselem->flag ^= flag; + changed |= outliner_flag_flip(&te->subtree, flag); } + + return changed; } /* Restriction Columns ------------------------------- */ @@ -780,181 +864,6 @@ int common_restrict_check(bContext *C, Object *ob) } /* =============================================== */ -/* Restriction toggles */ - -/* Toggle Visibility ---------------------------------------- */ - -void object_toggle_visibility_cb( - bContext *C, ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - Object *ob = (Object *)tselem->id; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - /* add check for edit mode */ - if (!common_restrict_check(C, ob)) return; - - if (base || (base = BKE_scene_base_find(scene, ob))) { - if ((base->object->restrictflag ^= OB_RESTRICT_VIEW)) { - ED_base_object_select(base, BA_DESELECT); - } - } -} - -void group_toggle_visibility_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_VIEW); -} - -static int outliner_toggle_visibility_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_visibility_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_visibility_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Visibility"; - ot->idname = "OUTLINER_OT_visibility_toggle"; - ot->description = "Toggle the visibility of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_visibility_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Selectability ---------------------------------------- */ - -void object_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_SELECT; - } -} - -void group_toggle_selectability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_SELECT); -} - -static int outliner_toggle_selectability_exec(bContext *C, wmOperator *op) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - ARegion *ar = CTX_wm_region(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_selectability_cb); - - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_selectability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Selectability"; - ot->idname = "OUTLINER_OT_selectability_toggle"; - ot->description = "Toggle the selectability"; - - /* callbacks */ - ot->exec = outliner_toggle_selectability_exec; - ot->poll = ED_operator_outliner_active_no_editobject; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* Toggle Renderability ---------------------------------------- */ - -void object_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *reports, Scene *scene, TreeElement *te, - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Base *base = (Base *)te->directdata; - - if (ID_IS_LINKED(tselem->id)) { - BKE_report(reports, RPT_WARNING, "Cannot edit external libdata"); - return; - } - - if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); - if (base) { - base->object->restrictflag ^= OB_RESTRICT_RENDER; - } -} - -void group_toggle_renderability_cb( - bContext *UNUSED(C), ReportList *UNUSED(reports), Scene *scene, TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) -{ - Group *group = (Group *)tselem->id; - restrictbutton_gr_restrict_flag(scene, group, OB_RESTRICT_RENDER); -} - -static int outliner_toggle_renderability_exec(bContext *C, wmOperator *op) -{ - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_toggle_renderability_cb); - - DAG_id_type_tag(bmain, ID_OB); - WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_renderability_toggle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Toggle Renderability"; - ot->idname = "OUTLINER_OT_renderability_toggle"; - ot->description = "Toggle the renderability of selected items"; - - /* callbacks */ - ot->exec = outliner_toggle_renderability_exec; - ot->poll = ED_operator_outliner_active; - - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/* =============================================== */ /* Outliner setting toggles */ /* Toggle Expanded (Outliner) ---------------------------------------- */ @@ -990,37 +899,50 @@ void OUTLINER_OT_expanded_toggle(wmOperatorType *ot) /* Toggle Selected (Outliner) ---------------------------------------- */ -static int outliner_toggle_selected_exec(bContext *C, wmOperator *UNUSED(op)) +static int outliner_select_all_exec(bContext *C, wmOperator *op) { SpaceOops *soops = CTX_wm_space_outliner(C); ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); + int action = RNA_enum_get(op->ptr, "action"); + if (action == SEL_TOGGLE) { + action = outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1) ? SEL_DESELECT : SEL_SELECT; + } - if (outliner_flag_is_any_test(&soops->tree, TSE_SELECTED, 1)) - outliner_flag_set(&soops->tree, TSE_SELECTED, 0); - else - outliner_flag_set(&soops->tree, TSE_SELECTED, 1); - - soops->storeflag |= SO_TREESTORE_REDRAW; + switch (action) { + case SEL_SELECT: + outliner_flag_set(&soops->tree, TSE_SELECTED, 1); + break; + case SEL_DESELECT: + outliner_flag_set(&soops->tree, TSE_SELECTED, 0); + break; + case SEL_INVERT: + outliner_flag_flip(&soops->tree, TSE_SELECTED); + break; + } + DEG_id_tag_update(&scene->id, DEG_TAG_SELECT_UPDATE); WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - ED_region_tag_redraw(ar); + ED_region_tag_redraw_no_rebuild(ar); return OPERATOR_FINISHED; } -void OUTLINER_OT_selected_toggle(wmOperatorType *ot) +void OUTLINER_OT_select_all(wmOperatorType *ot) { /* identifiers */ ot->name = "Toggle Selected"; - ot->idname = "OUTLINER_OT_selected_toggle"; + ot->idname = "OUTLINER_OT_select_all"; ot->description = "Toggle the Outliner selection of items"; /* callbacks */ - ot->exec = outliner_toggle_selected_exec; + ot->exec = outliner_select_all_exec; ot->poll = ED_operator_outliner_active; - /* no undo or registry, UI option */ + /* no undo or registry */ + + /* rna */ + WM_operator_properties_select_all(ot); } /* ************************************************************** */ @@ -1046,7 +968,7 @@ static void outliner_set_coordinates_element_recursive(SpaceOops *soops, TreeEle } /* to retrieve coordinates with redrawing the entire tree */ -static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops) +void outliner_set_coordinates(ARegion *ar, SpaceOops *soops) { TreeElement *te; int starty = (int)(ar->v2d.tot.ymax) - UI_UNIT_Y; @@ -1075,14 +997,14 @@ static int outliner_open_back(TreeElement *te) static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceOops *so = CTX_wm_space_outliner(C); - Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; TreeElement *te; int xdelta, ytop; - Object *obact = OBACT; + Object *obact = OBACT(view_layer); if (!obact) return OPERATOR_CANCELLED; @@ -1125,11 +1047,9 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op)) xdelta = (int)(te->xs - v2d->cur.xmin); v2d->cur.xmin += xdelta; v2d->cur.xmax += xdelta; - - so->storeflag |= SO_TREESTORE_REDRAW; } - ED_region_tag_redraw(ar); + ED_region_tag_redraw_no_rebuild(ar); return OPERATOR_FINISHED; } @@ -1161,7 +1081,7 @@ static int outliner_scroll_page_exec(bContext *C, wmOperator *op) ar->v2d.cur.ymin += dy; ar->v2d.cur.ymax += dy; - ED_region_tag_redraw(ar); + ED_region_tag_redraw_no_rebuild(ar); return OPERATOR_FINISHED; } @@ -1285,7 +1205,7 @@ static void outliner_find_panel(Scene *UNUSED(scene), ARegion *ar, SpaceOops *so soops->search_flags = flags; /* redraw */ - soops->storeflag |= SO_TREESTORE_REDRAW; + ED_region_tag_redraw_no_rebuild(ar); } } else { @@ -1443,7 +1363,7 @@ static bool ed_operator_outliner_datablocks_active(bContext *C) ScrArea *sa = CTX_wm_area(C); if ((sa) && (sa->spacetype == SPACE_OUTLINER)) { SpaceOops *so = CTX_wm_space_outliner(C); - return (so->outlinevis == SO_DATABLOCKS); + return (so->outlinevis == SO_DATA_API); } return 0; } @@ -1975,434 +1895,3 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } - -/* ************************************************************** */ -/* DRAG AND DROP OPERATORS */ - -/* ******************** Parent Drop Operator *********************** */ - -static int parent_drop_exec(bContext *C, wmOperator *op) -{ - Object *par = NULL, *ob = NULL; - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - int partype = -1; - char parname[MAX_ID_NAME], childname[MAX_ID_NAME]; - - partype = RNA_enum_get(op->ptr, "type"); - RNA_string_get(op->ptr, "parent", parname); - par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname); - RNA_string_get(op->ptr, "child", childname); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname); - - if (ID_IS_LINKED(ob)) { - BKE_report(op->reports, RPT_INFO, "Can't edit library linked object"); - return OPERATOR_CANCELLED; - } - - ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL); - - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); - - return OPERATOR_FINISHED; -} - -static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - Object *par = NULL; - Object *ob = NULL; - SpaceOops *soops = CTX_wm_space_outliner(C); - ARegion *ar = CTX_wm_region(C); - Main *bmain = CTX_data_main(C); - Scene *scene = NULL; - TreeElement *te = NULL; - char childname[MAX_ID_NAME]; - char parname[MAX_ID_NAME]; - int partype = 0; - float fmval[2]; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); - - /* Find object hovered over */ - te = outliner_dropzone_find(soops, fmval, true); - - if (te) { - RNA_string_set(op->ptr, "parent", te->name); - /* Identify parent and child */ - RNA_string_get(op->ptr, "child", childname); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, childname); - RNA_string_get(op->ptr, "parent", parname); - par = (Object *)BKE_libblock_find_name(bmain, ID_OB, parname); - - if (ELEM(NULL, ob, par)) { - if (par == NULL) printf("par==NULL\n"); - return OPERATOR_CANCELLED; - } - if (ob == par) { - return OPERATOR_CANCELLED; - } - if (ID_IS_LINKED(ob)) { - BKE_report(op->reports, RPT_INFO, "Can't edit library linked object"); - return OPERATOR_CANCELLED; - } - - scene = (Scene *)outliner_search_back(soops, te, ID_SCE); - - if (scene == NULL) { - /* currently outlier organized in a way, that if there's no parent scene - * element for object it means that all displayed objects belong to - * active scene and parenting them is allowed (sergey) - */ - - scene = CTX_data_scene(C); - } - - if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { - if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) { - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); - } - } - else { - /* Menu creation */ - wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false); - uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE); - uiLayout *layout = UI_popup_menu_layout(pup); - PointerRNA ptr; - - /* Cannot use uiItemEnumO()... have multiple properties to set. */ - uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_OBJECT); - - /* par becomes parent, make the associated menus */ - if (par->type == OB_ARMATURE) { - uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE); - - uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME); - - uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE); - - uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO); - - uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_BONE); - } - else if (par->type == OB_CURVE) { - uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_CURVE); - - uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_FOLLOW); - - uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_PATH_CONST); - } - else if (par->type == OB_LATTICE) { - uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr); - RNA_string_set(&ptr, "parent", parname); - RNA_string_set(&ptr, "child", childname); - RNA_enum_set(&ptr, "type", PAR_LATTICE); - } - - UI_popup_menu_end(C, pup); - - return OPERATOR_INTERFACE; - } - } - else { - return OPERATOR_CANCELLED; - } - - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_parent_drop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Drop to Set Parent"; - ot->description = "Drag to parent in Outliner"; - ot->idname = "OUTLINER_OT_parent_drop"; - - /* api callbacks */ - ot->invoke = parent_drop_invoke; - ot->exec = parent_drop_exec; - - ot->poll = ED_operator_outliner_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "child", "Object", MAX_ID_NAME, "Child", "Child Object"); - RNA_def_string(ot->srna, "parent", "Object", MAX_ID_NAME, "Parent", "Parent Object"); - RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", ""); -} - -static bool outliner_parenting_poll(bContext *C) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - - if (soops) { - return ELEM(soops->outlinevis, SO_ALL_SCENES, SO_CUR_SCENE, SO_VISIBLE, SO_GROUPS); - } - - return false; -} - -static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) -{ - Main *bmain = CTX_data_main(C); - Object *ob = NULL; - SpaceOops *soops = CTX_wm_space_outliner(C); - char obname[MAX_ID_NAME]; - - RNA_string_get(op->ptr, "dragged_obj", obname); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname); - - /* search forwards to find the object */ - outliner_find_id(soops, &soops->tree, (ID *)ob); - - ED_object_parent_clear(ob, RNA_enum_get(op->ptr, "type")); - - DAG_relations_tag_update(bmain); - WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); - return OPERATOR_FINISHED; -} - -void OUTLINER_OT_parent_clear(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Drop to Clear Parent"; - ot->description = "Drag to clear parent in Outliner"; - ot->idname = "OUTLINER_OT_parent_clear"; - - /* api callbacks */ - ot->invoke = parent_clear_invoke; - - ot->poll = outliner_parenting_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "dragged_obj", "Object", MAX_ID_NAME, "Child", "Child Object"); - RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", ""); -} - -static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - Scene *scene = NULL; - Object *ob = NULL; - SpaceOops *soops = CTX_wm_space_outliner(C); - ARegion *ar = CTX_wm_region(C); - Main *bmain = CTX_data_main(C); - TreeElement *te = NULL; - char obname[MAX_ID_NAME]; - float fmval[2]; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); - - /* Find object hovered over */ - te = outliner_dropzone_find(soops, fmval, false); - - if (te) { - Base *base; - - RNA_string_set(op->ptr, "scene", te->name); - scene = (Scene *)BKE_libblock_find_name(bmain, ID_SCE, te->name); - - RNA_string_get(op->ptr, "object", obname); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, obname); - - if (ELEM(NULL, ob, scene) || ID_IS_LINKED(scene)) { - return OPERATOR_CANCELLED; - } - - base = ED_object_scene_link(scene, ob); - - if (base == NULL) { - return OPERATOR_CANCELLED; - } - - if (scene == CTX_data_scene(C)) { - /* when linking to an inactive scene don't touch the layer */ - ob->lay = base->lay; - ED_base_object_select(base, BA_SELECT); - } - - DAG_relations_tag_update(bmain); - - WM_main_add_notifier(NC_SCENE | ND_OB_SELECT, scene); - - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -void OUTLINER_OT_scene_drop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Drop Object to Scene"; - ot->description = "Drag object to scene in Outliner"; - ot->idname = "OUTLINER_OT_scene_drop"; - - /* api callbacks */ - ot->invoke = scene_drop_invoke; - - ot->poll = ED_operator_outliner_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object"); - RNA_def_string(ot->srna, "scene", "Scene", MAX_ID_NAME, "Scene", "Target Scene"); -} - -static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - Material *ma = NULL; - Object *ob = NULL; - Main *bmain = CTX_data_main(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - ARegion *ar = CTX_wm_region(C); - TreeElement *te = NULL; - char mat_name[MAX_ID_NAME - 2]; - float fmval[2]; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); - - /* Find object hovered over */ - te = outliner_dropzone_find(soops, fmval, true); - - if (te) { - RNA_string_set(op->ptr, "object", te->name); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, te->name); - - RNA_string_get(op->ptr, "material", mat_name); - ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, mat_name); - - if (ELEM(NULL, ob, ma)) { - return OPERATOR_CANCELLED; - } - - assign_material(bmain, ob, ma, ob->totcol + 1, BKE_MAT_ASSIGN_USERPREF); - - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); - WM_event_add_notifier(C, NC_MATERIAL | ND_SHADING_LINKS, ma); - - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -void OUTLINER_OT_material_drop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Drop Material on Object"; - ot->description = "Drag material to object in Outliner"; - ot->idname = "OUTLINER_OT_material_drop"; - - /* api callbacks */ - ot->invoke = material_drop_invoke; - - ot->poll = ED_operator_outliner_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object"); - RNA_def_string(ot->srna, "material", "Material", MAX_ID_NAME, "Material", "Target Material"); -} - -static int group_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - Main *bmain = CTX_data_main(C); - Group *group = NULL; - Object *ob = NULL; - Scene *scene = CTX_data_scene(C); - SpaceOops *soops = CTX_wm_space_outliner(C); - ARegion *ar = CTX_wm_region(C); - TreeElement *te = NULL; - char ob_name[MAX_ID_NAME - 2]; - float fmval[2]; - - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); - - /* Find object hovered over */ - te = outliner_dropzone_find(soops, fmval, true); - - if (te) { - group = (Group *)BKE_libblock_find_name(bmain, ID_GR, te->name); - - RNA_string_get(op->ptr, "object", ob_name); - ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, ob_name); - - if (ELEM(NULL, group, ob)) { - return OPERATOR_CANCELLED; - } - if (BKE_group_object_exists(group, ob)) { - return OPERATOR_FINISHED; - } - - if (BKE_group_object_cyclic_check(bmain, ob, group)) { - BKE_report(op->reports, RPT_ERROR, "Could not add the group because of dependency cycle detected"); - return OPERATOR_CANCELLED; - } - - BKE_group_object_add(group, ob, scene, NULL); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - return OPERATOR_FINISHED; - } - - return OPERATOR_CANCELLED; -} - -void OUTLINER_OT_group_link(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Link Object to Group"; - ot->description = "Link Object to Group in Outliner"; - ot->idname = "OUTLINER_OT_group_link"; - - /* api callbacks */ - ot->invoke = group_link_invoke; - - ot->poll = ED_operator_outliner_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; - - /* properties */ - RNA_def_string(ot->srna, "object", "Object", MAX_ID_NAME, "Object", "Target Object"); -} |