The viewer JS/HTML/bundles are now committed in javascript/ (declared via pyproject [tool.comfy] web = "javascript") instead of being copied from the shared comfy-3d-viewers pip package at prestartup. Consequences: - requirements.txt is now just comfy-env (host env installs nothing else, per the never-touch-the-host-env principle) - prestartup_script.py no longer copies viewers or web_src; it keeps only setup_env() and the input-asset copies - WEB_DIRECTORY attribute removed; the pyproject declaration is the single source (served at /extensions/comfyui-geometrypack/, keyed by project name) - web_src/ deleted; its 6 widgets now live in javascript/js/ as the tracked source, edited directly - viewer_pbr.html hardcoded-fallback URL updated to the new mount name Iframe URLs auto-detect the mount from import.meta.url, so the folder rename and mount-name change are transparent at runtime.
277 lines
8.0 KiB
JavaScript
277 lines
8.0 KiB
JavaScript
/**
|
|
* ActorManager - Unified actor/property management for VTK viewers
|
|
*
|
|
* Handles actor configuration, appearance settings, edge visibility,
|
|
* and material properties. Works with both single actors and actor arrays.
|
|
*/
|
|
|
|
import { hexToRgb } from '../utils/ColorUtils.js';
|
|
|
|
/**
|
|
* Default actor appearance settings
|
|
*/
|
|
const DEFAULT_SETTINGS = {
|
|
color: [1.0, 1.0, 1.0], // White
|
|
edgeColor: [0.0, 0.0, 0.0], // Black edges
|
|
ambient: 0.4,
|
|
diffuse: 0.8,
|
|
specular: 0.3,
|
|
specularPower: 20,
|
|
edgeVisibility: false,
|
|
lineWidth: 1,
|
|
pointSize: 5,
|
|
representation: 2, // 0=Points, 1=Wireframe, 2=Surface
|
|
opacity: 1.0
|
|
};
|
|
|
|
/**
|
|
* Representation mode constants
|
|
*/
|
|
export const Representation = {
|
|
POINTS: 0,
|
|
WIREFRAME: 1,
|
|
SURFACE: 2
|
|
};
|
|
|
|
export class ActorManager {
|
|
/**
|
|
* Create an ActorManager
|
|
* @param {Object} renderWindow - VTK render window for triggering renders
|
|
*/
|
|
constructor(renderWindow) {
|
|
this.renderWindow = renderWindow;
|
|
this.actors = [];
|
|
this.settings = { ...DEFAULT_SETTINGS };
|
|
}
|
|
|
|
/**
|
|
* Add an actor to be managed
|
|
* @param {Object} actor - VTK actor instance
|
|
*/
|
|
addActor(actor) {
|
|
this.actors.push(actor);
|
|
this.configureActor(actor, this.settings);
|
|
}
|
|
|
|
/**
|
|
* Remove an actor from management
|
|
* @param {Object} actor - VTK actor instance
|
|
*/
|
|
removeActor(actor) {
|
|
const index = this.actors.indexOf(actor);
|
|
if (index > -1) {
|
|
this.actors.splice(index, 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear all managed actors
|
|
*/
|
|
clearActors() {
|
|
this.actors = [];
|
|
}
|
|
|
|
/**
|
|
* Set actors to manage (replaces existing)
|
|
* @param {Object[]} actors - Array of VTK actor instances
|
|
*/
|
|
setActors(actors) {
|
|
this.actors = Array.isArray(actors) ? actors : [actors];
|
|
this.actors.forEach(actor => this.configureActor(actor, this.settings));
|
|
}
|
|
|
|
/**
|
|
* Configure a single actor with settings
|
|
* @param {Object} actor - VTK actor instance
|
|
* @param {Object} settings - Settings object
|
|
*/
|
|
configureActor(actor, settings = {}) {
|
|
const merged = { ...this.settings, ...settings };
|
|
const property = actor.getProperty();
|
|
|
|
if (!property) {
|
|
console.warn('[ActorManager] Actor has no property object');
|
|
return;
|
|
}
|
|
|
|
// Color (supports hex string or RGB array)
|
|
if (merged.color) {
|
|
const rgb = typeof merged.color === 'string'
|
|
? hexToRgb(merged.color)
|
|
: merged.color;
|
|
property.setColor(...rgb);
|
|
}
|
|
|
|
// Edge color
|
|
if (merged.edgeColor) {
|
|
const rgb = typeof merged.edgeColor === 'string'
|
|
? hexToRgb(merged.edgeColor)
|
|
: merged.edgeColor;
|
|
property.setEdgeColor(...rgb);
|
|
}
|
|
|
|
// Lighting properties
|
|
if (merged.ambient !== undefined) property.setAmbient(merged.ambient);
|
|
if (merged.diffuse !== undefined) property.setDiffuse(merged.diffuse);
|
|
if (merged.specular !== undefined) property.setSpecular(merged.specular);
|
|
if (merged.specularPower !== undefined) property.setSpecularPower(merged.specularPower);
|
|
|
|
// Edge and line properties
|
|
if (merged.edgeVisibility !== undefined) property.setEdgeVisibility(merged.edgeVisibility);
|
|
if (merged.lineWidth !== undefined) property.setLineWidth(merged.lineWidth);
|
|
|
|
// Point properties
|
|
if (merged.pointSize !== undefined) property.setPointSize(merged.pointSize);
|
|
|
|
// Representation mode
|
|
if (merged.representation !== undefined) property.setRepresentation(merged.representation);
|
|
|
|
// Opacity
|
|
if (merged.opacity !== undefined) property.setOpacity(merged.opacity);
|
|
}
|
|
|
|
/**
|
|
* Apply settings to all managed actors
|
|
* @param {Object} settings - Settings object
|
|
* @param {boolean} render - Whether to trigger a render (default: true)
|
|
*/
|
|
applySettings(settings, render = true) {
|
|
this.settings = { ...this.settings, ...settings };
|
|
this.actors.forEach(actor => this.configureActor(actor, this.settings));
|
|
if (render) {
|
|
this.renderWindow.render();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set edge visibility on all managed actors
|
|
* @param {boolean} visible - Whether edges should be visible
|
|
*/
|
|
setEdgeVisibility(visible) {
|
|
this.applySettings({ edgeVisibility: visible });
|
|
}
|
|
|
|
/**
|
|
* Set color on all managed actors
|
|
* @param {string|number[]} color - Hex string or RGB array (0-1 range)
|
|
*/
|
|
setColor(color) {
|
|
this.applySettings({ color });
|
|
}
|
|
|
|
/**
|
|
* Set opacity on all managed actors
|
|
* @param {number} opacity - Opacity value (0-1)
|
|
*/
|
|
setOpacity(opacity) {
|
|
this.applySettings({ opacity });
|
|
}
|
|
|
|
/**
|
|
* Set representation mode on all managed actors
|
|
* @param {number} mode - 0=Points, 1=Wireframe, 2=Surface
|
|
*/
|
|
setRepresentation(mode) {
|
|
this.applySettings({ representation: mode });
|
|
}
|
|
|
|
/**
|
|
* Set line width for edges/wireframe
|
|
* @param {number} width - Line width in pixels
|
|
*/
|
|
setLineWidth(width) {
|
|
this.applySettings({ lineWidth: width });
|
|
}
|
|
|
|
/**
|
|
* Set point size for point cloud rendering
|
|
* @param {number} size - Point size in pixels
|
|
*/
|
|
setPointSize(size) {
|
|
this.applySettings({ pointSize: size });
|
|
}
|
|
|
|
/**
|
|
* Get current settings
|
|
* @returns {Object} Current settings object
|
|
*/
|
|
getSettings() {
|
|
return { ...this.settings };
|
|
}
|
|
|
|
/**
|
|
* Apply settings from a settings panel (handles hex colors and number parsing)
|
|
* @param {Object} panelValues - Values from settings panel inputs
|
|
*/
|
|
applyPanelSettings(panelValues) {
|
|
const settings = {};
|
|
|
|
if (panelValues.meshColor !== undefined) {
|
|
settings.color = panelValues.meshColor;
|
|
}
|
|
if (panelValues.pointSize !== undefined) {
|
|
settings.pointSize = parseFloat(panelValues.pointSize);
|
|
}
|
|
if (panelValues.edgeWidth !== undefined) {
|
|
settings.lineWidth = parseFloat(panelValues.edgeWidth);
|
|
}
|
|
if (panelValues.representation !== undefined) {
|
|
settings.representation = parseInt(panelValues.representation, 10);
|
|
}
|
|
if (panelValues.opacity !== undefined) {
|
|
settings.opacity = parseFloat(panelValues.opacity);
|
|
}
|
|
|
|
this.applySettings(settings);
|
|
}
|
|
|
|
/**
|
|
* Configure for textured mode (disables scalar visibility, sets material)
|
|
* @param {Object} actor - VTK actor instance
|
|
*/
|
|
configureForTexture(actor) {
|
|
const property = actor.getProperty();
|
|
const mapper = actor.getMapper();
|
|
|
|
if (property) {
|
|
// Material settings for proper texture display
|
|
if (typeof property.setMetallic === 'function') {
|
|
property.setMetallic(0.0);
|
|
}
|
|
if (typeof property.setRoughness === 'function') {
|
|
property.setRoughness(1.0);
|
|
}
|
|
if (typeof property.setInterpolation === 'function') {
|
|
property.setInterpolation(2); // Phong shading
|
|
}
|
|
|
|
// Remove metallic/roughness texture if present (common GLTF issue)
|
|
if (typeof property.setRMTexture === 'function') {
|
|
property.setRMTexture(null);
|
|
}
|
|
if (typeof property.setMetallicRoughnessTexture === 'function') {
|
|
property.setMetallicRoughnessTexture(null);
|
|
}
|
|
}
|
|
|
|
if (mapper) {
|
|
mapper.setScalarVisibility(false);
|
|
mapper.modified();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enable/disable scalar (field) visualization on mapper
|
|
* @param {Object} mapper - VTK mapper instance
|
|
* @param {boolean} enabled - Whether to show scalar colors
|
|
*/
|
|
setScalarVisibility(mapper, enabled) {
|
|
if (mapper) {
|
|
mapper.setScalarVisibility(enabled);
|
|
mapper.modified();
|
|
}
|
|
}
|
|
}
|
|
|
|
export default ActorManager;
|