mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 20:52:12 -03:00
Introduces an addLayers method to BatchPreviewManager for adding new layers to an active batch preview or showing the UI if inactive. Updates Canvas to use addLayers instead of show, and fixes a bug where new layers were only added if more than one was present.
204 lines
6.8 KiB
JavaScript
204 lines
6.8 KiB
JavaScript
import {createModuleLogger} from "./utils/LoggerUtils.js";
|
|
|
|
const log = createModuleLogger('BatchPreviewManager');
|
|
|
|
export class BatchPreviewManager {
|
|
constructor(canvas) {
|
|
this.canvas = canvas;
|
|
this.active = false;
|
|
this.layers = [];
|
|
this.currentIndex = 0;
|
|
this.element = null;
|
|
this.uiInitialized = false;
|
|
this.maskWasVisible = false;
|
|
}
|
|
|
|
_createUI() {
|
|
if (this.uiInitialized) return;
|
|
|
|
this.element = document.createElement('div');
|
|
this.element.id = 'layerforge-batch-preview';
|
|
this.element.style.cssText = `
|
|
position: absolute;
|
|
bottom: 20px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
background-color: #333;
|
|
color: white;
|
|
padding: 8px 15px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 4px 15px rgba(0,0,0,0.5);
|
|
display: none;
|
|
align-items: center;
|
|
gap: 15px;
|
|
font-family: sans-serif;
|
|
z-index: 1001;
|
|
border: 1px solid #555;
|
|
`;
|
|
|
|
const prevButton = this._createButton('◀', 'Previous'); // Left arrow
|
|
const nextButton = this._createButton('▶', 'Next'); // Right arrow
|
|
const confirmButton = this._createButton('✔', 'Confirm'); // Checkmark
|
|
const cancelButton = this._createButton('✖', 'Cancel All'); // X mark
|
|
const closeButton = this._createButton('➲', 'Close'); // Door icon
|
|
|
|
this.counterElement = document.createElement('span');
|
|
this.counterElement.style.minWidth = '40px';
|
|
this.counterElement.style.textAlign = 'center';
|
|
this.counterElement.style.fontWeight = 'bold';
|
|
|
|
prevButton.onclick = () => this.navigate(-1);
|
|
nextButton.onclick = () => this.navigate(1);
|
|
confirmButton.onclick = () => this.confirm();
|
|
cancelButton.onclick = () => this.cancelAndRemoveAll();
|
|
closeButton.onclick = () => this.hide();
|
|
|
|
this.element.append(prevButton, this.counterElement, nextButton, confirmButton, cancelButton, closeButton);
|
|
if (this.canvas.canvas.parentNode) {
|
|
this.canvas.canvas.parentNode.appendChild(this.element);
|
|
} else {
|
|
log.error("Could not find parent node to attach batch preview UI.");
|
|
}
|
|
this.uiInitialized = true;
|
|
}
|
|
|
|
_createButton(innerHTML, title) {
|
|
const button = document.createElement('button');
|
|
button.innerHTML = innerHTML;
|
|
button.title = title;
|
|
button.style.cssText = `
|
|
background: #555;
|
|
color: white;
|
|
border: 1px solid #777;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
width: 30px;
|
|
height: 30px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
`;
|
|
button.onmouseover = () => button.style.background = '#666';
|
|
button.onmouseout = () => button.style.background = '#555';
|
|
return button;
|
|
}
|
|
|
|
show(layers) {
|
|
if (!layers || layers.length <= 1) {
|
|
return;
|
|
}
|
|
|
|
this._createUI();
|
|
|
|
// Auto-hide mask logic
|
|
this.maskWasVisible = this.canvas.maskTool.isOverlayVisible;
|
|
if (this.maskWasVisible) {
|
|
this.canvas.maskTool.toggleOverlayVisibility();
|
|
const toggleBtn = document.getElementById(`toggle-mask-btn-${this.canvas.node.id}`);
|
|
if (toggleBtn) {
|
|
toggleBtn.classList.remove('primary');
|
|
toggleBtn.textContent = "Hide Mask";
|
|
}
|
|
this.canvas.render();
|
|
}
|
|
|
|
log.info(`Showing batch preview for ${layers.length} layers.`);
|
|
this.layers = layers;
|
|
this.currentIndex = 0;
|
|
this.element.style.display = 'flex';
|
|
this.active = true;
|
|
this._update();
|
|
}
|
|
|
|
hide() {
|
|
log.info('Hiding batch preview.');
|
|
this.element.style.display = 'none';
|
|
this.active = false;
|
|
this.layers = [];
|
|
this.currentIndex = 0;
|
|
|
|
// Restore mask visibility if it was hidden by this manager
|
|
if (this.maskWasVisible && !this.canvas.maskTool.isOverlayVisible) {
|
|
this.canvas.maskTool.toggleOverlayVisibility();
|
|
const toggleBtn = document.getElementById(`toggle-mask-btn-${this.canvas.node.id}`);
|
|
if (toggleBtn) {
|
|
toggleBtn.classList.add('primary');
|
|
toggleBtn.textContent = "Show Mask";
|
|
}
|
|
}
|
|
this.maskWasVisible = false; // Reset state
|
|
|
|
// Make all layers visible again upon closing
|
|
this.canvas.layers.forEach(l => l.visible = true);
|
|
this.canvas.render();
|
|
}
|
|
|
|
addLayers(newLayers) {
|
|
if (!newLayers || newLayers.length === 0) {
|
|
return;
|
|
}
|
|
|
|
if (this.active) {
|
|
// UI is already open, just add the new layers
|
|
log.info(`Adding ${newLayers.length} new layers to active batch preview.`);
|
|
this.layers.push(...newLayers);
|
|
this._update();
|
|
} else {
|
|
// UI is not open, show it with the new layers
|
|
this.show(newLayers);
|
|
}
|
|
}
|
|
|
|
navigate(direction) {
|
|
this.currentIndex += direction;
|
|
if (this.currentIndex < 0) {
|
|
this.currentIndex = this.layers.length - 1;
|
|
} else if (this.currentIndex >= this.layers.length) {
|
|
this.currentIndex = 0;
|
|
}
|
|
this._update();
|
|
}
|
|
|
|
confirm() {
|
|
const layerToKeep = this.layers[this.currentIndex];
|
|
log.info(`Confirming selection: Keeping layer ${layerToKeep.id}.`);
|
|
|
|
const layersToDelete = this.layers.filter(l => l.id !== layerToKeep.id);
|
|
const layerIdsToDelete = layersToDelete.map(l => l.id);
|
|
|
|
this.canvas.removeLayersByIds(layerIdsToDelete);
|
|
log.info(`Deleted ${layersToDelete.length} other layers.`);
|
|
|
|
this.hide();
|
|
}
|
|
|
|
cancelAndRemoveAll() {
|
|
log.info('Cancel clicked. Removing all new layers.');
|
|
|
|
const layerIdsToDelete = this.layers.map(l => l.id);
|
|
this.canvas.removeLayersByIds(layerIdsToDelete);
|
|
log.info(`Deleted all ${layerIdsToDelete.length} new layers.`);
|
|
|
|
this.hide();
|
|
}
|
|
|
|
_update() {
|
|
this.counterElement.textContent = `${this.currentIndex + 1} / ${this.layers.length}`;
|
|
this._focusOnLayer(this.layers[this.currentIndex]);
|
|
}
|
|
|
|
_focusOnLayer(layer) {
|
|
if (!layer) return;
|
|
log.debug(`Focusing on layer ${layer.id}`);
|
|
|
|
// Move the selected layer to the top of the layer stack
|
|
this.canvas.canvasLayers.moveLayers([layer], { toIndex: 0 });
|
|
|
|
this.canvas.updateSelection([layer]);
|
|
|
|
// Render is called by moveLayers, but we call it again to be safe
|
|
this.canvas.render();
|
|
}
|
|
}
|