diff options
Diffstat (limited to 'source/blender/editors/object/object_modes.c')
-rw-r--r-- | source/blender/editors/object/object_modes.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c index bc05a62759f..caba10c820b 100644 --- a/source/blender/editors/object/object_modes.c +++ b/source/blender/editors/object/object_modes.c @@ -26,6 +26,8 @@ #include "DNA_scene_types.h" #include "DNA_workspace_types.h" +#include "BLI_kdopbvh.h" +#include "BLI_math.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -44,10 +46,15 @@ #include "RNA_access.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "ED_armature.h" #include "ED_gpencil.h" #include "ED_screen.h" +#include "ED_transform_snap_object_context.h" +#include "ED_view3d.h" + +#include "WM_toolsystem.h" #include "ED_object.h" /* own include */ @@ -390,3 +397,114 @@ bool ED_object_mode_generic_has_data(struct Depsgraph *depsgraph, struct Object } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Switch Object + * + * Enters the same mode of the current active object in another object, leaving the mode of the + *current object. + * + * \{ */ + +bool OBJECT_switch_object_poll(bContext *C) +{ + Object *ob = CTX_data_active_object(C); + if (!CTX_wm_region_view3d(C)) { + return false; + } + return ob && ELEM(ob->mode, OB_MODE_EDIT, OB_MODE_SCULPT); +} + +static int object_switch_object_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ARegion *ar = CTX_wm_region(C); + struct Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + struct SnapObjectContext *sctx = ED_transform_snap_object_context_create(scene, 0); + + float global_normal[3], global_loc[3]; + float r_obmat[4][4]; + + float mouse[2]; + mouse[0] = event->mval[0]; + mouse[1] = event->mval[1]; + + float ray_co[3], ray_no[3]; + float ray_dist = BVH_RAYCAST_DIST_MAX; + int r_index; + ED_view3d_win_to_origin(ar, mouse, ray_co); + ED_view3d_win_to_vector(ar, mouse, ray_no); + + Object *r_ob = NULL; + + bool ret = ED_transform_snap_object_project_ray_ex(sctx, + depsgraph, + &(const struct SnapObjectParams){ + .snap_select = SNAP_NOT_ACTIVE, + }, + ray_co, + ray_no, + &ray_dist, + global_loc, + global_normal, + &r_index, + &r_ob, + (float(*)[4])r_obmat); + ED_transform_snap_object_context_destroy(sctx); + + Object *c_ob = CTX_data_active_object(C); + if (!ret || r_ob == NULL) { + return OPERATOR_CANCELLED; + } + if (r_ob == NULL || r_ob == c_ob) { + return OPERATOR_CANCELLED; + } + + eObjectMode last_mode = (eObjectMode)c_ob->mode; + if (!ED_object_mode_compat_test(r_ob, last_mode)) { + return OPERATOR_CANCELLED; + } + ED_object_mode_generic_exit(bmain, depsgraph, scene, c_ob); + + Object *ob_orig = DEG_get_original_object(r_ob); + Base *base = BKE_view_layer_base_find(view_layer, ob_orig); + BKE_view_layer_base_deselect_all(view_layer); + BKE_view_layer_base_select_and_set_active(view_layer, base); + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + + depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + ob_orig = DEG_get_original_object(r_ob); + ED_object_mode_set(C, last_mode); + + /* Update the viewport rotation origin to the mouse cursor. */ + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; + copy_v3_v3(ups->average_stroke_accum, global_loc); + ups->average_stroke_counter = 1; + ups->last_stroke_valid = true; + + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + WM_toolsystem_update_from_context_view3d(C); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_switch_object(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Switch Object"; + ot->idname = "OBJECT_OT_switch_object"; + ot->description = + "Switches the active object and assigns the same mode to a new one under the mouse cursor, " + "leaving the active mode in the current one"; + + /* api callbacks */ + ot->invoke = object_switch_object_invoke; + ot->poll = OBJECT_switch_object_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ |