Skip to content
241 changes: 165 additions & 76 deletions src/components/maskeditor/BrushSettingsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,119 +10,208 @@
{{ t('maskEditor.resetToDefault') }}
</button>

<!-- Brush Shape -->
<div class="flex flex-col gap-3 pb-3">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
t('maskEditor.brushShape')
}}</span>
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.brushShape') }}
</span>

<div
class="flex flex-row gap-2.5 items-center min-h-6 relative h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
class="flex flex-row gap-2.5 items-center h-[50px] w-full rounded-[10px] bg-secondary-background-hover"
>
<div
class="maskEditor_sidePanelBrushShapeCircle bg-transparent hover:bg-comfy-menu-bg"
:class="{ active: store.brushSettings.type === BrushShape.Arc }"
:style="{
background:
class="maskEditor_sidePanelBrushShapeCircle hover:bg-comfy-menu-bg"
:class="
cn(
store.brushSettings.type === BrushShape.Arc
? 'var(--p-button-text-primary-color)'
: ''
}"
? 'bg-[var(--p-button-text-primary-color)] active'
: 'bg-transparent'
)
"
@click="setBrushShape(BrushShape.Arc)"
></div>

<div
class="maskEditor_sidePanelBrushShapeSquare bg-transparent hover:bg-comfy-menu-bg"
:class="{ active: store.brushSettings.type === BrushShape.Rect }"
:style="{
background:
class="maskEditor_sidePanelBrushShapeSquare hover:bg-comfy-menu-bg"
:class="
cn(
store.brushSettings.type === BrushShape.Rect
? 'var(--p-button-text-primary-color)'
: ''
}"
? 'bg-[var(--p-button-text-primary-color)] active'
: 'bg-transparent'
)
"
@click="setBrushShape(BrushShape.Rect)"
></div>
Comment thread
brucew4yn3rp marked this conversation as resolved.
</div>
</div>

<!-- Color -->
<div class="flex flex-col gap-3 pb-3">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">{{
t('maskEditor.colorSelector')
}}</span>
<input type="color" :value="store.rgbColor" @input="onColorChange" />
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.colorSelector') }}
</span>
<input
type="color"
class="h-10 rounded-md cursor-pointer"
:value="store.rgbColor"
@input="onColorChange"
/>
</div>
Comment thread
brucew4yn3rp marked this conversation as resolved.

<!-- Thickness -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.thickness') }}
</span>
<input
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-[var(--comfy-menu-bg)] border-[var(--p-form-field-border-color)] text-[var(--input-text)]"
:min="1"
:max="250"
:step="1"
:value="store.brushSettings.size"
@input="thickness.onInputChange"
/>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
<SliderControl
class="flex-1"
label=""
:min="1"
:max="250"
:step="1"
:model-value="store.brushSettings.size"
@update:model-value="thickness.onSliderChange"
/>
</div>

<!-- Opacity -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.opacity') }}
</span>
<input
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-[var(--comfy-menu-bg)] border-[var(--p-form-field-border-color)] text-[var(--input-text)]"
:min="0"
:max="1"
:step="0.01"
:value="store.brushSettings.opacity"
@input="opacity.onInputChange"
/>
</div>
<SliderControl
class="flex-1"
label=""
:min="0"
:max="1"
:step="0.01"
:model-value="store.brushSettings.opacity"
@update:model-value="opacity.onSliderChange"
/>
</div>

<!-- Hardness -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.hardness') }}
</span>
<input
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-[var(--comfy-menu-bg)] border-[var(--p-form-field-border-color)] text-[var(--input-text)]"
Comment thread
brucew4yn3rp marked this conversation as resolved.
Outdated
:min="0"
:max="1"
:step="0.01"
:value="store.brushSettings.hardness"
@input="hardness.onInputChange"
/>
</div>
<SliderControl
class="flex-1"
label=""
:min="0"
:max="1"
:step="0.01"
:model-value="store.brushSettings.hardness"
@update:model-value="hardness.onSliderChange"
/>
</div>

<SliderControl
:label="t('maskEditor.thickness')"
:min="1"
:max="500"
:step="1"
:model-value="store.brushSettings.size"
@update:model-value="onThicknessChange"
/>

<SliderControl
:label="t('maskEditor.opacity')"
:min="0"
:max="1"
:step="0.01"
:model-value="store.brushSettings.opacity"
@update:model-value="onOpacityChange"
/>

<SliderControl
:label="t('maskEditor.hardness')"
:min="0"
:max="1"
:step="0.01"
:model-value="store.brushSettings.hardness"
@update:model-value="onHardnessChange"
/>

<SliderControl
:label="$t('maskEditor.stepSize')"
:min="1"
:max="100"
:step="1"
:model-value="store.brushSettings.stepSize"
@update:model-value="onStepSizeChange"
/>
<!-- Step Size -->
<div class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<span class="text-left text-xs font-sans text-[var(--descrip-text)]">
{{ t('maskEditor.stepSize') }}
</span>
<input
type="number"
class="w-16 px-2 py-1 text-sm text-center border rounded-md bg-[var(--comfy-menu-bg)] border-[var(--p-form-field-border-color)] text-[var(--input-text)]"
:min="1"
:max="100"
:step="1"
:value="store.brushSettings.stepSize"
@input="stepSize.onInputChange"
/>
</div>
<SliderControl
class="flex-1"
label=""
:min="1"
:max="100"
:step="1"
:model-value="store.brushSettings.stepSize"
@update:model-value="stepSize.onSliderChange"
/>
</div>
Comment thread
brucew4yn3rp marked this conversation as resolved.
</div>
</template>

<script setup lang="ts">
import { clamp } from 'es-toolkit'

import { BrushShape } from '@/extensions/core/maskeditor/types'
import { t } from '@/i18n'
import { useMaskEditorStore } from '@/stores/maskEditorStore'
import { cn } from '@/utils/tailwindUtil'

import SliderControl from './controls/SliderControl.vue'

const store = useMaskEditorStore()

const textButtonClass =
'h-7.5 w-32 rounded-[10px] border border-[var(--p-form-field-border-color)] text-[var(--input-text)] font-sans pointer-events-auto transition-colors duration-100 bg-[var(--comfy-menu-bg)] hover:bg-secondary-background-hover'
'h-7.5 w-32 rounded-[10px] border border-[var(--p-form-field-border-color)] text-[var(--input-text)] font-sans transition-colors duration-100 bg-[var(--comfy-menu-bg)] hover:bg-secondary-background-hover'

/* Brush shape */
const setBrushShape = (shape: BrushShape) => {
store.brushSettings.type = shape
}

const onColorChange = (event: Event) => {
store.rgbColor = (event.target as HTMLInputElement).value
}

const onThicknessChange = (value: number) => {
store.setBrushSize(value)
}

const onOpacityChange = (value: number) => {
store.setBrushOpacity(value)
}

const onHardnessChange = (value: number) => {
store.setBrushHardness(value)
}

const onStepSizeChange = (value: number) => {
store.setBrushStepSize(value)
/* Color */
const onColorChange = (e: Event) => {
store.rgbColor = (e.target as HTMLInputElement).value
}

/* Handler factory */
const createHandlers = (
setter: (value: number) => void,
min: number,
max: number
) => ({
onSliderChange: (value: number) => setter(value),
onInputChange: (e: Event) => {
const value = clamp(Number((e.target as HTMLInputElement).value), min, max)
setter(value)
}
})

const thickness = createHandlers((v) => store.setBrushSize(v), 1, 250)
const opacity = createHandlers((v) => store.setBrushOpacity(v), 0, 1)
const hardness = createHandlers((v) => store.setBrushHardness(v), 0, 1)
const stepSize = createHandlers((v) => store.setBrushStepSize(v), 1, 100)
Comment thread
brucew4yn3rp marked this conversation as resolved.
Outdated

/* Reset */
const resetToDefault = () => {
store.resetBrushToDefault()
}
Expand Down
18 changes: 16 additions & 2 deletions src/extensions/core/maskeditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,27 @@ app.registerExtension({
id: 'Comfy.MaskEditor.BrushSize.Increase',
icon: 'pi pi-plus-circle',
label: 'Increase Brush Size in MaskEditor',
function: () => changeBrushSize((old) => _.clamp(old + 4, 1, 100))
function: () => changeBrushSize((old) => _.clamp(old + 2, 1, 250))
},
{
id: 'Comfy.MaskEditor.BrushSize.Decrease',
icon: 'pi pi-minus-circle',
label: 'Decrease Brush Size in MaskEditor',
function: () => changeBrushSize((old) => _.clamp(old - 4, 1, 100))
function: () => changeBrushSize((old) => _.clamp(old - 2, 1, 250))
},
{
id: 'Comfy.MaskEditor.ColorPicker',
icon: 'pi pi-palette',
label: 'Open Color Picker in MaskEditor',
function: () => {
// Trigger the color picker's click event
const colorInput = document.querySelector(
'input[type="color"]'
) as HTMLInputElement
Comment thread
brucew4yn3rp marked this conversation as resolved.
Outdated
if (colorInput) {
colorInput.click()
}
}
}
Comment thread
brucew4yn3rp marked this conversation as resolved.
]
})
Expand Down
2 changes: 1 addition & 1 deletion src/stores/maskEditorStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ export const useMaskEditorStore = defineStore('maskEditor', () => {
})

function setBrushSize(size: number): void {
brushSettings.value.size = _.clamp(size, 1, 500)
brushSettings.value.size = _.clamp(size, 1, 250)
}

function setBrushOpacity(opacity: number): void {
Expand Down