Maskeditor: Added opacity controls for the color select tool and the paint bucket tool (#2955)

This commit is contained in:
Tristan Sommer
2025-03-10 14:05:21 +01:00
committed by GitHub
parent 9cea1fe0d3
commit e29a5d3047

View File

@@ -1305,6 +1305,7 @@ class PaintBucketTool {
private imageData: ImageData | null = null
private data: Uint8ClampedArray | null = null
private tolerance: number = 5
private fillOpacity: number = 255 // Add opacity property (default 100%)
constructor(maskEditor: MaskEditorDialog) {
this.maskEditor = maskEditor
@@ -1333,6 +1334,11 @@ class PaintBucketTool {
)
this.messageBroker.subscribe('invert', () => this.invertMask())
// Add new listener for opacity setting
this.messageBroker.subscribe('setFillOpacity', (opacity: number) =>
this.setFillOpacity(opacity)
)
}
private addPullTopics() {
@@ -1340,6 +1346,17 @@ class PaintBucketTool {
'getTolerance',
async () => this.tolerance
)
// Add pull topic for fillOpacity
this.messageBroker.createPullTopic(
'getFillOpacity',
async () => (this.fillOpacity / 255) * 100
)
}
// Add method to set opacity
setFillOpacity(opacity: number): void {
// Convert from percentage (0-100) to alpha value (0-255)
this.fillOpacity = Math.floor((opacity / 100) * 255)
}
private getPixel(x: number, y: number): number {
@@ -1439,8 +1456,8 @@ class PaintBucketTool {
}
visited[visitedIndex] = 1
// Set alpha to 255 for fill mode, 0 for erase mode
this.setPixel(x, y, isFillMode ? 255 : 0, maskColor)
// Set alpha to fillOpacity for fill mode, 0 for erase mode
this.setPixel(x, y, isFillMode ? this.fillOpacity : 0, maskColor)
// Check neighbors
const checkNeighbor = (nx: number, ny: number) => {
@@ -1540,6 +1557,7 @@ class ColorSelectTool {
private applyWholeImage: boolean = false
private maskBoundry: boolean = false
private maskTolerance: number = 0
private selectOpacity: number = 255 // Add opacity property (default 100%)
constructor(maskEditor: MaskEditorDialog) {
this.maskEditor = maskEditor
@@ -1587,6 +1605,11 @@ class ColorSelectTool {
this.messageBroker.subscribe('setMaskTolerance', (maskTolerance: number) =>
this.setMaskTolerance(maskTolerance)
)
// Add new listener for opacity setting
this.messageBroker.subscribe('setSelectionOpacity', (opacity: number) =>
this.setSelectOpacity(opacity)
)
}
private async addPullTopics() {
@@ -1805,7 +1828,7 @@ class ColorSelectTool {
const x = pixelIndex % width
const y = Math.floor(pixelIndex / width)
if (this.isPixelInRange(this.getPixel(x, y), targetPixel)) {
this.setPixel(x, y, 255, maskColor)
this.setPixel(x, y, this.selectOpacity, maskColor) // Use selectOpacity instead of 255
}
}
// Allow UI updates between chunks
@@ -1845,7 +1868,7 @@ class ColorSelectTool {
}
visited[visitedIndex] = 1
this.setPixel(x, y, 255, maskColor)
this.setPixel(x, y, this.selectOpacity, maskColor) // Use selectOpacity instead of 255
// Inline direction checks for better performance
if (
@@ -1941,6 +1964,18 @@ class ColorSelectTool {
setMaskTolerance(maskTolerance: number): void {
this.maskTolerance = maskTolerance
}
// Add method to set opacity
setSelectOpacity(opacity: number): void {
// Convert from percentage (0-100) to alpha value (0-255)
this.selectOpacity = Math.floor((opacity / 100) * 255)
// Update preview if applicable
if (this.lastPoint && this.livePreview) {
this.messageBroker.publish('undo')
this.fillColorSelection(this.lastPoint)
}
}
}
class BrushTool {
@@ -3011,10 +3046,25 @@ class UIManager {
}
)
// Add new slider for fill opacity
const fillOpacity = (await this.messageBroker.pull('getFillOpacity')) || 100
const fillOpacitySliderObj = this.createSlider(
'Fill Opacity',
0,
100,
1,
fillOpacity,
(event, value) => {
this.messageBroker.publish('setFillOpacity', parseInt(value))
}
)
paint_bucket_settings_container.appendChild(paint_bucket_settings_title)
paint_bucket_settings_container.appendChild(
paintBucketToleranceSliderObj.container
)
// Add the new opacity slider to the UI
paint_bucket_settings_container.appendChild(fillOpacitySliderObj.container)
return paint_bucket_settings_container
}
@@ -3038,6 +3088,18 @@ class UIManager {
}
)
// Add new slider for selection opacity
const selectionOpacitySliderObj = this.createSlider(
'Selection Opacity',
0,
100,
1,
100, // Default to 100%
(event, value) => {
this.messageBroker.publish('setSelectionOpacity', parseInt(value))
}
)
const livePreviewToggle = this.createToggle(
'Live Preview',
(event, value) => {
@@ -3083,6 +3145,10 @@ class UIManager {
color_select_settings_container.appendChild(
colorSelectToleranceSliderObj.container
)
// Add the new opacity slider to the UI
color_select_settings_container.appendChild(
selectionOpacitySliderObj.container
)
color_select_settings_container.appendChild(livePreviewToggle)
color_select_settings_container.appendChild(wholeImageToggle)
color_select_settings_container.appendChild(methodSelect)
@@ -4753,6 +4819,8 @@ class MessageBroker {
this.createPushTopic('setZoomText')
this.createPushTopic('resetZoom')
this.createPushTopic('invert')
this.createPushTopic('setSelectionOpacity')
this.createPushTopic('setFillOpacity')
}
/**