mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-03 00:47:53 +00:00
bug fixes
This commit is contained in:
1 parent
40a2e8a514
commit
e9316bcdb5
12 files changed
+64
-47
No files matched your search
@@ -152,15 +152,17 @@ export const ImageTo3DExperience = ({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (variant === "world" && pendingExternalImage) {
|
||||
// Read from store directly to avoid Strict Mode double-execution adding the image twice
|
||||
const pending = useImageTo3DWorldStore.getState().pendingExternalImage;
|
||||
if (variant === "world" && pending) {
|
||||
setWorldImages((prev) => {
|
||||
if (prev.length >= MAX_WORLD_IMAGES) return prev;
|
||||
return [
|
||||
...prev,
|
||||
{
|
||||
id: generateId(),
|
||||
preview: pendingExternalImage.url,
|
||||
mediaToken: pendingExternalImage.mediaToken,
|
||||
preview: pending.url,
|
||||
mediaToken: pending.mediaToken,
|
||||
name: "Library Image",
|
||||
isUploading: false,
|
||||
},
|
||||
@@ -400,9 +402,6 @@ export const ImageTo3DExperience = ({
|
||||
if ("error_type" in result) {
|
||||
throw new Error(result.error_message || result.error_type);
|
||||
}
|
||||
|
||||
setWorldImages([]);
|
||||
setWorldPrompt("");
|
||||
} else {
|
||||
const snapshotPrompt = prompt.trim();
|
||||
const snapshotPreview = uploadedPreview || undefined;
|
||||
@@ -735,7 +734,7 @@ export const ImageTo3DExperience = ({
|
||||
key={img.id}
|
||||
className={twMerge(
|
||||
"glass group relative aspect-square overflow-hidden rounded-lg border-2 border-white/30 transition-all",
|
||||
hasResults ? "w-10" : "w-14",
|
||||
hasResults ? "w-10" : "w-auto",
|
||||
img.isUploading
|
||||
? "cursor-default"
|
||||
: "cursor-pointer hover:cursor-zoom-in hover:border-white/80",
|
||||
|
||||
@@ -412,13 +412,21 @@ export const TaskQueue = () => {
|
||||
? getProviderDisplayName(String(t.provider).toLowerCase())
|
||||
: undefined;
|
||||
const taskTypeStr = t.task_type ? String(t.task_type).toLowerCase() : "";
|
||||
const modelTypeStr = t.model_type ? String(t.model_type).toLowerCase() : "";
|
||||
const isSplatModel =
|
||||
taskTypeStr.includes("gaussian") ||
|
||||
modelTypeStr.includes("marble") ||
|
||||
modelTypeStr.includes("worldlabs");
|
||||
const is3DModel =
|
||||
taskTypeStr.includes("3d") ||
|
||||
taskTypeStr.includes("object") ||
|
||||
taskTypeStr.includes("dimensional");
|
||||
taskTypeStr.includes("dimensional") ||
|
||||
isSplatModel;
|
||||
|
||||
let kind = undefined;
|
||||
if (taskTypeStr.includes("image") && is3DModel) {
|
||||
if (isSplatModel) {
|
||||
kind = "3D World";
|
||||
} else if (taskTypeStr.includes("image") && is3DModel) {
|
||||
kind = "Image to 3D";
|
||||
} else if (is3DModel) {
|
||||
kind = "3D Model";
|
||||
|
||||
@@ -26,7 +26,7 @@ import { OrbitSphere, snapToNearest } from "./OrbitSphere";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { LoadingSpinner } from "@storyteller/ui-loading-spinner";
|
||||
import { SliderV2 } from "@storyteller/ui-sliderv2";
|
||||
import { Switch } from "@headlessui/react";
|
||||
// import { Switch } from "@headlessui/react";
|
||||
import { EnqueueEditImage } from "@storyteller/tauri-api";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import {
|
||||
@@ -41,10 +41,7 @@ import {
|
||||
useCostBreakdownModalStore,
|
||||
} from "@storyteller/ui-pricing-modal";
|
||||
import { HelpMenuButton } from "@storyteller/ui-help-menu";
|
||||
import {
|
||||
HistoryStack,
|
||||
ImageBundle,
|
||||
} from "../PageEdit/HistoryStack";
|
||||
import { HistoryStack, ImageBundle } from "../PageEdit/HistoryStack";
|
||||
import type { BaseSelectorImage } from "../PageEdit/BaseImageSelector";
|
||||
|
||||
const ANGLES_MODEL_PAGE = ModelPage.Angles;
|
||||
@@ -84,9 +81,9 @@ export const Angles = () => {
|
||||
const sourceMediaToken = useAnglesStore((s) => s.sourceMediaToken);
|
||||
const imageDimensions = useAnglesStore((s) => s.imageDimensions);
|
||||
const angleConfig = useAnglesStore((s) => s.angleConfig);
|
||||
const generateFromBestAngles = useAnglesStore(
|
||||
(s) => s.generateFromBestAngles,
|
||||
);
|
||||
// const generateFromBestAngles = useAnglesStore(
|
||||
// (s) => s.generateFromBestAngles,
|
||||
// );
|
||||
const generatedAngles = useAnglesStore((s) => s.generatedAngles);
|
||||
const activeAngleId = useAnglesStore((s) => s.activeAngleId);
|
||||
const isProcessing = useAnglesStore((s) => s.isProcessing);
|
||||
@@ -98,9 +95,9 @@ export const Angles = () => {
|
||||
const setRotation = useAnglesStore((s) => s.setRotation);
|
||||
const setTilt = useAnglesStore((s) => s.setTilt);
|
||||
const setZoom = useAnglesStore((s) => s.setZoom);
|
||||
const setGenerateFromBestAngles = useAnglesStore(
|
||||
(s) => s.setGenerateFromBestAngles,
|
||||
);
|
||||
// const setGenerateFromBestAngles = useAnglesStore(
|
||||
// (s) => s.setGenerateFromBestAngles,
|
||||
// );
|
||||
const setActiveAngle = useAnglesStore((s) => s.setActiveAngle);
|
||||
const setIsLoadingImage = useAnglesStore((s) => s.setIsLoadingImage);
|
||||
const resetSource = useAnglesStore((s) => s.resetSource);
|
||||
@@ -160,9 +157,7 @@ export const Angles = () => {
|
||||
// Resolve pending placeholder
|
||||
const resolveId =
|
||||
event.maybe_frontend_subscriber_id ?? state.pendingSubscriberId;
|
||||
setPendingGenerations((prev) =>
|
||||
prev.filter((p) => p.id !== resolveId),
|
||||
);
|
||||
setPendingGenerations((prev) => prev.filter((p) => p.id !== resolveId));
|
||||
});
|
||||
|
||||
return () => {
|
||||
@@ -469,21 +464,18 @@ export const Angles = () => {
|
||||
[setActiveAngle],
|
||||
);
|
||||
|
||||
const handleHistoryImageRemove = useCallback(
|
||||
(image: BaseSelectorImage) => {
|
||||
setHistoryBundles((prev) =>
|
||||
prev
|
||||
.map((bundle) => ({
|
||||
...bundle,
|
||||
images: bundle.images.filter(
|
||||
(img) => img.mediaToken !== image.mediaToken,
|
||||
),
|
||||
}))
|
||||
.filter((bundle) => bundle.images.length > 0),
|
||||
);
|
||||
},
|
||||
[],
|
||||
);
|
||||
const handleHistoryImageRemove = useCallback((image: BaseSelectorImage) => {
|
||||
setHistoryBundles((prev) =>
|
||||
prev
|
||||
.map((bundle) => ({
|
||||
...bundle,
|
||||
images: bundle.images.filter(
|
||||
(img) => img.mediaToken !== image.mediaToken,
|
||||
),
|
||||
}))
|
||||
.filter((bundle) => bundle.images.length > 0),
|
||||
);
|
||||
}, []);
|
||||
|
||||
const handleHistoryClear = useCallback(() => {
|
||||
setHistoryBundles([]);
|
||||
@@ -738,7 +730,7 @@ export const Angles = () => {
|
||||
|
||||
{/* Toggle + Generate */}
|
||||
<div className="flex shrink-0 flex-col items-end gap-2.5">
|
||||
<Switch.Group>
|
||||
{/* <Switch.Group>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch.Label className="cursor-pointer whitespace-nowrap text-xs text-base-fg/50">
|
||||
Best 12 angles
|
||||
@@ -761,11 +753,10 @@ export const Angles = () => {
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
</Switch.Group>
|
||||
</Switch.Group> */}
|
||||
|
||||
<GenerateButton
|
||||
variant="primary"
|
||||
icon={faCrosshairs}
|
||||
onClick={handleGenerate}
|
||||
disabled={isProcessing || !sourceMediaToken}
|
||||
loading={isProcessing}
|
||||
|
||||
@@ -516,7 +516,7 @@ export const PageEditor = () => {
|
||||
onClick={handleOverlayClick}
|
||||
>
|
||||
<div
|
||||
className="absolute bottom-14 mb-4 ml-4 flex origin-bottom-left flex-col gap-2"
|
||||
className="absolute bottom-20 mb-4 ml-4 flex origin-bottom-left flex-col gap-2"
|
||||
style={{ transform: `scale(${getScale()})` }}
|
||||
>
|
||||
<Outliner />
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ export const ControlPanelSceneObject = () => {
|
||||
as="div"
|
||||
show={isShowing.value}
|
||||
className={twMerge(
|
||||
"glass absolute bottom-0 right-0 mb-4 mr-4 flex h-fit w-56 origin-bottom-right flex-col gap-2 rounded-lg border border-ui-panel-border p-3.5 text-white shadow-lg",
|
||||
"glass absolute bottom-16 right-0 mb-4 mr-4 flex h-fit w-56 origin-bottom-right flex-col gap-2 rounded-lg border border-ui-panel-border p-3.5 text-white shadow-lg",
|
||||
)}
|
||||
enter="transition-opacity duration-150"
|
||||
enterFrom="opacity-0"
|
||||
|
||||
@@ -6,5 +6,6 @@ export enum TaskType {
|
||||
ImageInpaintEdit = "image_inpaint_edit",
|
||||
VideoGeneration = "video_generation",
|
||||
ObjectGeneration = "object_generation",
|
||||
SplatGeneration = "gaussian_generation",
|
||||
BackgroundRemoval = "background_removal",
|
||||
}
|
||||
@@ -51,10 +51,14 @@ export const MODEL_TYPE_TO_CREATOR: Record<string, ModelCreator> = {
|
||||
hunyuan_3d: ModelCreator.Tencent,
|
||||
hunyuan_3d_2p0: ModelCreator.Tencent,
|
||||
hunyuan_3d_2p1: ModelCreator.Tencent,
|
||||
hunyuan_3d_2: ModelCreator.Tencent,
|
||||
hunyuan_3d_3: ModelCreator.Tencent,
|
||||
// Hunyuan — dot-normalized aliases
|
||||
hunyuan_3d_2_0: ModelCreator.Tencent,
|
||||
hunyuan_3d_2_1: ModelCreator.Tencent,
|
||||
worldlabs_gaussian: ModelCreator.WorldLabs,
|
||||
marble_0p1_mini: ModelCreator.WorldLabs,
|
||||
marble_0p1_plus: ModelCreator.WorldLabs,
|
||||
grok_image: ModelCreator.Grok,
|
||||
grok_video: ModelCreator.Grok,
|
||||
midjourney: ModelCreator.Midjourney,
|
||||
@@ -195,14 +199,18 @@ export const getModelDisplayName = (modelType: string): string => {
|
||||
|
||||
// Hunyuan (Tencent) — p-style IDs
|
||||
hunyuan_3d: "Hunyuan 3D",
|
||||
hunyuan_3d_2: "Hunyuan 3D 2.0",
|
||||
hunyuan_3d_2p0: "Hunyuan 3D 2.0",
|
||||
hunyuan_3d_2p1: "Hunyuan 3D 2.1",
|
||||
hunyuan_3d_3: "Hunyuan 3D 3.0",
|
||||
// Hunyuan — dot-normalized aliases
|
||||
hunyuan_3d_2_0: "Hunyuan 3D 2.0",
|
||||
hunyuan_3d_2_1: "Hunyuan 3D 2.1",
|
||||
|
||||
// World Labs
|
||||
worldlabs_gaussian: "World Labs Marble",
|
||||
marble_0p1_mini: "Marble Mini",
|
||||
marble_0p1_plus: "Marble Plus",
|
||||
|
||||
// Catch-all bucket for Midjourney.
|
||||
midjourney: "Midjourney",
|
||||
|
||||
@@ -15,4 +15,6 @@ export enum GenerationAction {
|
||||
GenerateVideo = "generate_video",
|
||||
RemoveBackground = "remove_background",
|
||||
ImageTo3d = "image_to_3d",
|
||||
GenerateGaussian = "generate_gaussian",
|
||||
ImageInpaintEdit = "image_inpaint_edit",
|
||||
}
|
||||
@@ -57,7 +57,9 @@ const makeMessage = (event: GenerationCompleteEvent) => {
|
||||
case GenerationAction.RemoveBackground:
|
||||
return "Background removal complete!";
|
||||
case GenerationAction.ImageTo3d:
|
||||
return "Image to 3D complete!";
|
||||
return "3D model generation complete!";
|
||||
case GenerationAction.GenerateGaussian:
|
||||
return "3D world generation complete!";
|
||||
default:
|
||||
return "Generation complete!";
|
||||
}
|
||||
|
||||
+3
-1
@@ -58,7 +58,9 @@ const makeMessage = (event: GenerationEnqueueFailureEvent) => {
|
||||
case GenerationAction.RemoveBackground:
|
||||
return "Couldn't enqueue background removal!";
|
||||
case GenerationAction.ImageTo3d:
|
||||
return "Couldn't enqueue image to 3D!";
|
||||
return "Couldn't enqueue 3D model generation!";
|
||||
case GenerationAction.GenerateGaussian:
|
||||
return "Couldn't enqueue 3D world generation!";
|
||||
default:
|
||||
return "Couldn't enqueue generation!";
|
||||
}
|
||||
|
||||
+3
-1
@@ -54,7 +54,9 @@ const makeMessage = (event: GenerationEnqueueSuccessEvent) => {
|
||||
case GenerationAction.RemoveBackground:
|
||||
return "Background removal enqueued!";
|
||||
case GenerationAction.ImageTo3d:
|
||||
return "Image to 3D enqueued!";
|
||||
return "3D model generation enqueued!";
|
||||
case GenerationAction.GenerateGaussian:
|
||||
return "3D world generation enqueued!";
|
||||
default:
|
||||
return "Generation enqueued!";
|
||||
}
|
||||
|
||||
@@ -58,7 +58,9 @@ const makeMessage = (event: GenerationFailedEvent) => {
|
||||
case GenerationAction.RemoveBackground:
|
||||
return "Background removal failed!";
|
||||
case GenerationAction.ImageTo3d:
|
||||
return "Image to 3D failed!";
|
||||
return "3D model generation failed!";
|
||||
case GenerationAction.GenerateGaussian:
|
||||
return "3D world generation failed!";
|
||||
default:
|
||||
return "Generation failed!";
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user