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:
authorHoward Trickey <howard.trickey@gmail.com>2021-10-24 15:31:22 +0300
committerHoward Trickey <howard.trickey@gmail.com>2021-10-24 15:31:22 +0300
commit1aa953bd1913c81b22c80a00edbf4ad88a32c52f (patch)
tree7fa65e43d5a9bac6496555b723f37e0031e2737e /source/blender/editors/space_view3d/view3d_placement.c
parentfc171c1be9da36485e892339b86dc8d4251914af (diff)
parent6ce383a9dfba5c49a48676c3a651804fde3dfe34 (diff)
Merge branch 'master' into soc-2020-io-performance
Diffstat (limited to 'source/blender/editors/space_view3d/view3d_placement.c')
-rw-r--r--source/blender/editors/space_view3d/view3d_placement.c941
1 files changed, 170 insertions, 771 deletions
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index 6cd6d85d204..7fe97705765 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";
+#define SNAP_MODE_GEOM \
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE | \
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR | SCE_SNAP_MODE_EDGE_MIDPOINT)
-static void preview_plane_cursor_setup(wmGizmoGroup *gzgroup);
-static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw);
+static const char *view3d_gzgt_placement_id = "VIEW3D_GGT_placement";
/**
* 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,
@@ -178,6 +151,7 @@ struct InteractivePlaceData {
float matrix_orient[3][3];
int orient_axis;
+ V3DSnapCursorState *snap_state;
bool use_snap, is_snap_found, is_snap_invert;
float snap_co[3];
@@ -198,9 +172,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,131 +222,8 @@ 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)
+static UNUSED_FUNCTION_WITH_RETURN_TYPE(wmGizmoGroup *,
+ idp_gizmogroup_from_region)(ARegion *region)
{
wmGizmoMap *gzmap = region->gizmo_map;
return gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
@@ -417,20 +265,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 +695,25 @@ 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,
- float r_co_src[3],
- float r_matrix_orient[3][3])
+static bool view3d_interactive_add_calc_snap(bContext *UNUSED(C),
+ const wmEvent *UNUSED(event),
+ float r_co_src[3],
+ float r_matrix_orient[3][3],
+ bool *r_is_enabled,
+ bool *r_is_snap_invert)
{
- 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);
- }
+ V3DSnapCursorData *snap_data = ED_view3d_cursor_snap_data_get(NULL, NULL, 0, 0);
+ copy_v3_v3(r_co_src, snap_data->loc);
+ if (r_matrix_orient) {
+ copy_m3_m3(r_matrix_orient, snap_data->plane_omat);
}
-
- 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 (r_is_enabled) {
+ *r_is_enabled = snap_data->is_enabled;
}
-
- if (snap_context_free) {
- ED_transform_snap_object_context_destroy(snap_context);
+ if (r_is_snap_invert) {
+ *r_is_snap_invert = snap_data->is_snap_invert;
}
+ return snap_data->snap_elem != 0;
}
/** \} */
@@ -1018,11 +724,11 @@ static void view3d_interactive_add_calc_plane(bContext *C,
static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEvent *event)
{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
- const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
- const bool plane_axis_auto = RNA_boolean_get(op->ptr, "plane_axis_auto");
+ const int plane_axis = snap_state->plane_axis;
const enum ePlace_SnapTo snap_to = RNA_enum_get(op->ptr, "snap_target");
- const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
+
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 +737,21 @@ 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;
- }
-
- /* Can be NULL when gizmos are disabled. */
- if (gzgroup->customdata != NULL) {
- preview_plane_cursor_visible_set(gzgroup, false);
- }
- }
- }
+ ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
- /* 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);
- }
- }
+ ipd->snap_state = ED_view3d_cursor_snap_active();
+ ipd->snap_state->draw_point = true;
+ ipd->snap_state->draw_plane = true;
- ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
+ ipd->is_snap_found =
+ view3d_interactive_add_calc_snap(
+ C, event, ipd->co_src, ipd->matrix_orient, &ipd->use_snap, &ipd->is_snap_invert) != 0;
- 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->snap_state->draw_plane = false;
+ ED_view3d_cursor_snap_prevpoint_set(ipd->snap_state, ipd->co_src);
ipd->orient_axis = plane_axis;
for (int i = 0; i < 2; i++) {
@@ -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);
@@ -1243,20 +905,12 @@ static void view3d_interactive_add_exit(bContext *C, wmOperator *op)
UNUSED_VARS(C);
struct InteractivePlaceData *ipd = op->customdata;
+ ED_view3d_cursor_snap_deactive(ipd->snap_state);
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 +1028,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->snap_state, ipd->co_src);
+
/* Set secondary plane. */
/* Create normal. */
@@ -1521,19 +1177,8 @@ static int view3d_interactive_add_modal(bContext *C, wmOperator *op, const wmEve
/* Calculate the snap location on mouse-move or when toggling snap. */
ipd->is_snap_found = false;
if (ipd->use_snap) {
- 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_snap(
+ C, event, ipd->snap_co, NULL, NULL, NULL);
}
if (ipd->step_index == STEP_BASE) {
@@ -1603,6 +1248,98 @@ static bool view3d_interactive_add_poll(bContext *C)
return ELEM(mode, CTX_MODE_OBJECT, CTX_MODE_EDIT_MESH);
}
+static int idp_rna_plane_axis_get_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop))
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ return snap_state->plane_axis;
+}
+
+static void idp_rna_plane_axis_set_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop),
+ int value)
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ snap_state->plane_axis = (short)value;
+ ED_view3d_cursor_snap_state_default_set(snap_state);
+}
+
+static int idp_rna_plane_depth_get_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop))
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ return snap_state->plane_depth;
+}
+
+static void idp_rna_plane_depth_set_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop),
+ int value)
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ snap_state->plane_depth = value;
+ ED_view3d_cursor_snap_state_default_set(snap_state);
+}
+
+static int idp_rna_plane_orient_get_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop))
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ return snap_state->plane_orient;
+}
+
+static void idp_rna_plane_orient_set_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop),
+ int value)
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ snap_state->plane_orient = value;
+ ED_view3d_cursor_snap_state_default_set(snap_state);
+}
+
+static int idp_rna_snap_target_get_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop))
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ if (!snap_state->snap_elem_force) {
+ return PLACE_SNAP_TO_DEFAULT;
+ }
+
+ /* Make sure you keep a consistent #snap_mode. */
+ snap_state->snap_elem_force = SNAP_MODE_GEOM;
+ return PLACE_SNAP_TO_GEOMETRY;
+}
+
+static void idp_rna_snap_target_set_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop),
+ int value)
+{
+ short snap_mode = 0; /* #toolsettings->snap_mode. */
+ const enum ePlace_SnapTo snap_to = value;
+ if (snap_to == PLACE_SNAP_TO_GEOMETRY) {
+ snap_mode = SNAP_MODE_GEOM;
+ }
+
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ snap_state->snap_elem_force = snap_mode;
+ ED_view3d_cursor_snap_state_default_set(snap_state);
+}
+
+static bool idp_rna_use_plane_axis_auto_get_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop))
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ return snap_state->use_plane_axis_auto;
+}
+
+static void idp_rna_use_plane_axis_auto_set_fn(struct PointerRNA *UNUSED(ptr),
+ struct PropertyRNA *UNUSED(prop),
+ bool value)
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_state_get();
+ snap_state->use_plane_axis_auto = value;
+ ED_view3d_cursor_snap_state_default_set(snap_state);
+}
+
void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
{
/* identifiers */
@@ -1623,6 +1360,12 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
/* properties */
PropertyRNA *prop;
+ /* WORKAROUND: properties with `_funcs_runtime` should not be saved in keymaps.
+ * So reassign the #PROP_IDPROPERTY flag to trick the property as not being set.
+ * (See #RNA_property_is_set). */
+ PropertyFlag unsalvageable = PROP_SKIP_SAVE | PROP_HIDDEN | PROP_PTR_NO_OWNERSHIP |
+ PROP_IDPROPERTY;
+
/* Normally not accessed directly, leave unset and check the active tool. */
static const EnumPropertyItem primitive_type[] = {
{PLACE_PRIMITIVE_TYPE_CUBE, "CUBE", 0, "Cube", ""},
@@ -1632,6 +1375,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);
@@ -1641,7 +1385,9 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
RNA_def_property_ui_text(prop, "Plane Axis", "The axis used for placing the base region");
RNA_def_property_enum_default(prop, 2);
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_enum_funcs_runtime(
+ prop, idp_rna_plane_axis_get_fn, idp_rna_plane_axis_set_fn, NULL);
+ RNA_def_property_flag(prop, unsalvageable);
prop = RNA_def_boolean(ot->srna,
"plane_axis_auto",
@@ -1649,21 +1395,23 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
"Auto Axis",
"Select the closest axis when placing objects "
"(surface overrides)");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_boolean_funcs_runtime(
+ prop, idp_rna_use_plane_axis_auto_get_fn, idp_rna_use_plane_axis_auto_set_fn);
+ RNA_def_property_flag(prop, unsalvageable);
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 +1420,19 @@ 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);
+ RNA_def_property_enum_funcs_runtime(
+ prop, idp_rna_plane_depth_get_fn, idp_rna_plane_depth_set_fn, NULL);
+ RNA_def_property_flag(prop, unsalvageable);
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,9 +1441,11 @@ 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);
+ RNA_def_property_enum_funcs_runtime(
+ prop, idp_rna_plane_orient_get_fn, idp_rna_plane_orient_set_fn, NULL);
+ RNA_def_property_flag(prop, unsalvageable);
static const EnumPropertyItem snap_to_items[] = {
{PLACE_SNAP_TO_GEOMETRY, "GEOMETRY", 0, "Geometry", "Snap to all geometry"},
@@ -1704,7 +1456,9 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
RNA_def_property_ui_text(prop, "Snap to", "The target to use while snapping");
RNA_def_property_enum_default(prop, PLACE_SNAP_TO_GEOMETRY);
RNA_def_property_enum_items(prop, snap_to_items);
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ RNA_def_property_enum_funcs_runtime(
+ prop, idp_rna_snap_target_get_fn, idp_rna_snap_target_set_fn, NULL);
+ RNA_def_property_flag(prop, unsalvageable);
{ /* Plane Origin. */
static const EnumPropertyItem items[] = {
@@ -1752,24 +1506,19 @@ 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_free_fn(void *customdata)
{
- 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});
+ V3DSnapCursorState *snap_state = customdata;
+ ED_view3d_cursor_snap_deactive(snap_state);
+}
- /* Don't handle any events, this is for display only. */
- gizmo->flag |= WM_GIZMO_HIDDEN_KEYMAP;
- }
+static void WIDGETGROUP_placement_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
+{
+ V3DSnapCursorState *snap_state = ED_view3d_cursor_snap_active();
+ snap_state->draw_plane = true;
- /* Sets the gizmos custom-data which has its own free callback. */
- preview_plane_cursor_setup(gzgroup);
+ gzgroup->customdata = snap_state;
+ gzgroup->customdata_free = preview_plane_free_fn;
}
void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
@@ -1787,353 +1536,3 @@ void VIEW3D_GGT_placement(wmGizmoGroupType *gzgt)
}
/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \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)
-{
- 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;
-}
-
-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])
-{
- 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);
-}
-
-/* -------------------------------------------------------------------- */
-/** \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)
-{
- 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) {
- return;
- }
-
- /* Check this gizmo group is in the region. */
- {
- 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;
- }
- }
-
- 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);
- }
- 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();
- }
-}
-
-static void preview_plane_cursor_free(void *customdata)
-{
- struct PlacementCursor *plc = customdata;
-
- /* 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);
-}
-
-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);
-}
-
-static void preview_plane_cursor_visible_set(wmGizmoGroup *gzgroup, bool do_draw)
-{
- struct PlacementCursor *plc = gzgroup->customdata;
- plc->do_draw = do_draw;
-}
-
-/** \} */