Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
| Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "WM_api.h" | #include "WM_api.h" | ||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "wm.h" | |||||
| /* own includes */ | /* own includes */ | ||||
| #include "../gizmo_geometry.h" | #include "../gizmo_geometry.h" | ||||
| #include "../gizmo_library_intern.h" | #include "../gizmo_library_intern.h" | ||||
| typedef struct SnapGizmo3D { | typedef struct SnapGizmo3D { | ||||
| wmGizmo gizmo; | wmGizmo gizmo; | ||||
| PropertyRNA *prop_prevpoint; | PropertyRNA *prop_prevpoint; | ||||
| PropertyRNA *prop_location; | PropertyRNA *prop_location; | ||||
| PropertyRNA *prop_normal; | PropertyRNA *prop_normal; | ||||
| PropertyRNA *prop_elem_index; | PropertyRNA *prop_elem_index; | ||||
| PropertyRNA *prop_snap_force; | PropertyRNA *prop_snap_force; | ||||
| /* We could have other snap contexts, for now only support 3D view. */ | /* We could have other snap contexts, for now only support 3D view. */ | ||||
| SnapObjectContext *snap_context_v3d; | SnapObjectContext *snap_context_v3d; | ||||
| int mval[2]; | |||||
| /* Copy of the parameters of the last event state in order to detect updates. */ | |||||
| struct { | |||||
| int x; | |||||
| int y; | |||||
| short shift, ctrl, alt, oskey; | |||||
| } last_eventstate; | |||||
| #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | ||||
| wmKeyMap *keymap; | wmKeyMap *keymap; | ||||
| int snap_on; | int snap_on; | ||||
| bool invert_snap; | bool invert_snap; | ||||
| #endif | #endif | ||||
| int use_snap_override; | int use_snap_override; | ||||
| short snap_elem; | short snap_elem; | ||||
| } SnapGizmo3D; | } SnapGizmo3D; | ||||
| /* Checks if the current event is different from the one captured in the last update. */ | |||||
| static bool eventstate_has_changed(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) | |||||
| { | |||||
| if (wm && wm->winactive) { | |||||
| const wmEvent *event = wm->winactive->eventstate; | |||||
| if ((event->x != snap_gizmo->last_eventstate.x) || | |||||
| (event->y != snap_gizmo->last_eventstate.y) || | |||||
| (event->ctrl != snap_gizmo->last_eventstate.ctrl) || | |||||
| (event->shift != snap_gizmo->last_eventstate.shift) || | |||||
| (event->alt != snap_gizmo->last_eventstate.alt) || | |||||
| (event->oskey != snap_gizmo->last_eventstate.oskey)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /* Copies the current eventstate. */ | |||||
| static void eventstate_save(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) | |||||
| { | |||||
| if (wm && wm->winactive) { | |||||
| const wmEvent *event = wm->winactive->eventstate; | |||||
| snap_gizmo->last_eventstate.x = event->x; | |||||
| snap_gizmo->last_eventstate.y = event->y; | |||||
| snap_gizmo->last_eventstate.ctrl = event->ctrl; | |||||
| snap_gizmo->last_eventstate.shift = event->shift; | |||||
| snap_gizmo->last_eventstate.alt = event->alt; | |||||
| snap_gizmo->last_eventstate.oskey = event->oskey; | |||||
| } | |||||
| } | |||||
| #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | ||||
| static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) | static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm) | ||||
| { | { | ||||
| if (!wm || !wm->winactive) { | if (!wm || !wm->winactive) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| const wmEvent *event = wm->winactive->eventstate; | |||||
| if ((event->ctrl == snap_gizmo->last_eventstate.ctrl) && | |||||
| (event->shift == snap_gizmo->last_eventstate.shift) && | |||||
| (event->alt == snap_gizmo->last_eventstate.alt) && | |||||
| (event->oskey == snap_gizmo->last_eventstate.oskey)) { | |||||
| /* Nothing has changed. */ | |||||
| return snap_gizmo->invert_snap; | |||||
| } | |||||
| if (snap_gizmo->keymap == NULL) { | if (snap_gizmo->keymap == NULL) { | ||||
| /* Lazy initialization. */ | /* Lazy initialization. */ | ||||
| snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); | snap_gizmo->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map"); | ||||
| RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on); | RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on); | ||||
| } | } | ||||
| const int snap_on = snap_gizmo->snap_on; | const int snap_on = snap_gizmo->snap_on; | ||||
| wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap); | wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap); | ||||
| const wmEvent *event = wm->winactive->eventstate; | |||||
| for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { | for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { | ||||
| if (kmi->flag & KMI_INACTIVE) { | if (kmi->flag & KMI_INACTIVE) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (kmi->propvalue == snap_on) { | if (kmi->propvalue == snap_on) { | ||||
| if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) || | if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) || | ||||
| (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) || | (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) || | ||||
| ▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | short ED_gizmotypes_snap_3d_update(wmGizmo *gz, | ||||
| const ARegion *region, | const ARegion *region, | ||||
| const View3D *v3d, | const View3D *v3d, | ||||
| const wmWindowManager *wm, | const wmWindowManager *wm, | ||||
| const float mval_fl[2], | const float mval_fl[2], | ||||
| float r_loc[3], | float r_loc[3], | ||||
| float r_nor[3]) | float r_nor[3]) | ||||
| { | { | ||||
| SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | ||||
| Scene *scene = DEG_get_input_scene(depsgraph); | |||||
| float co[3], no[3]; | |||||
| short snap_elem = 0; | |||||
| int snap_elem_index[3] = {-1, -1, -1}; | |||||
| int index = -1; | |||||
| if (snap_gizmo->use_snap_override != -1) { | if (snap_gizmo->use_snap_override != -1) { | ||||
| if (snap_gizmo->use_snap_override == false) { | if (snap_gizmo->use_snap_override == false) { | ||||
| snap_gizmo->snap_elem = 0; | snap_gizmo->snap_elem = 0; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | ||||
| snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm); | snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm); | ||||
| #endif | |||||
| eventstate_save(snap_gizmo, wm); | |||||
| Scene *scene = DEG_get_input_scene(depsgraph); | |||||
| #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | |||||
| if (snap_gizmo->use_snap_override == -1) { | if (snap_gizmo->use_snap_override == -1) { | ||||
| const ToolSettings *ts = scene->toolsettings; | const ToolSettings *ts = scene->toolsettings; | ||||
| if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) { | if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) { | ||||
| snap_gizmo->snap_elem = 0; | snap_gizmo->snap_elem = 0; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| #else | |||||
| UNUSED_VARS(wm); | |||||
| #endif | #endif | ||||
| float co[3], no[3]; | |||||
| short snap_elem = 0; | |||||
| int snap_elem_index[3] = {-1, -1, -1}; | |||||
| int index = -1; | |||||
| wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements"); | wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(gz, "snap_elements"); | ||||
| int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop); | int snap_elements = RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop); | ||||
| if (gz_prop->prop != snap_gizmo->prop_snap_force) { | if (gz_prop->prop != snap_gizmo->prop_snap_force) { | ||||
| int snap_elements_force = RNA_property_enum_get(gz->ptr, snap_gizmo->prop_snap_force); | int snap_elements_force = RNA_property_enum_get(gz->ptr, snap_gizmo->prop_snap_force); | ||||
| snap_elements |= snap_elements_force; | snap_elements |= snap_elements_force; | ||||
| } | } | ||||
| snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | | ||||
| SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR); | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR); | ||||
| ▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | |||||
| static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) | static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) | ||||
| { | { | ||||
| SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | ||||
| if (snap_gizmo->snap_elem == 0) { | if (snap_gizmo->snap_elem == 0) { | ||||
| return; | return; | ||||
| } | } | ||||
| ARegion *region = CTX_wm_region(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| RegionView3D *rv3d = region->regiondata; | if (eventstate_has_changed(snap_gizmo, wm)) { | ||||
| /* The eventstate has changed but the snap has not been updated. | |||||
| * This means that the current position is no longer valid. */ | |||||
| snap_gizmo->snap_elem = 0; | |||||
| return; | |||||
| } | |||||
| /* Ideally, we shouldn't assign values here. | RegionView3D *rv3d = CTX_wm_region_data(C); | ||||
| * But `test_select` is not called during navigation. | if (rv3d->rflag & RV3D_NAVIGATING) { | ||||
| * And `snap_elem` is not really useful in this case. */ | /* Don't draw the gizmo while navigating. It can be distracting. */ | ||||
| if ((rv3d->rflag & RV3D_NAVIGATING) || | |||||
| (!(gz->state & WM_GIZMO_STATE_HIGHLIGHT) && !wm_gizmomap_modal_get(region->gizmo_map))) { | |||||
| snap_gizmo->snap_elem = 0; | snap_gizmo->snap_elem = 0; | ||||
| return; | return; | ||||
| } | } | ||||
| float location[3], prev_point_stack[3], *prev_point = NULL; | float location[3], prev_point_stack[3], *prev_point = NULL; | ||||
| uchar color_line[4], color_point[4]; | uchar color_line[4], color_point[4]; | ||||
| RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_location, location); | RNA_property_float_get_array(gz->ptr, snap_gizmo->prop_location, location); | ||||
| Show All 13 Lines | static void snap_gizmo_draw(const bContext *C, wmGizmo *gz) | ||||
| GPU_line_width(1.0f); | GPU_line_width(1.0f); | ||||
| ED_gizmotypes_snap_3d_draw_util( | ED_gizmotypes_snap_3d_draw_util( | ||||
| rv3d, prev_point, location, NULL, color_line, color_point, snap_gizmo->snap_elem); | rv3d, prev_point, location, NULL, color_line, color_point, snap_gizmo->snap_elem); | ||||
| } | } | ||||
| static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2]) | static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2]) | ||||
| { | { | ||||
| SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz; | ||||
| #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK | |||||
| wmWindowManager *wm = CTX_wm_manager(C); | wmWindowManager *wm = CTX_wm_manager(C); | ||||
| const bool invert = invert_snap(snap_gizmo, wm); | if (!eventstate_has_changed(snap_gizmo, wm)) { | ||||
| if (snap_gizmo->invert_snap == invert && snap_gizmo->mval[0] == mval[0] && | |||||
| snap_gizmo->mval[1] == mval[1]) { | |||||
| /* Performance, do not update. */ | /* Performance, do not update. */ | ||||
| return snap_gizmo->snap_elem ? 0 : -1; | return snap_gizmo->snap_elem ? 0 : -1; | ||||
| } | } | ||||
| snap_gizmo->invert_snap = invert; | |||||
| #else | |||||
| if (snap_gizmo->mval[0] == mval[0] && snap_gizmo->mval[1] == mval[1]) { | |||||
| /* Performance, do not update. */ | |||||
| return snap_gizmo->snap_elem ? 0 : -1; | |||||
| } | |||||
| #endif | |||||
| copy_v2_v2_int(snap_gizmo->mval, mval); | |||||
| ARegion *region = CTX_wm_region(C); | ARegion *region = CTX_wm_region(C); | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| const float mval_fl[2] = {UNPACK2(mval)}; | const float mval_fl[2] = {UNPACK2(mval)}; | ||||
| short snap_elem = ED_gizmotypes_snap_3d_update( | short snap_elem = ED_gizmotypes_snap_3d_update( | ||||
| gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, NULL, mval_fl, NULL, NULL); | gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl, NULL, NULL); | ||||
| if (snap_elem) { | if (snap_elem) { | ||||
| ED_region_tag_redraw_editor_overlays(region); | ED_region_tag_redraw_editor_overlays(region); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 116 Lines • Show Last 20 Lines | |||||