pipe model info to inpainting editor

This commit is contained in:
Brandon Thomas committed 2025-08-19 19:20:30 -04:00
1 parent fbf914e24e
commit 80c9173a5e
6 files changed
+78 -28

No files matched your search

@@ -24,16 +24,30 @@ import { EditPaintSurface } from "./EditPaintSurface";
import { normalizeCanvas } from "../../Helpers/CanvasHelpers";
import { BaseImageSelector, BaseSelectorImage } from "./BaseImageSelector";
import DrawToolControlBar from "./DrawToolControlBar";
import { imageEditorModels, ModelCategory, ModelSelector, useModelSelectorStore } from "@storyteller/ui-model-selector";
import { ModelInfo } from "@storyteller/model-list";
const PageEdit = () => {
//useStateSceneLoader();
const { selectedModels } = useModelSelectorStore();
const selectedModel =
selectedModels[ModelCategory.Canvas2D] ||
imageEditorModels[0]?.label;
const selectedModelInfo: ModelInfo | undefined =
imageEditorModels.find(
(m) => m.label === selectedModel,
)?.modelInfo;
// State for canvas dimensions
const canvasWidth = useRef<number>(1024);
const canvasHeight = useRef<number>(1024);
// Add new state to track if user is selecting
const [isSelecting, setIsSelecting] = useState<boolean>(false);
const [selectedModel, setSelectedModel] = useState<string>("GPT-4o");
//const [selectedModel, setSelectedModel] = useState<string>("GPT-4o");
// Create refs for stage and image
const stageRef = useRef<Konva.Stage>({} as Konva.Stage);
const leftPanelRef = useRef<Konva.Layer>({} as Konva.Layer);
@@ -42,6 +56,7 @@ const PageEdit = () => {
const [isEnqueuing, setIsEnqueuing] = useState<boolean>(false);
const [generationCount, setGenerationCount] = useState<number>(1);
// Use the Zustand store
const store = useEditStore();
@@ -115,27 +130,6 @@ const PageEdit = () => {
};
}, [store]);
const modelList: PopoverItem[] = [
{
label: "GPT-4o",
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
selected: selectedModel === "GPT-4o",
description: "High quality model",
badges: [{ label: "2 min.", icon: <FontAwesomeIcon icon={faClock} /> }],
},
{
label: "FLUX.1 Kontext",
icon: <FontAwesomeIcon icon={faImage} className="h-4 w-4" />,
selected: selectedModel === "FLUX.1 Kontext",
description: "Fast and high-quality model",
badges: [{ label: "20 sec.", icon: <FontAwesomeIcon icon={faClock} /> }],
},
];
const handleModelSelect = (item: PopoverItem) => {
setSelectedModel(item.label);
};
const onFitPressed = async () => {
// Get the stage and its container dimensions
const stage = stageRef.current;
@@ -263,6 +257,7 @@ const PageEdit = () => {
}`}
>
<PromptEditor
modelInfo={selectedModelInfo}
onModeChange={(mode: string) => {
store.setActiveTool(mode as ActiveEditTool);
}}
@@ -328,10 +323,9 @@ const PageEdit = () => {
</ContextMenuContainer>
</div>
<div className="absolute bottom-6 left-6 z-20 flex items-center gap-2">
<PopoverMenu
items={modelList}
onSelect={handleModelSelect}
mode="hoverSelect"
<ModelSelector
items={imageEditorModels}
category={ModelCategory.ImageEditor}
panelTitle="Select Model"
panelClassName="min-w-[280px]"
buttonClassName="bg-transparent p-0 text-lg hover:bg-transparent text-white/80 hover:text-white"
@@ -3,4 +3,7 @@ export enum ModelCategory {
ImageToVideo = "image-to-video",
Canvas2D = "2d-canvas",
Editor3D = "3d-editor",
// The "inpainting + outpainting + text" image editor
ImageEditor = "image-editor",
}
@@ -5,6 +5,7 @@ import {
getCreatorIcon,
getModelsByCategory,
getInstructiveImageEditModels,
getEditorModels,
} from "@storyteller/model-list";
export type ModelList = Omit<PopoverItem, "selected">[];
@@ -35,6 +36,9 @@ const imageModels = getModelsByCategory("image");
const videoModels = getModelsByCategory("video");
const instructiveModels = getInstructiveImageEditModels();
// Models for the editor page (not 2d canvas, the inpaint/outpaint editor)
const imageEditModels = getEditorModels();
export const allModels = {
video: buildItems(
videoModels as any,
@@ -48,9 +52,15 @@ export const allModels = {
instructiveModels as any,
<FontAwesomeIcon icon={faImage} className="h-4 w-4" />
),
imageEditorModels: buildItems(
imageEditModels as any,
<FontAwesomeIcon icon={faImage} className="h-4 w-4" />
),
};
export const videoGenerationModels: ModelList = allModels.video;
export const imageGenerationModels: ModelList = allModels.image;
export const instructiveImageEditModels: ModelList =
allModels.instructiveImageEdits;
export const imageEditorModels: ModelList = allModels.imageEditorModels;
@@ -63,6 +63,7 @@ export const PromptBoxEdit = ({
// Build generation count options based on selected model
useEffect(() => {
const caps = getCapabilitiesForModel(modelInfo);
console.log(">>> caps", caps)
const items: PopoverItem[] = Array.from(
{ length: caps.maxGenerationCount },
(_, i) => i + 1
@@ -0,0 +1,11 @@
export enum ModelTag {
// Models that show up in the 2D and 3D editors
InstructiveEdit = "instructiveEdit",
// Models that show up in the inpainting editor and that use masking.
MaskedInpainting = "maskedInpainting",
// Models that show up in the inpainting editor, but that do not use masking.
NonMaskedInpainting = "nonMaskedInpainting",
}
+33 -2
View File
@@ -1,5 +1,6 @@
import { ModelCreator } from "./ModelCreator.js";
import { ModelInfo } from "./ModelInfo.js";
import { ModelTag } from "./ModelTag.js";
export type ModelCategory = "image" | "video";
@@ -11,7 +12,7 @@ export interface ModelConfig {
category: ModelCategory;
info: ModelInfo;
capabilities: ModelCapabilities;
tags?: string[]; // optional tags, e.g. ["instructiveEdit"] - for filtering
tags?: (ModelTag|string)[]; // optional tags, e.g. ["instructiveEdit"] - for filtering
}
const mc = ModelCreator;
@@ -130,7 +131,23 @@ export const ALL_MODELS: ModelConfig[] = [
description: "Fast and high-quality model",
badges: [{ label: "20 sec." }],
capabilities: { maxGenerationCount: 4 },
tags: ["instructiveEdit"],
tags: [
ModelTag.InstructiveEdit,
ModelTag.NonMaskedInpainting,
],
}),
cfg({
id: "flux_pro_inpaint",
category: "image",
info: {
name: "Flux Pro 1 (Inpainting)",
tauri_id: "flux_pro_1",
creator: mc.BlackForestLabs,
},
description: "Fast and high-quality model",
badges: [{ label: "20 sec." }],
capabilities: { maxGenerationCount: 4 },
tags: [ModelTag.MaskedInpainting],
}),
//////////////////////////////
@@ -204,6 +221,20 @@ export const getInstructiveImageEditModels = (): ModelConfig[] =>
(m) => m.category === "image" && m.tags?.includes("instructiveEdit")
);
export const getMaskedInpaintModels = (): ModelConfig[] =>
ALL_MODELS.filter(
(m) => m.category === "image" && m.tags?.includes(ModelTag.MaskedInpainting)
);
// Models for the editor page
export const getEditorModels = (): ModelConfig[] =>
ALL_MODELS.filter(
(m) => m.category === "image" && (
m.tags?.includes(ModelTag.MaskedInpainting)
|| m.tags?.includes(ModelTag.NonMaskedInpainting)
)
);
export const lookupModelByTauriId = (
tauriId: string
): ModelConfig | undefined =>