Skip to content

UV Shortest Mark

Interactive modal for marking shortest paths on a mesh with seams, sharp edges, crease, or bevel-weight, bounded by user-chosen barrier edges. Hover an edge (Direction mode) or click two vertices (Build mode) to preview a path, tune it with flow/smooth/curvature/arch wheel modifiers, then commit. Also provides a one-shot "mark by angle" pass and a separate sub-mode that re-routes already-marked chains through smoother neighbours.

bl_idname: iops.mesh_uv_shortest_mark Mode: Edit Mesh Context: VIEW_3D Modal: yes HUD: yes

Overview

The operator builds a per-topology graph (CSR adjacency + cached edge lengths, face-angle bias, barrier mask) and runs Dijkstra, A*, or a greedy edge-loop walk over it. A native Rust extension (mesh_uv_shortest_mark_lib) is used when present, with a Python fallback. The path can be steered by:

  • Barrier edges (Seam / Sharp / Crease / Bevel Weight) which the search refuses to cross.
  • Flow angle — caps the directional change between successive edges.
  • Curvature — biases the search toward convex or concave creases.
  • Smooth — a shortcut-based post-pass that tries to replace short sub-segments with shorter alternates.
  • Arch (Build mode only) — deforms the baseline path into a perpendicular-pushed arc using interior waypoints.

Two path modes coexist: Direction projects an arm forward from the hovered edge until it hits a barrier; Build chains anchor-to-target hops, committing on each click. A separate "Smooth Marked" sub-mode (F) recomputes all currently marked chains under a stronger smoothing window and previews the diff before commit.

A TRIANGULATE modifier on the active object, if present, is temporarily hidden during the modal so raycasts hit the original geometry; it is restored on exit.

Usage

  • Active object must be a mesh in Edit Mode.
  • No default keymap binding (the entry in hotkeys_default.py uses the F19 placeholder). Invoke via the operator search or any user-assigned shortcut/menu entry.
  • On invoke, Build mode is forced as the default regardless of the saved scene property.
  • Direction mode: hover an edge, scroll/keys to tune, LMB to apply.
  • Build mode: LMB once to set an anchor, hover to preview the path to the closest face vertex, LMB again to apply marks and chain the anchor forward to that vertex. Press Q to drop the anchor and start a fresh chain.

Persistent settings (barrier type, mark type, algorithm, flow, sharp angle, smooth level, path mode index, curvature) are stored on scene.IOPS on Space/Esc.

Key Action
MouseMove Raycast and update hovered edge / target vertex and preview path
LMB Direction: apply marks to preview path. Build: set anchor (first click) or apply + chain (second click)
E Cycle barrier type (Seam → Sharp → Crease → Bevel Weight)
R Cycle mark type (same enum as barrier)
A Cycle algorithm (Dijkstra → A* → Edge Loop)
Q New mark — clear Build-mode anchor
Ctrl+Q Toggle path mode (Direction ↔ Build)
S Mark / unmark every edge whose dihedral exceeds the current sharp-angle threshold (toggles each press)
D Clear marks of the current mark type along the preview path
F Enter Smooth Marked sub-mode
Ctrl+Wheel Adjust flow angle (0–180°, step 5)
Shift+Wheel Adjust smooth level (0–10, step 1)
Alt+Wheel Adjust sharp-angle threshold (0–180°, step 5; also resets the angle-mark toggle state)
Ctrl+Shift+Wheel Adjust curvature bias (−100…+100, step 10)
Ctrl+Alt+Wheel Adjust arch strength (−10…+10, step 1; Build mode)
MMB / Wheel (unmodified) Pass through to viewport navigation
Ctrl+Z Pop one undo step, invalidate graph cache, redraw preview
H Toggle HUD / help overlay (handled by shared HUD layer)
Space / Enter / NumpadEnter Finish (saves scene props)
Esc Cancel (also saves scene props)

Smooth Marked sub-mode (entered with F):

Key Action
Alt+Wheel Magnet (−10…+10) — maps to curvature bias for the re-route
Shift+Wheel Iteration count (1…100)
Space / Enter / NumpadEnter Accept proposal (clears dropped marks, applies new marks)
F / Esc Cancel sub-mode without committing
MMB / Wheel / MouseMove Pass through to viewport navigation

All other keys are swallowed while the sub-mode is active.

HUD

The HUD overlay (uv_shortest_mark) and the status bar both show the live parameter set:

  • Barrier → Mark labels, current algorithm, path mode.
  • Flow angle, smooth level, curvature, arch, sharp angle, current path edge count.
  • In Smooth Marked sub-mode the header switches to magnet / iteration / proposal-vs-original edge counts.

3D viewport draw layers (depth test forced to ALWAYS):

  • Path edges — cyan, width 3.
  • Hover highlight — yellow (edge in Direction mode, point in Build mode), width 4 / size 10.
  • Barrier edges adjacent to path vertices — red, width 2.5.
  • Build-mode anchor — green dot, size 10.
  • Smooth preview: proposed edges in amber (width 3.5), edges being dropped in faded red (width 2).

A help overlay (H toggle) lists every shortcut above.

Notes

  • The graph cache (edge lengths, face-angle bias, CSR adjacency, native graph handle) is keyed on (len(bm.edges), len(bm.verts)). Changing topology mid-modal invalidates it; an explicit Ctrl+Z also invalidates it.
  • The barrier mask is cached separately and rebuilt when the barrier type changes or marks are committed.
  • Path size is hard-capped at MAX_PATH_EDGES = 50000.
  • A* falls back to Dijkstra when no target vertex is set (Direction mode).
  • _apply_mark lazily creates the crease_edge / bevel_weight_edge float layers when first needed.
  • Each mark / clear / angle-mark / smooth commit pushes its own ed.undo_push so individual steps can be rolled back.
  • Operator commits are normal Blender undo steps; bl_options = {'REGISTER', 'UNDO'}.