mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-24 14:02:11 -03:00
Hide pending generation areas
This commit is contained in:
@@ -179,6 +179,8 @@ export class BatchPreviewManager {
|
|||||||
this.layers.forEach((layer) => {
|
this.layers.forEach((layer) => {
|
||||||
layer.visible = true;
|
layer.visible = true;
|
||||||
});
|
});
|
||||||
|
// Clear selection - deselect all layers
|
||||||
|
this.canvas.updateSelection([]);
|
||||||
// Update the layers panel to reflect visibility changes
|
// Update the layers panel to reflect visibility changes
|
||||||
if (this.canvas.canvasLayersPanel) {
|
if (this.canvas.canvasLayersPanel) {
|
||||||
this.canvas.canvasLayersPanel.onLayersChanged();
|
this.canvas.canvasLayersPanel.onLayersChanged();
|
||||||
|
|||||||
@@ -261,6 +261,45 @@ export class CanvasRenderer {
|
|||||||
}
|
}
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Check if custom shape overlaps with any active batch preview areas
|
||||||
|
*/
|
||||||
|
isCustomShapeOverlappingWithBatchAreas() {
|
||||||
|
if (!this.canvas.outputAreaShape || !this.canvas.batchPreviewManagers || this.canvas.batchPreviewManagers.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Get custom shape bounds
|
||||||
|
const bounds = this.canvas.outputAreaBounds;
|
||||||
|
const ext = this.canvas.outputAreaExtensionEnabled ? this.canvas.outputAreaExtensions : { top: 0, bottom: 0, left: 0, right: 0 };
|
||||||
|
const shapeOffsetX = bounds.x + ext.left;
|
||||||
|
const shapeOffsetY = bounds.y + ext.top;
|
||||||
|
const shape = this.canvas.outputAreaShape;
|
||||||
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
||||||
|
// Calculate shape bounding box
|
||||||
|
shape.points.forEach((point) => {
|
||||||
|
const worldX = shapeOffsetX + point.x;
|
||||||
|
const worldY = shapeOffsetY + point.y;
|
||||||
|
minX = Math.min(minX, worldX);
|
||||||
|
maxX = Math.max(maxX, worldX);
|
||||||
|
minY = Math.min(minY, worldY);
|
||||||
|
maxY = Math.max(maxY, worldY);
|
||||||
|
});
|
||||||
|
const shapeBounds = { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
||||||
|
// Check overlap with each active batch preview area
|
||||||
|
for (const manager of this.canvas.batchPreviewManagers) {
|
||||||
|
if (manager.generationArea) {
|
||||||
|
const area = manager.generationArea;
|
||||||
|
// Check if rectangles overlap
|
||||||
|
if (!(shapeBounds.x + shapeBounds.width < area.x ||
|
||||||
|
area.x + area.width < shapeBounds.x ||
|
||||||
|
shapeBounds.y + shapeBounds.height < area.y ||
|
||||||
|
area.y + area.height < shapeBounds.y)) {
|
||||||
|
return true; // Overlap detected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
drawCanvasOutline(ctx) {
|
drawCanvasOutline(ctx) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
|
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
|
||||||
@@ -276,7 +315,8 @@ export class CanvasRenderer {
|
|||||||
const textWorldX = bounds.x + bounds.width / 2;
|
const textWorldX = bounds.x + bounds.width / 2;
|
||||||
const textWorldY = bounds.y + bounds.height + (20 / this.canvas.viewport.zoom);
|
const textWorldY = bounds.y + bounds.height + (20 / this.canvas.viewport.zoom);
|
||||||
this.drawTextWithBackground(ctx, dimensionsText, textWorldX, textWorldY);
|
this.drawTextWithBackground(ctx, dimensionsText, textWorldX, textWorldY);
|
||||||
if (this.canvas.outputAreaShape) {
|
// Only draw custom shape if it doesn't overlap with batch preview areas
|
||||||
|
if (this.canvas.outputAreaShape && !this.isCustomShapeOverlappingWithBatchAreas()) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.strokeStyle = 'rgba(0, 255, 255, 0.9)';
|
ctx.strokeStyle = 'rgba(0, 255, 255, 0.9)';
|
||||||
ctx.lineWidth = 2 / this.canvas.viewport.zoom;
|
ctx.lineWidth = 2 / this.canvas.viewport.zoom;
|
||||||
@@ -351,29 +391,32 @@ export class CanvasRenderer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
drawPendingGenerationAreas(ctx) {
|
drawPendingGenerationAreas(ctx) {
|
||||||
const areasToDraw = [];
|
const pendingAreas = [];
|
||||||
// 1. Get areas from active managers
|
// 1. Get all pending generation areas (from pendingBatchContext)
|
||||||
if (this.canvas.batchPreviewManagers && this.canvas.batchPreviewManagers.length > 0) {
|
|
||||||
this.canvas.batchPreviewManagers.forEach((manager) => {
|
|
||||||
if (manager.generationArea) {
|
|
||||||
areasToDraw.push(manager.generationArea);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// 2. Get the area from the pending context (if it exists)
|
|
||||||
if (this.canvas.pendingBatchContext && this.canvas.pendingBatchContext.outputArea) {
|
if (this.canvas.pendingBatchContext && this.canvas.pendingBatchContext.outputArea) {
|
||||||
areasToDraw.push(this.canvas.pendingBatchContext.outputArea);
|
pendingAreas.push(this.canvas.pendingBatchContext.outputArea);
|
||||||
}
|
}
|
||||||
if (areasToDraw.length === 0) {
|
// 2. Draw only those pending areas, które NIE mają aktywnego batch preview managera dla tego samego obszaru
|
||||||
return;
|
const isAreaCoveredByBatch = (area) => {
|
||||||
}
|
if (!this.canvas.batchPreviewManagers)
|
||||||
// 3. Draw all collected areas
|
return false;
|
||||||
areasToDraw.forEach(area => {
|
return this.canvas.batchPreviewManagers.some((manager) => {
|
||||||
this.drawStyledRect(ctx, area, {
|
if (!manager.generationArea)
|
||||||
strokeStyle: 'rgba(0, 150, 255, 0.9)',
|
return false;
|
||||||
lineWidth: 3,
|
// Sprawdź czy obszary się pokrywają (prosty overlap AABB)
|
||||||
dashPattern: [12, 6]
|
const a = area;
|
||||||
|
const b = manager.generationArea;
|
||||||
|
return !(a.x + a.width < b.x || b.x + b.width < a.x || a.y + a.height < b.y || b.y + b.height < a.y);
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
pendingAreas.forEach(area => {
|
||||||
|
if (!isAreaCoveredByBatch(area)) {
|
||||||
|
this.drawStyledRect(ctx, area, {
|
||||||
|
strokeStyle: 'rgba(0, 150, 255, 0.9)',
|
||||||
|
lineWidth: 3,
|
||||||
|
dashPattern: [12, 6]
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
drawMaskAreaBounds(ctx) {
|
drawMaskAreaBounds(ctx) {
|
||||||
|
|||||||
@@ -234,6 +234,9 @@ export class BatchPreviewManager {
|
|||||||
layer.visible = true;
|
layer.visible = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clear selection - deselect all layers
|
||||||
|
this.canvas.updateSelection([]);
|
||||||
|
|
||||||
// Update the layers panel to reflect visibility changes
|
// Update the layers panel to reflect visibility changes
|
||||||
if (this.canvas.canvasLayersPanel) {
|
if (this.canvas.canvasLayersPanel) {
|
||||||
this.canvas.canvasLayersPanel.onLayersChanged();
|
this.canvas.canvasLayersPanel.onLayersChanged();
|
||||||
|
|||||||
@@ -325,6 +325,52 @@ export class CanvasRenderer {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if custom shape overlaps with any active batch preview areas
|
||||||
|
*/
|
||||||
|
isCustomShapeOverlappingWithBatchAreas(): boolean {
|
||||||
|
if (!this.canvas.outputAreaShape || !this.canvas.batchPreviewManagers || this.canvas.batchPreviewManagers.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get custom shape bounds
|
||||||
|
const bounds = this.canvas.outputAreaBounds;
|
||||||
|
const ext = this.canvas.outputAreaExtensionEnabled ? this.canvas.outputAreaExtensions : { top: 0, bottom: 0, left: 0, right: 0 };
|
||||||
|
const shapeOffsetX = bounds.x + ext.left;
|
||||||
|
const shapeOffsetY = bounds.y + ext.top;
|
||||||
|
|
||||||
|
const shape = this.canvas.outputAreaShape;
|
||||||
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
||||||
|
|
||||||
|
// Calculate shape bounding box
|
||||||
|
shape.points.forEach((point: { x: number; y: number }) => {
|
||||||
|
const worldX = shapeOffsetX + point.x;
|
||||||
|
const worldY = shapeOffsetY + point.y;
|
||||||
|
minX = Math.min(minX, worldX);
|
||||||
|
maxX = Math.max(maxX, worldX);
|
||||||
|
minY = Math.min(minY, worldY);
|
||||||
|
maxY = Math.max(maxY, worldY);
|
||||||
|
});
|
||||||
|
|
||||||
|
const shapeBounds = { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
||||||
|
|
||||||
|
// Check overlap with each active batch preview area
|
||||||
|
for (const manager of this.canvas.batchPreviewManagers) {
|
||||||
|
if (manager.generationArea) {
|
||||||
|
const area = manager.generationArea;
|
||||||
|
// Check if rectangles overlap
|
||||||
|
if (!(shapeBounds.x + shapeBounds.width < area.x ||
|
||||||
|
area.x + area.width < shapeBounds.x ||
|
||||||
|
shapeBounds.y + shapeBounds.height < area.y ||
|
||||||
|
area.y + area.height < shapeBounds.y)) {
|
||||||
|
return true; // Overlap detected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
drawCanvasOutline(ctx: any) {
|
drawCanvasOutline(ctx: any) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
|
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
|
||||||
@@ -345,7 +391,8 @@ export class CanvasRenderer {
|
|||||||
|
|
||||||
this.drawTextWithBackground(ctx, dimensionsText, textWorldX, textWorldY);
|
this.drawTextWithBackground(ctx, dimensionsText, textWorldX, textWorldY);
|
||||||
|
|
||||||
if (this.canvas.outputAreaShape) {
|
// Only draw custom shape if it doesn't overlap with batch preview areas
|
||||||
|
if (this.canvas.outputAreaShape && !this.isCustomShapeOverlappingWithBatchAreas()) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.strokeStyle = 'rgba(0, 255, 255, 0.9)';
|
ctx.strokeStyle = 'rgba(0, 255, 255, 0.9)';
|
||||||
ctx.lineWidth = 2 / this.canvas.viewport.zoom;
|
ctx.lineWidth = 2 / this.canvas.viewport.zoom;
|
||||||
@@ -432,33 +479,33 @@ export class CanvasRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawPendingGenerationAreas(ctx: any) {
|
drawPendingGenerationAreas(ctx: any) {
|
||||||
const areasToDraw = [];
|
const pendingAreas = [];
|
||||||
|
|
||||||
// 1. Get areas from active managers
|
// 1. Get all pending generation areas (from pendingBatchContext)
|
||||||
if (this.canvas.batchPreviewManagers && this.canvas.batchPreviewManagers.length > 0) {
|
|
||||||
this.canvas.batchPreviewManagers.forEach((manager: any) => {
|
|
||||||
if (manager.generationArea) {
|
|
||||||
areasToDraw.push(manager.generationArea);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Get the area from the pending context (if it exists)
|
|
||||||
if (this.canvas.pendingBatchContext && this.canvas.pendingBatchContext.outputArea) {
|
if (this.canvas.pendingBatchContext && this.canvas.pendingBatchContext.outputArea) {
|
||||||
areasToDraw.push(this.canvas.pendingBatchContext.outputArea);
|
pendingAreas.push(this.canvas.pendingBatchContext.outputArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (areasToDraw.length === 0) {
|
// 2. Draw only those pending areas, które NIE mają aktywnego batch preview managera dla tego samego obszaru
|
||||||
return;
|
const isAreaCoveredByBatch = (area: any) => {
|
||||||
}
|
if (!this.canvas.batchPreviewManagers) return false;
|
||||||
|
return this.canvas.batchPreviewManagers.some((manager: any) => {
|
||||||
// 3. Draw all collected areas
|
if (!manager.generationArea) return false;
|
||||||
areasToDraw.forEach(area => {
|
// Sprawdź czy obszary się pokrywają (prosty overlap AABB)
|
||||||
this.drawStyledRect(ctx, area, {
|
const a = area;
|
||||||
strokeStyle: 'rgba(0, 150, 255, 0.9)',
|
const b = manager.generationArea;
|
||||||
lineWidth: 3,
|
return !(a.x + a.width < b.x || b.x + b.width < a.x || a.y + a.height < b.y || b.y + b.height < a.y);
|
||||||
dashPattern: [12, 6]
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
pendingAreas.forEach(area => {
|
||||||
|
if (!isAreaCoveredByBatch(area)) {
|
||||||
|
this.drawStyledRect(ctx, area, {
|
||||||
|
strokeStyle: 'rgba(0, 150, 255, 0.9)',
|
||||||
|
lineWidth: 3,
|
||||||
|
dashPattern: [12, 6]
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const LAYERFORGE_TOOLS = {
|
|||||||
DELETE: 'delete',
|
DELETE: 'delete',
|
||||||
DUPLICATE: 'duplicate',
|
DUPLICATE: 'duplicate',
|
||||||
BLEND_MODE: 'blend_mode',
|
BLEND_MODE: 'blend_mode',
|
||||||
OPACITY: 'opacity',
|
OPACITY: 'opacity',
|
||||||
MASK: 'mask',
|
MASK: 'mask',
|
||||||
BRUSH: 'brush',
|
BRUSH: 'brush',
|
||||||
ERASER: 'eraser',
|
ERASER: 'eraser',
|
||||||
|
|||||||
Reference in New Issue
Block a user