Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_mode_snapsource.c
- This file was added.
| /* SPDX-License-Identifier: GPL-2.0-or-later | |||||
| * Copyright 2001-2002 NaN Holding BV. All rights reserved. */ | |||||
| /** \file | |||||
| * \ingroup edtransform | |||||
| */ | |||||
| #include "MEM_guardedalloc.h" | |||||
| #include "BLI_math.h" | |||||
| #include "DNA_windowmanager_types.h" | |||||
| #include "BKE_context.h" | |||||
| #include "ED_screen.h" | |||||
| #include "ED_transform_snap_object_context.h" | |||||
| #include "transform.h" | |||||
| #include "transform_convert.h" | |||||
| #include "transform_snap.h" | |||||
| #include "transform_mode.h" | |||||
| #define RESET_TRANSFORMATION | |||||
| #define REMOVE_GIZMO | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /** \name Transform Element | |||||
| * \{ */ | |||||
| /** | |||||
| * \note Small arrays / data-structures should be stored copied for faster memory access. | |||||
| */ | |||||
| struct SnapSouceCustomData { | |||||
| void (*transform_prev)(struct TransInfo *, const int[2]); | |||||
| eRedrawFlag (*handleEvent_prev)(struct TransInfo *, const struct wmEvent *); | |||||
| void *customdata_mode_prev; | |||||
| #ifdef REMOVE_GIZMO | |||||
| struct wmGizmo *gz; | |||||
| #endif | |||||
| eSnapTargetOP target_operation_prev; | |||||
| struct { | |||||
| void (*apply)(struct TransInfo *t, | |||||
| struct MouseInput *mi, | |||||
| const double mval[2], | |||||
| float output[3]); | |||||
| void (*post)(struct TransInfo *t, float values[3]); | |||||
| bool use_virtual_mval; | |||||
| } mouse_prev; | |||||
| }; | |||||
| static void snapsource_end(TransInfo *t) | |||||
| { | |||||
| t->modifiers &= ~MOD_EDIT_SNAP_SOURCE; | |||||
| /* Restore. */ | |||||
| struct SnapSouceCustomData *customdata = t->custom.mode.data; | |||||
| t->transform = customdata->transform_prev; | |||||
| t->custom.mode.data = customdata->customdata_mode_prev; | |||||
| t->handleEvent = customdata->handleEvent_prev; | |||||
| t->tsnap.target_operation = customdata->target_operation_prev; | |||||
| t->mouse.apply = customdata->mouse_prev.apply; | |||||
| t->mouse.post = customdata->mouse_prev.post; | |||||
| t->mouse.use_virtual_mval = customdata->mouse_prev.use_virtual_mval; | |||||
| if (customdata->gz) { | |||||
| WM_gizmo_modal_set_from_setup_weak( | |||||
| t->region->gizmo_map, t->context, customdata->gz, CTX_wm_window(t->context)->eventstate); | |||||
| } | |||||
| MEM_freeN(customdata); | |||||
| t->tsnap.snap_source_fn = NULL; | |||||
| tranform_snap_source_restore_context(t); | |||||
| } | |||||
| static void snapsource_confirm(TransInfo *t) | |||||
| { | |||||
| BLI_assert(t->modifiers & MOD_EDIT_SNAP_SOURCE); | |||||
| getSnapPoint(t, t->tsnap.snap_source); | |||||
| int mval[2]; | |||||
| #ifndef RESET_TRANSFORMATION | |||||
| if (true) { | |||||
| if (t->transform_matrix) { | |||||
| float mat_inv[4][4]; | |||||
| unit_m4(mat_inv); | |||||
| t->transform_matrix(t, mat_inv); | |||||
| invert_m4(mat_inv); | |||||
| mul_m4_v3(mat_inv, t->tsnap.snap_source); | |||||
| } | |||||
| else { | |||||
| float mat_inv[3][3]; | |||||
| invert_m3_m3(mat_inv, t->mat); | |||||
| mul_m3_v3(mat_inv, t->tsnap.snap_source); | |||||
| sub_v3_v3(t->tsnap.snap_source, t->vec); | |||||
| } | |||||
| projectIntView(t, t->tsnap.snap_source, mval); | |||||
| } | |||||
| else | |||||
| #endif | |||||
| { | |||||
| copy_v2_v2_int(mval, t->mval); | |||||
| } | |||||
| snapsource_end(t); | |||||
| transform_input_reset(t, mval); | |||||
| } | |||||
| static eRedrawFlag snapsource_handleEvent(struct TransInfo *t, const struct wmEvent *event) | |||||
| { | |||||
| if (event->type == EVT_MODAL_MAP) { | |||||
| switch (event->val) { | |||||
| case TFM_MODAL_CONFIRM: | |||||
| case TFM_MODAL_EDIT_SNAP_SOURCE: | |||||
| if (t->modifiers & MOD_EDIT_SNAP_SOURCE) { | |||||
| snapsource_confirm(t); | |||||
| BLI_assert(t->state != TRANS_CONFIRM); | |||||
| } | |||||
| else { | |||||
| t->modifiers |= MOD_EDIT_SNAP_SOURCE; | |||||
| } | |||||
| break; | |||||
| case TFM_MODAL_CANCEL: | |||||
| snapsource_end(t); | |||||
| t->state = TRANS_CANCEL; | |||||
| return TREDRAW_SOFT; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| else if (event->val == KM_RELEASE && t->state == TRANS_CONFIRM) { | |||||
| if (t->flag & T_RELEASE_CONFIRM && t->modifiers & MOD_EDIT_SNAP_SOURCE) { | |||||
| snapsource_confirm(t); | |||||
| t->flag &= ~T_RELEASE_CONFIRM; | |||||
| t->state = TRANS_RUNNING; | |||||
| } | |||||
| } | |||||
| return TREDRAW_NOTHING; | |||||
| } | |||||
| static void snapsource_update(TransInfo *t, const int UNUSED(mval[2])) | |||||
| { | |||||
| BLI_assert(t->modifiers & MOD_EDIT_SNAP_SOURCE); | |||||
| t->tsnap.snap_target_fn(t, NULL); | |||||
| t->redraw |= TREDRAW_SOFT; | |||||
| } | |||||
| void transform_mode_snap_source_init(TransInfo *t) | |||||
| { | |||||
| if (t->transform == snapsource_update) { | |||||
| /* Already running. */ | |||||
| return; | |||||
| } | |||||
| if (ELEM(t->mode, TFM_INIT, TFM_DUMMY)) { | |||||
| /* Fallback */ | |||||
| transform_mode_init(t, NULL, TFM_TRANSLATION); | |||||
| } | |||||
| struct SnapSouceCustomData *customdata = MEM_callocN(sizeof(*customdata), __func__); | |||||
| customdata->transform_prev = t->transform; | |||||
| customdata->customdata_mode_prev = t->custom.mode.data; | |||||
| customdata->handleEvent_prev = t->handleEvent; | |||||
| customdata->target_operation_prev = t->tsnap.target_operation; | |||||
| customdata->mouse_prev.apply = t->mouse.apply; | |||||
| customdata->mouse_prev.post = t->mouse.post; | |||||
| customdata->mouse_prev.use_virtual_mval = t->mouse.use_virtual_mval; | |||||
| t->custom.mode.data = customdata; | |||||
| // t->custom.mode.use_free = true; | |||||
| t->transform = snapsource_update; | |||||
| t->handleEvent = snapsource_handleEvent; | |||||
| if (!(t->modifiers & MOD_SNAP) || !transformModeUseSnap(t)) { | |||||
| t->modifiers |= MOD_SNAP; | |||||
| t->tsnap.status |= SNAP_FORCED; | |||||
| } | |||||
| t->tsnap.target_operation = SCE_SNAP_TARGET_ALL; | |||||
| if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) { | |||||
| if (t->tsnap.snap_source_fn) { | |||||
| /* Calculate the current snap source for perpendicular snap. */ | |||||
| t->tsnap.snap_source_fn(t); | |||||
| } | |||||
| if ((t->tsnap.status & SNAP_SOURCE_FOUND) == 0) { | |||||
| /* Fallback. */ | |||||
| copy_v3_v3(t->tsnap.snap_source, t->center_global); | |||||
| t->tsnap.status |= SNAP_SOURCE_FOUND; | |||||
| } | |||||
| } | |||||
| if ((t->tsnap.mode & ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) == 0) { | |||||
| /* Initialize snap modes for geometry. */ | |||||
| t->tsnap.mode &= ~(SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID); | |||||
| t->tsnap.mode |= SCE_SNAP_MODE_GEOM & ~SCE_SNAP_MODE_FACE_NEAREST; | |||||
| } | |||||
| if (t->data_type == &TransConvertType_Mesh) { | |||||
| ED_transform_snap_object_context_set_editmesh_callbacks( | |||||
| t->tsnap.object_context, NULL, NULL, NULL, NULL); | |||||
| } | |||||
| #ifdef RESET_TRANSFORMATION | |||||
| restoreTransObjects(t); | |||||
| /* Reset initial values to restore gizmo position. */ | |||||
| applyMouseInput(t, &t->mouse, t->mouse.imval, t->values_final); | |||||
| #endif | |||||
| #ifdef REMOVE_GIZMO | |||||
| struct wmGizmo *gz = WM_gizmomap_get_modal(t->region->gizmo_map); | |||||
| if (gz) { | |||||
| const struct wmEvent *event = CTX_wm_window(t->context)->eventstate; | |||||
| # ifdef RESET_TRANSFORMATION | |||||
| wmGizmoFnModal modal_fn = gz->custom_modal ? gz->custom_modal : gz->type->modal; | |||||
| modal_fn(t->context, gz, event, 0); | |||||
| # endif | |||||
| WM_gizmo_modal_set_from_setup_weak(t->region->gizmo_map, t->context, NULL, event); | |||||
| customdata->gz = gz; | |||||
| } | |||||
| #endif | |||||
| t->mouse.apply = NULL; | |||||
| t->mouse.post = NULL; | |||||
| t->mouse.use_virtual_mval = false; | |||||
| } | |||||
| /** \} */ | |||||