[Bf-blender-cvs] [80393a0ebad] master: UV: add rip tool

Campbell Barton noreply at git.blender.org
Mon Jul 6 10:30:15 CEST 2020


Commit: 80393a0ebadc7b8e825a6ce64204bf4424650fe5
Author: Campbell Barton
Date:   Mon Jul 6 17:41:36 2020 +1000
Branches: master
https://developer.blender.org/rB80393a0ebadc7b8e825a6ce64204bf4424650fe5

UV: add rip tool

New rip tool matching edit-mesh rip functionality.

Useful as disconnecting UV's, especially for loops is inconvenient
without this.

This uses 'V' to rip, changing stitch to 'Alt-V'.

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

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	source/blender/editors/include/ED_uvedit.h
M	source/blender/editors/space_api/spacetypes.c
M	source/blender/editors/uvedit/CMakeLists.txt
M	source/blender/editors/uvedit/uvedit_intern.h
M	source/blender/editors/uvedit/uvedit_ops.c
A	source/blender/editors/uvedit/uvedit_rip.c

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

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 4b037f209bb..ec5216226ec 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -867,7 +867,8 @@ def km_uv_editor(params):
         *_template_items_select_actions(params, "uv.select_all"),
         ("uv.select_pinned", {"type": 'P', "value": 'PRESS', "shift": True}, None),
         op_menu("IMAGE_MT_uvs_weldalign", {"type": 'W', "value": 'PRESS', "shift": True}),
-        ("uv.stitch", {"type": 'V', "value": 'PRESS'}, None),
+        ("uv.stitch", {"type": 'V', "value": 'PRESS', "alt": True}, None),
+        ("uv.rip_move", {"type": 'V', "value": 'PRESS'}, None),
         ("uv.pin", {"type": 'P', "value": 'PRESS'},
          {"properties": [("clear", False)]}),
         ("uv.pin", {"type": 'P', "value": 'PRESS', "alt": True},
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index f656aaf9c07..7e9c3ba90ad 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -47,6 +47,7 @@ struct wmKeyConfig;
 
 /* uvedit_ops.c */
 void ED_operatortypes_uvedit(void);
+void ED_operatormacros_uvedit(void);
 void ED_keymap_uvedit(struct wmKeyConfig *keyconf);
 
 bool ED_uvedit_minmax(const struct Scene *scene,
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index e084d5fcdf2..49dbba5eba9 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -159,6 +159,7 @@ void ED_spacemacros_init(void)
    * We need to have them go after python operators too */
   ED_operatormacros_armature();
   ED_operatormacros_mesh();
+  ED_operatormacros_uvedit();
   ED_operatormacros_metaball();
   ED_operatormacros_node();
   ED_operatormacros_object();
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index b40b82c50fb..72a262b8983 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -39,6 +39,7 @@ set(SRC
   uvedit_buttons.c
   uvedit_draw.c
   uvedit_ops.c
+  uvedit_rip.c
   uvedit_parametrizer.c
   uvedit_select.c
   uvedit_smart_stitch.c
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 31384d6df17..1d90cc5ae91 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -106,6 +106,7 @@ void UV_OT_pack_islands(struct wmOperatorType *ot);
 void UV_OT_reset(struct wmOperatorType *ot);
 void UV_OT_sphere_project(struct wmOperatorType *ot);
 void UV_OT_unwrap(struct wmOperatorType *ot);
+void UV_OT_rip(struct wmOperatorType *ot);
 void UV_OT_stitch(struct wmOperatorType *ot);
 
 /* uvedit_select.c */
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 8d85de3b141..3b913a49a16 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -2087,6 +2087,7 @@ void ED_operatortypes_uvedit(void)
 
   WM_operatortype_append(UV_OT_align);
 
+  WM_operatortype_append(UV_OT_rip);
   WM_operatortype_append(UV_OT_stitch);
 
   WM_operatortype_append(UV_OT_seams_from_islands);
@@ -2111,6 +2112,21 @@ void ED_operatortypes_uvedit(void)
   WM_operatortype_append(UV_OT_cursor_set);
 }
 
+void ED_operatormacros_uvedit(void)
+{
+  wmOperatorType *ot;
+  wmOperatorTypeMacro *otmacro;
+
+  ot = WM_operatortype_append_macro("UV_OT_rip_move",
+                                    "UV Rip Move",
+                                    "unstitch UV's and move the result",
+                                    OPTYPE_UNDO | OPTYPE_REGISTER);
+  WM_operatortype_macro_define(ot, "UV_OT_rip");
+  otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+  RNA_enum_set(otmacro->ptr, "proportional", 0);
+  RNA_boolean_set(otmacro->ptr, "mirror", false);
+}
+
 void ED_keymap_uvedit(wmKeyConfig *keyconf)
 {
   wmKeyMap *keymap;
diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c
new file mode 100644
index 00000000000..99d1b4f1bf5
--- /dev/null
+++ b/source/blender/editors/uvedit/uvedit_rip.c
@@ -0,0 +1,1028 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup eduv
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_ghash.h"
+#include "BLI_linklist_stack.h"
+#include "BLI_math.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_image_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
+#include "BKE_report.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_uvedit.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "UI_view2d.h"
+
+#include "uvedit_intern.h"
+
+/* -------------------------------------------------------------------- */
+/** \name UV Loop Rip Data Struct
+ * \{ */
+
+/** Unordered loop data, stored in #BMLoop.head.index. */
+typedef struct ULData {
+  /** When this UV is selected as well as the next UV. */
+  uint is_select_edge : 1;
+  /**
+   * When only this UV is selected and none of the other UV's
+   * around the connected fan are attached to an edge.
+   *
+   * In this case there is no need to detect contiguous loops,
+   * each isolated case is handled on it's own, no need to walk over selected edges.
+   *
+   * \note This flag isn't flushed to other loops which could also have this enabled.
+   * Currently it's not necessary since we can start off on any one of these loops,
+   * then walk onto the other loops around the uv-fan, without having the flag to be
+   * set on all loops.
+   */
+  uint is_select_vert_single : 1;
+  /** This could be a face-tag. */
+  uint is_select_all : 1;
+  /** Use when building the rip-pairs stack. */
+  uint in_stack : 1;
+  /** Set once this has been added into a #UVRipPairs. */
+  uint in_rip_pairs : 1;
+  /** The side this loop is part of. */
+  uint side : 1;
+  /**
+   * Paranoid check to ensure we don't enter eternal loop swapping sides,
+   * this could happen with float precision error, making a swap to measure as slightly better
+   * depending on the order of addition.
+   */
+  uint side_was_swapped : 1;
+} ULData;
+
+/** Ensure this fits in an int (loop index). */
+BLI_STATIC_ASSERT(sizeof(ULData) <= sizeof(int), "");
+
+BLI_INLINE ULData *UL(BMLoop *l)
+{
+  return (ULData *)&l->head.index;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name UV Utilities
+ * \{ */
+
+static bool bm_loop_share_uv_by_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+{
+  BLI_assert(l_a->e == l_b->e);
+  MLoopUV *luv_a_curr = BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
+  MLoopUV *luv_a_next = BM_ELEM_CD_GET_VOID_P(l_a->next, cd_loop_uv_offset);
+  MLoopUV *luv_b_curr = BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
+  MLoopUV *luv_b_next = BM_ELEM_CD_GET_VOID_P(l_b->next, cd_loop_uv_offset);
+  if (l_a->v != l_b->v) {
+    SWAP(MLoopUV *, luv_b_curr, luv_b_next);
+  }
+  return (equals_v2v2(luv_a_curr->uv, luv_b_curr->uv) &&
+          equals_v2v2(luv_a_next->uv, luv_b_next->uv));
+}
+
+static bool bm_loop_share_uv_by_vert_check(BMEdge *e,
+                                           BMLoop *l_a,
+                                           BMLoop *l_b,
+                                           const int cd_loop_uv_offset)
+{
+  BLI_assert(l_a->v == l_b->v);
+
+  {
+    const MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
+    const MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
+    if (!equals_v2v2(luv_a->uv, luv_b->uv)) {
+      return false;
+    }
+  }
+
+  /* No need for NULL checks, these will always succeed. */
+  const BMLoop *l_other_a = BM_loop_other_vert_loop_by_edge(l_a, e);
+  const BMLoop *l_other_b = BM_loop_other_vert_loop_by_edge(l_b, e);
+
+  {
+    const MLoopUV *luv_other_a = BM_ELEM_CD_GET_VOID_P(l_other_a, cd_loop_uv_offset);
+    const MLoopUV *luv_other_b = BM_ELEM_CD_GET_VOID_P(l_other_b, cd_loop_uv_offset);
+    if (!equals_v2v2(luv_other_a->uv, luv_other_b->uv)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static BMLoop *bm_loop_find_other_radial_loop_with_visible_face(BMLoop *l_src,
+                                                                const int cd_loop_uv_offset)
+{
+  BMLoop *l_other = NULL;
+  BMLoop *l_iter = l_src->radial_next;
+  if (l_iter != l_src) {
+    do {
+      if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) && UL(l_iter)->is_select_edge &&
+          bm_loop_share_uv_by_edge_check(l_src, l_iter, cd_loop_uv_offset)) {
+        /* Check UV's are contiguous. */
+        if (l_other == NULL) {
+          l_other = l_iter;
+        }
+        else {
+          /* Only use when there is a single alternative. */
+          l_other = NULL;
+          break;
+        }
+      }
+    } while ((l_iter = l_iter->radial_ne

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list