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:
@@ -346,8 +346,11 @@ function LayerRow({
|
||||
const layerMask = getLayerMask(layer);
|
||||
const maskLayer = layerMask ? documentIndex.layerById.get(layerMask.maskLayerId) : undefined;
|
||||
const maskAsset = maskLayer && (maskLayer.type === "image" || maskLayer.type === "raster") ? documentIndex.assetById.get(maskLayer.assetId) : undefined;
|
||||
const inpaintRegion = document.inpaintRegions.find((region) => region.targetLayerId === layer.id && region.enabled);
|
||||
const inpaintMaskAsset = inpaintRegion ? documentIndex.assetById.get(inpaintRegion.maskAssetId) : undefined;
|
||||
const canAddMask = Boolean(layerInfo && (layer.type === "image" || layer.type === "raster") && !layerMask);
|
||||
const editingMask = Boolean(maskEdit && layerMask && maskEdit.targetLayerId === layer.id && maskEdit.maskLayerId === layerMask.maskLayerId);
|
||||
const editingInpaintRegion = Boolean(maskEdit?.kind === "inpaintRegion" && inpaintRegion && maskEdit.inpaintRegionId === inpaintRegion.id);
|
||||
const thumbnail = thumbnailByLayerId.get(layer.id) ?? { kind: "empty" };
|
||||
const maskThumbnail = maskLayer ? thumbnailByLayerId.get(maskLayer.id) : undefined;
|
||||
const rowPadding = 12 + depth * 16;
|
||||
@@ -479,6 +482,16 @@ function LayerRow({
|
||||
</button>
|
||||
</div>
|
||||
) : null}
|
||||
{inpaintRegion ? (
|
||||
<div role="group" aria-label={`AI edit region attached to ${layer.name}`} className={`relative mt-1 ml-8 flex min-h-11 flex-wrap items-center gap-1.5 border-l-2 py-1.5 pl-3 pr-1.5 text-xs transition ${editingInpaintRegion ? "border-red-300 text-red-50" : "border-red-300/25 text-red-100/65"}`}>
|
||||
<span aria-hidden="true" className="absolute -left-2 top-1/2 h-px w-2 bg-red-300/40" />
|
||||
{inpaintMaskAsset ? <img src={inpaintMaskAsset.source} alt={`${layer.name} AI edit mask preview`} className="h-8 w-11 rounded-md bg-black/30 object-cover ring-1 ring-red-300/30" /> : <Stack size={24} weight="fill" />}
|
||||
<span className="min-w-28 flex-1 truncate font-medium">{editingInpaintRegion ? "Editing AI region" : inpaintRegion.name}</span>
|
||||
{inpaintMaskAsset ? <MaskStatus asset={inpaintMaskAsset} purpose="inpaint" /> : null}
|
||||
<button type="button" className={`h-8 rounded-md px-3 text-xs font-medium ${editingInpaintRegion ? "bg-red-200 text-red-950" : "hover:bg-white/[0.07]"}`} onClick={() => editingInpaintRegion ? dispatch(commandIds.toolExitMaskEdit, undefined) : dispatch(commandIds.toolEnterInpaintRegionEdit, { targetLayerId: layer.id, regionId: inpaintRegion.id })}>{editingInpaintRegion ? "Done" : "Edit"}</button>
|
||||
<button type="button" className="h-8 rounded-md px-3 text-xs font-medium text-red-100/50 transition hover:bg-red-400/15 hover:text-red-100" onClick={() => dispatch(commandIds.documentRemoveInpaintRegion, { regionId: inpaintRegion.id })}>Remove</button>
|
||||
</div>
|
||||
) : null}
|
||||
{layer.type === "group"
|
||||
? layer.children.map((child) => (
|
||||
<LayerRow
|
||||
|
||||
Reference in New Issue
Block a user