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()
This commit is contained in:
Dan Eicher 2012-05-29 08:20:11 +00:00
parent a537355426
commit e0c2ddb886
7 changed files with 155 additions and 29 deletions

@ -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

@ -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;

@ -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");
}

@ -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 ---------------------------------------------- */

@ -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)

@ -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)

@ -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); */