Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this

## [Unreleased]

### Fixed
- Bounded the source-shell overlap scan used by grouped UV transfer so highly fragmented, attacker-controlled meshes cannot trigger an unbounded quadratic pre-transfer pass and stall the Unity Editor.

### Added
- **`UvProgress` service** (`Editor/Framework/UvProgress.cs`) — central non-modal progress reporting. Routes status to `UnityEditor.Progress` (Background Tasks panel) plus an inline strip drawn at the bottom of the hub window. Supports nested scopes, phase labels, indeterminate/determinate fractions, cooperative cancellation via `UvProgress.CancelRequested` (`Volatile.Read`-backed `_cancelFlag` so background `Task.Run` work observes user-cancel reliably across the memory barrier), a thread-safe `ReportFromBackground` for `Task.Run` callers (with `Interlocked.Exchange`-guarded snapshot/clear so a racing writer can't lose an update; the `EditorApplication.update` pump is hooked once on assembly load from the main thread via `[InitializeOnLoadMethod]`), and a `Last` outcome shown while idle.
- **Inline progress strip in `UvToolHub`** — sits at the bottom of the window as a status bar. Reserves fixed height unconditionally so toggling active state doesn't displace any layout. Shows title · phase · detail · elapsed in distinct columns with a Cancel button pinned to the right; while idle displays `✓ / ✗ Last-operation · 12.3s`. Marquee animation for indeterminate fractions; orange tint while cancelling.
Expand Down
20 changes: 17 additions & 3 deletions Editor/GroupedShellTransfer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ namespace SashaRX.UnityMeshLab
{
public static class GroupedShellTransfer
{
// Keep overlap detection bounded: FindOverlapGroups compares every shell pair.
// Typical production meshes stay well below this limit; pathological meshes
// fall back to the original fixed retry count instead of stalling the Editor.
const int kMaxShellsForOverlapScan = 512;

// ─── Similarity Transform (4 params: a, b, tx, ty) ───
public struct SimilarityTransform
{
Expand Down Expand Up @@ -1180,12 +1185,21 @@ static TransferResult TransferCore(
: 0.001f;
float kUv0BadThreshold = Mathf.Max(avgUv0Edge * avgUv0Edge, 0.001f);

// Adaptive kMaxRetries based on overlap group size
var overlapGroups = UvShellExtractor.FindOverlapGroups(srcShells);
// Adaptive kMaxRetries based on overlap group size. The overlap detector is
// quadratic, so never run it for attacker-controlled, highly fragmented meshes.
bool scanOverlapGroups = srcShells.Count <= kMaxShellsForOverlapScan;
var overlapGroups = scanOverlapGroups
? UvShellExtractor.FindOverlapGroups(srcShells)
: new List<List<int>>();
int maxOverlapGroupSize = 0;
foreach (var group in overlapGroups)
maxOverlapGroupSize = Mathf.Max(maxOverlapGroupSize, group.Count);
int kMaxRetries = Mathf.Clamp(maxOverlapGroupSize + 2, 5, srcShells.Count);
int kMaxRetries = scanOverlapGroups
? Mathf.Clamp(maxOverlapGroupSize + 2, 5, srcShells.Count)
: Mathf.Min(5, srcShells.Count);

if (!scanOverlapGroups)
UvtLog.Warn($"[GroupedTransfer] Skipping quadratic UV overlap scan for {srcShells.Count} source shells (limit {kMaxShellsForOverlapScan}).");

// Build overlap group membership: srcShell → list of all group members
var srcShellOverlapMembers = new List<int>[srcShells.Count];
Expand Down
Loading