- 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.
95 lines
4.0 KiB
TypeScript
95 lines
4.0 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import type { ImageDocument } from "@core/document";
|
|
import type { GenerateSettings } from "@editor/tools";
|
|
import { createInitialAppState } from "@editor/initial-state";
|
|
import { resolveGeneratedOutputPlacement } from "./outputPlacement";
|
|
|
|
describe("generated output placement", () => {
|
|
test("centers text-to-image output in the active artboard", () => {
|
|
const placement = resolveGeneratedOutputPlacement({
|
|
document: document(),
|
|
selection: { artboardId: "artboard", layerIds: [] },
|
|
settings: settings("text-to-image"),
|
|
intrinsicSize: { w: 400, h: 200 },
|
|
});
|
|
|
|
expect(placement).toEqual({
|
|
artboardId: "artboard",
|
|
layerName: "Generated image",
|
|
transform: { position: { x: 310, y: 270 }, scale: { x: 1, y: 1 }, rotation: 0 },
|
|
});
|
|
});
|
|
|
|
test("matches image-to-image output to the selected layer bounds", () => {
|
|
const placement = resolveGeneratedOutputPlacement({
|
|
document: document(),
|
|
selection: selected(),
|
|
settings: settings("image-to-image"),
|
|
intrinsicSize: { w: 200, h: 250 },
|
|
});
|
|
|
|
expect(placement.transform).toEqual({
|
|
position: { x: 80, y: 90 },
|
|
scale: { x: 0.75, y: 1 },
|
|
rotation: 12,
|
|
});
|
|
});
|
|
|
|
test("places an inpaint crop at its recorded document bounds", () => {
|
|
const placement = resolveGeneratedOutputPlacement({
|
|
document: document(),
|
|
selection: selected(),
|
|
settings: settings("inpaint"),
|
|
intrinsicSize: { w: 128, h: 64 },
|
|
inpaintBundle: {
|
|
inputImage: "input", sourceImage: "source", contextImage: "context", maskImage: "mask", editMaskImage: "edit", blendMaskImage: "blend", width: 256, height: 128,
|
|
targetLayerId: "source", regionId: "region", sourceAssetId: "source-asset", maskAssetId: "mask-asset", revision: { source: "source-revision", mask: "mask-revision" },
|
|
crop: { assetBounds: { x: 0, y: 0, w: 256, h: 128 }, documentBounds: { x: 140, y: 150, w: 384, h: 64 }, padding: 16, maskedAreaOnly: true },
|
|
mask: { polarity: "hidden", activeBounds: { x: 20, y: 20, w: 40, h: 40 } },
|
|
placement: { artboardId: "artboard", layerName: "Source inpaint", transform: { position: { x: 140, y: 150 }, scale: { x: 1.5, y: 0.5 }, rotation: 12 } },
|
|
backend: { growMaskBy: 6, maskedContent: "neutral", maskBlur: 0, maskFeather: 0, maskExpand: 0, cropPadding: 16 },
|
|
},
|
|
});
|
|
|
|
expect(placement.transform).toEqual({ position: { x: 140, y: 150 }, scale: { x: 3, y: 1 }, rotation: 12 });
|
|
});
|
|
|
|
test("extends outpaint output left and top while preserving source pixel scale", () => {
|
|
const outpaint = { ...settings("outpaint"), outpaint: { left: 40, top: 20, right: 10, bottom: 30, feathering: 8 } };
|
|
const placement = resolveGeneratedOutputPlacement({
|
|
document: document(),
|
|
selection: selected(),
|
|
settings: outpaint,
|
|
intrinsicSize: { w: 150, h: 550 },
|
|
});
|
|
|
|
expect(placement.transform).toEqual({
|
|
position: { x: 20, y: 80 },
|
|
scale: { x: 1.5, y: 0.5 },
|
|
rotation: 12,
|
|
});
|
|
});
|
|
});
|
|
|
|
function settings(mode: GenerateSettings["mode"]): GenerateSettings {
|
|
return { ...createInitialAppState("Test").editor.tools.generate, mode };
|
|
}
|
|
|
|
function selected() {
|
|
return { artboardId: "artboard", layerIds: ["source"] };
|
|
}
|
|
|
|
function document(): ImageDocument {
|
|
return {
|
|
id: "document", name: "Test", version: 1, inpaintRegions: [],
|
|
assets: [
|
|
{ id: "source-asset", name: "Source", mimeType: "image/png", source: "source", intrinsicSize: { w: 100, h: 500 } },
|
|
{ id: "mask-asset", name: "Mask", mimeType: "image/png", source: "mask", intrinsicSize: { w: 100, h: 500 } },
|
|
],
|
|
artboards: [{
|
|
id: "artboard", name: "Artboard", bounds: { x: 10, y: 20, w: 1000, h: 700 }, backgroundColor: "transparent", visible: true, locked: false,
|
|
layers: [{ id: "source", type: "raster", name: "Source", visible: true, locked: false, opacity: 1, assetId: "source-asset", transform: { position: { x: 80, y: 90 }, scale: { x: 1.5, y: 0.5 }, rotation: 12 } }],
|
|
}],
|
|
};
|
|
}
|