diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-09-06 11:35:27 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-09-06 11:42:16 +0300 |
commit | e56ff76db5b44ae6784a26ff6daf9864b2387712 (patch) | |
tree | 03ffd243bb948574d95556f593c8770730b24e9a /source | |
parent | 5faf72bb719b075e8ef4bf4371cc13c35557eba9 (diff) |
Viewport: support dropping object-data to create instances
This allows orphan object data for example (meshes, curves, etc)
to be dropped into the 3D View from the outliner,
creating a new object instance.
Previously the only way to do this was to add the same type of object
then swap it's data through the ID selector drop-down.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/object/object_add.c | 86 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 47 |
4 files changed, 130 insertions, 5 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 72180d58ecb..d35ac4840bd 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1489,6 +1489,92 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Add Data Instance Operator + * + * Use for dropping ID's from the outliner. + * \{ */ + +static int object_data_instance_add_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + ID *id = NULL; + ushort local_view_bits; + float loc[3], rot[3]; + + PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name"); + PropertyRNA *prop_type = RNA_struct_find_property(op->ptr, "type"); + PropertyRNA *prop_location = RNA_struct_find_property(op->ptr, "location"); + + /* These shouldn't fail when created by outliner dropping as it checks the ID is valid. */ + if (!RNA_property_is_set(op->ptr, prop_name) || !RNA_property_is_set(op->ptr, prop_type)) { + return OPERATOR_CANCELLED; + } + const short id_type = RNA_property_enum_get(op->ptr, prop_type); + char name[MAX_ID_NAME - 2]; + RNA_property_string_get(op->ptr, prop_name, name); + id = BKE_libblock_find_name(bmain, id_type, name); + if (id == NULL) { + return OPERATOR_CANCELLED; + } + const int object_type = BKE_object_obdata_to_type(id); + if (object_type == -1) { + return OPERATOR_CANCELLED; + } + + if (!RNA_property_is_set(op->ptr, prop_location)) { + const wmEvent *event = CTX_wm_window(C)->eventstate; + ARegion *region = CTX_wm_region(C); + const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin}; + ED_object_location_from_view(C, loc); + ED_view3d_cursor3d_position(C, mval, false, loc); + RNA_property_float_set_array(op->ptr, prop_location, loc); + } + + if (!ED_object_add_generic_get_opts(C, op, 'Z', loc, rot, NULL, NULL, &local_view_bits, NULL)) { + return OPERATOR_CANCELLED; + } + + Scene *scene = CTX_data_scene(C); + + Object *ob = ED_object_add_type(C, object_type, id->name + 2, loc, rot, false, local_view_bits); + ob->data = id; + id_us_plus(id); + + BKE_object_materials_test(bmain, ob, ob->data); + + /* Works without this except if you try render right after, see: T22027. */ + DEG_relations_tag_update(bmain); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_data_instance_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Object Data Instance"; + ot->description = "Add an object data instance"; + ot->idname = "OBJECT_OT_data_instance_add"; + + /* api callbacks */ + ot->exec = object_data_instance_add_exec; + ot->poll = ED_operator_objectmode; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_string(ot->srna, "name", "Name", MAX_ID_NAME - 2, "Name", "ID name to add"); + PropertyRNA *prop = RNA_def_enum(ot->srna, "type", rna_enum_id_type_items, 0, "Type", ""); + RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID); + ED_object_add_generic_props(ot, false); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Add Speaker Operator * \{ */ diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 50825ae1ae4..99e139b823e 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -117,6 +117,7 @@ void OBJECT_OT_speaker_add(struct wmOperatorType *ot); void OBJECT_OT_hair_add(struct wmOperatorType *ot); void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot); void OBJECT_OT_collection_instance_add(struct wmOperatorType *ot); +void OBJECT_OT_data_instance_add(struct wmOperatorType *ot); void OBJECT_OT_duplicates_make_real(struct wmOperatorType *ot); void OBJECT_OT_duplicate(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 92880e5a114..8b3837edce2 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -117,6 +117,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_add_named); WM_operatortype_append(OBJECT_OT_effector_add); WM_operatortype_append(OBJECT_OT_collection_instance_add); + WM_operatortype_append(OBJECT_OT_data_instance_add); WM_operatortype_append(OBJECT_OT_metaball_add); WM_operatortype_append(OBJECT_OT_duplicates_make_real); WM_operatortype_append(OBJECT_OT_duplicate); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index de0b420a3b5..4fdfc18c9ff 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -37,6 +37,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLT_translation.h" + #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_global.h" @@ -459,16 +461,24 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *region) ED_view3d_stop_render_preview(wm, region); } -static bool view3d_drop_id_in_main_region_poll(bContext *C, - wmDrag *drag, - const wmEvent *event, - ID_Type id_type) +static ID *view3d_drop_id_in_main_region_poll_id(bContext *C, + wmDrag *drag, + const wmEvent *event, + ID_Type id_type) { ScrArea *area = CTX_wm_area(C); if (ED_region_overlap_isect_any_xy(area, &event->x)) { return false; } - return WM_drag_ID(drag, id_type) != NULL; + return WM_drag_ID(drag, id_type); +} + +static bool view3d_drop_id_in_main_region_poll(bContext *C, + wmDrag *drag, + const wmEvent *event, + ID_Type id_type) +{ + return (view3d_drop_id_in_main_region_poll_id(C, drag, event, id_type) != NULL); } static bool view3d_ob_drop_poll(bContext *C, @@ -495,6 +505,21 @@ static bool view3d_mat_drop_poll(bContext *C, return view3d_drop_id_in_main_region_poll(C, drag, event, ID_MA); } +static bool view3d_object_data_drop_poll(bContext *C, + wmDrag *drag, + const wmEvent *event, + const char **r_tooltip) +{ + ID *id = view3d_drop_id_in_main_region_poll_id(C, drag, event, 0); + if (id != NULL) { + if (BKE_object_obdata_to_type(id) != -1) { + *r_tooltip = TIP_("Create object instance from object-data"); + return true; + } + } + return false; +} + static bool view3d_ima_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event, @@ -591,6 +616,14 @@ static void view3d_id_drop_copy(wmDrag *drag, wmDropBox *drop) RNA_string_set(drop->ptr, "name", id->name + 2); } +static void view3d_id_drop_copy_with_type(wmDrag *drag, wmDropBox *drop) +{ + ID *id = WM_drag_ID(drag, 0); + + RNA_string_set(drop->ptr, "name", id->name + 2); + RNA_enum_set(drop->ptr, "type", GS(id->name)); +} + static void view3d_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) { ID *id = WM_drag_ID(drag, 0); @@ -642,6 +675,10 @@ static void view3d_dropboxes(void) "OBJECT_OT_collection_instance_add", view3d_collection_drop_poll, view3d_collection_drop_copy); + WM_dropbox_add(lb, + "OBJECT_OT_data_instance_add", + view3d_object_data_drop_poll, + view3d_id_drop_copy_with_type); } static void view3d_widgets(void) |