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.
243 lines
6.5 KiB
JavaScript
243 lines
6.5 KiB
JavaScript
/**
|
|
* AxisIndicator - Orientation widget for VTK viewers
|
|
*
|
|
* Creates and manages an annotated cube axis indicator that shows
|
|
* the current camera orientation.
|
|
*/
|
|
|
|
import { rgbToString } from '../utils/ColorUtils.js';
|
|
|
|
/**
|
|
* Default axis colors
|
|
*/
|
|
const DEFAULT_COLORS = {
|
|
x: '#ff5555', // Red for X axis
|
|
y: '#55ff55', // Green for Y axis
|
|
z: '#5555ff' // Blue for Z axis
|
|
};
|
|
|
|
/**
|
|
* Default widget configuration
|
|
*/
|
|
const DEFAULT_CONFIG = {
|
|
enabled: false,
|
|
corner: 'BOTTOM_LEFT', // BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT
|
|
viewportSize: 0.15,
|
|
minPixelSize: 100,
|
|
maxPixelSize: 300,
|
|
faceColor: rgbToString(0.5, 0.5, 0.5)
|
|
};
|
|
|
|
export class AxisIndicator {
|
|
/**
|
|
* Create an AxisIndicator
|
|
* @param {Object} vtk - VTK.js global object
|
|
* @param {Object} interactor - VTK interactor (from renderWindow.getInteractor())
|
|
* @param {Object} config - Configuration options
|
|
*/
|
|
constructor(vtk, interactor, config = {}) {
|
|
this.vtk = vtk;
|
|
this.interactor = interactor;
|
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
|
|
// VTK classes
|
|
this.vtkOrientationMarkerWidget = vtk.Interaction.Widgets.vtkOrientationMarkerWidget;
|
|
this.vtkAnnotatedCubeActor = vtk.Rendering.Core.vtkAnnotatedCubeActor;
|
|
|
|
// Widget state
|
|
this.widget = null;
|
|
this.cubeActor = null;
|
|
this.enabled = this.config.enabled;
|
|
|
|
this._createWidget();
|
|
}
|
|
|
|
/**
|
|
* Create the orientation widget
|
|
* @private
|
|
*/
|
|
_createWidget() {
|
|
// Create annotated cube actor
|
|
this.cubeActor = this.vtkAnnotatedCubeActor.newInstance();
|
|
|
|
// Set default style
|
|
this.cubeActor.setDefaultStyle({
|
|
text: '+X',
|
|
fontStyle: 'bold',
|
|
fontFamily: 'Arial',
|
|
fontColor: 'white',
|
|
fontSizeScale: (res) => res / 2,
|
|
faceColor: this.config.faceColor,
|
|
faceRotation: 0,
|
|
edgeThickness: 0.1,
|
|
edgeColor: 'white',
|
|
resolution: 400,
|
|
});
|
|
|
|
// Customize each face with axis colors
|
|
this.cubeActor.setXPlusFaceProperty({ text: '+X', faceColor: DEFAULT_COLORS.x });
|
|
this.cubeActor.setXMinusFaceProperty({ text: '-X', faceColor: DEFAULT_COLORS.x });
|
|
this.cubeActor.setYPlusFaceProperty({ text: '+Y', faceColor: DEFAULT_COLORS.y });
|
|
this.cubeActor.setYMinusFaceProperty({ text: '-Y', faceColor: DEFAULT_COLORS.y });
|
|
this.cubeActor.setZPlusFaceProperty({ text: '+Z', faceColor: DEFAULT_COLORS.z });
|
|
this.cubeActor.setZMinusFaceProperty({ text: '-Z', faceColor: DEFAULT_COLORS.z });
|
|
|
|
// Create orientation marker widget
|
|
this.widget = this.vtkOrientationMarkerWidget.newInstance({
|
|
actor: this.cubeActor,
|
|
interactor: this.interactor,
|
|
});
|
|
|
|
// Configure widget position and size
|
|
this._applyCornerConfig();
|
|
this.widget.setViewportSize(this.config.viewportSize);
|
|
this.widget.setMinPixelSize(this.config.minPixelSize);
|
|
this.widget.setMaxPixelSize(this.config.maxPixelSize);
|
|
|
|
// Set initial enabled state
|
|
this.widget.setEnabled(this.enabled);
|
|
}
|
|
|
|
/**
|
|
* Apply corner configuration
|
|
* @private
|
|
*/
|
|
_applyCornerConfig() {
|
|
const Corners = this.vtkOrientationMarkerWidget.Corners;
|
|
const cornerMap = {
|
|
'BOTTOM_LEFT': Corners.BOTTOM_LEFT,
|
|
'BOTTOM_RIGHT': Corners.BOTTOM_RIGHT,
|
|
'TOP_LEFT': Corners.TOP_LEFT,
|
|
'TOP_RIGHT': Corners.TOP_RIGHT
|
|
};
|
|
|
|
const corner = cornerMap[this.config.corner] || Corners.BOTTOM_LEFT;
|
|
this.widget.setViewportCorner(corner);
|
|
}
|
|
|
|
/**
|
|
* Enable the axis indicator
|
|
*/
|
|
enable() {
|
|
this.enabled = true;
|
|
if (this.widget) {
|
|
this.widget.setEnabled(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable the axis indicator
|
|
*/
|
|
disable() {
|
|
this.enabled = false;
|
|
if (this.widget) {
|
|
this.widget.setEnabled(false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Toggle the axis indicator
|
|
* @returns {boolean} New enabled state
|
|
*/
|
|
toggle() {
|
|
if (this.enabled) {
|
|
this.disable();
|
|
} else {
|
|
this.enable();
|
|
}
|
|
return this.enabled;
|
|
}
|
|
|
|
/**
|
|
* Set enabled state
|
|
* @param {boolean} enabled - Whether to enable the indicator
|
|
*/
|
|
setEnabled(enabled) {
|
|
if (enabled) {
|
|
this.enable();
|
|
} else {
|
|
this.disable();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if enabled
|
|
* @returns {boolean}
|
|
*/
|
|
isEnabled() {
|
|
return this.enabled;
|
|
}
|
|
|
|
/**
|
|
* Set the corner position
|
|
* @param {string} corner - 'BOTTOM_LEFT', 'BOTTOM_RIGHT', 'TOP_LEFT', 'TOP_RIGHT'
|
|
*/
|
|
setCorner(corner) {
|
|
this.config.corner = corner;
|
|
this._applyCornerConfig();
|
|
}
|
|
|
|
/**
|
|
* Set viewport size (0-1 range)
|
|
* @param {number} size - Viewport size as fraction
|
|
*/
|
|
setViewportSize(size) {
|
|
this.config.viewportSize = size;
|
|
if (this.widget) {
|
|
this.widget.setViewportSize(size);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set axis colors
|
|
* @param {Object} colors - Color object with x, y, z properties (hex strings)
|
|
*/
|
|
setAxisColors(colors) {
|
|
if (colors.x) {
|
|
this.cubeActor.setXPlusFaceProperty({ faceColor: colors.x });
|
|
this.cubeActor.setXMinusFaceProperty({ faceColor: colors.x });
|
|
}
|
|
if (colors.y) {
|
|
this.cubeActor.setYPlusFaceProperty({ faceColor: colors.y });
|
|
this.cubeActor.setYMinusFaceProperty({ faceColor: colors.y });
|
|
}
|
|
if (colors.z) {
|
|
this.cubeActor.setZPlusFaceProperty({ faceColor: colors.z });
|
|
this.cubeActor.setZMinusFaceProperty({ faceColor: colors.z });
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the underlying VTK widget
|
|
* @returns {Object} VTK orientation marker widget
|
|
*/
|
|
getWidget() {
|
|
return this.widget;
|
|
}
|
|
|
|
/**
|
|
* Get the cube actor
|
|
* @returns {Object} VTK annotated cube actor
|
|
*/
|
|
getCubeActor() {
|
|
return this.cubeActor;
|
|
}
|
|
|
|
/**
|
|
* Cleanup resources
|
|
*/
|
|
destroy() {
|
|
if (this.widget) {
|
|
this.widget.setEnabled(false);
|
|
this.widget.delete();
|
|
this.widget = null;
|
|
}
|
|
if (this.cubeActor) {
|
|
this.cubeActor.delete();
|
|
this.cubeActor = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default AxisIndicator;
|