Object: add-object option to place on the surface normal
Optionally use the surface normal under the mouse cursor.
This commit is contained in:
parent
980dd43bd4
commit
4950022e7d
@ -455,6 +455,11 @@ class _defs_view3d_add:
|
||||
row = layout.row()
|
||||
row.prop(props, "plane_axis", text="")
|
||||
row = layout.row()
|
||||
row.scale_x = 0.8
|
||||
row.label(text="Orientation:")
|
||||
row = layout.row()
|
||||
row.prop(props, "plane_orientation", text="")
|
||||
row = layout.row()
|
||||
row.scale_x = 0.7
|
||||
row.prop(props, "plane_origin")
|
||||
|
||||
|
@ -86,6 +86,11 @@ enum ePlace_Depth {
|
||||
PLACE_DEPTH_CURSOR_VIEW = 3,
|
||||
};
|
||||
|
||||
enum ePlace_Orient {
|
||||
PLACE_ORIENT_SURFACE = 1,
|
||||
PLACE_ORIENT_DEFAULT = 2,
|
||||
};
|
||||
|
||||
struct InteractivePlaceData {
|
||||
/* Window manager variables (set these even when waiting for input). */
|
||||
Scene *scene;
|
||||
@ -145,16 +150,96 @@ struct InteractivePlaceData {
|
||||
/* On-screen snap distance. */
|
||||
#define MVAL_MAX_PX_DIST 12.0f
|
||||
|
||||
static bool idp_snap_point_from_gizmo(wmGizmo *gz, float r_location[3])
|
||||
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, "location");
|
||||
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,
|
||||
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,
|
||||
SCE_SNAP_MODE_FACE,
|
||||
&(const struct SnapObjectParams){
|
||||
.snap_select = SNAP_ALL,
|
||||
.use_object_edit_cage = true,
|
||||
},
|
||||
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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@ -549,21 +634,14 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
|
||||
const int plane_axis = RNA_enum_get(op->ptr, "plane_axis");
|
||||
const enum ePlace_Depth plane_depth = RNA_enum_get(op->ptr, "plane_depth");
|
||||
const enum ePlace_Origin plane_origin = RNA_enum_get(op->ptr, "plane_origin");
|
||||
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;
|
||||
|
||||
RegionView3D *rv3d = ipd->region->regiondata;
|
||||
|
||||
ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
|
||||
|
||||
ED_transform_calc_orientation_from_type(C, ipd->matrix_orient);
|
||||
|
||||
ipd->orient_axis = plane_axis;
|
||||
ipd->is_centered_init = (plane_origin == PLACE_ORIGIN_CENTER);
|
||||
ipd->step[0].is_centered = ipd->is_centered_init;
|
||||
ipd->step[1].is_centered = ipd->is_centered_init;
|
||||
ipd->step_index = STEP_BASE;
|
||||
|
||||
/* Assign snap gizmo which is may be used as part of the tool. */
|
||||
{
|
||||
wmGizmoMap *gzmap = ipd->region->gizmo_map;
|
||||
@ -573,6 +651,52 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
|
||||
}
|
||||
}
|
||||
|
||||
ipd->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
|
||||
|
||||
ED_transform_calc_orientation_from_type(C, ipd->matrix_orient);
|
||||
|
||||
/* Set the orientation. */
|
||||
if (plane_orient == PLACE_ORIENT_SURFACE) {
|
||||
bool snap_context_free = false;
|
||||
SnapObjectContext *snap_context =
|
||||
(ipd->snap_gizmo ? ED_gizmotypes_snap_3d_context_ensure(
|
||||
ipd->scene, ipd->region, ipd->v3d, ipd->snap_gizmo) :
|
||||
NULL);
|
||||
if (snap_context == NULL) {
|
||||
snap_context = ED_transform_snap_object_context_create_view3d(
|
||||
ipd->scene, 0, ipd->region, ipd->v3d);
|
||||
snap_context_free = true;
|
||||
}
|
||||
|
||||
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 = ipd->snap_gizmo ?
|
||||
idp_snap_normal_from_gizmo(ipd->snap_gizmo, normal_fallback) :
|
||||
false;
|
||||
|
||||
if (idp_poject_surface_normal(snap_context,
|
||||
CTX_data_ensure_evaluated_depsgraph(C),
|
||||
mval_fl,
|
||||
use_normal_fallback ? ipd->matrix_orient : NULL,
|
||||
use_normal_fallback ? normal_fallback : NULL,
|
||||
matrix_orient_surface)) {
|
||||
copy_m3_m3(ipd->matrix_orient, matrix_orient_surface);
|
||||
}
|
||||
|
||||
if (snap_context_free) {
|
||||
ED_transform_snap_object_context_destroy(snap_context);
|
||||
}
|
||||
}
|
||||
|
||||
ipd->orient_axis = plane_axis;
|
||||
ipd->is_centered_init = (plane_origin == PLACE_ORIGIN_CENTER);
|
||||
ipd->step[0].is_centered = ipd->is_centered_init;
|
||||
ipd->step[1].is_centered = ipd->is_centered_init;
|
||||
ipd->step_index = STEP_BASE;
|
||||
|
||||
{
|
||||
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "primitive_type");
|
||||
if (RNA_property_is_set(op->ptr, prop)) {
|
||||
@ -618,8 +742,6 @@ static void view3d_interactive_add_begin(bContext *C, wmOperator *op, const wmEv
|
||||
plane_from_point_normal_v3(
|
||||
ipd->step[0].plane, ipd->scene->cursor.location, ipd->matrix_orient[ipd->orient_axis]);
|
||||
|
||||
const float mval_fl[2] = {UNPACK2(event->mval)};
|
||||
|
||||
const bool is_snap_found = ipd->snap_gizmo ?
|
||||
idp_snap_point_from_gizmo(ipd->snap_gizmo, ipd->co_src) :
|
||||
false;
|
||||
@ -1102,6 +1224,25 @@ void VIEW3D_OT_interactive_add(struct wmOperatorType *ot)
|
||||
RNA_def_property_enum_items(prop, origin_items);
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
static const EnumPropertyItem plane_orientation_items[] = {
|
||||
{PLACE_ORIENT_SURFACE,
|
||||
"SURFACE",
|
||||
ICON_SNAP_NORMAL,
|
||||
"Surface",
|
||||
"Use the surface normal (the transform orientation as a fallback)"},
|
||||
{PLACE_ORIENT_DEFAULT,
|
||||
"DEFAULT",
|
||||
ICON_ORIENTATION_GLOBAL,
|
||||
"Default",
|
||||
"Use the current transform orientation"},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
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_items(prop, plane_orientation_items);
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* When not accessed via a tool. */
|
||||
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
|
||||
|
Loading…
x
Reference in New Issue
Block a user