mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 20:52:12 -03:00
Refine shape mask UI and ensure hard-edged mask removal
Consolidates shape mask controls into a styled container, improves UI logic for showing/hiding sub-options, and updates slider initialization to reflect current values. Mask removal now always uses a hard-edged shape, even if feathering was previously applied, ensuring complete erasure of feathered areas. The mask application logic also clears the maximum possible mask area before applying the new mask to prevent artifacts from previous slider values. Checkbox and slider labels are updated for clarity.
This commit is contained in:
@@ -63,9 +63,7 @@ export class CustomShapeMenu {
|
||||
`;
|
||||
// Create menu content
|
||||
const lines = [
|
||||
"🎯 Custom Output Area Active",
|
||||
"Press Shift+S to modify shape",
|
||||
"Shape defines generation area"
|
||||
"🎯 Custom Output Area Active"
|
||||
];
|
||||
lines.forEach(line => {
|
||||
const lineElement = document.createElement('div');
|
||||
@@ -76,7 +74,17 @@ export class CustomShapeMenu {
|
||||
`;
|
||||
this.element.appendChild(lineElement);
|
||||
});
|
||||
// Add main auto-apply checkbox
|
||||
// Create a container for the entire shape mask feature set
|
||||
const featureContainer = document.createElement('div');
|
||||
featureContainer.id = 'shape-mask-feature-container';
|
||||
featureContainer.style.cssText = `
|
||||
background-color: #282828;
|
||||
border-radius: 6px;
|
||||
margin-top: 6px;
|
||||
padding: 4px 0;
|
||||
border: 1px solid #444;
|
||||
`;
|
||||
// Add main auto-apply checkbox to the new container
|
||||
const checkboxContainer = this._createCheckbox(() => `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`, () => {
|
||||
this.canvas.autoApplyShapeMask = !this.canvas.autoApplyShapeMask;
|
||||
if (this.canvas.autoApplyShapeMask) {
|
||||
@@ -85,13 +93,15 @@ export class CustomShapeMenu {
|
||||
}
|
||||
else {
|
||||
this.canvas.maskTool.removeShapeMask();
|
||||
log.info("Auto-apply shape mask disabled - mask removed automatically");
|
||||
this.canvas.shapeMaskExpansion = false;
|
||||
this.canvas.shapeMaskFeather = false;
|
||||
log.info("Auto-apply shape mask disabled - mask area removed and sub-options reset.");
|
||||
}
|
||||
this._updateUI();
|
||||
this.canvas.render();
|
||||
});
|
||||
this.element.appendChild(checkboxContainer);
|
||||
// Add expansion checkbox (only visible when auto-apply is enabled)
|
||||
featureContainer.appendChild(checkboxContainer);
|
||||
// Add expansion checkbox
|
||||
const expansionContainer = this._createCheckbox(() => `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Expand/Contract mask`, () => {
|
||||
this.canvas.shapeMaskExpansion = !this.canvas.shapeMaskExpansion;
|
||||
this._updateUI();
|
||||
@@ -101,12 +111,12 @@ export class CustomShapeMenu {
|
||||
}
|
||||
});
|
||||
expansionContainer.id = 'expansion-checkbox';
|
||||
this.element.appendChild(expansionContainer);
|
||||
// Add expansion slider container (only visible when expansion is enabled)
|
||||
featureContainer.appendChild(expansionContainer);
|
||||
// Add expansion slider container
|
||||
const expansionSliderContainer = document.createElement('div');
|
||||
expansionSliderContainer.id = 'expansion-slider-container';
|
||||
expansionSliderContainer.style.cssText = `
|
||||
margin: 6px 0;
|
||||
margin: 0 8px 6px 8px;
|
||||
padding: 4px 8px;
|
||||
display: none;
|
||||
`;
|
||||
@@ -121,7 +131,7 @@ export class CustomShapeMenu {
|
||||
expansionSlider.type = 'range';
|
||||
expansionSlider.min = '-300';
|
||||
expansionSlider.max = '300';
|
||||
expansionSlider.value = '0';
|
||||
expansionSlider.value = String(this.canvas.shapeMaskExpansionValue);
|
||||
expansionSlider.style.cssText = `
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
@@ -141,41 +151,25 @@ export class CustomShapeMenu {
|
||||
this.canvas.shapeMaskExpansionValue = value;
|
||||
expansionValueDisplay.textContent = value > 0 ? `+${value}px` : `${value}px`;
|
||||
};
|
||||
// Add preview system for expansion slider
|
||||
let expansionTimeout = null;
|
||||
let isExpansionDragging = false;
|
||||
expansionSlider.onmousedown = () => {
|
||||
isExpansionDragging = true;
|
||||
};
|
||||
expansionSlider.onmousedown = () => { isExpansionDragging = true; };
|
||||
expansionSlider.oninput = () => {
|
||||
updateExpansionSliderDisplay();
|
||||
if (this.canvas.autoApplyShapeMask) {
|
||||
// Clear previous timeout
|
||||
if (expansionTimeout) {
|
||||
clearTimeout(expansionTimeout);
|
||||
}
|
||||
if (isExpansionDragging) {
|
||||
// Show blue preview line while dragging - NO mask application
|
||||
const featherValue = this.canvas.shapeMaskFeather ? this.canvas.shapeMaskFeatherValue : 0;
|
||||
this.canvas.maskTool.showShapePreview(this.canvas.shapeMaskExpansionValue, featherValue);
|
||||
}
|
||||
else {
|
||||
// Apply mask immediately for programmatic changes (not user dragging)
|
||||
this.canvas.maskTool.hideShapePreview();
|
||||
this.canvas.maskTool.applyShapeMask(false);
|
||||
this.canvas.render();
|
||||
}
|
||||
// Clear any pending timeout - we only apply mask on mouseup now
|
||||
if (expansionTimeout) {
|
||||
clearTimeout(expansionTimeout);
|
||||
expansionTimeout = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
expansionSlider.onmouseup = () => {
|
||||
isExpansionDragging = false;
|
||||
if (this.canvas.autoApplyShapeMask) {
|
||||
// Apply final mask immediately when user releases slider
|
||||
this.canvas.maskTool.hideShapePreview();
|
||||
this.canvas.maskTool.applyShapeMask(true);
|
||||
this.canvas.render();
|
||||
@@ -185,8 +179,8 @@ export class CustomShapeMenu {
|
||||
expansionSliderContainer.appendChild(expansionSliderLabel);
|
||||
expansionSliderContainer.appendChild(expansionSlider);
|
||||
expansionSliderContainer.appendChild(expansionValueDisplay);
|
||||
this.element.appendChild(expansionSliderContainer);
|
||||
// Add feather checkbox (only visible when auto-apply is enabled)
|
||||
featureContainer.appendChild(expansionSliderContainer);
|
||||
// Add feather checkbox
|
||||
const featherContainer = this._createCheckbox(() => `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`, () => {
|
||||
this.canvas.shapeMaskFeather = !this.canvas.shapeMaskFeather;
|
||||
this._updateUI();
|
||||
@@ -196,12 +190,12 @@ export class CustomShapeMenu {
|
||||
}
|
||||
});
|
||||
featherContainer.id = 'feather-checkbox';
|
||||
this.element.appendChild(featherContainer);
|
||||
// Add feather slider container (only visible when feather is enabled)
|
||||
featureContainer.appendChild(featherContainer);
|
||||
// Add feather slider container
|
||||
const featherSliderContainer = document.createElement('div');
|
||||
featherSliderContainer.id = 'feather-slider-container';
|
||||
featherSliderContainer.style.cssText = `
|
||||
margin: 6px 0;
|
||||
margin: 0 8px 6px 8px;
|
||||
padding: 4px 8px;
|
||||
display: none;
|
||||
`;
|
||||
@@ -216,7 +210,7 @@ export class CustomShapeMenu {
|
||||
featherSlider.type = 'range';
|
||||
featherSlider.min = '0';
|
||||
featherSlider.max = '300';
|
||||
featherSlider.value = '0';
|
||||
featherSlider.value = String(this.canvas.shapeMaskFeatherValue);
|
||||
featherSlider.style.cssText = `
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
@@ -236,22 +230,16 @@ export class CustomShapeMenu {
|
||||
this.canvas.shapeMaskFeatherValue = value;
|
||||
featherValueDisplay.textContent = `${value}px`;
|
||||
};
|
||||
// Add preview system for feather slider (mirrors expansion slider)
|
||||
let featherTimeout = null;
|
||||
let isFeatherDragging = false;
|
||||
featherSlider.onmousedown = () => {
|
||||
isFeatherDragging = true;
|
||||
};
|
||||
featherSlider.onmousedown = () => { isFeatherDragging = true; };
|
||||
featherSlider.oninput = () => {
|
||||
updateFeatherSliderDisplay();
|
||||
if (this.canvas.autoApplyShapeMask) {
|
||||
if (isFeatherDragging) {
|
||||
// Show blue preview line while dragging
|
||||
const expansionValue = this.canvas.shapeMaskExpansion ? this.canvas.shapeMaskExpansionValue : 0;
|
||||
this.canvas.maskTool.showShapePreview(expansionValue, this.canvas.shapeMaskFeatherValue);
|
||||
}
|
||||
else {
|
||||
// Apply immediately for programmatic changes
|
||||
this.canvas.maskTool.hideShapePreview();
|
||||
this.canvas.maskTool.applyShapeMask(false);
|
||||
this.canvas.render();
|
||||
@@ -261,7 +249,6 @@ export class CustomShapeMenu {
|
||||
featherSlider.onmouseup = () => {
|
||||
isFeatherDragging = false;
|
||||
if (this.canvas.autoApplyShapeMask) {
|
||||
// Apply final mask when user releases slider
|
||||
this.canvas.maskTool.hideShapePreview();
|
||||
this.canvas.maskTool.applyShapeMask(true); // true = save state
|
||||
this.canvas.render();
|
||||
@@ -271,7 +258,8 @@ export class CustomShapeMenu {
|
||||
featherSliderContainer.appendChild(featherSliderLabel);
|
||||
featherSliderContainer.appendChild(featherSlider);
|
||||
featherSliderContainer.appendChild(featherValueDisplay);
|
||||
this.element.appendChild(featherSliderContainer);
|
||||
featureContainer.appendChild(featherSliderContainer);
|
||||
this.element.appendChild(featureContainer);
|
||||
// Add to DOM
|
||||
if (this.canvas.canvas.parentElement) {
|
||||
this.canvas.canvas.parentElement.appendChild(this.element);
|
||||
@@ -315,27 +303,23 @@ export class CustomShapeMenu {
|
||||
_updateUI() {
|
||||
if (!this.element)
|
||||
return;
|
||||
// Update expansion checkbox visibility
|
||||
// Toggle visibility of sub-options based on the main checkbox state
|
||||
const expansionCheckbox = this.element.querySelector('#expansion-checkbox');
|
||||
if (expansionCheckbox) {
|
||||
expansionCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none';
|
||||
}
|
||||
// Update expansion slider container visibility
|
||||
const expansionSliderContainer = this.element.querySelector('#expansion-slider-container');
|
||||
if (expansionSliderContainer) {
|
||||
expansionSliderContainer.style.display =
|
||||
(this.canvas.autoApplyShapeMask && this.canvas.shapeMaskExpansion) ? 'block' : 'none';
|
||||
}
|
||||
// Update feather checkbox visibility
|
||||
const featherCheckbox = this.element.querySelector('#feather-checkbox');
|
||||
if (featherCheckbox) {
|
||||
featherCheckbox.style.display = this.canvas.autoApplyShapeMask ? 'block' : 'none';
|
||||
}
|
||||
// Update feather slider container visibility
|
||||
// Update sliders visibility based on their respective checkboxes
|
||||
const expansionSliderContainer = this.element.querySelector('#expansion-slider-container');
|
||||
if (expansionSliderContainer) {
|
||||
expansionSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskExpansion) ? 'block' : 'none';
|
||||
}
|
||||
const featherSliderContainer = this.element.querySelector('#feather-slider-container');
|
||||
if (featherSliderContainer) {
|
||||
featherSliderContainer.style.display =
|
||||
(this.canvas.autoApplyShapeMask && this.canvas.shapeMaskFeather) ? 'block' : 'none';
|
||||
featherSliderContainer.style.display = (this.canvas.autoApplyShapeMask && this.canvas.shapeMaskFeather) ? 'block' : 'none';
|
||||
}
|
||||
// Update checkbox texts
|
||||
const checkboxes = this.element.querySelectorAll('div[style*="cursor: pointer"]');
|
||||
@@ -344,7 +328,7 @@ export class CustomShapeMenu {
|
||||
checkbox.textContent = `${this.canvas.autoApplyShapeMask ? "☑" : "☐"} Auto-apply shape mask`;
|
||||
}
|
||||
else if (index === 1) { // Expansion checkbox
|
||||
checkbox.textContent = `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Expand/Contract mask`;
|
||||
checkbox.textContent = `${this.canvas.shapeMaskExpansion ? "☑" : "☐"} Dilate/Erode mask`;
|
||||
}
|
||||
else if (index === 2) { // Feather checkbox
|
||||
checkbox.textContent = `${this.canvas.shapeMaskFeather ? "☑" : "☐"} Feather edges`;
|
||||
|
||||
Reference in New Issue
Block a user