feat: add inpaint region functionality and related tools
- Enhanced cursor behavior for new tools: semantic select, mask lasso, and mask rectangle. - Updated mask edit state to include mask asset ID and kind. - Implemented inpaint region commands for adding, applying, and removing inpaint regions. - Introduced new operations for lasso and semantic selection tools. - Created UI components for candidate review and inpaint region management. - Added tests for inpaint region commands to ensure functionality. - Updated various components to support new inpaint features and improve user experience.
This commit is contained in:
@@ -13,6 +13,7 @@ export type BrushControlsProps = {
|
||||
tool: Extract<ToolId, "brush" | "eraser">;
|
||||
settings: BrushSettings;
|
||||
editingMask?: boolean;
|
||||
maskKind?: "layerMask" | "inpaintRegion";
|
||||
maskViewMode?: MaskViewMode;
|
||||
dispatch: AppStore["dispatch"];
|
||||
};
|
||||
@@ -24,7 +25,8 @@ const maskViewModeOptions = [
|
||||
{ value: "overlay", label: "Overlay" },
|
||||
] satisfies readonly BottomControlSelectOption<MaskViewMode>[];
|
||||
|
||||
export function BrushControls({ tool, settings, editingMask = false, maskViewMode = "composite", dispatch }: BrushControlsProps) {
|
||||
export function BrushControls({ tool, settings, editingMask = false, maskKind = "layerMask", maskViewMode = "composite", dispatch }: BrushControlsProps) {
|
||||
const inpaintRegion = editingMask && maskKind === "inpaintRegion";
|
||||
return (
|
||||
<div className={bottomControlMenuClass()}>
|
||||
<span className={bottomControlIconSlotClass()} title={editingMask ? `Mask ${tool === "eraser" ? "hide" : "reveal"}` : tool === "eraser" ? "Eraser" : "Brush"}>
|
||||
@@ -33,8 +35,8 @@ export function BrushControls({ tool, settings, editingMask = false, maskViewMod
|
||||
<BottomControlDivider />
|
||||
{editingMask ? (
|
||||
<>
|
||||
<button type="button" className={maskModeButtonClass(tool === "brush")} aria-pressed={tool === "brush"} onClick={() => dispatch(commandIds.toolSetActive, { tool: "brush" })}>Reveal</button>
|
||||
<button type="button" className={maskModeButtonClass(tool === "eraser")} aria-pressed={tool === "eraser"} onClick={() => dispatch(commandIds.toolSetActive, { tool: "eraser" })}>Hide</button>
|
||||
<button type="button" className={maskModeButtonClass(tool === "brush")} aria-pressed={tool === "brush"} onClick={() => dispatch(commandIds.toolSetActive, { tool: "brush" })}>{inpaintRegion ? "Replace" : "Reveal"}</button>
|
||||
<button type="button" className={maskModeButtonClass(tool === "eraser")} aria-pressed={tool === "eraser"} onClick={() => dispatch(commandIds.toolSetActive, { tool: "eraser" })}>{inpaintRegion ? "Protect" : "Hide"}</button>
|
||||
<BottomControlDivider />
|
||||
</>
|
||||
) : null}
|
||||
@@ -61,6 +63,13 @@ export function BrushControls({ tool, settings, editingMask = false, maskViewMod
|
||||
<span className="w-9 text-right text-xs font-medium text-white/85">{Math.round(settings.size)}</span>
|
||||
</label>
|
||||
<BottomControlDivider />
|
||||
<label className={bottomControlFieldClass()}><span className={bottomControlLabelClass()}>Opacity</span><BottomControlSlider min={0} max={100} value={settings.opacity} className="min-w-10 w-[clamp(2.5rem,7vw,6rem)] shrink" aria-label="Brush opacity" onValueChange={(opacity) => dispatch(commandIds.toolSetBrushSettings, { opacity })} /><span className="w-9 text-right text-xs font-medium text-white/85">{Math.round(settings.opacity)}</span></label>
|
||||
<BottomControlDivider />
|
||||
<label className={bottomControlFieldClass()}><span className={bottomControlLabelClass()}>Flow</span><BottomControlSlider min={1} max={100} value={settings.flow} className="min-w-10 w-[clamp(2.5rem,7vw,6rem)] shrink" aria-label="Brush flow" onValueChange={(flow) => dispatch(commandIds.toolSetBrushSettings, { flow })} /><span className="w-9 text-right text-xs font-medium text-white/85">{Math.round(settings.flow)}</span></label>
|
||||
<BottomControlDivider />
|
||||
<label className={bottomControlFieldClass()}><span className={bottomControlLabelClass()}>Smooth</span><BottomControlSlider min={0} max={100} value={settings.smoothing} className="min-w-10 w-[clamp(2.5rem,7vw,6rem)] shrink" aria-label="Brush smoothing" onValueChange={(smoothing) => dispatch(commandIds.toolSetBrushSettings, { smoothing })} /><span className="w-9 text-right text-xs font-medium text-white/85">{Math.round(settings.smoothing)}</span></label>
|
||||
<button type="button" className={maskModeButtonClass(settings.pressureSize)} aria-pressed={settings.pressureSize} title="Use pen pressure for brush size" onClick={() => dispatch(commandIds.toolSetBrushSettings, { pressureSize: !settings.pressureSize })}>Pressure</button>
|
||||
<BottomControlDivider />
|
||||
<label className={bottomControlFieldClass()}>
|
||||
<span className={bottomControlLabelClass()}>Hard</span>
|
||||
<BottomControlSlider
|
||||
|
||||
Reference in New Issue
Block a user