diff options
author | Germano Cavalcante <germano.costa@ig.com.br> | 2021-10-19 18:55:20 +0300 |
---|---|---|
committer | Germano Cavalcante <germano.costa@ig.com.br> | 2021-10-20 14:28:58 +0300 |
commit | 9001dd7f29a2f22534cf5549bc500422b1243c97 (patch) | |
tree | 4722af399c6b7144d2db49222dd08e4ce623c01a /source/blender/editors/space_view3d | |
parent | 690e1baf722c6c79ec6a7eaa548cff4c0538f5d3 (diff) |
View3D: Cursor Snap Refactor
Make the snap system consistent with the placement tool and leak-safe.
**Changes:**
- Store `SnapCursorDataIntern` in a `static` variable;
- Initialize (lazily) `SnapCursorDataIntern` only once (for the keymap).
- Move setup members of `V3DSnapCursorData` to a new struct `V3DSnapCursorState`
- Merge `ED_view3d_cursor_snap_activate_point` and `ED_view3d_cursor_snap_activate_plane` into `state = ED_view3d_cursor_snap_active()`
- Merge `ED_view3d_cursor_snap_deactivate_point` and `ED_view3d_cursor_snap_deactivate_plane` into `ED_view3d_cursor_snap_deactive(state)`
- Be sure to free the snap context when closing via `ED_view3d_cursor_snap_exit`
- Use RNA properties callbacks to update the properties of the `"Add Primitive Object"` operator
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 4 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_cursor_snap.c | 401 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_placement.c | 250 |
3 files changed, 363 insertions, 292 deletions
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 83aa2d93fbb..787cf529483 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -355,10 +355,6 @@ static void view3d_exit(wmWindowManager *UNUSED(wm), ScrArea *area) BLI_assert(area->spacetype == SPACE_VIEW3D); View3D *v3d = area->spacedata.first; MEM_SAFE_FREE(v3d->runtime.local_stats); - - /* Be sure to release the #V3DSnapCursorData from the cursor, or it will get lost. */ - ED_view3d_cursor_snap_deactivate_point(); - ED_view3d_cursor_snap_deactivate_plane(); } static SpaceLink *view3d_duplicate(SpaceLink *sl) diff --git a/source/blender/editors/space_view3d/view3d_cursor_snap.c b/source/blender/editors/space_view3d/view3d_cursor_snap.c index 590f0b4563a..06a37703648 100644 --- a/source/blender/editors/space_view3d/view3d_cursor_snap.c +++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c @@ -53,14 +53,26 @@ #include "DEG_depsgraph_query.h" #include "WM_api.h" -#include "wm.h" + +#define STATE_LEN 3 + +typedef struct SnapStateIntern { + V3DSnapCursorState snap_state; + float prevpoint_stack[3]; + int state_active_prev; + bool is_active; +} SnapStateIntern; typedef struct SnapCursorDataIntern { - /* Keep as first member. */ - struct V3DSnapCursorData snap_data; + V3DSnapCursorState state_default; + SnapStateIntern state_intern[STATE_LEN]; + V3DSnapCursorData snap_data; + + int state_active_len; + int state_active; struct SnapObjectContext *snap_context_v3d; - float prevpoint_stack[3]; + const Scene *scene; short snap_elem_hidden; /* Copy of the parameters of the last event state in order to detect updates. */ @@ -79,10 +91,11 @@ typedef struct SnapCursorDataIntern { struct wmPaintCursor *handle; - bool draw_point; - bool draw_plane; + bool is_initiated; } SnapCursorDataIntern; +static SnapCursorDataIntern g_data_intern = {{0}}; + /** * Calculate a 3x3 orientation matrix from the surface under the cursor. */ @@ -437,23 +450,23 @@ void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d, * \{ */ /* Checks if the current event is different from the one captured in the last update. */ -static bool v3d_cursor_eventstate_has_changed(SnapCursorDataIntern *sdata_intern, +static bool v3d_cursor_eventstate_has_changed(SnapCursorDataIntern *data_intern, + V3DSnapCursorState *state, const wmWindowManager *wm, const int x, const int y) { - V3DSnapCursorData *snap_data = (V3DSnapCursorData *)sdata_intern; if (wm && wm->winactive) { const wmEvent *event = wm->winactive->eventstate; - if ((x != sdata_intern->last_eventstate.x) || (y != sdata_intern->last_eventstate.y)) { + if ((x != data_intern->last_eventstate.x) || (y != data_intern->last_eventstate.y)) { return true; } #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - if (!(snap_data && (snap_data->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE))) { - if ((event->ctrl != sdata_intern->last_eventstate.ctrl) || - (event->shift != sdata_intern->last_eventstate.shift) || - (event->alt != sdata_intern->last_eventstate.alt) || - (event->oskey != sdata_intern->last_eventstate.oskey)) { + if (!(state && (state->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE))) { + if ((event->ctrl != data_intern->last_eventstate.ctrl) || + (event->shift != data_intern->last_eventstate.shift) || + (event->alt != data_intern->last_eventstate.alt) || + (event->oskey != data_intern->last_eventstate.oskey)) { return true; } } @@ -472,31 +485,30 @@ static void v3d_cursor_eventstate_save_xy(SnapCursorDataIntern *cursor_snap, } #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK -static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *sdata_intern, - const wmWindowManager *wm) +static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *data_intern, const wmWindowManager *wm) { if (!wm || !wm->winactive) { return false; } const wmEvent *event = wm->winactive->eventstate; - if ((event->ctrl == sdata_intern->last_eventstate.ctrl) && - (event->shift == sdata_intern->last_eventstate.shift) && - (event->alt == sdata_intern->last_eventstate.alt) && - (event->oskey == sdata_intern->last_eventstate.oskey)) { + if ((event->ctrl == data_intern->last_eventstate.ctrl) && + (event->shift == data_intern->last_eventstate.shift) && + (event->alt == data_intern->last_eventstate.alt) && + (event->oskey == data_intern->last_eventstate.oskey)) { /* Nothing has changed. */ - return sdata_intern->snap_data.is_snap_invert; + return data_intern->snap_data.is_snap_invert; } /* Save new eventstate. */ - sdata_intern->last_eventstate.ctrl = event->ctrl; - sdata_intern->last_eventstate.shift = event->shift; - sdata_intern->last_eventstate.alt = event->alt; - sdata_intern->last_eventstate.oskey = event->oskey; + data_intern->last_eventstate.ctrl = event->ctrl; + data_intern->last_eventstate.shift = event->shift; + data_intern->last_eventstate.alt = event->alt; + data_intern->last_eventstate.oskey = event->oskey; - const int snap_on = sdata_intern->snap_on; + const int snap_on = data_intern->snap_on; - wmKeyMap *keymap = WM_keymap_active(wm, sdata_intern->keymap); + wmKeyMap *keymap = WM_keymap_active(wm, data_intern->keymap); for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) { if (kmi->flag & KMI_INACTIVE) { continue; @@ -521,34 +533,41 @@ static bool v3d_cursor_is_snap_invert(SnapCursorDataIntern *sdata_intern, /** \name Update * \{ */ -static short v3d_cursor_snap_elements(V3DSnapCursorData *cursor_snap, Scene *scene) +static short v3d_cursor_snap_elements(V3DSnapCursorState *snap_state, Scene *scene) { - short snap_elements = cursor_snap->snap_elem_force; + short snap_elements = snap_state->snap_elem_force; if (!snap_elements) { return scene->toolsettings->snap_mode; } return snap_elements; } -static void v3d_cursor_snap_context_ensure(SnapCursorDataIntern *sdata_intern, Scene *scene) +static void v3d_cursor_snap_context_ensure(Scene *scene) { - if (sdata_intern->snap_context_v3d == NULL) { - sdata_intern->snap_context_v3d = ED_transform_snap_object_context_create(scene, 0); + SnapCursorDataIntern *data_intern = &g_data_intern; + if (data_intern->snap_context_v3d && (data_intern->scene != scene)) { + ED_transform_snap_object_context_destroy(data_intern->snap_context_v3d); + data_intern->snap_context_v3d = NULL; + } + if (data_intern->snap_context_v3d == NULL) { + data_intern->snap_context_v3d = ED_transform_snap_object_context_create(scene, 0); + data_intern->scene = scene; } } -static void v3d_cursor_snap_update(const bContext *C, +static void v3d_cursor_snap_update(V3DSnapCursorState *state, + const bContext *C, wmWindowManager *wm, Depsgraph *depsgraph, Scene *scene, ARegion *region, View3D *v3d, int x, - int y, - SnapCursorDataIntern *sdata_intern) + int y) { - v3d_cursor_snap_context_ensure(sdata_intern, scene); - V3DSnapCursorData *snap_data = (V3DSnapCursorData *)sdata_intern; + SnapCursorDataIntern *data_intern = &g_data_intern; + V3DSnapCursorData *snap_data = &data_intern->snap_data; + v3d_cursor_snap_context_ensure(scene); float co[3], no[3], face_nor[3], obmat[4][4], omat[3][3]; short snap_elem = 0; @@ -560,18 +579,18 @@ static void v3d_cursor_snap_update(const bContext *C, zero_v3(face_nor); unit_m3(omat); - ushort snap_elements = v3d_cursor_snap_elements(snap_data, scene); - sdata_intern->snap_elem_hidden = 0; - const bool draw_plane = sdata_intern->draw_plane; + ushort snap_elements = v3d_cursor_snap_elements(state, scene); + data_intern->snap_elem_hidden = 0; + const bool draw_plane = state->draw_plane; if (draw_plane && !(snap_elements & SCE_SNAP_MODE_FACE)) { - sdata_intern->snap_elem_hidden = SCE_SNAP_MODE_FACE; + data_intern->snap_elem_hidden = SCE_SNAP_MODE_FACE; snap_elements |= SCE_SNAP_MODE_FACE; } snap_data->is_enabled = true; #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - if (!(snap_data->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE)) { - snap_data->is_snap_invert = v3d_cursor_is_snap_invert(sdata_intern, wm); + if (!(state->flag & V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE)) { + snap_data->is_snap_invert = v3d_cursor_is_snap_invert(data_intern, wm); const ToolSettings *ts = scene->toolsettings; if (snap_data->is_snap_invert != !(ts->snap_flag & SCE_SNAP)) { @@ -580,7 +599,7 @@ static void v3d_cursor_snap_update(const bContext *C, snap_data->snap_elem = 0; return; } - snap_elements = sdata_intern->snap_elem_hidden = SCE_SNAP_MODE_FACE; + snap_elements = data_intern->snap_elem_hidden = SCE_SNAP_MODE_FACE; } } #endif @@ -588,30 +607,28 @@ static void v3d_cursor_snap_update(const bContext *C, if (snap_elements & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) { float prev_co[3] = {0.0f}; - if (snap_data->prevpoint) { - copy_v3_v3(prev_co, snap_data->prevpoint); + if (state->prevpoint) { + copy_v3_v3(prev_co, state->prevpoint); } else { snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR; } - eSnapSelect snap_select = (snap_data->flag & V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE) ? - SNAP_ONLY_ACTIVE : - SNAP_ALL; + eSnapSelect snap_select = (state->flag & V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE) ? SNAP_ONLY_ACTIVE : + SNAP_ALL; - eSnapEditType edit_mode_type = (snap_data->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ? + eSnapEditType edit_mode_type = (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ? SNAP_GEOM_FINAL : - (snap_data->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE) ? + (state->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE) ? SNAP_GEOM_CAGE : SNAP_GEOM_EDIT; - bool use_occlusion_test = (snap_data->flag & V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE) ? false : - true; + bool use_occlusion_test = (state->flag & V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE) ? false : true; float dist_px = 12.0f * U.pixelsize; snap_elem = ED_transform_snap_object_project_view3d_ex( - sdata_intern->snap_context_v3d, + data_intern->snap_context_v3d, depsgraph, region, v3d, @@ -633,11 +650,11 @@ static void v3d_cursor_snap_update(const bContext *C, } if (is_zero_v3(face_nor)) { - face_nor[snap_data->plane_axis] = 1.0f; + face_nor[state->plane_axis] = 1.0f; } if (draw_plane) { - bool orient_surface = snap_elem && (snap_data->plane_orient == V3D_PLACE_ORIENT_SURFACE); + bool orient_surface = snap_elem && (state->plane_orient == V3D_PLACE_ORIENT_SURFACE); if (orient_surface) { copy_m3_m4(omat, obmat); } @@ -650,8 +667,8 @@ static void v3d_cursor_snap_update(const bContext *C, scene, view_layer, v3d, region->regiondata, ob, ob, orient_index, pivot_point, omat); RegionView3D *rv3d = region->regiondata; - if (snap_data->use_plane_axis_auto) { - mat3_align_axis_to_v3(omat, snap_data->plane_axis, rv3d->viewinv[2]); + if (state->use_plane_axis_auto) { + mat3_align_axis_to_v3(omat, state->plane_axis, rv3d->viewinv[2]); } } @@ -659,7 +676,7 @@ static void v3d_cursor_snap_update(const bContext *C, * * While making orthogonal doesn't always work well (especially with gimbal orientation for * e.g.) it's a corner case, without better alternatives as objects don't support shear. */ - orthogonalize_m3(omat, snap_data->plane_axis); + orthogonalize_m3(omat, state->plane_axis); if (orient_surface) { v3d_cursor_poject_surface_normal(face_nor, obmat, omat); @@ -667,21 +684,21 @@ static void v3d_cursor_snap_update(const bContext *C, } float *co_depth = snap_elem ? co : scene->cursor.location; - snap_elem &= ~sdata_intern->snap_elem_hidden; + snap_elem &= ~data_intern->snap_elem_hidden; if (snap_elem == 0) { float plane[4]; - if (snap_data->plane_depth != V3D_PLACE_DEPTH_CURSOR_VIEW) { - const float *plane_normal = omat[snap_data->plane_axis]; + if (state->plane_depth != V3D_PLACE_DEPTH_CURSOR_VIEW) { + const float *plane_normal = omat[state->plane_axis]; plane_from_point_normal_v3(plane, co_depth, plane_normal); } - if ((snap_data->plane_depth == V3D_PLACE_DEPTH_CURSOR_VIEW) || + if ((state->plane_depth == V3D_PLACE_DEPTH_CURSOR_VIEW) || !ED_view3d_win_to_3d_on_plane(region, plane, mval_fl, true, co)) { ED_view3d_win_to_3d(v3d, region, co_depth, mval_fl, co); } if (snap_data->is_enabled && (snap_elements & SCE_SNAP_MODE_INCREMENT)) { - v3d_cursor_snap_calc_incremental(scene, v3d, region, snap_data->prevpoint, co); + v3d_cursor_snap_calc_incremental(scene, v3d, region, state->prevpoint, co); } } else if (snap_elem == SCE_SNAP_MODE_VERTEX) { @@ -703,7 +720,7 @@ static void v3d_cursor_snap_update(const bContext *C, copy_m3_m3(snap_data->plane_omat, omat); - v3d_cursor_eventstate_save_xy(sdata_intern, x, y); + v3d_cursor_eventstate_save_xy(data_intern, x, y); } /** \} */ @@ -739,21 +756,22 @@ static bool v3d_cursor_snap_pool_fn(bContext *C) static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void *customdata) { - V3DSnapCursorData *snap_data = customdata; - SnapCursorDataIntern *sdata_intern = customdata; + SnapCursorDataIntern *data_intern = &g_data_intern; + V3DSnapCursorState *state = ED_view3d_cursor_snap_state_get(); + V3DSnapCursorData *snap_data = &data_intern->snap_data; wmWindowManager *wm = CTX_wm_manager(C); ARegion *region = CTX_wm_region(C); x -= region->winrct.xmin; y -= region->winrct.ymin; - if (v3d_cursor_eventstate_has_changed(sdata_intern, wm, x, y)) { + if (v3d_cursor_eventstate_has_changed(data_intern, state, wm, x, y)) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = DEG_get_input_scene(depsgraph); View3D *v3d = CTX_wm_view3d(C); - v3d_cursor_snap_update(C, wm, depsgraph, scene, region, v3d, x, y, sdata_intern); + v3d_cursor_snap_update(state, C, wm, depsgraph, scene, region, v3d, x, y); } - const bool draw_plane = sdata_intern->draw_plane; + const bool draw_plane = state->draw_plane; if (!snap_data->snap_elem && !draw_plane) { return; } @@ -773,12 +791,12 @@ static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void *customdata) copy_m4_m3(matrix, snap_data->plane_omat); copy_v3_v3(matrix[3], snap_data->loc); - v3d_cursor_plane_draw(rv3d, snap_data->plane_axis, matrix); + v3d_cursor_plane_draw(rv3d, state->plane_axis, matrix); } - if (snap_data->snap_elem && sdata_intern->draw_point) { + if (snap_data->snap_elem && state->draw_point) { const float *prev_point = (snap_data->snap_elem & SCE_SNAP_MODE_EDGE_PERPENDICULAR) ? - snap_data->prevpoint : + state->prevpoint : NULL; GPU_line_smooth(false); @@ -788,8 +806,8 @@ static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void *customdata) prev_point, snap_data->loc, NULL, - snap_data->color_line, - snap_data->color_point, + state->color_line, + state->color_point, snap_data->snap_elem); } @@ -802,158 +820,177 @@ static void v3d_cursor_snap_draw_fn(bContext *C, int x, int y, void *customdata) /** \} */ -V3DSnapCursorData *ED_view3d_cursor_snap_data_get(void) +V3DSnapCursorState *ED_view3d_cursor_snap_state_get(void) { - LISTBASE_FOREACH_MUTABLE (wmWindowManager *, wm, &G.main->wm) { - LISTBASE_FOREACH_MUTABLE (wmPaintCursor *, pc, &wm->paintcursors) { - if (pc->draw == v3d_cursor_snap_draw_fn) { - return (V3DSnapCursorData *)pc->customdata; - } - } + if (!g_data_intern.state_active_len) { + return &g_data_intern.state_default; } - return NULL; + return (V3DSnapCursorState *)&g_data_intern.state_intern[g_data_intern.state_active]; } -static void v3d_cursor_snap_data_init(SnapCursorDataIntern *sdata_intern) +static void v3d_cursor_snap_state_init(V3DSnapCursorState *state) { + state->prevpoint = NULL; + state->snap_elem_force = (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | + SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT); + state->plane_axis = 2; + rgba_uchar_args_set(state->color_point, 255, 255, 255, 255); + UI_GetThemeColor3ubv(TH_TRANSFORM, state->color_line); + state->color_line[3] = 128; + state->draw_point = true; + state->draw_plane = false; +} + +static void v3d_cursor_snap_activate(void) +{ + SnapCursorDataIntern *data_intern = &g_data_intern; + if (!data_intern->handle) { + if (!data_intern->is_initiated) { + /* Only initiate intern data once. + * TODO: ED_view3d_cursor_snap_init */ + #ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK - struct wmKeyConfig *keyconf = ((wmWindowManager *)G.main->wm.first)->defaultconf; + struct wmKeyConfig *keyconf = ((wmWindowManager *)G.main->wm.first)->defaultconf; - sdata_intern->keymap = WM_modalkeymap_find(keyconf, "Generic Gizmo Tweak Modal Map"); - RNA_enum_value_from_id(sdata_intern->keymap->modal_items, "SNAP_ON", &sdata_intern->snap_on); + data_intern->keymap = WM_modalkeymap_find(keyconf, "Generic Gizmo Tweak Modal Map"); + RNA_enum_value_from_id(data_intern->keymap->modal_items, "SNAP_ON", &data_intern->snap_on); #endif + V3DSnapCursorState *state_default = &data_intern->state_default; + state_default->prevpoint = NULL; + state_default->snap_elem_force = (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | + SCE_SNAP_MODE_FACE | SCE_SNAP_MODE_EDGE_PERPENDICULAR | + SCE_SNAP_MODE_EDGE_MIDPOINT); + state_default->plane_axis = 2; + rgba_uchar_args_set(state_default->color_point, 255, 255, 255, 255); + UI_GetThemeColor3ubv(TH_TRANSFORM, state_default->color_line); + state_default->color_line[3] = 128; + state_default->draw_point = true; + state_default->draw_plane = false; + + data_intern->is_initiated = true; + } - V3DSnapCursorData *snap_data = &sdata_intern->snap_data; - snap_data->snap_elem_force = (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | - SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT); - snap_data->plane_axis = 2; - rgba_uchar_args_set(snap_data->color_point, 255, 255, 255, 255); - UI_GetThemeColor3ubv(TH_TRANSFORM, snap_data->color_line); - snap_data->color_line[3] = 128; + struct wmPaintCursor *pc = WM_paint_cursor_activate( + SPACE_VIEW3D, RGN_TYPE_WINDOW, v3d_cursor_snap_pool_fn, v3d_cursor_snap_draw_fn, NULL); + data_intern->handle = pc; + } } -static SnapCursorDataIntern *v3d_cursor_snap_ensure(void) +static void v3d_cursor_snap_free(void) { - SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { - sdata_intern = MEM_callocN(sizeof(*sdata_intern), __func__); - v3d_cursor_snap_data_init(sdata_intern); - - struct wmPaintCursor *pc = WM_paint_cursor_activate(SPACE_VIEW3D, - RGN_TYPE_WINDOW, - v3d_cursor_snap_pool_fn, - v3d_cursor_snap_draw_fn, - sdata_intern); - sdata_intern->handle = pc; - } - return sdata_intern; -} + SnapCursorDataIntern *data_intern = &g_data_intern; + if (data_intern->handle) { + WM_paint_cursor_end(data_intern->handle); + data_intern->handle = NULL; + } + if (data_intern->snap_context_v3d) { + ED_transform_snap_object_context_destroy(data_intern->snap_context_v3d); + data_intern->snap_context_v3d = NULL; + } -void ED_view3d_cursor_snap_activate_point(void) -{ - SnapCursorDataIntern *sdata_intern = v3d_cursor_snap_ensure(); - sdata_intern->draw_point = true; + for (SnapStateIntern *state_intern = data_intern->state_intern; + state_intern < &data_intern->state_intern[STATE_LEN]; + state_intern++) { + state_intern->is_active = false; + } } -void ED_view3d_cursor_snap_activate_plane(void) +void ED_view3d_cursor_snap_state_default_set(V3DSnapCursorState *state) { - SnapCursorDataIntern *sdata_intern = v3d_cursor_snap_ensure(); - sdata_intern->draw_plane = true; + g_data_intern.state_default = *state; } -static void v3d_cursor_snap_free(SnapCursorDataIntern *sdata_intern) +V3DSnapCursorState *ED_view3d_cursor_snap_active(void) { - WM_paint_cursor_end(sdata_intern->handle); - if (sdata_intern->snap_context_v3d) { - ED_transform_snap_object_context_destroy(sdata_intern->snap_context_v3d); + SnapCursorDataIntern *data_intern = &g_data_intern; + if (!data_intern->state_active_len) { + v3d_cursor_snap_activate(); + } + + data_intern->state_active_len++; + for (int i = 0; i < STATE_LEN; i++) { + SnapStateIntern *state_intern = &g_data_intern.state_intern[i]; + if (!state_intern->is_active) { + state_intern->snap_state = g_data_intern.state_default; + state_intern->is_active = true; + state_intern->state_active_prev = data_intern->state_active; + data_intern->state_active = i; + return (V3DSnapCursorState *)state_intern; + } } - MEM_freeN(sdata_intern); + + BLI_assert(false); + data_intern->state_active_len--; + return NULL; } -void ED_view3d_cursor_snap_deactivate_point(void) +void ED_view3d_cursor_snap_deactive(V3DSnapCursorState *state) { - SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { + SnapCursorDataIntern *data_intern = &g_data_intern; + if (!data_intern->state_active_len) { + BLI_assert(false); return; } - sdata_intern->draw_point = false; - sdata_intern->snap_data.prevpoint = NULL; - if (sdata_intern->draw_plane) { + SnapStateIntern *state_intern = (SnapStateIntern *)state; + if (!state_intern->is_active) { return; } - v3d_cursor_snap_free(sdata_intern); -} - -void ED_view3d_cursor_snap_deactivate_plane(void) -{ - SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { - return; + state_intern->is_active = false; + data_intern->state_active_len--; + if (!data_intern->state_active_len) { + v3d_cursor_snap_free(); } - - sdata_intern->draw_plane = false; - sdata_intern->snap_data.prevpoint = NULL; - if (sdata_intern->draw_point) { - return; + else { + data_intern->state_active = state_intern->state_active_prev; } - - v3d_cursor_snap_free(sdata_intern); } -void ED_view3d_cursor_snap_prevpoint_set(const float prev_point[3]) +void ED_view3d_cursor_snap_prevpoint_set(V3DSnapCursorState *state, const float prev_point[3]) { - SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { - return; - } + SnapStateIntern *state_intern = (SnapStateIntern *)state; if (prev_point) { - copy_v3_v3(sdata_intern->prevpoint_stack, prev_point); - sdata_intern->snap_data.prevpoint = sdata_intern->prevpoint_stack; + copy_v3_v3(state_intern->prevpoint_stack, prev_point); + state->prevpoint = state_intern->prevpoint_stack; } else { - sdata_intern->snap_data.prevpoint = NULL; + state->prevpoint = NULL; } } -void ED_view3d_cursor_snap_update(const bContext *C, - const int x, - const int y, - V3DSnapCursorData *snap_data) +V3DSnapCursorData *ED_view3d_cursor_snap_data_get(V3DSnapCursorState *state, + const bContext *C, + const int x, + const int y) { - SnapCursorDataIntern stack = {0}, *sdata_intern; - sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { - sdata_intern = &stack; - v3d_cursor_snap_data_init(sdata_intern); - sdata_intern->draw_plane = true; + SnapCursorDataIntern *data_intern = &g_data_intern; + if (C && data_intern->state_active_len) { + wmWindowManager *wm = CTX_wm_manager(C); + if (v3d_cursor_eventstate_has_changed(data_intern, state, wm, x, y)) { + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = DEG_get_input_scene(depsgraph); + ARegion *region = CTX_wm_region(C); + View3D *v3d = CTX_wm_view3d(C); + + if (!state) { + state = ED_view3d_cursor_snap_state_get(); + } + v3d_cursor_snap_update(state, C, wm, depsgraph, scene, region, v3d, x, y); + } } - wmWindowManager *wm = CTX_wm_manager(C); - if (v3d_cursor_eventstate_has_changed(sdata_intern, wm, x, y)) { - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = DEG_get_input_scene(depsgraph); - ARegion *region = CTX_wm_region(C); - View3D *v3d = CTX_wm_view3d(C); + return &data_intern->snap_data; +} - v3d_cursor_snap_update(C, wm, depsgraph, scene, region, v3d, x, y, sdata_intern); - } - if ((void *)snap_data != (void *)sdata_intern) { - if ((sdata_intern == &stack) && sdata_intern->snap_context_v3d) { - ED_transform_snap_object_context_destroy(sdata_intern->snap_context_v3d); - sdata_intern->snap_context_v3d = NULL; - } - *snap_data = *(V3DSnapCursorData *)sdata_intern; - } +struct SnapObjectContext *ED_view3d_cursor_snap_context_ensure(Scene *scene) +{ + SnapCursorDataIntern *data_intern = &g_data_intern; + v3d_cursor_snap_context_ensure(scene); + return data_intern->snap_context_v3d; } -struct SnapObjectContext *ED_view3d_cursor_snap_context_ensure(struct Scene *scene) +void ED_view3d_cursor_snap_exit(void) { - SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get(); - if (!sdata_intern) { - return NULL; - } - v3d_cursor_snap_context_ensure(sdata_intern, scene); - return sdata_intern->snap_context_v3d; + v3d_cursor_snap_free(); } diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c index adff75b571d..bffcdcfc320 100644 --- a/source/blender/editors/space_view3d/view3d_placement.c +++ b/source/blender/editors/space_view3d/view3d_placement.c @@ -45,11 +45,11 @@ #include "view3d_intern.h" -static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement"; +#define SNAP_MODE_GEOM \ + (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | \ + SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT) -static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, - bool do_draw_plane, - bool do_draw_point); +static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement"; /** * Dot products below this will be considered view aligned. @@ -151,6 +151,7 @@ struct InteractivePlaceData { float matrix_orient[3][3]; int orient_axis; + V3DSnapCursorState *snap_state; bool use_snap, is_snap_found, is_snap_invert; float snap_co[3]; @@ -693,18 +694,25 @@ static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region * Use by both the operator and placement cursor. * \{ */ -static bool view3d_interactive_add_calc_plane(bContext *C, - const wmEvent *event, - float r_co_src[3], - float r_matrix_orient[3][3]) +static bool view3d_interactive_add_calc_snap(bContext *C, + const wmEvent *event, + float r_co_src[3], + float r_matrix_orient[3][3], + bool *r_is_enabled, + bool *r_is_snap_invert) { - V3DSnapCursorData snap_data; - ED_view3d_cursor_snap_update(C, UNPACK2(event->mval), &snap_data); - copy_v3_v3(r_co_src, snap_data.loc); + V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(NULL, NULL, 0, 0); + copy_v3_v3(r_co_src, snap_data->loc); if (r_matrix_orient) { - copy_m3_m3(r_matrix_orient, snap_data.plane_omat); + copy_m3_m3(r_matrix_orient, snap_data->plane_omat); + } + if (r_is_enabled) { + *r_is_enabled = snap_data->is_enabled; } - return snap_data.snap_elem != 0; + if (r_is_snap_invert) { + *r_is_snap_invert = snap_data->is_snap_invert; + } + return snap_data->snap_elem != 0; } /** \} */ @@ -715,12 +723,11 @@ static bool view3d_interactive_add_calc_plane(bContext *C, static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event) { + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); - const int plane_axis = RNA_enum_get(op->ptr, "plane_axis"); - const bool plane_axis_auto = RNA_boolean_get(op->ptr, "plane_axis_auto"); + const int plane_axis = snap_state->plane_axis; const enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target"); - const eV3DPlaceDepth plane_depth = RNA_enum_get(op->ptr, "plane_depth"); - const eV3DPlaceOrient plane_orient = RNA_enum_get(op->ptr, "plane_orient"); + const enum ePlace_Origin plane_origin[2] = { RNA_enum_get(op->ptr, "plane_origin_base"), RNA_enum_get(op->ptr, "plane_origin_depth"), @@ -734,24 +741,16 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type); - ED_view3d_cursor_snap_activate_point(); - { - V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(); - snap_data->plane_depth = plane_depth; - snap_data->plane_orient = plane_orient; - snap_data->plane_axis = plane_axis; - snap_data->use_plane_axis_auto = plane_axis_auto; - - ED_view3d_cursor_snap_activate_plane(); - view3d_interactive_add_calc_plane(C, event, ipd->co_src, ipd->matrix_orient); - ED_view3d_cursor_snap_deactivate_plane(); + ipd->snap_state = ED_view3d_cursor_snap_active(); + ipd->snap_state->draw_point = true; + ipd->snap_state->draw_plane = true; - ED_view3d_cursor_snap_prevpoint_set(ipd->co_src); + ipd->is_snap_found = + view3d_interactive_add_calc_snap( + C, event, ipd->co_src, ipd->matrix_orient, &ipd->use_snap, &ipd->is_snap_invert) != 0; - ipd->use_snap = snap_data->is_enabled; - ipd->is_snap_invert = snap_data->is_snap_invert; - ipd->is_snap_found = snap_data->snap_elem != 0; - } + ipd->snap_state->draw_plane = false; + ED_view3d_cursor_snap_prevpoint_set(ipd->snap_state, ipd->co_src); ipd->orient_axis = plane_axis; for (int i = 0; i < 2; i++) { @@ -905,14 +904,7 @@ static void view3d_interactive_add_exit(bContext *C, wmOperator *op) UNUSED_VARS(C); struct InteractivePlaceData *ipd = op->customdata; - - wmGizmoGroup *gzgroup = idp_gizmogroup_from_region(ipd->region); - if (gzgroup != NULL) { - preview_plane_cursor_visible_set(gzgroup, true, true); - } - else { - ED_view3d_cursor_snap_deactivate_point(); - } + ED_view3d_cursor_snap_deactive(ipd->snap_state); ED_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view); @@ -1035,7 +1027,7 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve if (ipd->step_index == STEP_BASE) { if (ELEM(event->type, ipd->launch_event, LEFTMOUSE)) { if (event->val == KM_RELEASE) { - ED_view3d_cursor_snap_prevpoint_set(ipd->co_src); + ED_view3d_cursor_snap_prevpoint_set(ipd->snap_state, ipd->co_src); /* Set secondary plane. */ @@ -1184,7 +1176,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve /* Calculate the snap location on mouse-move or when toggling snap. */ ipd->is_snap_found = false; if (ipd->use_snap) { - ipd->is_snap_found = view3d_interactive_add_calc_plane(C, event, ipd->snap_co, NULL); + ipd->is_snap_found = view3d_interactive_add_calc_snap( + C, event, ipd->snap_co, NULL, NULL, NULL); } if (ipd->step_index == STEP_BASE) { @@ -1254,6 +1247,98 @@ static bool view3d_interactive_add_poll(bContext *C) return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH); } +static int idp_rna_plane_axis_get_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop)) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + return snap_state->plane_axis; +} + +static void idp_rna_plane_axis_set_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop), + int value) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + snap_state->plane_axis = value; + ED_view3d_cursor_snap_state_default_set(snap_state); +} + +static int idp_rna_plane_depth_get_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop)) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + return snap_state->plane_depth; +} + +static void idp_rna_plane_depth_set_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop), + int value) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + snap_state->plane_depth = value; + ED_view3d_cursor_snap_state_default_set(snap_state); +} + +static int idp_rna_plane_orient_get_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop)) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + return snap_state->plane_orient; +} + +static void idp_rna_plane_orient_set_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop), + int value) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + snap_state->plane_orient = value; + ED_view3d_cursor_snap_state_default_set(snap_state); +} + +static int idp_rna_snap_target_get_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop)) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + if (!snap_state->snap_elem_force) { + return PLACE_SNAP_TO_DEFAULT; + } + + /* Make sure you keep a consistent #snap_mode. */ + snap_state->snap_elem_force = SNAP_MODE_GEOM; + return PLACE_SNAP_TO_GEOMETRY; +} + +static void idp_rna_snap_target_set_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop), + int value) +{ + short snap_mode = 0; /* #toolsettings->snap_mode. */ + const enum ePlace_SnapTo snap_to = value; + if (snap_to == PLACE_SNAP_TO_GEOMETRY) { + snap_mode = SNAP_MODE_GEOM; + } + + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + snap_state->snap_elem_force = snap_mode; + ED_view3d_cursor_snap_state_default_set(snap_state); +} + +static bool idp_rna_use_plane_axis_auto_get_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop)) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + return snap_state->use_plane_axis_auto; +} + +static void idp_rna_use_plane_axis_auto_set_fn(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *UNUSED(prop), + bool value) +{ + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get(); + snap_state->use_plane_axis_auto = value; + ED_view3d_cursor_snap_state_default_set(snap_state); +} + void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) { /* identifiers */ @@ -1294,6 +1379,8 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) RNA_def_property_enum_default(prop, 2); RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_enum_funcs_runtime( + prop, idp_rna_plane_axis_get_fn, idp_rna_plane_axis_set_fn, NULL); prop = RNA_def_boolean(ot->srna, "plane_axis_auto", @@ -1302,6 +1389,8 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) "Select the closest axis when placing objects " "(surface overrides)"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_boolean_funcs_runtime( + prop, idp_rna_use_plane_axis_auto_get_fn, idp_rna_use_plane_axis_auto_set_fn); static const EnumPropertyItem plane_depth_items[] = { {V3D_PLACE_DEPTH_SURFACE, @@ -1327,6 +1416,8 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) RNA_def_property_enum_default(prop, V3D_PLACE_DEPTH_SURFACE); RNA_def_property_enum_items(prop, plane_depth_items); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_enum_funcs_runtime( + prop, idp_rna_plane_depth_get_fn, idp_rna_plane_depth_set_fn, NULL); static const EnumPropertyItem plane_orientation_items[] = { {V3D_PLACE_ORIENT_SURFACE, @@ -1346,6 +1437,8 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) RNA_def_property_enum_default(prop, V3D_PLACE_ORIENT_SURFACE); RNA_def_property_enum_items(prop, plane_orientation_items); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_enum_funcs_runtime( + prop, idp_rna_plane_orient_get_fn, idp_rna_plane_orient_set_fn, NULL); static const EnumPropertyItem snap_to_items[] = { {PLACE_SNAP_TO_GEOMETRY, "GEOMETRY", 0, "Geometry", "Snap to all geometry"}, @@ -1357,6 +1450,8 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) RNA_def_property_enum_default(prop, PLACE_SNAP_TO_GEOMETRY); RNA_def_property_enum_items(prop, snap_to_items); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + RNA_def_property_enum_funcs_runtime( + prop, idp_rna_snap_target_get_fn, idp_rna_snap_target_set_fn, NULL); { /* Plane Origin. */ static const EnumPropertyItem items[] = { @@ -1404,75 +1499,19 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot) * we could show a placement plane here. * \{ */ -static void preview_plane_cursor_visible_set(wmGizmoGroup *UNUSED(gzgroup), - bool do_draw_plane, - bool do_draw_point) -{ - V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(); - - if (do_draw_point) { - ED_view3d_cursor_snap_activate_point(); - } - - if (do_draw_plane) { - ED_view3d_cursor_snap_activate_plane(); - } - else { - ED_view3d_cursor_snap_deactivate_plane(); - } - - if (!do_draw_point) { - ED_view3d_cursor_snap_deactivate_point(); - } - - if (!snap_data && (do_draw_point || do_draw_plane)) { - snap_data = ED_view3d_cursor_snap_data_get(); - UI_GetThemeColor3ubv(TH_TRANSFORM, snap_data->color_line); - snap_data->color_line[3] = 128; - rgba_uchar_args_set(snap_data->color_point, 255, 255, 255, 255); - } -} - static void preview_plane_free_fn(void *customdata) { - preview_plane_cursor_visible_set(customdata, false, false); + V3DSnapCursorState *snap_state = customdata; + ED_view3d_cursor_snap_deactive(snap_state); } static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup) { - preview_plane_cursor_visible_set(gzgroup, true, true); - gzgroup->customdata = gzgroup; - gzgroup->customdata_free = preview_plane_free_fn; -} - -static void WIDGETGROUP_placement_draw_prepare(const bContext *C, wmGizmoGroup *UNUSED(gzgroup)) -{ - V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(); - if (!snap_data) { - return; - } - - PointerRNA ptr; - { - wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_interactive_add", true); - BLI_assert(ot != NULL); - - ScrArea *area = CTX_wm_area(C); - bToolRef *tref = area->runtime.tool; - WM_toolsystem_ref_properties_ensure_from_operator(tref, ot, &ptr); - } + V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_active(); + snap_state->draw_plane = true; - short snap_mode = 0; /* #toolsettings->snap_mode. */ - const enum ePlace_SnapTo snap_to = RNA_enum_get(&ptr, "snap_target"); - if (snap_to == PLACE_SNAP_TO_GEOMETRY) { - snap_mode = (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | - SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT); - } - snap_data->snap_elem_force = snap_mode; - snap_data->plane_depth = (eV3DPlaceDepth)RNA_enum_get(&ptr, "plane_depth"); - snap_data->plane_orient = (eV3DPlaceOrient)RNA_enum_get(&ptr, "plane_orientation"); - snap_data->plane_axis = RNA_enum_get(&ptr, "plane_axis"); - snap_data->use_plane_axis_auto = RNA_boolean_get(&ptr, "plane_axis_auto"); + gzgroup->customdata = snap_state; + gzgroup->customdata_free = preview_plane_free_fn; } void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt) @@ -1487,7 +1526,6 @@ void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt) gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool; gzgt->setup = WIDGETGROUP_placement_setup; - gzgt->draw_prepare = WIDGETGROUP_placement_draw_prepare; } /** \} */ |