Files
PozzettiAndrea feb273ad0a Isolation-clean frontend: delete dead JS, guard listeners, leave shared DOM
- Delete 7 dead-squat widgets (registered UI only for other packs' nodes:
  UniRig/SAM3D/Mocap/FBXPreview/BVH/pointcloud) + their 6 orphaned viewer
  HTMLs + the entire unused js/viewer tree (21 files, imported by nothing;
  only ui/styles.css survives) + unused utils barrel.
- Rename namespace geompack -> geometrypack (= DisplayName, lowercased);
  all 17 surviving extensions now geometrypack.*.
- Add event.source provenance guards to every message listener (2 inline,
  2 factory handlers via new iframe param).
- Stop touching document.body: upload file input stays detached (click()
  works detached in modern browsers); folder autocomplete dropdown becomes
  a manual popover inside the widget's own DOM (top layer escapes canvas
  transforms without shared-DOM appends).

Passes comfy-test's javascript isolation lint with 0 errors.
2026-08-13 14:31:51 +02:00

120 lines
5.4 KiB
JavaScript

/**
* ComfyUI GeomPack - UV Mesh Preview Widget
* Synchronized 3D mesh and 2D UV layout viewer with interactive picking
*/
import { app } from "../../../scripts/app.js";
// Auto-detect extension folder name (handles ComfyUI-GeometryPack or comfyui-geometrypack)
const EXTENSION_FOLDER = (() => {
const url = import.meta.url;
const match = url.match(/\/extensions\/([^/]+)\//);
return match ? match[1] : "ComfyUI-GeometryPack";
})();
console.log("[GeomPack] Loading UV mesh preview extension...");
app.registerExtension({
name: "geometrypack.meshpreviewuv",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "GeomPackPreviewMeshUV") {
console.log("[GeomPack] Registering Preview Mesh UV node");
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function() {
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
console.log("[GeomPack UV] Node created, adding widget");
// Create iframe for UV viewer
const iframe = document.createElement("iframe");
iframe.style.width = "100%";
iframe.style.height = "100%";
iframe.style.border = "none";
iframe.style.backgroundColor = "#2a2a2a";
iframe.style.aspectRatio = "2"; // Wide aspect for split view
// Point to our UV viewer HTML
iframe.src = `/extensions/${EXTENSION_FOLDER}/viewer_uv.html?v=` + Date.now();
// Add widget
const widget = this.addDOMWidget("uv_preview", "MESH_UV_PREVIEW", iframe, {
getValue() { return ""; },
setValue(v) { }
});
// Set widget size - wider for split view
widget.computeSize = function(width) {
const w = width || 600;
const h = w / 2; // 2:1 aspect ratio
return [w, h];
};
widget.element = iframe;
// Store iframe reference
this.uvViewerIframe = iframe;
// Set initial node size (wide for split view)
this.setSize([600, 350]);
// Handle execution
const onExecuted = this.onExecuted;
this.onExecuted = function(message) {
console.log("[GeomPack UV] onExecuted called with message:", message);
onExecuted?.apply(this, arguments);
if (message?.mesh_file && message.mesh_file[0]) {
const meshFilename = message.mesh_file[0];
const uvDataFilename = message.uv_data_file ? message.uv_data_file[0] : null;
const showChecker = message.show_checker ? message.show_checker[0] : false;
const showWireframe = message.show_wireframe ? message.show_wireframe[0] : true;
console.log(`[GeomPack UV] Loading mesh: ${meshFilename}`);
console.log(`[GeomPack UV] UV data: ${uvDataFilename}`);
console.log(`[GeomPack UV] Checker: ${showChecker}, Wireframe: ${showWireframe}`);
// Build file URLs
const meshPath = `/view?filename=${encodeURIComponent(meshFilename)}&type=output&subfolder=`;
const uvDataPath = uvDataFilename ?
`/view?filename=${encodeURIComponent(uvDataFilename)}&type=output&subfolder=` : null;
// Send message to iframe
setTimeout(() => {
if (iframe.contentWindow) {
console.log(`[GeomPack UV] Sending postMessage to iframe`);
iframe.contentWindow.postMessage({
type: "LOAD_MESH_UV",
meshPath: meshPath,
uvDataPath: uvDataPath,
checker: showChecker,
wireframe: showWireframe,
timestamp: Date.now()
}, "*");
} else {
console.error("[GeomPack UV] Iframe contentWindow not available");
}
}, 100);
// Update node title with UV info
if (message.has_uvs && message.has_uvs[0]) {
const coverage = message.uv_coverage ? message.uv_coverage[0].toFixed(3) : "?";
const inUnit = message.uv_in_unit_square ? message.uv_in_unit_square[0] : false;
console.log(`[GeomPack UV] UV Coverage: ${coverage}, In Unit Square: ${inUnit}`);
} else {
console.warn("[GeomPack UV] No UV data found on mesh");
}
} else {
console.log("[GeomPack UV] No mesh_file in message data. Keys:", Object.keys(message || {}));
}
};
return r;
};
}
}
});
console.log("[GeomPack] UV mesh preview extension registered");