Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <mano-wii>2021-10-18 06:32:23 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2021-10-18 07:58:00 +0300
commit69d6222481b4342dc2a153e62752145aa37ea101 (patch)
treefe84a99c2cf3bc7b2ddce62a302e5498a126a9e4 /source/blender/editors
parentbe22e36692f0989e52b4a4f286d7d3d3fe8186bd (diff)
Snap and Placement Gizmo Refactor
Move most of the gizmo snap and placement code to `view_cursor_snap.c`. Simplify and extend the snap API. Differential Revision: https://developer.blender.org/D12868
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c589
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h41
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h3
-rw-r--r--source/blender/editors/include/ED_view3d.h68
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_cursor_snap.c954
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c20
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c854
-rw-r--r--source/blender/editors/transform/transform_snap.c10
-rw-r--r--source/blender/editors/transform/transform_snap_object.c47
12 files changed, 1290 insertions, 1304 deletions
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index 322ae87befa..fccb65bad68 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -27,420 +27,122 @@
* \brief Snap gizmo which exposes the location, normal and index in the props.
*/
+#include "MEM_guardedalloc.h"
+
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "DNA_scene_types.h"
-
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
-#include "GPU_immediate.h"
-#include "GPU_state.h"
-
#include "ED_gizmo_library.h"
#include "ED_screen.h"
#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
-#include "UI_resources.h" /* icons */
+#include "UI_resources.h"
#include "RNA_access.h"
#include "RNA_define.h"
-#include "DEG_depsgraph_query.h"
-
#include "WM_api.h"
-#include "WM_types.h"
/* own includes */
-#include "../gizmo_geometry.h"
#include "../gizmo_library_intern.h"
typedef struct SnapGizmo3D {
wmGizmo gizmo;
-
- /* We could have other snap contexts, for now only support 3D view. */
- SnapObjectContext *snap_context_v3d;
-
- /* Copy of the parameters of the last event state in order to detect updates. */
- struct {
- int x;
- int y;
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- short shift, ctrl, alt, oskey;
-#endif
- } last_eventstate;
-
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- wmKeyMap *keymap;
- int snap_on;
- bool invert_snap;
-#endif
-
- /* Setup. */
- eSnapGizmo flag;
- float *prevpoint;
- float prevpoint_stack[3];
- short snap_elem_force;
-
- /* Return values. */
- short snap_elem;
- float loc[3];
- float nor[3];
- int elem_index[3];
-
- /** Enabled when snap is activated, even if it didn't find anything. */
- bool is_enabled;
+ V3DSnapCursorData *cursor_handle;
} 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)
+static void snap_gizmo_snap_elements_update(SnapGizmo3D *snap_gizmo)
{
- 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)) {
- return true;
- }
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- if (!(snap_gizmo->flag & ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE)) {
- 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)) {
- return true;
- }
- }
-#endif
- }
- return false;
-}
+ V3DSnapCursorData *snap_data = snap_gizmo->cursor_handle;
+ wmGizmoProperty *gz_prop_snap;
+ gz_prop_snap = WM_gizmo_target_property_find(&snap_gizmo->gizmo, "snap_elements");
-/* Copies the current eventstate. */
-static void eventstate_save_xy(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;
- }
-}
-
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
-static bool invert_snap(SnapGizmo3D *snap_gizmo, const wmWindowManager *wm)
-{
- if (!wm || !wm->winactive) {
- 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;
- }
-
- /* Save new eventstate. */
- 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;
-
- const int snap_on = snap_gizmo->snap_on;
-
- wmKeyMap *keymap = WM_keymap_active(wm, snap_gizmo->keymap);
- for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
- if (kmi->flag & KMI_INACTIVE) {
- continue;
- }
-
- if (kmi->propvalue == snap_on) {
- if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) ||
- (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) ||
- (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) ||
- ((kmi->type == EVT_OSKEY) && event->oskey)) {
- return true;
- }
- }
+ if (gz_prop_snap->prop) {
+ snap_data->snap_elem_force |= RNA_property_enum_get(&gz_prop_snap->ptr, gz_prop_snap->prop);
}
- return false;
-}
-#endif
-
-static short snap_gizmo_snap_elements(SnapGizmo3D *snap_gizmo)
-{
- int snap_elements = snap_gizmo->snap_elem_force;
- wmGizmoProperty *gz_prop = WM_gizmo_target_property_find(&snap_gizmo->gizmo, "snap_elements");
- if (gz_prop->prop) {
- snap_elements |= RNA_property_enum_get(&gz_prop->ptr, gz_prop->prop);
- }
- snap_elements &= (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR);
- return (ushort)snap_elements;
+ UI_GetThemeColor3ubv(TH_TRANSFORM, snap_data->color_line);
+ snap_data->color_line[3] = 128;
+ rgba_float_to_uchar(snap_data->color_point, snap_gizmo->gizmo.color);
}
/* -------------------------------------------------------------------- */
/** \name ED_gizmo_library specific API
* \{ */
-void ED_gizmotypes_snap_3d_draw_util(RegionView3D *rv3d,
- const float loc_prev[3],
- const float loc_curr[3],
- const float normal[3],
- const uchar color_line[4],
- const uchar color_point[4],
- const short snap_elem_type)
+SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene, wmGizmo *UNUSED(gz))
{
- if (!loc_prev && !loc_curr) {
- return;
- }
-
- float view_inv[4][4];
- copy_m4_m4(view_inv, rv3d->viewinv);
-
- /* The size of the circle is larger than the vertex size.
- * This prevents a drawing overlaps the other. */
- float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
-
- if (loc_curr) {
- immUniformColor4ubv(color_point);
- imm_drawcircball(loc_curr, ED_view3d_pixel_size(rv3d, loc_curr) * radius, view_inv, pos);
-
- /* draw normal if needed */
- if (normal) {
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, loc_curr);
- immVertex3f(pos, loc_curr[0] + normal[0], loc_curr[1] + normal[1], loc_curr[2] + normal[2]);
- immEnd();
- }
- }
-
- if (loc_prev) {
- /* Draw an "X" indicating where the previous snap point is.
- * This is useful for indicating perpendicular snap. */
-
- /* v1, v2, v3 and v4 indicate the coordinates of the ends of the "X". */
- float vx[3], vy[3], v1[3], v2[3], v3[3], v4[4];
-
- /* Multiply by 0.75f so that the final size of the "X" is close to that of
- * the circle.
- * (A closer value is 0.7071f, but we don't need to be exact here). */
- float x_size = 0.75f * radius * ED_view3d_pixel_size(rv3d, loc_prev);
-
- mul_v3_v3fl(vx, view_inv[0], x_size);
- mul_v3_v3fl(vy, view_inv[1], x_size);
-
- add_v3_v3v3(v1, vx, vy);
- sub_v3_v3v3(v2, vx, vy);
- negate_v3_v3(v3, v1);
- negate_v3_v3(v4, v2);
-
- add_v3_v3(v1, loc_prev);
- add_v3_v3(v2, loc_prev);
- add_v3_v3(v3, loc_prev);
- add_v3_v3(v4, loc_prev);
-
- immUniformColor4ubv(color_line);
- immBegin(GPU_PRIM_LINES, 4);
- immVertex3fv(pos, v3);
- immVertex3fv(pos, v1);
- immVertex3fv(pos, v4);
- immVertex3fv(pos, v2);
- immEnd();
-
- if (loc_curr && (snap_elem_type & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
- /* Dashed line. */
- immUnbindProgram();
-
- immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
- float viewport_size[4];
- GPU_viewport_size_get_f(viewport_size);
- immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
- immUniform1f("dash_width", 6.0f * U.pixelsize);
- immUniform1f("dash_factor", 1.0f / 4.0f);
- immUniformColor4ubv(color_line);
-
- immBegin(GPU_PRIM_LINES, 2);
- immVertex3fv(pos, loc_prev);
- immVertex3fv(pos, loc_curr);
- immEnd();
- }
- }
-
- immUnbindProgram();
-}
-
-SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene, wmGizmo *gz)
-{
- SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- if (snap_gizmo->snap_context_v3d == NULL) {
- snap_gizmo->snap_context_v3d = ED_transform_snap_object_context_create(scene, 0);
- }
- return snap_gizmo->snap_context_v3d;
+ ED_view3d_cursor_snap_activate_point();
+ return ED_view3d_cursor_snap_context_ensure(scene);
}
-void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, eSnapGizmo flag)
+void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, int flag)
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- snap_gizmo->flag |= flag;
+ snap_gizmo->cursor_handle->flag |= flag;
}
-void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, eSnapGizmo flag)
+void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, int flag)
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- snap_gizmo->flag &= ~flag;
+ snap_gizmo->cursor_handle->flag &= ~flag;
}
-bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, eSnapGizmo flag)
+bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, int flag)
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- return (snap_gizmo->flag & flag) != 0;
+ return (snap_gizmo->cursor_handle->flag & flag) != 0;
}
bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz)
{
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- return snap_gizmo->invert_snap;
-#else
- return false;
-#endif
+ return snap_gizmo->cursor_handle->is_snap_invert;
}
bool ED_gizmotypes_snap_3d_is_enabled(const wmGizmo *gz)
{
const SnapGizmo3D *snap_gizmo = (const SnapGizmo3D *)gz;
- return snap_gizmo->is_enabled;
+ return snap_gizmo->cursor_handle->is_enabled;
}
-short ED_gizmotypes_snap_3d_update(wmGizmo *gz,
- struct Depsgraph *depsgraph,
- const ARegion *region,
- const View3D *v3d,
- const wmWindowManager *wm,
- const float mval_fl[2])
+void ED_gizmotypes_snap_3d_data_get(const struct bContext *C,
+ wmGizmo *gz,
+ float r_loc[3],
+ float r_nor[3],
+ int r_elem_index[3],
+ int *r_snap_elem)
{
- SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- snap_gizmo->is_enabled = false;
-
- Scene *scene = DEG_get_input_scene(depsgraph);
-
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- if (!(snap_gizmo->flag & ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE)) {
- snap_gizmo->invert_snap = invert_snap(snap_gizmo, wm);
-
- const ToolSettings *ts = scene->toolsettings;
- if (snap_gizmo->invert_snap != !(ts->snap_flag & SCE_SNAP)) {
- snap_gizmo->snap_elem = 0;
- return 0;
- }
- }
-#endif
- eventstate_save_xy(snap_gizmo, wm);
-
- snap_gizmo->is_enabled = true;
-
- float co[3], no[3];
- short snap_elem = 0;
- int snap_elem_index[3] = {-1, -1, -1};
- int index = -1;
-
- ushort snap_elements = snap_gizmo_snap_elements(snap_gizmo);
-
- if (snap_elements) {
- float prev_co[3] = {0.0f};
- if (snap_gizmo->prevpoint) {
- copy_v3_v3(prev_co, snap_gizmo->prevpoint);
+ V3DSnapCursorData *snap_data = ((SnapGizmo3D *)gz)->cursor_handle;
+
+ if (C) {
+ /* Snap values are updated too late at the cursor. Be sure to update ahead of time. */
+ wmWindowManager *wm = CTX_wm_manager(C);
+ const wmEvent *event = wm->winactive ? wm->winactive->eventstate : NULL;
+ if (event) {
+ ARegion *region = CTX_wm_region(C);
+ int x = event->x - region->winrct.xmin;
+ int y = event->y - region->winrct.ymin;
+ ED_view3d_cursor_snap_update(C, x, y, snap_data);
}
- else {
- snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR;
- }
-
- eSnapSelect snap_select = (snap_gizmo->flag & ED_SNAPGIZMO_SNAP_ONLY_ACTIVE) ?
- SNAP_ONLY_ACTIVE :
- SNAP_ALL;
-
- eSnapEditType edit_mode_type = (snap_gizmo->flag & ED_SNAPGIZMO_SNAP_EDIT_GEOM_FINAL) ?
- SNAP_GEOM_FINAL :
- (snap_gizmo->flag & ED_SNAPGIZMO_SNAP_EDIT_GEOM_CAGE) ?
- SNAP_GEOM_CAGE :
- SNAP_GEOM_EDIT;
-
- bool use_occlusion_test = (snap_gizmo->flag & ED_SNAPGIZMO_OCCLUSION_ALWAYS_TRUE) ? false :
- true;
-
- float dist_px = 12.0f * U.pixelsize;
-
- ED_gizmotypes_snap_3d_context_ensure(scene, gz);
- snap_elem = ED_transform_snap_object_project_view3d_ex(
- snap_gizmo->snap_context_v3d,
- depsgraph,
- region,
- v3d,
- snap_elements,
- &(const struct SnapObjectParams){
- .snap_select = snap_select,
- .edit_mode_type = edit_mode_type,
- .use_occlusion_test = use_occlusion_test,
- },
- mval_fl,
- prev_co,
- &dist_px,
- co,
- no,
- &index,
- NULL,
- NULL);
}
- if (snap_elem == 0) {
- RegionView3D *rv3d = region->regiondata;
- ED_view3d_win_to_3d(v3d, region, rv3d->ofs, mval_fl, co);
- zero_v3(no);
- }
- else if (snap_elem == SCE_SNAP_MODE_VERTEX) {
- snap_elem_index[0] = index;
- }
- else if (snap_elem &
- (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
- snap_elem_index[1] = index;
- }
- else if (snap_elem == SCE_SNAP_MODE_FACE) {
- snap_elem_index[2] = index;
- }
-
- snap_gizmo->snap_elem = snap_elem;
- copy_v3_v3(snap_gizmo->loc, co);
- copy_v3_v3(snap_gizmo->nor, no);
- copy_v3_v3_int(snap_gizmo->elem_index, snap_elem_index);
-
- return snap_elem;
-}
-
-void ED_gizmotypes_snap_3d_data_get(
- wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], int *r_snap_elem)
-{
- SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- BLI_assert(snap_gizmo->is_enabled);
if (r_loc) {
- copy_v3_v3(r_loc, snap_gizmo->loc);
+ copy_v3_v3(r_loc, snap_data->loc);
}
if (r_nor) {
- copy_v3_v3(r_nor, snap_gizmo->nor);
+ copy_v3_v3(r_nor, snap_data->nor);
}
if (r_elem_index) {
- copy_v3_v3_int(r_elem_index, snap_gizmo->elem_index);
+ copy_v3_v3_int(r_elem_index, snap_data->elem_index);
}
if (r_snap_elem) {
- *r_snap_elem = snap_gizmo->snap_elem;
+ *r_snap_elem = snap_data->snap_elem;
}
}
@@ -450,115 +152,80 @@ void ED_gizmotypes_snap_3d_data_get(
/** \name RNA callbacks
* \{ */
-/* Based on 'rna_GizmoProperties_find_operator'. */
-static struct SnapGizmo3D *gizmo_snap_rna_find_operator(PointerRNA *ptr)
-{
- IDProperty *properties = ptr->data;
- for (bScreen *screen = G_MAIN->screens.first; screen; screen = screen->id.next) {
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- if (area->spacetype != SPACE_VIEW3D) {
- continue;
- }
- LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
- if (region->regiontype == RGN_TYPE_WINDOW && region->gizmo_map) {
- wmGizmoMap *gzmap = region->gizmo_map;
- LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(gzmap)) {
- LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
- if (gz->properties == properties) {
- return (SnapGizmo3D *)gz;
- }
- }
- }
- }
- }
- }
- }
- return NULL;
-}
-
-static int gizmo_snap_rna_snap_elements_force_get_fn(struct PointerRNA *ptr,
+static int gizmo_snap_rna_snap_elements_force_get_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop))
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- return snap_gizmo->snap_elem_force;
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ return snap_data->snap_elem_force;
}
return 0;
}
-static void gizmo_snap_rna_snap_elements_force_set_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_snap_elements_force_set_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
int value)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- snap_gizmo->snap_elem_force = (short)value;
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ snap_data->snap_elem_force = (short)value;
}
}
-static void gizmo_snap_rna_prevpoint_get_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_prevpoint_get_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
float *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- copy_v3_v3(values, snap_gizmo->prevpoint_stack);
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data && snap_data->prevpoint) {
+ copy_v3_v3(values, snap_data->prevpoint);
}
}
-static void gizmo_snap_rna_prevpoint_set_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_prevpoint_set_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
const float *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- if (values) {
- copy_v3_v3(snap_gizmo->prevpoint_stack, values);
- snap_gizmo->prevpoint = snap_gizmo->prevpoint_stack;
- }
- else {
- snap_gizmo->prevpoint = NULL;
- }
- }
+ ED_view3d_cursor_snap_prevpoint_set(values);
}
-static void gizmo_snap_rna_location_get_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_location_get_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
float *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- copy_v3_v3(values, snap_gizmo->loc);
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ copy_v3_v3(values, snap_data->loc);
}
}
-static void gizmo_snap_rna_location_set_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_location_set_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
const float *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- copy_v3_v3(snap_gizmo->loc, values);
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ copy_v3_v3(snap_data->loc, values);
}
}
-static void gizmo_snap_rna_normal_get_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_normal_get_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
float *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- copy_v3_v3(values, snap_gizmo->nor);
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ copy_v3_v3(values, snap_data->nor);
}
}
-static void gizmo_snap_rna_snap_elem_index_get_fn(struct PointerRNA *ptr,
+static void gizmo_snap_rna_snap_elem_index_get_fn(struct PointerRNA *UNUSED(ptr),
struct PropertyRNA *UNUSED(prop),
int *values)
{
- SnapGizmo3D *snap_gizmo = gizmo_snap_rna_find_operator(ptr);
- if (snap_gizmo) {
- copy_v3_v3_int(values, snap_gizmo->elem_index);
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (snap_data) {
+ copy_v3_v3_int(values, snap_data->elem_index);
}
}
@@ -571,91 +238,44 @@ static void gizmo_snap_rna_snap_elem_index_get_fn(struct PointerRNA *ptr,
static void snap_gizmo_setup(wmGizmo *gz)
{
gz->flag |= WM_GIZMO_NO_TOOLTIP;
-
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- wmKeyConfig *keyconf = gz->parent_gzgroup->type->keyconf;
- if (!keyconf) {
- /* It can happen when gizmo-group-type is not linked at startup. */
- keyconf = ((wmWindowManager *)G.main->wm.first)->defaultconf;
- }
- snap_gizmo->keymap = WM_modalkeymap_find(keyconf, "Generic Gizmo Tweak Modal Map");
- RNA_enum_value_from_id(snap_gizmo->keymap->modal_items, "SNAP_ON", &snap_gizmo->snap_on);
-#endif
+ ED_view3d_cursor_snap_activate_point();
+ snap_gizmo->cursor_handle = ED_view3d_cursor_snap_data_get();
}
-static void snap_gizmo_draw(const bContext *C, wmGizmo *gz)
+static void snap_gizmo_draw(const bContext *UNUSED(C), wmGizmo *UNUSED(gz))
{
- SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- if (snap_gizmo->snap_elem == 0) {
- return;
- }
-
- wmWindowManager *wm = CTX_wm_manager(C);
- 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;
- }
-
- RegionView3D *rv3d = CTX_wm_region_data(C);
- if (rv3d->rflag & RV3D_NAVIGATING) {
- /* Don't draw the gizmo while navigating. It can be distracting. */
- snap_gizmo->snap_elem = 0;
- return;
- }
-
- uchar color_line[4], color_point[4];
- UI_GetThemeColor3ubv(TH_TRANSFORM, color_line);
- color_line[3] = 128;
-
- rgba_float_to_uchar(color_point, gz->color);
-
- GPU_line_smooth(false);
-
- GPU_line_width(1.0f);
-
- const float *prev_point = (snap_gizmo_snap_elements(snap_gizmo) &
- SCE_SNAP_MODE_EDGE_PERPENDICULAR) ?
- snap_gizmo->prevpoint :
- NULL;
-
- ED_gizmotypes_snap_3d_draw_util(
- rv3d, prev_point, snap_gizmo->loc, NULL, color_line, color_point, snap_gizmo->snap_elem);
+ /* All drawing is handled at the paint cursor. */
}
static int snap_gizmo_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- wmWindowManager *wm = CTX_wm_manager(C);
- ARegion *region = CTX_wm_region(C);
-
- /* FIXME: this hack is to ignore drag events, otherwise drag events
- * cause momentary snap gizmo re-positioning at the drag-start location, see: T87511. */
- if (wm && wm->winactive) {
- const wmEvent *event = wm->winactive->eventstate;
- int mval_compare[2] = {event->x - region->winrct.xmin, event->y - region->winrct.ymin};
- if (!equals_v2v2_int(mval_compare, mval)) {
- return snap_gizmo->snap_elem ? 0 : -1;
- }
- }
+ V3DSnapCursorData *snap_data = snap_gizmo->cursor_handle;
- if (!eventstate_has_changed(snap_gizmo, wm)) {
- /* Performance, do not update. */
- return snap_gizmo->snap_elem ? 0 : -1;
- }
+ /* Snap Elements can change while the gizmo is active. Need to be updated somewhere. */
+ snap_gizmo_snap_elements_update(snap_gizmo);
- View3D *v3d = CTX_wm_view3d(C);
- const float mval_fl[2] = {UNPACK2(mval)};
- short snap_elem = ED_gizmotypes_snap_3d_update(
- gz, CTX_data_ensure_evaluated_depsgraph(C), region, v3d, wm, mval_fl);
+ /* Snap values are updated too late at the cursor. Be sure to update ahead of time. */
+ int x, y;
+ {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ const wmEvent *event = wm->winactive ? wm->winactive->eventstate : NULL;
+ if (event) {
+ ARegion *region = CTX_wm_region(C);
+ x = event->x - region->winrct.xmin;
+ y = event->y - region->winrct.ymin;
+ }
+ else {
+ x = mval[0];
+ y = mval[1];
+ }
+ }
+ ED_view3d_cursor_snap_update(C, x, y, snap_data);
- if (snap_elem) {
- ED_region_tag_redraw_editor_overlays(region);
+ if (snap_data && snap_data->snap_elem) {
return 0;
}
-
return -1;
}
@@ -677,9 +297,9 @@ static int snap_gizmo_invoke(bContext *UNUSED(C),
static void snap_gizmo_free(wmGizmo *gz)
{
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
- if (snap_gizmo->snap_context_v3d) {
- ED_transform_snap_object_context_destroy(snap_gizmo->snap_context_v3d);
- snap_gizmo->snap_context_v3d = NULL;
+ V3DSnapCursorData *snap_data = snap_gizmo->cursor_handle;
+ if (snap_data) {
+ ED_view3d_cursor_snap_deactivate_point();
}
}
@@ -719,7 +339,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE,
"Snap Elements",
"");
-
RNA_def_property_enum_funcs_runtime(prop,
gizmo_snap_rna_snap_elements_force_get_fn,
gizmo_snap_rna_snap_elements_force_set_fn,
@@ -735,7 +354,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
"Point that defines the location of the perpendicular snap",
FLT_MIN,
FLT_MAX);
-
RNA_def_property_float_array_funcs_runtime(
prop, gizmo_snap_rna_prevpoint_get_fn, gizmo_snap_rna_prevpoint_set_fn, NULL);
@@ -750,7 +368,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
"Snap Point Location",
FLT_MIN,
FLT_MAX);
-
RNA_def_property_float_array_funcs_runtime(
prop, gizmo_snap_rna_location_get_fn, gizmo_snap_rna_location_set_fn, NULL);
@@ -764,7 +381,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
"Snap Point Normal",
FLT_MIN,
FLT_MAX);
-
RNA_def_property_float_array_funcs_runtime(prop, gizmo_snap_rna_normal_get_fn, NULL, NULL);
prop = RNA_def_int_vector(gzt->srna,
@@ -777,7 +393,6 @@ static void GIZMO_GT_snap_3d(wmGizmoType *gzt)
"Array index of face, edge and vert snapped",
INT_MIN,
INT_MAX);
-
RNA_def_property_int_array_funcs_runtime(
prop, gizmo_snap_rna_snap_elem_index_get_fn, NULL, NULL);
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index 9bef5a17d12..4d922162ee9 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -41,11 +41,7 @@ void ED_gizmotypes_primitive_3d(void);
void ED_gizmotypes_blank_3d(void);
void ED_gizmotypes_snap_3d(void);
-struct ARegion;
-struct Depsgraph;
struct Object;
-struct SnapObjectContext;
-struct View3D;
struct bContext;
struct wmGizmo;
struct wmWindowManager;
@@ -248,41 +244,22 @@ void ED_gizmotypes_dial_3d_draw_util(const float matrix_basis[4][4],
struct Dial3dParams *params);
/* snap3d_gizmo.c */
-#define USE_SNAP_DETECT_FROM_KEYMAP_HACK
-void ED_gizmotypes_snap_3d_draw_util(struct RegionView3D *rv3d,
- const float loc_prev[3],
- const float loc_curr[3],
- const float normal[3],
- const uchar color_line[4],
- const uchar color_point[4],
- const short snap_elem_type);
struct SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(struct Scene *scene,
struct wmGizmo *gz);
-typedef enum {
- ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE = 1 << 0,
- ED_SNAPGIZMO_OCCLUSION_ALWAYS_TRUE = 1 << 1,
- ED_SNAPGIZMO_OCCLUSION_ALWAYS_FALSE = 1 << 2, /* TODO. */
- ED_SNAPGIZMO_SNAP_ONLY_ACTIVE = 1 << 3,
- ED_SNAPGIZMO_SNAP_EDIT_GEOM_FINAL = 1 << 4,
- ED_SNAPGIZMO_SNAP_EDIT_GEOM_CAGE = 1 << 5,
-} eSnapGizmo;
-
-void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, eSnapGizmo flag);
-void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, eSnapGizmo flag);
-bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, eSnapGizmo flag);
+void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, int flag);
+void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, int flag);
+bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, int flag);
bool ED_gizmotypes_snap_3d_invert_snap_get(struct wmGizmo *gz);
bool ED_gizmotypes_snap_3d_is_enabled(const struct wmGizmo *gz);
-short ED_gizmotypes_snap_3d_update(struct wmGizmo *gz,
- struct Depsgraph *depsgraph,
- const struct ARegion *region,
- const struct View3D *v3d,
- const struct wmWindowManager *wm,
- const float mval_fl[2]);
-void ED_gizmotypes_snap_3d_data_get(
- struct wmGizmo *gz, float r_loc[3], float r_nor[3], int r_elem_index[3], int *r_snap_elem);
+void ED_gizmotypes_snap_3d_data_get(const struct bContext *C,
+ struct wmGizmo *gz,
+ float r_loc[3],
+ float r_nor[3],
+ int r_elem_index[3],
+ int *r_snap_elem);
#ifdef __cplusplus
}
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 7311303d7cd..7002db163b6 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -139,7 +139,8 @@ short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
float r_no[3],
int *r_index,
struct Object **r_ob,
- float r_obmat[4][4]);
+ float r_obmat[4][4],
+ float r_face_nor[3]);
bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
struct Depsgraph *depsgraph,
const ARegion *region,
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index cf8dcbd7995..593d1be9444 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -52,6 +52,7 @@ struct RegionView3D;
struct RenderEngineType;
struct Scene;
struct ScrArea;
+struct SnapObjectContext;
struct View3D;
struct ViewContext;
struct ViewLayer;
@@ -228,6 +229,73 @@ typedef enum {
(V3D_PROJ_TEST_CLIP_CONTENT | V3D_PROJ_TEST_CLIP_NEAR | V3D_PROJ_TEST_CLIP_FAR | \
V3D_PROJ_TEST_CLIP_WIN)
+/* view3d_cursor_snap.c */
+#define USE_SNAP_DETECT_FROM_KEYMAP_HACK
+typedef enum {
+ V3D_SNAPCURSOR_TOGGLE_ALWAYS_TRUE = 1 << 0,
+ V3D_SNAPCURSOR_OCCLUSION_ALWAYS_TRUE = 1 << 1,
+ V3D_SNAPCURSOR_OCCLUSION_ALWAYS_FALSE = 1 << 2, /* TODO. */
+ V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE = 1 << 3,
+ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL = 1 << 4,
+ V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE = 1 << 5,
+} eV3DSnapCursor;
+
+typedef enum {
+ V3D_PLACE_DEPTH_SURFACE = 0,
+ V3D_PLACE_DEPTH_CURSOR_PLANE = 1,
+ V3D_PLACE_DEPTH_CURSOR_VIEW = 2,
+} eV3DPlaceDepth;
+
+typedef enum {
+ V3D_PLACE_ORIENT_SURFACE = 0,
+ V3D_PLACE_ORIENT_DEFAULT = 1,
+} eV3DPlaceOrient;
+
+typedef struct V3DSnapCursorData {
+ /* Setup. */
+ eV3DSnapCursor flag;
+ eV3DPlaceDepth plane_depth;
+ eV3DPlaceOrient plane_orient;
+ uchar color_line[4];
+ uchar color_point[4];
+ float *prevpoint;
+ short snap_elem_force; /* If zero, use scene settings. */
+ short plane_axis;
+ bool use_plane_axis_auto;
+
+ /* Return values. */
+ short snap_elem;
+ float loc[3];
+ float nor[3];
+ float face_nor[3];
+ float obmat[4][4];
+ int elem_index[3];
+ float plane_omat[3][3];
+ bool is_snap_invert;
+
+ /** Enabled when snap is activated, even if it didn't find anything. */
+ bool is_enabled;
+} V3DSnapCursorData;
+
+V3DSnapCursorData *ED_view3d_cursor_snap_data_get(void);
+void ED_view3d_cursor_snap_activate_point(void);
+void ED_view3d_cursor_snap_activate_plane(void);
+void ED_view3d_cursor_snap_deactivate_point(void);
+void ED_view3d_cursor_snap_deactivate_plane(void);
+void ED_view3d_cursor_snap_update(const struct bContext *C,
+ const int x,
+ const int y,
+ V3DSnapCursorData *snap_data);
+void ED_view3d_cursor_snap_prevpoint_set(const float prev_point[3]);
+struct SnapObjectContext *ED_view3d_cursor_snap_context_ensure(struct Scene *scene);
+void ED_view3d_cursor_snap_draw_util(struct RegionView3D *rv3d,
+ const float loc_prev[3],
+ const float loc_curr[3],
+ const float normal[3],
+ const uchar color_line[4],
+ const uchar color_point[4],
+ const short snap_elem_type);
+
/* view3d_iterators.c */
/* foreach iterators */
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index fe84a3b8ae9..19f869ed50b 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -44,6 +44,7 @@ set(SRC
space_view3d.c
view3d_buttons.c
view3d_camera_control.c
+ view3d_cursor_snap.c
view3d_draw.c
view3d_edit.c
view3d_gizmo_armature.c
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 787cf529483..83aa2d93fbb 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -355,6 +355,10 @@ 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
new file mode 100644
index 00000000000..03aa9316a38
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_cursor_snap.c
@@ -0,0 +1,954 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup wm
+ *
+ * \brief Snap cursor.
+ */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_object.h"
+#include "BKE_scene.h"
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_transform_snap_object_context.h"
+#include "ED_view3d.h"
+
+#include "UI_resources.h"
+
+#include "RNA_access.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "WM_api.h"
+#include "wm.h"
+
+typedef struct SnapCursorDataIntern {
+ /* Keep as first member. */
+ struct V3DSnapCursorData snap_data;
+
+ struct SnapObjectContext *snap_context_v3d;
+ float prevpoint_stack[3];
+ short snap_elem_hidden;
+
+ /* Copy of the parameters of the last event state in order to detect updates. */
+ struct {
+ int x;
+ int y;
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ short shift, ctrl, alt, oskey;
+#endif
+ } last_eventstate;
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ struct wmKeyMap *keymap;
+ int snap_on;
+#endif
+
+ struct wmPaintCursor *handle;
+
+ bool draw_point;
+ bool draw_plane;
+} SnapCursorDataIntern;
+
+/**
+ * Calculate a 3x3 orientation matrix from the surface under the cursor.
+ */
+static void cursor_poject_surface_normal(const float normal[3],
+ const float obmat[4][4],
+ float r_mat[3][3])
+{
+ float mat[3][3];
+ copy_m3_m4(mat, obmat);
+ normalize_m3(mat);
+
+ float dot_best = fabsf(dot_v3v3(mat[0], normal));
+ int i_best = 0;
+ for (int i = 1; i < 3; i++) {
+ float dot_test = fabsf(dot_v3v3(mat[i], normal));
+ if (dot_test > dot_best) {
+ i_best = i;
+ dot_best = dot_test;
+ }
+ }
+ if (dot_v3v3(mat[i_best], normal) < 0.0f) {
+ negate_v3(mat[(i_best + 1) % 3]);
+ negate_v3(mat[(i_best + 2) % 3]);
+ }
+ copy_v3_v3(mat[i_best], normal);
+ orthogonalize_m3(mat, i_best);
+ normalize_m3(mat);
+
+ copy_v3_v3(r_mat[0], mat[(i_best + 1) % 3]);
+ copy_v3_v3(r_mat[1], mat[(i_best + 2) % 3]);
+ copy_v3_v3(r_mat[2], mat[i_best]);
+}
+
+/**
+ * Calculate 3D view incremental (grid) snapping.
+ *
+ * \note This could be moved to a public function.
+ */
+static bool cursor_snap_calc_incremental(
+ Scene *scene, View3D *v3d, ARegion *region, const float co_relative[3], float co[3])
+{
+ const float grid_size = ED_view3d_grid_view_scale(scene, v3d, region, NULL);
+ if (UNLIKELY(grid_size == 0.0f)) {
+ return false;
+ }
+
+ if (scene->toolsettings->snap_flag & SCE_SNAP_ABS_GRID) {
+ co_relative = NULL;
+ }
+
+ if (co_relative != NULL) {
+ sub_v3_v3(co, co_relative);
+ }
+ mul_v3_fl(co, 1.0f / grid_size);
+ co[0] = roundf(co[0]);
+ co[1] = roundf(co[1]);
+ co[2] = roundf(co[2]);
+ mul_v3_fl(co, grid_size);
+ if (co_relative != NULL) {
+ add_v3_v3(co, co_relative);
+ }
+
+ return true;
+}
+
+/**
+ * Re-order \a mat so \a axis_align uses its own axis which is closest to \a v.
+ */
+static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
+{
+ float dot_best = -1.0f;
+ int axis_found = axis_align;
+ for (int i = 0; i < 3; i++) {
+ const float dot_test = fabsf(dot_v3v3(mat[i], v));
+ if (dot_test > dot_best) {
+ dot_best = dot_test;
+ axis_found = i;
+ }
+ }
+
+ if (axis_align != axis_found) {
+ float tmat[3][3];
+ copy_m3_m3(tmat, mat);
+ const int offset = mod_i(axis_found - axis_align, 3);
+ for (int i = 0; i < 3; i++) {
+ copy_v3_v3(mat[i], tmat[(i + offset) % 3]);
+ }
+ return true;
+ }
+ return false;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Drawings
+ * \{ */
+
+static void cursor_plane_draw_grid(const int resolution,
+ const float scale,
+ const float scale_fade,
+ const float matrix[4][4],
+ const int plane_axis,
+ const float color[4])
+{
+ BLI_assert(scale_fade <= scale);
+ const int resolution_min = resolution - 1;
+ float color_fade[4] = {UNPACK4(color)};
+ const float *center = matrix[3];
+
+ GPU_blend(GPU_BLEND_ADDITIVE);
+ GPU_line_smooth(true);
+ GPU_line_width(1.0f);
+
+ GPUVertFormat *format = immVertexFormat();
+ const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ const uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+
+ const size_t coords_len = resolution * resolution;
+ float(*coords)[3] = MEM_mallocN(sizeof(*coords) * coords_len, __func__);
+
+ const int axis_x = (plane_axis + 0) % 3;
+ const int axis_y = (plane_axis + 1) % 3;
+ const int axis_z = (plane_axis + 2) % 3;
+
+ int i;
+ const float resolution_div = (float)1.0f / (float)resolution;
+ i = 0;
+ for (int x = 0; x < resolution; x++) {
+ const float x_fl = (x * resolution_div) - 0.5f;
+ for (int y = 0; y < resolution; y++) {
+ const float y_fl = (y * resolution_div) - 0.5f;
+ coords[i][axis_x] = 0.0f;
+ coords[i][axis_y] = x_fl * scale;
+ coords[i][axis_z] = y_fl * scale;
+ mul_m4_v3(matrix, coords[i]);
+ i += 1;
+ }
+ }
+ BLI_assert(i == coords_len);
+ immBeginAtMost(GPU_PRIM_LINES, coords_len * 4);
+ i = 0;
+ for (int x = 0; x < resolution_min; x++) {
+ for (int y = 0; y < resolution_min; y++) {
+
+ /* Add #resolution_div to ensure we fade-out entirely. */
+#define FADE(v) \
+ max_ff(0.0f, (1.0f - square_f(((len_v3v3(v, center) / scale_fade) + resolution_div) * 2.0f)))
+
+ const float *v0 = coords[(resolution * x) + y];
+ const float *v1 = coords[(resolution * (x + 1)) + y];
+ const float *v2 = coords[(resolution * x) + (y + 1)];
+
+ const float f0 = FADE(v0);
+ const float f1 = FADE(v1);
+ const float f2 = FADE(v2);
+
+ if (f0 > 0.0f || f1 > 0.0f) {
+ color_fade[3] = color[3] * f0;
+ immAttr4fv(col_id, color_fade);
+ immVertex3fv(pos_id, v0);
+ color_fade[3] = color[3] * f1;
+ immAttr4fv(col_id, color_fade);
+ immVertex3fv(pos_id, v1);
+ }
+ if (f0 > 0.0f || f2 > 0.0f) {
+ color_fade[3] = color[3] * f0;
+ immAttr4fv(col_id, color_fade);
+ immVertex3fv(pos_id, v0);
+
+ color_fade[3] = color[3] * f2;
+ immAttr4fv(col_id, color_fade);
+ immVertex3fv(pos_id, v2);
+ }
+
+#undef FADE
+
+ i++;
+ }
+ }
+
+ MEM_freeN(coords);
+
+ immEnd();
+
+ immUnbindProgram();
+
+ GPU_line_smooth(false);
+ GPU_blend(GPU_BLEND_NONE);
+}
+
+static void cursor_plane_draw(const RegionView3D *rv3d,
+ const int plane_axis,
+ const float matrix[4][4])
+{
+ /* Draw */
+ float pixel_size;
+
+ if (rv3d->is_persp) {
+ float center[3];
+ negate_v3_v3(center, rv3d->ofs);
+ pixel_size = ED_view3d_pixel_size(rv3d, center);
+ }
+ else {
+ pixel_size = ED_view3d_pixel_size(rv3d, matrix[3]);
+ }
+
+ if (pixel_size > FLT_EPSILON) {
+
+ /* Arbitrary, 1.0 is a little too strong though. */
+ float color_alpha = 0.75f;
+ if (rv3d->is_persp) {
+ /* Scale down the alpha when this is drawn very small,
+ * since the add shader causes the small size to show too dense & bright. */
+ const float relative_pixel_scale = pixel_size / ED_view3d_pixel_size(rv3d, matrix[3]);
+ if (relative_pixel_scale < 1.0f) {
+ color_alpha *= max_ff(square_f(relative_pixel_scale), 0.3f);
+ }
+ }
+
+ {
+ /* Extra adjustment when it's near view-aligned as it seems overly bright. */
+ float view_vector[3];
+ ED_view3d_global_to_vector(rv3d, matrix[3], view_vector);
+ float view_dot = fabsf(dot_v3v3(matrix[plane_axis], view_vector));
+ color_alpha *= max_ff(0.3f, 1.0f - square_f(square_f(1.0f - view_dot)));
+ }
+
+ const float scale_mod = U.gizmo_size * 2 * U.dpi_fac / U.pixelsize;
+
+ float final_scale = (scale_mod * pixel_size);
+
+ const int lines_subdiv = 10;
+ int lines = lines_subdiv;
+
+ float final_scale_fade = final_scale;
+ final_scale = ceil_power_of_10(final_scale);
+
+ float fac = final_scale_fade / final_scale;
+
+ float color[4] = {1, 1, 1, color_alpha};
+ color[3] *= square_f(1.0f - fac);
+ if (color[3] > 0.0f) {
+ cursor_plane_draw_grid(
+ lines * lines_subdiv, final_scale, final_scale_fade, matrix, plane_axis, color);
+ }
+
+ color[3] = color_alpha;
+ /* When the grid is large, we only need the 2x lines in the middle. */
+ if (fac < 0.2f) {
+ lines = 1;
+ final_scale = final_scale_fade;
+ }
+ cursor_plane_draw_grid(lines, final_scale, final_scale_fade, matrix, plane_axis, color);
+ }
+}
+
+void ED_view3d_cursor_snap_draw_util(RegionView3D *rv3d,
+ const float loc_prev[3],
+ const float loc_curr[3],
+ const float normal[3],
+ const uchar color_line[4],
+ const uchar color_point[4],
+ const short snap_elem_type)
+{
+ if (!loc_prev && !loc_curr) {
+ return;
+ }
+
+ float view_inv[4][4];
+ copy_m4_m4(view_inv, rv3d->viewinv);
+
+ /* The size of the circle is larger than the vertex size.
+ * This prevents a drawing overlaps the other. */
+ float radius = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (loc_curr) {
+ immUniformColor4ubv(color_point);
+ imm_drawcircball(loc_curr, ED_view3d_pixel_size(rv3d, loc_curr) * radius, view_inv, pos);
+
+ /* draw normal if needed */
+ if (normal) {
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, loc_curr);
+ immVertex3f(pos, loc_curr[0] + normal[0], loc_curr[1] + normal[1], loc_curr[2] + normal[2]);
+ immEnd();
+ }
+ }
+
+ if (loc_prev) {
+ /* Draw an "X" indicating where the previous snap point is.
+ * This is useful for indicating perpendicular snap. */
+
+ /* v1, v2, v3 and v4 indicate the coordinates of the ends of the "X". */
+ float vx[3], vy[3], v1[3], v2[3], v3[3], v4[4];
+
+ /* Multiply by 0.75f so that the final size of the "X" is close to that of
+ * the circle.
+ * (A closer value is 0.7071f, but we don't need to be exact here). */
+ float x_size = 0.75f * radius * ED_view3d_pixel_size(rv3d, loc_prev);
+
+ mul_v3_v3fl(vx, view_inv[0], x_size);
+ mul_v3_v3fl(vy, view_inv[1], x_size);
+
+ add_v3_v3v3(v1, vx, vy);
+ sub_v3_v3v3(v2, vx, vy);
+ negate_v3_v3(v3, v1);
+ negate_v3_v3(v4, v2);
+
+ add_v3_v3(v1, loc_prev);
+ add_v3_v3(v2, loc_prev);
+ add_v3_v3(v3, loc_prev);
+ add_v3_v3(v4, loc_prev);
+
+ immUniformColor4ubv(color_line);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ if (loc_curr && (snap_elem_type & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ /* Dashed line. */
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2], viewport_size[3]);
+ immUniform1f("dash_width", 6.0f * U.pixelsize);
+ immUniform1f("dash_factor", 1.0f / 4.0f);
+ immUniformColor4ubv(color_line);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, loc_prev);
+ immVertex3fv(pos, loc_curr);
+ immEnd();
+ }
+ }
+
+ immUnbindProgram();
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Event State
+ * \{ */
+
+/* Checks if the current event is different from the one captured in the last update. */
+static bool eventstate_has_changed(SnapCursorDataIntern *sdata_intern,
+ 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)) {
+ 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)) {
+ return true;
+ }
+ }
+#endif
+ }
+ return false;
+}
+
+/* Copies the current eventstate. */
+static void eventstate_save_xy(SnapCursorDataIntern *cursor_snap, const int x, const int y)
+{
+ cursor_snap->last_eventstate.x = x;
+ cursor_snap->last_eventstate.y = y;
+}
+
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+static bool invert_snap(SnapCursorDataIntern *sdata_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)) {
+ /* Nothing has changed. */
+ return sdata_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;
+
+ const int snap_on = sdata_intern->snap_on;
+
+ wmKeyMap *keymap = WM_keymap_active(wm, sdata_intern->keymap);
+ for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
+ if (kmi->flag & KMI_INACTIVE) {
+ continue;
+ }
+
+ if (kmi->propvalue == snap_on) {
+ if ((ELEM(kmi->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY) && event->ctrl) ||
+ (ELEM(kmi->type, EVT_LEFTSHIFTKEY, EVT_RIGHTSHIFTKEY) && event->shift) ||
+ (ELEM(kmi->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY) && event->alt) ||
+ ((kmi->type == EVT_OSKEY) && event->oskey)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+#endif
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Update
+ * \{ */
+
+static short cursor_snap_elements(V3DSnapCursorData *cursor_snap, Scene *scene)
+{
+ short snap_elements = cursor_snap->snap_elem_force;
+ if (!snap_elements) {
+ return scene->toolsettings->snap_mode;
+ }
+ return snap_elements;
+}
+
+static void wm_paint_cursor_snap_context_ensure(SnapCursorDataIntern *sdata_intern, Scene *scene)
+{
+ if (sdata_intern->snap_context_v3d == NULL) {
+ sdata_intern->snap_context_v3d = ED_transform_snap_object_context_create(scene, 0);
+ }
+}
+
+static void cursor_snap_update(const bContext *C,
+ wmWindowManager *wm,
+ Depsgraph *depsgraph,
+ Scene *scene,
+ ARegion *region,
+ View3D *v3d,
+ int x,
+ int y,
+ SnapCursorDataIntern *sdata_intern)
+{
+ wm_paint_cursor_snap_context_ensure(sdata_intern, scene);
+ V3DSnapCursorData *snap_data = (V3DSnapCursorData *)sdata_intern;
+
+ float co[3], no[3], face_nor[3], obmat[4][4], omat[3][3];
+ short snap_elem = 0;
+ int snap_elem_index[3] = {-1, -1, -1};
+ int index = -1;
+
+ const float mval_fl[2] = {x, y};
+ zero_v3(no);
+ zero_v3(face_nor);
+ unit_m3(omat);
+
+ ushort snap_elements = cursor_snap_elements(snap_data, scene);
+ sdata_intern->snap_elem_hidden = 0;
+ const bool draw_plane = sdata_intern->draw_plane;
+ if (draw_plane && !(snap_elements & SCE_SNAP_MODE_FACE)) {
+ sdata_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 = invert_snap(sdata_intern, wm);
+
+ const ToolSettings *ts = scene->toolsettings;
+ if (snap_data->is_snap_invert != !(ts->snap_flag & SCE_SNAP)) {
+ snap_data->is_enabled = false;
+ if (!draw_plane) {
+ snap_data->snap_elem = 0;
+ return;
+ }
+ snap_elements = sdata_intern->snap_elem_hidden = SCE_SNAP_MODE_FACE;
+ }
+ }
+#endif
+
+ 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);
+ }
+ else {
+ snap_elements &= ~SCE_SNAP_MODE_EDGE_PERPENDICULAR;
+ }
+
+ eSnapSelect snap_select = (snap_data->flag & V3D_SNAPCURSOR_SNAP_ONLY_ACTIVE) ?
+ SNAP_ONLY_ACTIVE :
+ SNAP_ALL;
+
+ eSnapEditType edit_mode_type = (snap_data->flag & V3D_SNAPCURSOR_SNAP_EDIT_GEOM_FINAL) ?
+ SNAP_GEOM_FINAL :
+ (snap_data->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;
+
+ float dist_px = 12.0f * U.pixelsize;
+
+ snap_elem = ED_transform_snap_object_project_view3d_ex(
+ sdata_intern->snap_context_v3d,
+ depsgraph,
+ region,
+ v3d,
+ snap_elements,
+ &(const struct SnapObjectParams){
+ .snap_select = snap_select,
+ .edit_mode_type = edit_mode_type,
+ .use_occlusion_test = use_occlusion_test,
+ },
+ mval_fl,
+ prev_co,
+ &dist_px,
+ co,
+ no,
+ &index,
+ NULL,
+ obmat,
+ face_nor);
+ }
+
+ if (is_zero_v3(face_nor)) {
+ face_nor[snap_data->plane_axis] = 1.0f;
+ }
+
+ if (draw_plane) {
+ bool orient_surface = snap_elem && (snap_data->plane_orient == V3D_PLACE_ORIENT_SURFACE);
+ if (orient_surface) {
+ copy_m3_m4(omat, obmat);
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ const short orient_index = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
+ ED_transform_calc_orientation_from_type_ex(
+ 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]);
+ }
+ }
+
+ /* Non-orthogonal matrices cause the preview and final result not to match.
+ *
+ * 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);
+
+ if (orient_surface) {
+ cursor_poject_surface_normal(snap_data->face_nor, obmat, omat);
+ }
+ }
+
+ float *co_depth = snap_elem ? co : scene->cursor.location;
+ snap_elem &= ~sdata_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];
+ plane_from_point_normal_v3(plane, co_depth, plane_normal);
+ }
+
+ if ((snap_data->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)) {
+ cursor_snap_calc_incremental(scene, v3d, region, snap_data->prevpoint, co);
+ }
+ }
+ else if (snap_elem == SCE_SNAP_MODE_VERTEX) {
+ snap_elem_index[0] = index;
+ }
+ else if (snap_elem &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ snap_elem_index[1] = index;
+ }
+ else if (snap_elem == SCE_SNAP_MODE_FACE) {
+ snap_elem_index[2] = index;
+ }
+
+ snap_data->snap_elem = snap_elem;
+ copy_v3_v3(snap_data->loc, co);
+ copy_v3_v3(snap_data->nor, no);
+ copy_v3_v3(snap_data->face_nor, face_nor);
+ copy_m4_m4(snap_data->obmat, obmat);
+ copy_v3_v3_int(snap_data->elem_index, snap_elem_index);
+
+ copy_m3_m3(snap_data->plane_omat, omat);
+
+ eventstate_save_xy(sdata_intern, x, y);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks
+ * \{ */
+
+static bool cursor_snap_pool_fn(bContext *C)
+{
+ if (G.moving) {
+ return false;
+ }
+
+ ARegion *region = CTX_wm_region(C);
+ if (region->regiontype != RGN_TYPE_WINDOW) {
+ return false;
+ }
+
+ ScrArea *area = CTX_wm_area(C);
+ if (area->spacetype != SPACE_VIEW3D) {
+ return false;
+ }
+
+ RegionView3D *rv3d = region->regiondata;
+ if (rv3d->rflag & RV3D_NAVIGATING) {
+ /* Don't draw the cursor while navigating. It can be distracting. */
+ return false;
+ };
+
+ return true;
+}
+
+static void cursor_snap_draw_fn(bContext *C, int x, int y, void *customdata)
+{
+ V3DSnapCursorData *snap_data = customdata;
+ SnapCursorDataIntern *sdata_intern = customdata;
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ ARegion *region = CTX_wm_region(C);
+ x -= region->winrct.xmin;
+ y -= region->winrct.ymin;
+ if (eventstate_has_changed(sdata_intern, wm, x, y)) {
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ View3D *v3d = CTX_wm_view3d(C);
+ cursor_snap_update(C, wm, depsgraph, scene, region, v3d, x, y, sdata_intern);
+ }
+
+ const bool draw_plane = sdata_intern->draw_plane;
+ if (!snap_data->snap_elem && !draw_plane) {
+ return;
+ }
+
+ /* Setup viewport & matrix. */
+ RegionView3D *rv3d = region->regiondata;
+ wmViewport(&region->winrct);
+ GPU_matrix_push_projection();
+ GPU_matrix_push();
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+
+ GPU_blend(GPU_BLEND_ALPHA);
+
+ float matrix[4][4];
+ if (draw_plane) {
+ copy_m4_m3(matrix, snap_data->plane_omat);
+ copy_v3_v3(matrix[3], snap_data->loc);
+
+ cursor_plane_draw(rv3d, snap_data->plane_axis, matrix);
+ }
+
+ if (snap_data->snap_elem && sdata_intern->draw_point) {
+ const float *prev_point = (snap_data->snap_elem & SCE_SNAP_MODE_EDGE_PERPENDICULAR) ?
+ snap_data->prevpoint :
+ NULL;
+
+ GPU_line_smooth(false);
+ GPU_line_width(1.0f);
+
+ ED_view3d_cursor_snap_draw_util(rv3d,
+ prev_point,
+ snap_data->loc,
+ NULL,
+ snap_data->color_line,
+ snap_data->color_point,
+ snap_data->snap_elem);
+ }
+
+ GPU_blend(GPU_BLEND_NONE);
+
+ /* Restore matrix. */
+ GPU_matrix_pop();
+ GPU_matrix_pop_projection();
+}
+
+/** \} */
+
+V3DSnapCursorData *ED_view3d_cursor_snap_data_get(void)
+{
+ LISTBASE_FOREACH_MUTABLE (wmWindowManager *, wm, &G.main->wm) {
+ LISTBASE_FOREACH_MUTABLE (wmPaintCursor *, pc, &wm->paintcursors) {
+ if (pc->draw == cursor_snap_draw_fn) {
+ return (V3DSnapCursorData *)pc->customdata;
+ }
+ }
+ }
+ return NULL;
+}
+
+static void wm_paint_cursor_snap_data_init(SnapCursorDataIntern *sdata_intern)
+{
+#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
+ 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);
+#endif
+
+ 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;
+}
+
+static SnapCursorDataIntern *wm_paint_cursor_snap_ensure(void)
+{
+ SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get();
+ if (!sdata_intern) {
+ sdata_intern = MEM_callocN(sizeof(*sdata_intern), __func__);
+ wm_paint_cursor_snap_data_init(sdata_intern);
+
+ struct wmPaintCursor *pc = WM_paint_cursor_activate(
+ SPACE_VIEW3D, RGN_TYPE_WINDOW, cursor_snap_pool_fn, cursor_snap_draw_fn, sdata_intern);
+ sdata_intern->handle = pc;
+ }
+ return sdata_intern;
+}
+
+void ED_view3d_cursor_snap_activate_point(void)
+{
+ SnapCursorDataIntern *sdata_intern = wm_paint_cursor_snap_ensure();
+ sdata_intern->draw_point = true;
+}
+
+void ED_view3d_cursor_snap_activate_plane(void)
+{
+ SnapCursorDataIntern *sdata_intern = wm_paint_cursor_snap_ensure();
+ sdata_intern->draw_plane = true;
+}
+
+static void wm_paint_cursor_snap_free(SnapCursorDataIntern *sdata_intern)
+{
+ WM_paint_cursor_end(sdata_intern->handle);
+ if (sdata_intern->snap_context_v3d) {
+ ED_transform_snap_object_context_destroy(sdata_intern->snap_context_v3d);
+ }
+ MEM_freeN(sdata_intern);
+}
+
+void ED_view3d_cursor_snap_deactivate_point(void)
+{
+ SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get();
+ if (!sdata_intern) {
+ return;
+ }
+
+ sdata_intern->draw_point = false;
+ sdata_intern->snap_data.prevpoint = NULL;
+ if (sdata_intern->draw_plane) {
+ return;
+ }
+
+ wm_paint_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;
+ }
+
+ sdata_intern->draw_plane = false;
+ sdata_intern->snap_data.prevpoint = NULL;
+ if (sdata_intern->draw_point) {
+ return;
+ }
+
+ wm_paint_cursor_snap_free(sdata_intern);
+}
+
+void ED_view3d_cursor_snap_update(const bContext *C,
+ const int x,
+ const int y,
+ V3DSnapCursorData *snap_data)
+{
+ SnapCursorDataIntern stack = {0}, *sdata_intern;
+ sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get();
+ if (!sdata_intern) {
+ sdata_intern = &stack;
+ wm_paint_cursor_snap_data_init(sdata_intern);
+ sdata_intern->draw_plane = true;
+ }
+
+ wmWindowManager *wm = CTX_wm_manager(C);
+ if (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);
+
+ 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;
+ }
+}
+
+void ED_view3d_cursor_snap_prevpoint_set(const float prev_point[3])
+{
+ SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get();
+ if (!sdata_intern) {
+ return;
+ }
+ if (prev_point) {
+ copy_v3_v3(sdata_intern->prevpoint_stack, prev_point);
+ sdata_intern->snap_data.prevpoint = sdata_intern->prevpoint_stack;
+ }
+ else {
+ sdata_intern->snap_data.prevpoint = NULL;
+ }
+}
+
+struct SnapObjectContext *ED_view3d_cursor_snap_context_ensure(struct Scene *scene)
+{
+ SnapCursorDataIntern *sdata_intern = (SnapCursorDataIntern *)ED_view3d_cursor_snap_data_get();
+ if (!sdata_intern) {
+ return NULL;
+ }
+ wm_paint_cursor_snap_context_ensure(sdata_intern, scene);
+ return sdata_intern->snap_context_v3d;
+}
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index d34fbc4562a..ba9b104a9cc 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -5122,7 +5122,8 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
ray_no,
NULL,
&ob_dummy,
- obmat) != 0) {
+ obmat,
+ NULL) != 0) {
if (use_depth) {
copy_v3_v3(cursor_co, ray_co);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 573f5348b5e..34e3b808b50 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -332,7 +332,8 @@ static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], cons
/**
* Use for mouse-move events.
*/
-static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
+static bool view3d_ruler_item_mousemove(const bContext *C,
+ struct Depsgraph *depsgraph,
RulerInfo *ruler_info,
RulerItem *ruler_item,
const int mval[2],
@@ -401,7 +402,6 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
#endif
{
View3D *v3d = ruler_info->area->spacedata.first;
- const float mval_fl[2] = {UNPACK2(mval)};
float *prev_point = NULL;
if (inter->co_index != 1) {
@@ -420,11 +420,8 @@ static bool view3d_ruler_item_mousemove(struct Depsgraph *depsgraph,
snap_gizmo->ptr, ruler_info->snap_data.prop_prevpoint, prev_point);
}
- ED_gizmotypes_snap_3d_update(
- snap_gizmo, depsgraph, ruler_info->region, v3d, ruler_info->wm, mval_fl);
-
if (ED_gizmotypes_snap_3d_is_enabled(snap_gizmo)) {
- ED_gizmotypes_snap_3d_data_get(snap_gizmo, co, NULL, NULL, NULL);
+ ED_gizmotypes_snap_3d_data_get(C, snap_gizmo, co, NULL, NULL, NULL);
}
#ifdef USE_AXIS_CONSTRAINTS
@@ -1050,7 +1047,8 @@ static int gizmo_ruler_modal(bContext *C,
if (do_cursor_update) {
if (ruler_info->state == RULER_STATE_DRAG) {
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- if (view3d_ruler_item_mousemove(depsgraph,
+ if (view3d_ruler_item_mousemove(C,
+ depsgraph,
ruler_info,
ruler_item,
event->mval,
@@ -1117,7 +1115,8 @@ static int gizmo_ruler_invoke(bContext *C, wmGizmo *gz, const wmEvent *event)
/* update the new location */
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- view3d_ruler_item_mousemove(depsgraph,
+ view3d_ruler_item_mousemove(C,
+ depsgraph,
ruler_info,
ruler_item_pick,
event->mval,
@@ -1236,7 +1235,7 @@ static void WIDGETGROUP_ruler_setup(const bContext *C, wmGizmoGroup *gzgroup)
(SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
/* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT));
- ED_gizmotypes_snap_3d_flag_set(gizmo, ED_SNAPGIZMO_SNAP_EDIT_GEOM_CAGE);
+ ED_gizmotypes_snap_3d_flag_set(gizmo, V3D_SNAPCURSOR_SNAP_EDIT_GEOM_CAGE);
WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_ruler_add", true);
@@ -1321,7 +1320,8 @@ static int view3d_ruler_add_invoke(bContext *C, wmOperator *op, const wmEvent *e
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
/* snap the first point added, not essential but handy */
inter->co_index = 0;
- view3d_ruler_item_mousemove(depsgraph,
+ view3d_ruler_item_mousemove(C,
+ depsgraph,
ruler_info,
ruler_item,
event->mval,
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 6cd6d85d204..adff75b571d 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -25,17 +25,7 @@
#include "MEM_guardedalloc.h"
-#include "DNA_collection_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_vfont_types.h"
-
-#include "BLI_math.h"
-#include "BLI_utildefines.h"
-
#include "BKE_context.h"
-#include "BKE_global.h"
-#include "BKE_main.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -43,29 +33,23 @@
#include "WM_api.h"
#include "WM_toolsystem.h"
-#include "WM_types.h"
-#include "ED_gizmo_library.h"
#include "ED_gizmo_utils.h"
#include "ED_screen.h"
#include "ED_space_api.h"
-#include "ED_transform.h"
-#include "ED_transform_snap_object_context.h"
#include "ED_view3d.h"
#include "UI_resources.h"
-#include "GPU_batch.h"
#include "GPU_immediate.h"
-#include "GPU_matrix.h"
-#include "GPU_state.h"
#include "view3d_intern.h"
static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
-static void preview_plane_cursor_setup(wmGizmoGroup *gzgroup);
-static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw);
+static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup,
+ bool do_draw_plane,
+ bool do_draw_point);
/**
* Dot products below this will be considered view aligned.
@@ -96,17 +80,6 @@ enum ePlace_Aspect {
PLACE_ASPECT_FIXED = 2,
};
-enum ePlace_Depth {
- PLACE_DEPTH_SURFACE = 1,
- PLACE_DEPTH_CURSOR_PLANE = 2,
- PLACE_DEPTH_CURSOR_VIEW = 3,
-};
-
-enum ePlace_Orient {
- PLACE_ORIENT_SURFACE = 1,
- PLACE_ORIENT_DEFAULT = 2,
-};
-
enum ePlace_SnapTo {
PLACE_SNAP_TO_GEOMETRY = 1,
PLACE_SNAP_TO_DEFAULT = 2,
@@ -198,9 +171,6 @@ struct InteractivePlaceData {
/** When activated without a tool. */
bool wait_for_input;
- /** Optional snap gizmo, needed for snapping. */
- wmGizmo *snap_gizmo;
-
enum ePlace_SnapTo snap_to;
};
@@ -251,130 +221,6 @@ static int dot_v3_array_find_max_index(const float dirs[][3],
return index_found;
}
-/**
- * Re-order \a mat so \a axis_align uses its own axis which is closest to \a v.
- */
-static bool mat3_align_axis_to_v3(float mat[3][3], const int axis_align, const float v[3])
-{
- float dot_best = -1.0f;
- int axis_found = axis_align;
- for (int i = 0; i < 3; i++) {
- const float dot_test = fabsf(dot_v3v3(mat[i], v));
- if (dot_test > dot_best) {
- dot_best = dot_test;
- axis_found = i;
- }
- }
-
- if (axis_align != axis_found) {
- float tmat[3][3];
- copy_m3_m3(tmat, mat);
- const int offset = mod_i(axis_found - axis_align, 3);
- for (int i = 0; i < 3; i++) {
- copy_v3_v3(mat[i], tmat[(i + offset) % 3]);
- }
- return true;
- }
- return false;
-}
-
-/* On-screen snap distance. */
-#define MVAL_MAX_PX_DIST 12.0f
-
-static bool idp_snap_point_from_gizmo_ex(wmGizmo *gz, const char *prop_id, float r_location[3])
-{
- if (gz->state & WM_GIZMO_STATE_HIGHLIGHT) {
- PropertyRNA *prop_location = RNA_struct_find_property(gz->ptr, prop_id);
- RNA_property_float_get_array(gz->ptr, prop_location, r_location);
- return true;
- }
- return false;
-}
-
-static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
-{
- return idp_snap_point_from_gizmo_ex(gz, "location", r_location);
-}
-
-static bool idp_snap_normal_from_gizmo(wmGizmo *gz, float r_normal[3])
-{
- return idp_snap_point_from_gizmo_ex(gz, "normal", r_normal);
-}
-
-/**
- * Calculate a 3x3 orientation matrix from the surface under the cursor.
- */
-static bool idp_poject_surface_normal(SnapObjectContext *snap_context,
- struct Depsgraph *depsgraph,
- ARegion *region,
- View3D *v3d,
- const float mval_fl[2],
- const float mat_fallback[3][3],
- const float normal_fallback[3],
- float r_mat[3][3])
-{
- bool success = false;
- float normal[3] = {0.0f};
- float co_dummy[3];
- /* We could use the index to get the orientation from the face. */
- Object *ob_snap;
- float obmat[4][4];
-
- if (ED_transform_snap_object_project_view3d_ex(snap_context,
- depsgraph,
- region,
- v3d,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .edit_mode_type = SNAP_GEOM_EDIT,
- },
- mval_fl,
- NULL,
- NULL,
- co_dummy,
- normal,
- NULL,
- &ob_snap,
- obmat)) {
- /* pass */
- }
- else if (normal_fallback != NULL) {
- copy_m4_m3(obmat, mat_fallback);
- copy_v3_v3(normal, normal_fallback);
- }
-
- if (!is_zero_v3(normal)) {
- float mat[3][3];
- copy_m3_m4(mat, obmat);
- normalize_m3(mat);
-
- float dot_best = fabsf(dot_v3v3(mat[0], normal));
- int i_best = 0;
- for (int i = 1; i < 3; i++) {
- float dot_test = fabsf(dot_v3v3(mat[i], normal));
- if (dot_test > dot_best) {
- i_best = i;
- dot_best = dot_test;
- }
- }
- if (dot_v3v3(mat[i_best], normal) < 0.0f) {
- negate_v3(mat[(i_best + 1) % 3]);
- negate_v3(mat[(i_best + 2) % 3]);
- }
- copy_v3_v3(mat[i_best], normal);
- orthogonalize_m3(mat, i_best);
- normalize_m3(mat);
-
- copy_v3_v3(r_mat[0], mat[(i_best + 1) % 3]);
- copy_v3_v3(r_mat[1], mat[(i_best + 2) % 3]);
- copy_v3_v3(r_mat[2], mat[i_best]);
- success = true;
- }
-
- return success;
-}
-
static wmGizmoGroup *idp_gizmogroup_from_region(ARegion *region)
{
wmGizmoMap *gzmap = region->gizmo_map;
@@ -417,20 +263,6 @@ static bool idp_snap_calc_incremental(
return true;
}
-static void idp_snap_gizmo_update_snap_elements(Scene *scene,
- enum ePlace_SnapTo snap_to,
- wmGizmo *gizmo)
-{
- const int snap_mode =
- (snap_to == PLACE_SNAP_TO_GEOMETRY) ?
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
- /* SCE_SNAP_MODE_VOLUME | SCE_SNAP_MODE_GRID | SCE_SNAP_MODE_INCREMENT | */
- SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT) :
- scene->toolsettings->snap_mode;
-
- RNA_enum_set(gizmo->ptr, "snap_elements_force", snap_mode);
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -861,153 +693,18 @@ static void draw_primitive_view(const struct bContext *C, ARegion *UNUSED(region
* Use by both the operator and placement cursor.
* \{ */
-static void view3d_interactive_add_calc_plane(bContext *C,
- Scene *scene,
- View3D *v3d,
- ARegion *region,
- const float mval_fl[2],
- wmGizmo *snap_gizmo,
- const enum ePlace_SnapTo snap_to,
- const enum ePlace_Depth plane_depth,
- const enum ePlace_Orient plane_orient,
- const int plane_axis,
- const bool plane_axis_auto,
+static bool view3d_interactive_add_calc_plane(bContext *C,
+ const wmEvent *event,
float r_co_src[3],
float r_matrix_orient[3][3])
{
- const RegionView3D *rv3d = region->regiondata;
- ED_transform_calc_orientation_from_type(C, r_matrix_orient);
-
- /* Non-orthogonal matrices cause the preview and final result not to match.
- *
- * 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(r_matrix_orient, plane_axis);
-
- SnapObjectContext *snap_context = NULL;
- bool snap_context_free = false;
-
- /* Set the orientation. */
- if ((plane_orient == PLACE_ORIENT_SURFACE) || (plane_depth == PLACE_DEPTH_SURFACE)) {
- snap_context = (snap_gizmo ? ED_gizmotypes_snap_3d_context_ensure(scene, snap_gizmo) : NULL);
- if (snap_context == NULL) {
- snap_context = ED_transform_snap_object_context_create(scene, 0);
- snap_context_free = true;
- }
- }
-
- if (plane_orient == PLACE_ORIENT_SURFACE) {
- bool found_surface_or_normal = false;
- float matrix_orient_surface[3][3];
-
- /* Use the snap normal as a fallback in case the cursor isn't over a surface
- * but snapping is enabled. */
- float normal_fallback[3];
- bool use_normal_fallback = snap_gizmo ?
- idp_snap_normal_from_gizmo(snap_gizmo, normal_fallback) :
- false;
-
- if ((snap_context != NULL) &&
- idp_poject_surface_normal(snap_context,
- CTX_data_ensure_evaluated_depsgraph(C),
- region,
- v3d,
- mval_fl,
- use_normal_fallback ? r_matrix_orient : NULL,
- use_normal_fallback ? normal_fallback : NULL,
- matrix_orient_surface)) {
- copy_m3_m3(r_matrix_orient, matrix_orient_surface);
- found_surface_or_normal = true;
- }
-
- if (!found_surface_or_normal && plane_axis_auto) {
- /* Drawing into empty space, draw onto the plane most aligned to the view direction. */
- mat3_align_axis_to_v3(r_matrix_orient, plane_axis, rv3d->viewinv[2]);
- }
- }
-
- const bool is_snap_found = snap_gizmo ? idp_snap_point_from_gizmo(snap_gizmo, r_co_src) : false;
-
- if (is_snap_found) {
- /* pass */
- }
- else {
- bool use_depth_fallback = true;
- if (plane_depth == PLACE_DEPTH_CURSOR_VIEW) {
- /* View plane. */
- ED_view3d_win_to_3d(v3d, region, scene->cursor.location, mval_fl, r_co_src);
- use_depth_fallback = false;
- }
- else if (plane_depth == PLACE_DEPTH_SURFACE) {
- if ((snap_context != NULL) &&
- ED_transform_snap_object_project_view3d(snap_context,
- CTX_data_ensure_evaluated_depsgraph(C),
- region,
- v3d,
- SCE_SNAP_MODE_FACE,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- .edit_mode_type = SNAP_GEOM_EDIT,
- },
- mval_fl,
- NULL,
- NULL,
- r_co_src,
- NULL)) {
- use_depth_fallback = false;
- }
- }
-
- /* Use as fallback to surface. */
- if (use_depth_fallback || (plane_depth == PLACE_DEPTH_CURSOR_PLANE)) {
- /* Cursor plane. */
- float plane[4];
- const float *plane_normal = r_matrix_orient[plane_axis];
-
- const float view_axis_dot = fabsf(dot_v3v3(rv3d->viewinv[2], r_matrix_orient[plane_axis]));
- if (view_axis_dot < eps_view_align) {
- /* In this case, just project onto the view plane as it's important the location
- * is _always_ under the mouse cursor, even if it turns out that won't lie on
- * the original 'plane' that's been calculated for us. */
- plane_normal = rv3d->viewinv[2];
- }
-
- plane_from_point_normal_v3(plane, scene->cursor.location, plane_normal);
-
- if (view3d_win_to_3d_on_plane_maybe_fallback(region, plane, mval_fl, NULL, r_co_src)) {
- use_depth_fallback = false;
- }
-
- /* Even if the calculation works, it's possible the point found is behind the view,
- * or very far away (past the far clipping).
- * In either case creating objects won't be useful. */
- if (rv3d->is_persp) {
- float dir[3];
- sub_v3_v3v3(dir, rv3d->viewinv[3], r_co_src);
- const float dot = dot_v3v3(dir, rv3d->viewinv[2]);
- if (dot < v3d->clip_start || dot > v3d->clip_end) {
- use_depth_fallback = true;
- }
- }
- }
-
- if (use_depth_fallback) {
- float co_depth[3];
- /* Fallback to view center. */
- negate_v3_v3(co_depth, rv3d->ofs);
- ED_view3d_win_to_3d(v3d, region, co_depth, mval_fl, r_co_src);
- }
- }
-
- if (!is_snap_found && ((snap_gizmo != NULL) && ED_gizmotypes_snap_3d_is_enabled(snap_gizmo))) {
- if (snap_to == PLACE_SNAP_TO_DEFAULT) {
- idp_snap_calc_incremental(scene, v3d, region, NULL, r_co_src);
- }
- }
-
- if (snap_context_free) {
- ED_transform_snap_object_context_destroy(snap_context);
+ V3DSnapCursorData snap_data;
+ ED_view3d_cursor_snap_update(C, UNPACK2(event->mval), &snap_data);
+ copy_v3_v3(r_co_src, snap_data.loc);
+ if (r_matrix_orient) {
+ copy_m3_m3(r_matrix_orient, snap_data.plane_omat);
}
+ return snap_data.snap_elem != 0;
}
/** \} */
@@ -1022,7 +719,8 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
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 enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target");
- const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
+ 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"),
@@ -1031,58 +729,29 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
RNA_enum_get(op->ptr, "plane_aspect_base"),
RNA_enum_get(op->ptr, "plane_aspect_depth"),
};
- const enum ePlace_Orient plane_orient = RNA_enum_get(op->ptr, "plane_orientation");
-
- const float mval_fl[2] = {UNPACK2(event->mval)};
struct InteractivePlaceData *ipd = op->customdata;
- /* Assign snap gizmo which is may be used as part of the tool. */
- {
- wmGizmoGroup *gzgroup = idp_gizmogroup_from_region(ipd->region);
- if (gzgroup != NULL) {
- if (gzgroup->gizmos.first) {
- ipd->snap_gizmo = gzgroup->gizmos.first;
- }
+ ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
- /* Can be NULL when gizmos are disabled. */
- if (gzgroup->customdata != NULL) {
- preview_plane_cursor_visible_set(gzgroup, false);
- }
- }
- }
+ 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;
- /* For tweak events the snap target may have changed since dragging,
- * update the snap target at the cursor location where tweak began.
- *
- * NOTE: we could investigating solving this in a more generic way,
- * so each operator doesn't have to account for it. */
- if (ISTWEAK(event->type)) {
- if (ipd->snap_gizmo != NULL) {
- ED_gizmotypes_snap_3d_update(ipd->snap_gizmo,
- CTX_data_ensure_evaluated_depsgraph(C),
- ipd->region,
- ipd->v3d,
- G_MAIN->wm.first,
- mval_fl);
- }
- }
+ 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->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
+ ED_view3d_cursor_snap_prevpoint_set(ipd->co_src);
- view3d_interactive_add_calc_plane(C,
- ipd->scene,
- ipd->v3d,
- ipd->region,
- mval_fl,
- ipd->snap_gizmo,
- snap_to,
- plane_depth,
- plane_orient,
- plane_axis,
- plane_axis_auto,
- ipd->co_src,
- ipd->matrix_orient);
+ 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->orient_axis = plane_axis;
for (int i = 0; i < 2; i++) {
@@ -1161,13 +830,6 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
}
}
- ipd->is_snap_invert = ipd->snap_gizmo ? ED_gizmotypes_snap_3d_invert_snap_get(ipd->snap_gizmo) :
- false;
- {
- const ToolSettings *ts = ipd->scene->toolsettings;
- ipd->use_snap = (ipd->is_snap_invert == !(ts->snap_flag & SCE_SNAP));
- }
-
ipd->draw_handle_view = ED_region_draw_cb_activate(
ipd->region->type, draw_primitive_view, ipd, REGION_DRAW_POST_VIEW);
@@ -1244,19 +906,18 @@ static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
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_region_draw_cb_exit(ipd->region->type, ipd->draw_handle_view);
ED_region_tag_redraw(ipd->region);
- {
- wmGizmoGroup *gzgroup = idp_gizmogroup_from_region(ipd->region);
- if (gzgroup != NULL) {
- if (gzgroup->customdata != NULL) {
- preview_plane_cursor_visible_set(gzgroup, true);
- }
- }
- }
-
MEM_freeN(ipd);
}
@@ -1374,6 +1035,8 @@ 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);
+
/* Set secondary plane. */
/* Create normal. */
@@ -1521,19 +1184,7 @@ 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) {
- if (ipd->snap_gizmo != NULL) {
- ED_gizmotypes_snap_3d_flag_set(ipd->snap_gizmo, ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE);
- if (ED_gizmotypes_snap_3d_update(ipd->snap_gizmo,
- CTX_data_ensure_evaluated_depsgraph(C),
- ipd->region,
- ipd->v3d,
- G_MAIN->wm.first,
- mval_fl)) {
- ED_gizmotypes_snap_3d_data_get(ipd->snap_gizmo, ipd->snap_co, NULL, NULL, NULL);
- ipd->is_snap_found = true;
- }
- ED_gizmotypes_snap_3d_flag_clear(ipd->snap_gizmo, ED_SNAPGIZMO_TOGGLE_ALWAYS_TRUE);
- }
+ ipd->is_snap_found = view3d_interactive_add_calc_plane(C, event, ipd->snap_co, NULL);
}
if (ipd->step_index == STEP_BASE) {
@@ -1632,6 +1283,7 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
{PLACE_PRIMITIVE_TYPE_SPHERE_ICO, "SPHERE_ICO", 0, "ICO Sphere", ""},
{0, NULL, 0, NULL, NULL},
};
+
prop = RNA_def_property(ot->srna, "primitive_type", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Primitive", "");
RNA_def_property_enum_items(prop, primitive_type);
@@ -1652,18 +1304,18 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
static const EnumPropertyItem plane_depth_items[] = {
- {PLACE_DEPTH_SURFACE,
+ {V3D_PLACE_DEPTH_SURFACE,
"SURFACE",
0,
"Surface",
"Start placing on the surface, using the 3D cursor position as a fallback"},
- {PLACE_DEPTH_CURSOR_PLANE,
+ {V3D_PLACE_DEPTH_CURSOR_PLANE,
"CURSOR_PLANE",
0,
"Cursor Plane",
"Start placement using a point projected onto the orientation axis "
"at the 3D cursor position"},
- {PLACE_DEPTH_CURSOR_VIEW,
+ {V3D_PLACE_DEPTH_CURSOR_VIEW,
"CURSOR_VIEW",
0,
"Cursor View",
@@ -1672,17 +1324,17 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
};
prop = RNA_def_property(ot->srna, "plane_depth", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Position", "The initial depth used when placing the cursor");
- RNA_def_property_enum_default(prop, PLACE_DEPTH_SURFACE);
+ 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);
static const EnumPropertyItem plane_orientation_items[] = {
- {PLACE_ORIENT_SURFACE,
+ {V3D_PLACE_ORIENT_SURFACE,
"SURFACE",
ICON_SNAP_NORMAL,
"Surface",
"Use the surface normal (using the transform orientation as a fallback)"},
- {PLACE_ORIENT_DEFAULT,
+ {V3D_PLACE_ORIENT_DEFAULT,
"DEFAULT",
ICON_ORIENTATION_GLOBAL,
"Default",
@@ -1691,7 +1343,7 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
};
prop = RNA_def_property(ot->srna, "plane_orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Orientation", "The initial depth used when placing the cursor");
- RNA_def_property_enum_default(prop, PLACE_ORIENT_SURFACE);
+ 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);
@@ -1752,388 +1404,90 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
* we could show a placement plane here.
* \{ */
-static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+static void preview_plane_cursor_visible_set(wmGizmoGroup *UNUSED(gzgroup),
+ bool do_draw_plane,
+ bool do_draw_point)
{
- wmGizmo *gizmo;
-
- {
- /* The gizmo snap has to be the first gizmo. */
- const wmGizmoType *gzt_snap;
- gzt_snap = WM_gizmotype_find("GIZMO_GT_snap_3d", true);
- gizmo = WM_gizmo_new_ptr(gzt_snap, gzgroup, NULL);
-
- WM_gizmo_set_color(gizmo, (float[4]){1.0f, 1.0f, 1.0f, 1.0f});
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
- /* Don't handle any events, this is for display only. */
- gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP;
+ if (do_draw_point) {
+ ED_view3d_cursor_snap_activate_point();
}
- /* Sets the gizmos custom-data which has its own free callback. */
- preview_plane_cursor_setup(gzgroup);
-}
-
-void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
-{
- gzgt->name = "Placement Widget";
- gzgt->idname = view3d_gzgt_placement_id;
-
- gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
+ if (do_draw_plane) {
+ ED_view3d_cursor_snap_activate_plane();
+ }
+ else {
+ ED_view3d_cursor_snap_deactivate_plane();
+ }
- gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
- gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
+ if (!do_draw_point) {
+ ED_view3d_cursor_snap_deactivate_point();
+ }
- gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
- gzgt->setup = WIDGETGROUP_placement_setup;
+ 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);
+ }
}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Placement Preview Plane
- *
- * Preview the plane that will be used for placement.
- *
- * Note that we might want to split this into its own file,
- * for now this is coupled with the 3D view placement gizmo.
- * \{ */
-
-static void gizmo_plane_update_cursor(const bContext *C,
- ARegion *region,
- const int mval[2],
- float r_co[3],
- float r_matrix_orient[3][3],
- int *r_plane_axis)
+static void preview_plane_free_fn(void *customdata)
{
- wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_interactive_add", true);
- BLI_assert(ot != NULL);
- PointerRNA ptr;
-
- ScrArea *area = CTX_wm_area(C);
- BLI_assert(region == CTX_wm_region(C));
- bToolRef *tref = area->runtime.tool;
- WM_toolsystem_ref_properties_ensure_from_operator(tref, ot, &ptr);
-
- const enum ePlace_SnapTo snap_to = RNA_enum_get(&ptr, "snap_target");
- const int plane_axis = RNA_enum_get(&ptr, "plane_axis");
- const bool plane_axis_auto = RNA_boolean_get(&ptr, "plane_axis_auto");
- const enum ePlace_Depth plane_depth = RNA_enum_get(&ptr, "plane_depth");
- const enum ePlace_Orient plane_orient = RNA_enum_get(&ptr, "plane_orientation");
-
- const float mval_fl[2] = {UNPACK2(mval)};
-
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
-
- /* Assign snap gizmo which is may be used as part of the tool. */
- wmGizmo *snap_gizmo = NULL;
- {
- wmGizmoGroup *gzgroup = idp_gizmogroup_from_region(region);
- if ((gzgroup != NULL) && gzgroup->gizmos.first) {
- snap_gizmo = gzgroup->gizmos.first;
- }
- }
-
- /* This ensures the snap gizmo has settings from this tool.
- * This function call could be moved a more appropriate place,
- * responding to the setting being changed for example,
- * however setting the value isn't expensive, so do it here. */
- idp_snap_gizmo_update_snap_elements(scene, snap_to, snap_gizmo);
-
- view3d_interactive_add_calc_plane((bContext *)C,
- scene,
- v3d,
- region,
- mval_fl,
- snap_gizmo,
- snap_to,
- plane_depth,
- plane_orient,
- plane_axis,
- plane_axis_auto,
- r_co,
- r_matrix_orient);
- *r_plane_axis = plane_axis;
+ preview_plane_cursor_visible_set(customdata, false, false);
}
-static void gizmo_plane_draw_grid(const int resolution,
- const float scale,
- const float scale_fade,
- const float matrix[4][4],
- const int plane_axis,
- const float color[4])
+static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
{
- BLI_assert(scale_fade <= scale);
- const int resolution_min = resolution - 1;
- float color_fade[4] = {UNPACK4(color)};
- const float *center = matrix[3];
-
- GPU_blend(GPU_BLEND_ADDITIVE);
- GPU_line_smooth(true);
- GPU_line_width(1.0f);
-
- GPUVertFormat *format = immVertexFormat();
- const uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
- const uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
-
- const size_t coords_len = resolution * resolution;
- float(*coords)[3] = MEM_mallocN(sizeof(*coords) * coords_len, __func__);
-
- const int axis_x = (plane_axis + 0) % 3;
- const int axis_y = (plane_axis + 1) % 3;
- const int axis_z = (plane_axis + 2) % 3;
-
- int i;
- const float resolution_div = (float)1.0f / (float)resolution;
- i = 0;
- for (int x = 0; x < resolution; x++) {
- const float x_fl = (x * resolution_div) - 0.5f;
- for (int y = 0; y < resolution; y++) {
- const float y_fl = (y * resolution_div) - 0.5f;
- coords[i][axis_x] = 0.0f;
- coords[i][axis_y] = x_fl * scale;
- coords[i][axis_z] = y_fl * scale;
- mul_m4_v3(matrix, coords[i]);
- i += 1;
- }
- }
- BLI_assert(i == coords_len);
- immBeginAtMost(GPU_PRIM_LINES, coords_len * 4);
- i = 0;
- for (int x = 0; x < resolution_min; x++) {
- for (int y = 0; y < resolution_min; y++) {
-
- /* Add #resolution_div to ensure we fade-out entirely. */
-#define FADE(v) \
- max_ff(0.0f, (1.0f - square_f(((len_v3v3(v, center) / scale_fade) + resolution_div) * 2.0f)))
-
- const float *v0 = coords[(resolution * x) + y];
- const float *v1 = coords[(resolution * (x + 1)) + y];
- const float *v2 = coords[(resolution * x) + (y + 1)];
-
- const float f0 = FADE(v0);
- const float f1 = FADE(v1);
- const float f2 = FADE(v2);
-
- if (f0 > 0.0f || f1 > 0.0f) {
- color_fade[3] = color[3] * f0;
- immAttr4fv(col_id, color_fade);
- immVertex3fv(pos_id, v0);
- color_fade[3] = color[3] * f1;
- immAttr4fv(col_id, color_fade);
- immVertex3fv(pos_id, v1);
- }
- if (f0 > 0.0f || f2 > 0.0f) {
- color_fade[3] = color[3] * f0;
- immAttr4fv(col_id, color_fade);
- immVertex3fv(pos_id, v0);
-
- color_fade[3] = color[3] * f2;
- immAttr4fv(col_id, color_fade);
- immVertex3fv(pos_id, v2);
- }
-
-#undef FADE
-
- i++;
- }
- }
-
- MEM_freeN(coords);
-
- immEnd();
-
- immUnbindProgram();
-
- GPU_line_smooth(false);
- GPU_blend(GPU_BLEND_NONE);
+ preview_plane_cursor_visible_set(gzgroup, true, true);
+ gzgroup->customdata = gzgroup;
+ gzgroup->customdata_free = preview_plane_free_fn;
}
-/* -------------------------------------------------------------------- */
-/** \name Preview Plane Cursor
- * \{ */
-
-struct PlacementCursor {
- /**
- * Back-pointer to the gizmo-group that uses this cursor.
- * Needed so we know that the cursor belongs to the region.
- */
- wmGizmoGroup *gzgroup;
-
- /**
- * Enable this while the modal operator is running,
- * so the preview-plane doesn't show at the same time as add-object preview shape
- * since it's distracting & not helpful.
- */
- bool do_draw;
-
- void *paintcursor;
-
- int plane_axis;
- float matrix[4][4];
-
- /* Check if we need to re-calculate the plane matrix. */
- int mval_prev[2];
- float persmat_prev[4][4];
-};
-
-static void cursor_plane_draw(bContext *C, int x, int y, void *customdata)
+static void WIDGETGROUP_placement_draw_prepare(const bContext *C, wmGizmoGroup *UNUSED(gzgroup))
{
- struct PlacementCursor *plc = (struct PlacementCursor *)customdata;
- ARegion *region = CTX_wm_region(C);
- const RegionView3D *rv3d = region->regiondata;
-
- /* Early exit.
- * Note that we can't do most of these checks in the poll function (besides global checks)
- * so test them here instead.
- *
- * This cursor is only active while the gizmo is being used
- * so it's not so important to have a poll function. */
- if (plc->do_draw == false) {
- return;
- }
- if (G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) {
- return;
- }
- if (rv3d->rflag & RV3D_NAVIGATING) {
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get();
+ if (!snap_data) {
return;
}
- /* Check this gizmo group is in the region. */
+ PointerRNA ptr;
{
- wmGizmoMap *gzmap = region->gizmo_map;
- wmGizmoGroup *gzgroup_test = WM_gizmomap_group_find_ptr(gzmap, plc->gzgroup->type);
- if (gzgroup_test != plc->gzgroup) {
- /* Wrong viewport. */
- return;
- }
- }
+ wmOperatorType *ot = WM_operatortype_find("VIEW3D_OT_interactive_add", true);
+ BLI_assert(ot != NULL);
- const int mval[2] = {x - region->winrct.xmin, y - region->winrct.ymin};
-
- /* Update matrix? */
- if ((plc->mval_prev[0] != mval[0]) || (plc->mval_prev[1] != mval[1]) ||
- !equals_m4m4(plc->persmat_prev, rv3d->persmat)) {
- plc->mval_prev[0] = mval[0];
- plc->mval_prev[1] = mval[1];
-
- float orient_matrix[3][3];
- float co[3];
- gizmo_plane_update_cursor(C, region, mval, co, orient_matrix, &plc->plane_axis);
- copy_m4_m3(plc->matrix, orient_matrix);
- copy_v3_v3(plc->matrix[3], co);
-
- copy_m4_m4(plc->persmat_prev, rv3d->persmat);
- }
-
- /* Draw */
- float pixel_size;
-
- if (rv3d->is_persp) {
- float center[3];
- negate_v3_v3(center, rv3d->ofs);
- pixel_size = ED_view3d_pixel_size(rv3d, center);
+ ScrArea *area = CTX_wm_area(C);
+ bToolRef *tref = area->runtime.tool;
+ WM_toolsystem_ref_properties_ensure_from_operator(tref, ot, &ptr);
}
- else {
- pixel_size = ED_view3d_pixel_size(rv3d, plc->matrix[3]);
- }
-
- if (pixel_size > FLT_EPSILON) {
-
- /* Arbitrary, 1.0 is a little too strong though. */
- float color_alpha = 0.75f;
- if (rv3d->is_persp) {
- /* Scale down the alpha when this is drawn very small,
- * since the add shader causes the small size to show too dense & bright. */
- const float relative_pixel_scale = pixel_size / ED_view3d_pixel_size(rv3d, plc->matrix[3]);
- if (relative_pixel_scale < 1.0f) {
- color_alpha *= max_ff(square_f(relative_pixel_scale), 0.3f);
- }
- }
- {
- /* Extra adjustment when it's near view-aligned as it seems overly bright. */
- float view_vector[3];
- ED_view3d_global_to_vector(rv3d, plc->matrix[3], view_vector);
- float view_dot = fabsf(dot_v3v3(plc->matrix[plc->plane_axis], view_vector));
- color_alpha *= max_ff(0.3f, 1.0f - square_f(square_f(1.0f - view_dot)));
- }
-
- /* Setup viewport & matrix. */
- wmViewport(&region->winrct);
- GPU_matrix_push_projection();
- GPU_matrix_push();
- GPU_matrix_projection_set(rv3d->winmat);
- GPU_matrix_set(rv3d->viewmat);
-
- const float scale_mod = U.gizmo_size * 2 * U.dpi_fac / U.pixelsize;
-
- float final_scale = (scale_mod * pixel_size);
-
- const int lines_subdiv = 10;
- int lines = lines_subdiv;
-
- float final_scale_fade = final_scale;
- final_scale = ceil_power_of_10(final_scale);
-
- float fac = final_scale_fade / final_scale;
-
- float color[4] = {1, 1, 1, color_alpha};
- color[3] *= square_f(1.0f - fac);
- if (color[3] > 0.0f) {
- gizmo_plane_draw_grid(lines * lines_subdiv,
- final_scale,
- final_scale_fade,
- plc->matrix,
- plc->plane_axis,
- color);
- }
-
- color[3] = color_alpha;
- /* When the grid is large, we only need the 2x lines in the middle. */
- if (fac < 0.2f) {
- lines = 1;
- final_scale = final_scale_fade;
- }
- gizmo_plane_draw_grid(
- lines, final_scale, final_scale_fade, plc->matrix, plc->plane_axis, color);
-
- /* Restore matrix. */
- GPU_matrix_pop();
- GPU_matrix_pop_projection();
- }
+ 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");
}
-static void preview_plane_cursor_free(void *customdata)
+void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
{
- struct PlacementCursor *plc = customdata;
+ gzgt->name = "Placement Widget";
+ gzgt->idname = view3d_gzgt_placement_id;
- /* The window manager is freed first on exit. */
- wmWindowManager *wm = G_MAIN->wm.first;
- if (UNLIKELY(wm != NULL)) {
- WM_paint_cursor_end(plc->paintcursor);
- }
- MEM_freeN(plc);
-}
+ gzgt->flag |= WM_GIZMOGROUPTYPE_3D | WM_GIZMOGROUPTYPE_SCALE | WM_GIZMOGROUPTYPE_DRAW_MODAL_ALL;
-static void preview_plane_cursor_setup(wmGizmoGroup *gzgroup)
-{
- BLI_assert(gzgroup->customdata == NULL);
- struct PlacementCursor *plc = MEM_callocN(sizeof(*plc), __func__);
- plc->gzgroup = gzgroup;
- plc->paintcursor = WM_paint_cursor_activate(
- SPACE_VIEW3D, RGN_TYPE_WINDOW, NULL, cursor_plane_draw, plc);
- gzgroup->customdata = plc;
- gzgroup->customdata_free = preview_plane_cursor_free;
-
- preview_plane_cursor_visible_set(gzgroup, true);
-}
+ gzgt->gzmap_params.spaceid = SPACE_VIEW3D;
+ gzgt->gzmap_params.regionid = RGN_TYPE_WINDOW;
-static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw)
-{
- struct PlacementCursor *plc = gzgroup->customdata;
- plc->do_draw = do_draw;
+ gzgt->poll = ED_gizmo_poll_or_unlink_delayed_from_tool;
+ gzgt->setup = WIDGETGROUP_placement_setup;
+ gzgt->draw_prepare = WIDGETGROUP_placement_draw_prepare;
}
/** \} */
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 2e1e8eb4ca4..7f27d5fb180 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -48,6 +48,7 @@
#include "ED_node.h"
#include "ED_transform_snap_object_context.h"
#include "ED_uvedit.h"
+#include "ED_view3d.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -247,7 +248,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
loc_cur = t->tsnap.snapPoint;
}
- ED_gizmotypes_snap_3d_draw_util(
+ ED_view3d_cursor_snap_draw_util(
rv3d, loc_prev, loc_cur, normal, col, activeCol, t->tsnap.snapElem);
GPU_depth_test(GPU_DEPTH_LESS_EQUAL);
@@ -1243,7 +1244,7 @@ short snapObjectsTransform(
TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
{
float *target = (t->tsnap.status & TARGET_INIT) ? t->tsnap.snapTarget : t->center_global;
- return ED_transform_snap_object_project_view3d_ex(
+ return ED_transform_snap_object_project_view3d(
t->tsnap.object_context,
t->depsgraph,
t->region,
@@ -1259,10 +1260,7 @@ short snapObjectsTransform(
target,
dist_px,
r_loc,
- r_no,
- NULL,
- NULL,
- NULL);
+ r_no);
}
/** \} */
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 5f9250e87f7..17326001a99 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -3020,7 +3020,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
float r_no[3],
int *r_index,
Object **r_ob,
- float r_obmat[4][4])
+ float r_obmat[4][4],
+ float r_face_nor[3])
{
BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) !=
@@ -3067,22 +3068,27 @@ static short transform_snap_context_project_view3d_mixed_impl(
&ob_eval,
obmat,
NULL);
+ if (has_hit) {
+ if (r_face_nor) {
+ copy_v3_v3(r_face_nor, no);
+ }
- if (has_hit && (snap_to_flag & SCE_SNAP_MODE_FACE)) {
- retval = SCE_SNAP_MODE_FACE;
+ if ((snap_to_flag & SCE_SNAP_MODE_FACE)) {
+ retval = SCE_SNAP_MODE_FACE;
- copy_v3_v3(r_loc, loc);
- if (r_no) {
- copy_v3_v3(r_no, no);
- }
- if (r_ob) {
- *r_ob = ob_eval;
- }
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
- }
- if (r_index) {
- *r_index = index;
+ copy_v3_v3(r_loc, loc);
+ if (r_no) {
+ copy_v3_v3(r_no, no);
+ }
+ if (r_ob) {
+ *r_ob = ob_eval;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ if (r_index) {
+ *r_index = index;
+ }
}
}
}
@@ -3182,6 +3188,10 @@ static short transform_snap_context_project_view3d_mixed_impl(
if (r_index) {
*r_index = index;
}
+ if (r_face_nor && !has_hit) {
+ /* Fallback. */
+ copy_v3_v3(r_face_nor, no);
+ }
*dist_px = dist_px_tmp;
}
@@ -3203,7 +3213,8 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
float r_no[3],
int *r_index,
Object **r_ob,
- float r_obmat[4][4])
+ float r_obmat[4][4],
+ float r_face_nor[3])
{
return transform_snap_context_project_view3d_mixed_impl(sctx,
depsgraph,
@@ -3218,7 +3229,8 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
r_no,
r_index,
r_ob,
- r_obmat);
+ r_obmat,
+ r_face_nor);
}
/**
@@ -3259,6 +3271,7 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
r_no,
NULL,
NULL,
+ NULL,
NULL) != 0;
}