From e0c2ddb8863c90b46725afaca0dce99b463c13d6 Mon Sep 17 00:00:00 2001 From: Dan Eicher Date: Tue, 29 May 2012 08:20:11 +0000 Subject: [PATCH] OUTLINER_OT_scene_drop -- "Drag object to scene in Outliner" operator Refactored the two (well, three now) other places where an object is linked to a scene into ED_object_scene_link() --- source/blender/editors/include/ED_object.h | 2 +- .../blender/editors/object/object_relations.c | 42 ++++++--- .../editors/space_outliner/outliner_edit.c | 92 ++++++++++++++++++- .../editors/space_outliner/outliner_intern.h | 3 +- .../editors/space_outliner/outliner_ops.c | 1 + .../editors/space_outliner/space_outliner.c | 30 ++++++ source/blender/makesrna/intern/rna_scene.c | 14 +-- 7 files changed, 155 insertions(+), 29 deletions(-) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 522c387ddcf..dc7bfd6aff2 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -86,7 +86,7 @@ extern struct EnumPropertyItem prop_make_parent_types[]; int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, struct Object *par, int partype); void ED_object_parent_clear(struct bContext *C, int type); - +struct Base *ED_object_scene_link(struct ReportList *reports, struct Scene *scene, struct Object *ob); /* generic editmode keys like pet * do_pet diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 2b622b21d2c..8657ac3622c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1195,33 +1195,45 @@ static void link_to_scene(Main *UNUSED(bmain), unsigned short UNUSED(nr)) } #endif +Base *ED_object_scene_link(ReportList *reports, Scene *scene, Object *ob) +{ + Base *base; + + if (ELEM(NULL, ob, scene)) { + BKE_report(reports, RPT_ERROR, "Couldn't find scene"); + return NULL; + } + + if (BKE_scene_base_find(scene, ob)) { + BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is already in scene \"%s\"", ob->id.name + 2, scene->id.name + 2); + return NULL; + } + + if (scene->id.lib) { + BKE_report(reports, RPT_ERROR, "Can't link objects into a linked scene"); + return NULL; + } + + base = BKE_scene_base_add(scene, ob); + id_us_plus(&ob->id); + + return base; +} + static int make_links_scene_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene_to = BLI_findlink(&CTX_data_main(C)->scene, RNA_enum_get(op->ptr, "scene")); - if (scene_to == NULL) { - BKE_report(op->reports, RPT_ERROR, "Scene not found"); - return OPERATOR_CANCELLED; - } - if (scene_to == CTX_data_scene(C)) { BKE_report(op->reports, RPT_ERROR, "Can't link objects into the same scene"); return OPERATOR_CANCELLED; } - if (scene_to->id.lib) { - BKE_report(op->reports, RPT_ERROR, "Can't link objects into a linked scene"); - return OPERATOR_CANCELLED; - } - CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - if (!BKE_scene_base_find(scene_to, base->object)) { - Base *nbase = MEM_mallocN(sizeof(Base), "newbase"); - *nbase = *base; - BLI_addhead(&(scene_to->base), nbase); - id_us_plus((ID *)base->object); + if (ED_object_scene_link(op->reports, scene_to, base->object) == NULL) { + return OPERATOR_CANCELLED; } } CTX_DATA_END; diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 0232006829f..79a1e0c7634 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1426,8 +1426,7 @@ TreeElement *outliner_dropzone_parent(bContext *C, wmEvent *event, TreeElement * /* name and first icon */ if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) { /* always makes active object */ - if (te->idcode == ID_OB && - !ELEM4(tselem->type, TSE_MODIFIER_BASE, TSE_MODIFIER, TSE_CONSTRAINT_BASE, TSE_CONSTRAINT)) { + if (te->idcode == ID_OB && tselem->type == 0) { return te; } else { @@ -1690,3 +1689,92 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot) 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", ""); } + +TreeElement *outliner_dropzone_scene(bContext *C, wmEvent *UNUSED(event), TreeElement *te, float *fmval) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + TreeStoreElem *tselem = TREESTORE(te); + + 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)) { + if (te->idcode == ID_SCE && tselem->type == 0) { + return te; + } + } + } + return NULL; +} + +static int scene_drop_invoke(bContext *C, wmOperator *op, 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; + TreeElement *te_found = 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 */ + for (te = soops->tree.first; te; te = te->next) { + te_found = outliner_dropzone_scene(C, event, te, fmval); + if (te_found) + break; + } + + if (te_found) { + Base *base; + + RNA_string_set(op->ptr, "scene", te_found->name); + scene = (Scene *)BKE_libblock_find_name(ID_SCE, te_found->name); + + RNA_string_get(op->ptr, "object", obname); + ob = (Object *)BKE_libblock_find_name(ID_OB, obname); + + base = ED_object_scene_link(op->reports, 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_scene_sort(bmain, scene); + DAG_ids_flush_update(bmain, 0); + + 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; + + /* 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"); +} diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index f73c031dc7f..5274410214a 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -190,7 +190,7 @@ void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, st TreeElement *outliner_dropzone_parent(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); int outliner_dropzone_parent_clear(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); - +TreeElement *outliner_dropzone_scene(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); /* ...................................................... */ void OUTLINER_OT_item_activate(struct wmOperatorType *ot); @@ -220,6 +220,7 @@ void OUTLINER_OT_drivers_delete_selected(struct wmOperatorType *ot); void OUTLINER_OT_parent_drop(struct wmOperatorType *ot); void OUTLINER_OT_parent_clear(struct wmOperatorType *ot); +void OUTLINER_OT_scene_drop(struct wmOperatorType *ot); /* outliner_tools.c ---------------------------------------------- */ diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 12f8f2cb38b..0b3a226cca1 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -76,6 +76,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_parent_drop); WM_operatortype_append(OUTLINER_OT_parent_clear); + WM_operatortype_append(OUTLINER_OT_scene_drop); } void outliner_keymap(wmKeyConfig *keyconf) diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 3110ff3e29e..f3f6e3cf49f 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -144,6 +144,35 @@ static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop) RNA_enum_set(drop->ptr, "type", 0); } +static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + TreeElement *te = NULL; + float fmval[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); + + if (drag->type == WM_DRAG_ID) { + ID *id = (ID *)drag->poin; + if (GS(id->name) == ID_OB) { + /* Ensure item under cursor is valid drop target */ + /* Find object hovered over */ + for (te = soops->tree.first; te; te = te->next) { + if (outliner_dropzone_scene(C, event, te, fmval)) + return 1; + } + } + } + return 0; +} + +static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop) +{ + ID *id = (ID *)drag->poin; + + RNA_string_set(drop->ptr, "object", id->name + 2); +} + /* region dropbox definition */ static void outliner_dropboxes(void) { @@ -151,6 +180,7 @@ static void outliner_dropboxes(void) WM_dropbox_add(lb, "OUTLINER_OT_parent_drop", outliner_parent_drop_poll, outliner_parent_drop_copy); WM_dropbox_add(lb, "OUTLINER_OT_parent_clear", outliner_parent_clear_poll, outliner_parent_clear_copy); + WM_dropbox_add(lb, "OUTLINER_OT_scene_drop", outliner_scene_drop_poll, outliner_scene_drop_copy); } static void outliner_main_area_draw(const bContext *C, ARegion *ar) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 5b355e56911..33f1c529b18 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -304,6 +304,7 @@ EnumPropertyItem image_color_depth_items[] = { #include "ED_mesh.h" #include "ED_keyframing.h" #include "ED_image.h" +#include "ED_object.h" #include "RE_engine.h" @@ -338,24 +339,17 @@ static PointerRNA rna_Scene_objects_get(CollectionPropertyIterator *iter) static Base *rna_Scene_object_link(Scene *scene, bContext *C, ReportList *reports, Object *ob) { Scene *scene_act = CTX_data_scene(C); - Base *base; + Base *base = ED_object_scene_link(reports, scene, ob); - if (BKE_scene_base_find(scene, ob)) { - BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is already in scene \"%s\"", ob->id.name + 2, scene->id.name + 2); + if (base == NULL) { return NULL; } - base = BKE_scene_base_add(scene, ob); - id_us_plus(&ob->id); - - /* this is similar to what object_add_type and BKE_object_add do */ - base->lay = scene->lay; - /* when linking to an inactive scene don't touch the layer */ if (scene == scene_act) ob->lay = base->lay; - ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + /* ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; */ /* slows down importers too much, run scene.update() */ /* DAG_scene_sort(G.main, scene); */