diff options
-rw-r--r-- | source/blender/editors/object/object_add.c | 116 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 1 |
2 files changed, 102 insertions, 15 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 03ff8808423..a01f19f4706 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -189,6 +189,80 @@ static const EnumPropertyItem align_options[] = { /** \} */ /* -------------------------------------------------------------------- */ +/** \name Local Helpers + * \{ */ + +/** + * Operator properties for creating an object under a screen space (2D) coordinate. + * Used for object dropping like behavior (drag object and drop into 3D View). + */ +static void object_add_drop_xy_props(wmOperatorType *ot) +{ + PropertyRNA *prop; + + prop = RNA_def_int(ot->srna, + "drop_x", + 0, + INT_MIN, + INT_MAX, + "Drop X", + "X-coordinate (screen space) to place the new object under", + INT_MIN, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, + "drop_y", + 0, + INT_MIN, + INT_MAX, + "Drop Y", + "Y-coordinate (screen space) to place the new object under", + INT_MIN, + INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); +} + +static bool object_add_drop_xy_is_set(const wmOperator *op) +{ + return RNA_struct_property_is_set(op->ptr, "drop_x") && + RNA_struct_property_is_set(op->ptr, "drop_y"); +} + +/** + * Query the currently set X- and Y-coordinate to position the new object under. + * \param r_mval: Returned pointer to the coordinate in region-space. + */ +static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int (*r_mval)[2]) +{ + if (!object_add_drop_xy_is_set(op)) { + (*r_mval)[0] = 0.0f; + (*r_mval)[1] = 0.0f; + return false; + } + + const ARegion *region = CTX_wm_region(C); + (*r_mval)[0] = RNA_int_get(op->ptr, "drop_x") - region->winrct.xmin; + (*r_mval)[1] = RNA_int_get(op->ptr, "drop_y") - region->winrct.ymin; + + return true; +} + +/** + * Set the drop coordinate to the mouse position (if not already set) and call the operator's + * `exec()` callback. + */ +static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (!object_add_drop_xy_is_set(op)) { + RNA_int_set(op->ptr, "drop_x", event->x); + RNA_int_set(op->ptr, "drop_y", event->y); + } + return op->type->exec(C, op); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Public Add Object API * * \{ */ @@ -1447,10 +1521,8 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) RNA_property_string_get(op->ptr, prop_name, name); collection = (Collection *)BKE_libblock_find_name(bmain, ID_GR, name); - 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}; + int mval[2]; + if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) { 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); @@ -1493,6 +1565,19 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int object_instance_add_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + if (!object_add_drop_xy_is_set(op)) { + RNA_int_set(op->ptr, "drop_x", event->x); + RNA_int_set(op->ptr, "drop_y", event->y); + } + + if (!RNA_struct_property_is_set(op->ptr, "name")) { + return WM_enum_search_invoke(C, op, event); + } + return op->type->exec(C, op); +} + /* only used as menu */ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) { @@ -1504,7 +1589,7 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) ot->idname = "OBJECT_OT_collection_instance_add"; /* api callbacks */ - ot->invoke = WM_enum_search_invoke; + ot->invoke = object_instance_add_invoke; ot->exec = collection_instance_add_exec; ot->poll = ED_operator_objectmode; @@ -1519,6 +1604,8 @@ void OBJECT_OT_collection_instance_add(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE); ot->prop = prop; ED_object_add_generic_props(ot, false); + + object_add_drop_xy_props(ot); } /** \} */ @@ -1556,10 +1643,8 @@ static int object_data_instance_add_exec(bContext *C, wmOperator *op) 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}; + int mval[2]; + if (!RNA_property_is_set(op->ptr, prop_location) && object_add_drop_xy_get(C, op, &mval)) { 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); @@ -1591,6 +1676,7 @@ void OBJECT_OT_data_instance_add(wmOperatorType *ot) ot->idname = "OBJECT_OT_data_instance_add"; /* api callbacks */ + ot->invoke = object_add_drop_xy_generic_invoke; ot->exec = object_data_instance_add_exec; ot->poll = ED_operator_objectmode; @@ -1602,6 +1688,8 @@ void OBJECT_OT_data_instance_add(wmOperatorType *ot) 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); + + object_add_drop_xy_props(ot); } /** \} */ @@ -3228,8 +3316,6 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) static int object_add_named_exec(bContext *C, wmOperator *op) { - wmWindow *win = CTX_wm_window(C); - const wmEvent *event = win ? win->eventstate : NULL; Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); @@ -3258,9 +3344,8 @@ static int object_add_named_exec(bContext *C, wmOperator *op) basen->object->restrictflag &= ~OB_RESTRICT_VIEWPORT; - if (event) { - ARegion *region = CTX_wm_region(C); - const int mval[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin}; + int mval[2]; + if (object_add_drop_xy_get(C, op, &mval)) { ED_object_location_from_view(C, basen->object->loc); ED_view3d_cursor3d_position(C, mval, false, basen->object->loc); } @@ -3290,6 +3375,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot) ot->idname = "OBJECT_OT_add_named"; /* api callbacks */ + ot->invoke = object_add_drop_xy_generic_invoke; ot->exec = object_add_named_exec; ot->poll = ED_operator_objectmode; @@ -3302,6 +3388,8 @@ void OBJECT_OT_add_named(wmOperatorType *ot) "Linked", "Duplicate object but not object data, linking to the original data"); RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add"); + + object_add_drop_xy_props(ot); } /** \} */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 82a20451d26..34d342ddd94 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -616,7 +616,6 @@ static void view3d_collection_drop_copy(wmDrag *drag, wmDropBox *drop) { ID *id = WM_drag_get_local_ID_or_import_from_asset(drag, ID_GR); - drop->opcontext = WM_OP_EXEC_DEFAULT; RNA_string_set(drop->ptr, "name", id->name + 2); } |