Fix UV gizmos poll failing with multiple objects
authorCampbell Barton <ideasman42@gmail.com>
Thu, 9 Jan 2020 06:50:52 +0000 (17:50 +1100)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 9 Jan 2020 06:50:52 +0000 (17:50 +1100)
Only the active objects UV selection was checked.
This also avoids checking UV selection for every poll call,
now this is only done on refresh.

source/blender/editors/include/ED_uvedit.h
source/blender/editors/transform/transform_gizmo_2d.c
source/blender/editors/uvedit/uvedit_ops.c

index 1debdee53e9c199f9d960393742034fe5021646f..c912778afd8c0a938276f0a83fd13d1338667208 100644 (file)
@@ -65,6 +65,12 @@ bool ED_uvedit_center_multi(const struct Scene *scene,
                             float r_cent[2],
                             char mode);
 
+bool ED_uvedit_center_from_pivot_ex(struct SpaceImage *sima,
+                                    struct Scene *scene,
+                                    struct ViewLayer *view_layer,
+                                    float r_center[2],
+                                    char mode,
+                                    bool *r_has_select);
 bool ED_uvedit_center_from_pivot(struct SpaceImage *sima,
                                  struct Scene *scene,
                                  struct ViewLayer *view_layer,
index 84309c541af6de5a5425708942fbd4246d32d3d3..793552865a654691e0972d655676cda804b01470 100644 (file)
 /** \name Shared Callback's
  */
 
+static bool gizmo2d_generic_poll(const bContext *C, wmGizmoGroupType *gzgt)
+{
+  if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
+    return false;
+  }
+
+  if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
+    return false;
+  }
+
+  ScrArea *sa = CTX_wm_area(C);
+  switch (sa->spacetype) {
+    case SPACE_IMAGE: {
+      SpaceImage *sima = sa->spacedata.first;
+      Object *obedit = CTX_data_edit_object(C);
+      if (!ED_space_image_show_uvedit(sima, obedit)) {
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
 static void gizmo2d_pivot_point_message_subscribe(struct wmGizmoGroup *gzgroup,
                                                   struct wmMsgBus *mbus,
                                                   /* Additional args. */
@@ -180,7 +204,7 @@ static GizmoGroup2D *gizmogroup2d_init(wmGizmoGroup *gzgroup)
 /**
  * Calculates origin in view space, use with #gizmo2d_origin_to_region.
  */
-static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max)
+static bool gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min, float *r_max)
 {
   float min_buf[2], max_buf[2];
   if (r_min == NULL) {
@@ -191,6 +215,7 @@ static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
   }
 
   ScrArea *sa = CTX_wm_area(C);
+  bool changed = false;
   if (sa->spacetype == SPACE_IMAGE) {
     SpaceImage *sima = sa->spacedata.first;
     Scene *scene = CTX_data_scene(C);
@@ -199,29 +224,33 @@ static void gizmo2d_calc_bounds(const bContext *C, float *r_center, float *r_min
     uint objects_len = 0;
     Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
         view_layer, NULL, &objects_len);
-    if (!ED_uvedit_minmax_multi(scene, ima, objects, objects_len, r_min, r_max)) {
-      zero_v2(r_min);
-      zero_v2(r_max);
+    if (ED_uvedit_minmax_multi(scene, ima, objects, objects_len, r_min, r_max)) {
+      changed = true;
     }
     MEM_freeN(objects);
   }
-  else {
+
+  if (changed == false) {
     zero_v2(r_min);
     zero_v2(r_max);
   }
+
   mid_v2_v2v2(r_center, r_min, r_max);
+  return changed;
 }
 
-static void gizmo2d_calc_center(const bContext *C, float r_center[2])
+static bool gizmo2d_calc_center(const bContext *C, float r_center[2])
 {
   ScrArea *sa = CTX_wm_area(C);
+  bool has_select = false;
   zero_v2(r_center);
   if (sa->spacetype == SPACE_IMAGE) {
     SpaceImage *sima = sa->spacedata.first;
     Scene *scene = CTX_data_scene(C);
     ViewLayer *view_layer = CTX_data_view_layer(C);
-    ED_uvedit_center_from_pivot(sima, scene, view_layer, r_center, sima->around);
+    ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, sima->around, &has_select);
   }
+  return has_select;
 }
 
 /**
@@ -366,11 +395,12 @@ static void gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 {
   GizmoGroup2D *ggd = gzgroup->customdata;
   float origin[3];
+  bool has_select;
   if (ggd->no_cage) {
-    gizmo2d_calc_center(C, origin);
+    has_select = gizmo2d_calc_center(C, origin);
   }
   else {
-    gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
+    has_select = gizmo2d_calc_bounds(C, origin, ggd->min, ggd->max);
   }
   copy_v2_v2(ggd->origin, origin);
   bool show_cage = !ggd->no_cage && !equals_v2v2(ggd->min, ggd->max);
@@ -385,58 +415,66 @@ static void gizmo2d_xform_refresh(const bContext *C, wmGizmoGroup *gzgroup)
     }
   }
 
-  if (show_cage) {
-    ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
+  if (has_select == false) {
     for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
-      wmGizmo *gz = ggd->translate_xy[i];
-      gz->flag |= WM_GIZMO_HIDDEN;
+      ggd->translate_xy[i]->flag |= WM_GIZMO_HIDDEN;
     }
+    ggd->cage->flag |= WM_GIZMO_HIDDEN;
   }
   else {
-    ggd->cage->flag |= WM_GIZMO_HIDDEN;
-    for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
-      wmGizmo *gz = ggd->translate_xy[i];
-      gz->flag &= ~WM_GIZMO_HIDDEN;
+    if (show_cage) {
+      ggd->cage->flag &= ~WM_GIZMO_HIDDEN;
+      for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
+        wmGizmo *gz = ggd->translate_xy[i];
+        gz->flag |= WM_GIZMO_HIDDEN;
+      }
+    }
+    else {
+      ggd->cage->flag |= WM_GIZMO_HIDDEN;
+      for (int i = 0; i < ARRAY_SIZE(ggd->translate_xy); i++) {
+        wmGizmo *gz = ggd->translate_xy[i];
+        gz->flag &= ~WM_GIZMO_HIDDEN;
+      }
     }
-  }
 
-  if (show_cage) {
-    wmGizmoOpElem *gzop;
-    float mid[2];
-    const float *min = ggd->min;
-    const float *max = ggd->max;
-    mid_v2_v2v2(mid, min, max);
-
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
-    PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
-
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
-
-    gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
-    RNA_property_float_set_array(
-        &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+    if (show_cage) {
+      wmGizmoOpElem *gzop;
+      float mid[2];
+      const float *min = ggd->min;
+      const float *max = ggd->max;
+      mid_v2_v2v2(mid, min, max);
+
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X);
+      PropertyRNA *prop_center_override = RNA_struct_find_property(&gzop->ptr, "center_override");
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){max[0], mid[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){min[0], mid[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){mid[0], max[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){mid[0], min[1], 0.0f});
+
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MIN_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){max[0], max[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MIN_X_MAX_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){max[0], min[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MIN_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){min[0], max[1], 0.0f});
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_SCALE_MAX_X_MAX_Y);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){min[0], min[1], 0.0f});
+
+      gzop = WM_gizmo_operator_get(ggd->cage, ED_GIZMO_CAGE2D_PART_ROTATE);
+      RNA_property_float_set_array(
+          &gzop->ptr, prop_center_override, (float[3]){mid[0], mid[1], 0.0f});
+    }
   }
 }
 
@@ -460,50 +498,6 @@ static void gizmo2d_xform_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
   ggd->cage->matrix_offset[1][1] = (ggd->max[1] - ggd->min[1]);
 }
 
-/* TODO (Julian)
- * - Called on every redraw, better to do a more simple poll and check for selection in _refresh
- * - UV editing only, could be expanded for other things.
- */
-static bool gizmo2d_xform_poll(const bContext *C, wmGizmoGroupType *gzgt)
-{
-  if (!ED_gizmo_poll_or_unlink_delayed_from_tool(C, gzgt)) {
-    return false;
-  }
-
-  if ((U.gizmo_flag & USER_GIZMO_DRAW) == 0) {
-    return false;
-  }
-
-  SpaceImage *sima = CTX_wm_space_image(C);
-  Object *obedit = CTX_data_edit_object(C);
-
-  if (ED_space_image_show_uvedit(sima, obedit)) {
-    Image *ima = ED_space_image(sima);
-    Scene *scene = CTX_data_scene(C);
-    BMEditMesh *em = BKE_editmesh_from_object(obedit);
-    BMFace *efa;
-    BMLoop *l;
-    BMIter iter, liter;
-
-    const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
-
-    /* check if there's a selected poly */
-    BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
-      if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
-        continue;
-      }
-
-      BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
-        if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
-          return true;
-        }
-      }
-    }
-  }
-
-  return false;
-}
-
 static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C,
                                                     struct wmGizmoGroup *gzgroup,
                                                     struct wmMsgBus *mbus)
@@ -516,7 +510,7 @@ static void gizmo2d_xform_no_cage_message_subscribe(const struct bContext *C,
 
 void ED_widgetgroup_gizmo2d_xform_callbacks_set(wmGizmoGroupType *gzgt)
 {
-  gzgt->poll = gizmo2d_xform_poll;
+  gzgt->poll = gizmo2d_generic_poll;
   gzgt->setup = gizmo2d_xform_setup;
   gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
   gzgt->refresh = gizmo2d_xform_refresh;
@@ -564,8 +558,19 @@ static void gizmo2d_resize_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 {
   GizmoGroup_Resize2D *ggd = gzgroup->customdata;
   float origin[3];
-  gizmo2d_calc_center(C, origin);
-  copy_v2_v2(ggd->origin, origin);
+  const bool has_select = gizmo2d_calc_center(C, origin);
+
+  if (has_select == false) {
+    for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) {
+      ggd->gizmo_xy[i]->flag |= WM_GIZMO_HIDDEN;
+    }
+  }
+  else {
+    for (int i = 0; i < ARRAY_SIZE(ggd->gizmo_xy); i++) {
+      ggd->gizmo_xy[i]->flag &= ~WM_GIZMO_HIDDEN;
+    }
+    copy_v2_v2(ggd->origin, origin);
+  }
 }
 
 static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
@@ -592,11 +597,6 @@ static void gizmo2d_resize_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup
   }
 }
 
-static bool gizmo2d_resize_poll(const bContext *C, wmGizmoGroupType *gzgt)
-{
-  return gizmo2d_xform_poll(C, gzgt);
-}
-
 static void gizmo2d_resize_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 {
 
@@ -666,7 +666,7 @@ static void gizmo2d_resize_message_subscribe(const struct bContext *C,
 
 void ED_widgetgroup_gizmo2d_resize_callbacks_set(wmGizmoGroupType *gzgt)
 {
-  gzgt->poll = gizmo2d_resize_poll;
+  gzgt->poll = gizmo2d_generic_poll;
   gzgt->setup = gizmo2d_resize_setup;
   gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
   gzgt->refresh = gizmo2d_resize_refresh;
@@ -705,8 +705,15 @@ static void gizmo2d_rotate_refresh(const bContext *C, wmGizmoGroup *gzgroup)
 {
   GizmoGroup_Rotate2D *ggd = gzgroup->customdata;
   float origin[3];
-  gizmo2d_calc_center(C, origin);
-  copy_v2_v2(ggd->origin, origin);
+  const bool has_select = gizmo2d_calc_center(C, origin);
+
+  if (has_select == false) {
+    ggd->gizmo->flag |= WM_GIZMO_HIDDEN;
+  }
+  else {
+    ggd->gizmo->flag &= ~WM_GIZMO_HIDDEN;
+    copy_v2_v2(ggd->origin, origin);
+  }
 }
 
 static void gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup)
@@ -731,11 +738,6 @@ static void gizmo2d_rotate_draw_prepare(const bContext *C, wmGizmoGroup *gzgroup
   WM_gizmo_set_matrix_location(gz, origin);
 }
 
-static bool gizmo2d_rotate_poll(const bContext *C, wmGizmoGroupType *gzgt)
-{
-  return gizmo2d_xform_poll(C, gzgt);
-}
-
 static void gizmo2d_rotate_setup(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
 {
 
@@ -780,7 +782,7 @@ static void gizmo2d_rotate_message_subscribe(const struct bContext *C,
 
 void ED_widgetgroup_gizmo2d_rotate_callbacks_set(wmGizmoGroupType *gzgt)
 {
-  gzgt->poll = gizmo2d_rotate_poll;
+  gzgt->poll = gizmo2d_generic_poll;
   gzgt->setup = gizmo2d_rotate_setup;
   gzgt->setup_keymap = WM_gizmogroup_setup_keymap_generic_maybe_drag;
   gzgt->refresh = gizmo2d_rotate_refresh;
index 2b26151af8604c377ff3d68a9d1ac2709f47d008..5be3f67665890e0affb26b835ded4d2aee0118d3 100644 (file)
@@ -755,14 +755,25 @@ bool ED_uvedit_center_multi(const Scene *scene,
   return changed;
 }
 
-bool ED_uvedit_center_from_pivot(
-    SpaceImage *sima, Scene *scene, ViewLayer *view_layer, float r_center[2], char mode)
+bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima,
+                                    Scene *scene,
+                                    ViewLayer *view_layer,
+                                    float r_center[2],
+                                    char mode,
+                                    bool *r_has_select)
 {
   bool changed = false;
   switch (mode) {
     case V3D_AROUND_CURSOR: {
       copy_v2_v2(r_center, sima->cursor);
       changed = true;
+      if (r_has_select != NULL) {
+        uint objects_len = 0;
+        Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
+            view_layer, ((View3D *)NULL), &objects_len);
+        *r_has_select = uv_select_is_any_selected_multi(scene, sima->image, objects, objects_len);
+        MEM_freeN(objects);
+      }
       break;
     }
     default: {
@@ -771,12 +782,21 @@ bool ED_uvedit_center_from_pivot(
           view_layer, ((View3D *)NULL), &objects_len);
       changed = ED_uvedit_center_multi(scene, sima->image, objects, objects_len, r_center, mode);
       MEM_freeN(objects);
+      if (r_has_select != NULL) {
+        *r_has_select = changed;
+      }
       break;
     }
   }
   return changed;
 }
 
+bool ED_uvedit_center_from_pivot(
+    SpaceImage *sima, Scene *scene, ViewLayer *view_layer, float r_center[2], char mode)
+{
+  return ED_uvedit_center_from_pivot_ex(sima, scene, view_layer, r_center, mode, NULL);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */