diff --git a/js/BatchPreviewManager.js b/js/BatchPreviewManager.js index 8989fef..4a54999 100644 --- a/js/BatchPreviewManager.js +++ b/js/BatchPreviewManager.js @@ -11,6 +11,25 @@ export class BatchPreviewManager { this.element = null; this.uiInitialized = false; this.maskWasVisible = false; + + // Position in canvas world coordinates + this.worldX = 0; + this.worldY = 0; + this.isDragging = false; + } + + updateScreenPosition(viewport) { + if (!this.active || !this.element) return; + + // Translate world coordinates to screen coordinates + const screenX = (this.worldX - viewport.x) * viewport.zoom; + const screenY = (this.worldY - viewport.y) * viewport.zoom; + + // We can also scale the menu with zoom, but let's keep it constant for now for readability + const scale = 1; // viewport.zoom; + + // Use transform for performance + this.element.style.transform = `translate(${screenX}px, ${screenY}px) scale(${scale})`; } _createUI() { @@ -20,9 +39,8 @@ export class BatchPreviewManager { this.element.id = 'layerforge-batch-preview'; this.element.style.cssText = ` position: absolute; - bottom: 20px; - left: 50%; - transform: translateX(-50%); + top: 0; + left: 0; background-color: #333; color: white; padding: 8px 15px; @@ -34,8 +52,42 @@ export class BatchPreviewManager { font-family: sans-serif; z-index: 1001; border: 1px solid #555; + cursor: move; + user-select: none; `; + this.element.addEventListener('mousedown', (e) => { + if (e.target.tagName === 'BUTTON') return; + + e.preventDefault(); + e.stopPropagation(); + + this.isDragging = true; + + const handleMouseMove = (moveEvent) => { + if (this.isDragging) { + // Convert screen pixel movement to world coordinate movement + const deltaX = moveEvent.movementX / this.canvas.viewport.zoom; + const deltaY = moveEvent.movementY / this.canvas.viewport.zoom; + + this.worldX += deltaX; + this.worldY += deltaY; + + // The render loop will handle updating the screen position, but we need to trigger it. + this.canvas.render(); + } + }; + + const handleMouseUp = () => { + this.isDragging = false; + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseup', handleMouseUp); + }; + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseup', handleMouseUp); + }); + const prevButton = this._createButton('◀', 'Previous'); // Left arrow const nextButton = this._createButton('▶', 'Next'); // Right arrow const confirmButton = this._createButton('✔', 'Confirm'); // Checkmark @@ -91,6 +143,13 @@ export class BatchPreviewManager { this._createUI(); + // Set initial position to be centered horizontally and just below the output area + const menuWidthInWorld = this.element.offsetWidth / this.canvas.viewport.zoom; + const paddingInWorld = 20 / this.canvas.viewport.zoom; // 20px padding in screen space + + this.worldX = (this.canvas.width / 2) - (menuWidthInWorld / 2); + this.worldY = this.canvas.height + paddingInWorld; + // Auto-hide mask logic this.maskWasVisible = this.canvas.maskTool.isOverlayVisible; if (this.maskWasVisible) { @@ -134,22 +193,6 @@ export class BatchPreviewManager { 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) { diff --git a/js/Canvas.js b/js/Canvas.js index d95e6b9..20bd719 100644 --- a/js/Canvas.js +++ b/js/Canvas.js @@ -493,8 +493,8 @@ export class Canvas { log.info('Auto-refresh triggered, importing latest images.'); const newLayers = await this.canvasIO.importLatestImages(lastExecutionStartTime); - if (newLayers && newLayers.length > 0) { - this.batchPreviewManager.addLayers(newLayers); + if (newLayers && newLayers.length > 1) { + this.batchPreviewManager.show(newLayers); } } }; diff --git a/js/CanvasRenderer.js b/js/CanvasRenderer.js index e128158..237a25b 100644 --- a/js/CanvasRenderer.js +++ b/js/CanvasRenderer.js @@ -112,6 +112,11 @@ export class CanvasRenderer { this.canvas.canvas.height = this.canvas.offscreenCanvas.height; } this.canvas.ctx.drawImage(this.canvas.offscreenCanvas, 0, 0); + + // Update Batch Preview UI position + if (this.canvas.batchPreviewManager) { + this.canvas.batchPreviewManager.updateScreenPosition(this.canvas.viewport); + } } renderInteractionElements(ctx) {