OUTLINER_OT_scene_drop -- "Drag object to scene in Outliner" operator
authorDan Eicher <dan@eu.phorio.us>
Tue, 29 May 2012 08:20:11 +0000 (08:20 +0000)
committerDan Eicher <dan@eu.phorio.us>
Tue, 29 May 2012 08:20:11 +0000 (08:20 +0000)
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
source/blender/editors/object/object_relations.c
source/blender/editors/space_outliner/outliner_edit.c
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/makesrna/intern/rna_scene.c

index 522c387ddcfb50c66b574db26d32204c77574536..dc7bfd6aff21aea6f370b5b5b2eeb1c7c47fe69c 100644 (file)
@@ -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
index 2b622b21d2c6dc9622d508b92b20e8a75969c9ae..8657ac3622cc5ab34d41cee95f1d87c8be3e2ffb 100644 (file)
@@ -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;
index 0232006829fb205d16d5ca8f946e08a65e15110a..79a1e0c76345afda73a5d2ec784b1da18b0bef1a 100644 (file)
@@ -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");
+}
index f73c031dc7f663852a744d37862d4a1e5cfcb9cc..5274410214a8e6f0591ee4a2c313912072951f34 100644 (file)
@@ -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 ---------------------------------------------- */
 
index 12f8f2cb38b82a67d688c476fea38517616592f9..0b3a226cca183c44255b512bde40bf3e75e7f854 100644 (file)
@@ -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)
index 3110ff3e29eb322c8436cdc630969992a5621164..f3f6e3cf49f55976e2bd6ff7e6248b237d8dd96a 100644 (file)
@@ -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)
index 5b355e569116f8424d5124de11acbe7004b2b88f..33f1c529b181bba176f2bf6ae562aee655439ca5 100644 (file)
@@ -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); */