[Bf-blender-cvs] [4950022e7d1] master: Object: add-object option to place on the surface normal

Campbell Barton noreply at git.blender.org
Wed Jul 22 14:39:38 CEST 2020


Commit: 4950022e7d1aa7d01301f7d2bf173e84ca95b719
Author: Campbell Barton
Date:   Wed Jul 22 22:28:13 2020 +1000
Branches: master
https://developer.blender.org/rB4950022e7d1aa7d01301f7d2bf173e84ca95b719

Object: add-object option to place on the surface normal

Optionally use the surface normal under the mouse cursor.

===================================================================

M	release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
M	source/blender/editors/space_view3d/view3d_placement.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 818130976d3..83b3a27154a 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -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")
 
diff --git a/source/blender/editors/space_view3d/view3d_placement.c b/source/blender/editors/space_view3d/view3d_placement.c
index ee14d19c177..b7219290654 100644
--- a/source/blender/editors/space_view3d/view3d_placement.c
+++ b/source/blender/editors/space_view3d/view3d_placement.c
@@ -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,30 +634,69 @@ 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;
 
+  /* Assign snap gizmo which is may be used as part of the tool. */
+  {
+    wmGizmoMap *gzmap = ipd->region->gizmo_map;
+    wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
+    if ((gzgroup != NULL) && gzgroup->gizmos.first) {
+      ipd->snap_gizmo = gzgroup->gizmos.first;
+    }
+  }
+
   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;
 
-  /* Assign snap gizmo which is may be used as part of the tool. */
-  {
-    wmGizmoMap *gzmap = ipd->region->gizmo_map;
-    wmGizmoGroup *gzgroup = gzmap ? WM_gizmomap_group_find(gzmap, view3d_gzgt_placement_id) : NULL;
-    if ((gzgroup != NULL) && gzgroup->gizmos.first) {
-      ipd->snap_gizmo = gzgroup->gizmos.first;
-    }
-  }
-
   {
     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);



More information about the Bf-blender-cvs mailing list