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
This commit is contained in:
parent
be22e36692
commit
69d6222481
Notes:
blender-bot
2023-08-21 20:26:50 +02:00
Referenced by commit56ee96349d
, Fix snap cursor not active even if gizmo is available Referenced by commitc0fbbc53e8
, Fix T92605: Snapping not aligning to face extension Referenced by commit2944f3e92b
, Fix 1 frame delayed orientation in Placement Gizmo Referenced by commitc02f2f4947
, Fix #109454: Snapping from Tools doesn't work if Depth option is not `Surface`
|
@ -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;
|
||||
if (gz_prop_snap->prop) {
|
||||
snap_data->snap_elem_force |= RNA_property_enum_get(&gz_prop_snap->ptr, gz_prop_snap->prop);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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();
|
||||
ED_view3d_cursor_snap_activate_point();
|
||||
return ED_view3d_cursor_snap_context_ensure(scene);
|
||||
}
|
||||
|
||||
SnapObjectContext *ED_gizmotypes_snap_3d_context_ensure(Scene *scene, wmGizmo *gz)
|
||||
void ED_gizmotypes_snap_3d_flag_set(struct wmGizmo *gz, int flag)
|
||||
{
|
||||
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;
|
||||
snap_gizmo->cursor_handle->flag |= flag;
|
||||
}
|
||||
|
||||
void ED_gizmotypes_snap_3d_flag_set(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;
|
||||
}
|
||||
|
||||
void ED_gizmotypes_snap_3d_flag_clear(struct wmGizmo *gz, eSnapGizmo flag)
|
||||
bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, int flag)
|
||||
{
|
||||
SnapGizmo3D *snap_gizmo = (SnapGizmo3D *)gz;
|
||||
snap_gizmo->flag &= ~flag;
|
||||
}
|
||||
|
||||
bool ED_gizmotypes_snap_3d_flag_test(struct wmGizmo *gz, eSnapGizmo 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;
|
||||
V3DSnapCursorData *snap_data = ((SnapGizmo3D *)gz)->cursor_handle;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
#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);
|
||||
}
|
||||
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);
|
||||
V3DSnapCursorData *snap_data = snap_gizmo->cursor_handle;
|
||||
|
||||
/* 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;
|
||||
/* Snap Elements can change while the gizmo is active. Need to be updated somewhere. */
|
||||
snap_gizmo_snap_elements_update(snap_gizmo);
|
||||
|
||||
/* 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 (!eventstate_has_changed(snap_gizmo, wm)) {
|
||||
/* Performance, do not update. */
|
||||
return snap_gizmo->snap_elem ? 0 : -1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(®ion->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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue