139 lines
4.4 KiB
TypeScript
139 lines
4.4 KiB
TypeScript
export const availableToolIds = ["select", "brush", "eraser", "magicWand", "pan"] as const;
|
|
|
|
export const availableOperationIds = ["generate", "chromaKey"] as const;
|
|
|
|
export type ToolId = (typeof availableToolIds)[number];
|
|
export type OperationId = (typeof availableOperationIds)[number];
|
|
|
|
export type InteractionMode =
|
|
| { type: "tool"; tool: ToolId }
|
|
| { type: "temporary-pan"; previousTool: ToolId };
|
|
|
|
export type BrushSettings = {
|
|
color: string;
|
|
size: number;
|
|
hardness: number;
|
|
};
|
|
|
|
export type ChromaKeySettings = {
|
|
color: string;
|
|
tolerance: number;
|
|
softness: number;
|
|
feather: number;
|
|
choke: number;
|
|
despeckle: number;
|
|
spill: number;
|
|
};
|
|
|
|
export type MagicWandMode = "replace" | "add" | "subtract";
|
|
|
|
export type GenerateMode = "text-to-image" | "image-to-image" | "inpaint" | "outpaint";
|
|
export type GenerateIntent = "create" | "replace" | "extend" | "variations";
|
|
|
|
export const generateArchitectures = ["sdxl", "z-image", "z-image-turbo", "anima"] as const;
|
|
export type GenerateArchitecture = (typeof generateArchitectures)[number];
|
|
|
|
export type GenerateModel = string;
|
|
export type InpaintMaskedContent = "neutral" | "original" | "originalColor" | "edges";
|
|
|
|
export type GenerateSettings = {
|
|
architecture: GenerateArchitecture;
|
|
mode: GenerateMode;
|
|
model: GenerateModel;
|
|
textEncoder: string;
|
|
vae: string;
|
|
prompt: string;
|
|
negativePrompt: string;
|
|
strength: number;
|
|
steps: number;
|
|
cfg: number;
|
|
seed: number;
|
|
sampler: string;
|
|
scheduler: string;
|
|
width: number;
|
|
height: number;
|
|
outpaint: {
|
|
left: number;
|
|
top: number;
|
|
right: number;
|
|
bottom: number;
|
|
feathering: number;
|
|
};
|
|
inpaint: {
|
|
maskedAreaOnly: boolean;
|
|
cropPadding: number;
|
|
maskPolarity: "hidden" | "revealed";
|
|
maskedContent: InpaintMaskedContent;
|
|
growMaskBy: number;
|
|
maskExpand: number;
|
|
maskFeather: number;
|
|
maskBlur: number;
|
|
maskDespeckle: number;
|
|
};
|
|
};
|
|
|
|
export const generateArchitectureDefaults: Record<GenerateArchitecture, {
|
|
model: GenerateModel;
|
|
textEncoder: string;
|
|
vae: string;
|
|
steps: number;
|
|
cfg: number;
|
|
sampler: string;
|
|
scheduler: string;
|
|
supportedModes: readonly GenerateMode[];
|
|
}> = {
|
|
sdxl: { model: "auto", textEncoder: "auto", vae: "auto", steps: 30, cfg: 7, sampler: "euler", scheduler: "normal", supportedModes: ["text-to-image", "image-to-image", "inpaint", "outpaint"] },
|
|
"z-image": { model: "auto", textEncoder: "qwen_3_4b.safetensors", vae: "ae.safetensors", steps: 30, cfg: 4, sampler: "res_multistep", scheduler: "simple", supportedModes: ["text-to-image"] },
|
|
"z-image-turbo": { model: "auto", textEncoder: "qwen_3_4b.safetensors", vae: "ae.safetensors", steps: 8, cfg: 1, sampler: "res_multistep", scheduler: "simple", supportedModes: ["text-to-image"] },
|
|
anima: { model: "auto", textEncoder: "qwen_3_06b_base.safetensors", vae: "qwen_image_vae.safetensors", steps: 30, cfg: 4, sampler: "er_sde", scheduler: "simple", supportedModes: ["text-to-image"] },
|
|
};
|
|
|
|
export type MagicWandSettings = {
|
|
tolerance: number;
|
|
feather: number;
|
|
choke: number;
|
|
despeckle: number;
|
|
contiguous: boolean;
|
|
mode: MagicWandMode;
|
|
};
|
|
|
|
export type ToolState = {
|
|
activeTool: ToolId;
|
|
interactionMode: InteractionMode;
|
|
brush: BrushSettings;
|
|
chromaKey: ChromaKeySettings;
|
|
magicWand: MagicWandSettings;
|
|
generate: GenerateSettings;
|
|
};
|
|
|
|
export const initialToolState: ToolState = {
|
|
activeTool: "select",
|
|
interactionMode: { type: "tool", tool: "select" },
|
|
brush: { color: "#111827", size: 8, hardness: 100 },
|
|
chromaKey: { color: "#00ff00", tolerance: 32, softness: 24, feather: 0, choke: 0, despeckle: 0, spill: 50 },
|
|
magicWand: { tolerance: 32, feather: 0, choke: 0, despeckle: 0, contiguous: true, mode: "replace" },
|
|
generate: {
|
|
architecture: "sdxl",
|
|
mode: "text-to-image",
|
|
model: "auto",
|
|
textEncoder: "auto",
|
|
vae: "auto",
|
|
prompt: "",
|
|
negativePrompt: "",
|
|
strength: 75,
|
|
steps: 30,
|
|
cfg: 7,
|
|
seed: -1,
|
|
sampler: "euler",
|
|
scheduler: "normal",
|
|
width: 1024,
|
|
height: 1024,
|
|
outpaint: { left: 128, top: 128, right: 128, bottom: 128, feathering: 32 },
|
|
inpaint: { maskedAreaOnly: true, cropPadding: 96, maskPolarity: "hidden", maskedContent: "neutral", growMaskBy: 6, maskExpand: 0, maskFeather: 0, maskBlur: 0, maskDespeckle: 0 },
|
|
},
|
|
};
|
|
|
|
export function isPanInteractionMode(interactionMode: InteractionMode): boolean {
|
|
return interactionMode.type === "temporary-pan" || (interactionMode.type === "tool" && interactionMode.tool === "pan");
|
|
}
|