Align LibTV image composer overlay
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-18 21:38:20 +08:00
parent 7bc4e768b6
commit 0c12132bb4

View File

@ -177,6 +177,7 @@ type PresetControlAnchor = {
bottomY: number;
centerX: number;
topY: number;
zoom: number;
};
type ComposerSettings = {
@ -996,6 +997,10 @@ function getPresetMode(node: CloneNode | null | undefined): ActiveStarterScene {
return null;
}
function isOfficialImageControlNode(node: CloneNode | null | undefined): node is CloneNode {
return !!node && node.kind === "media" && node.inputType === "image" && !!getNodeMediaUrl(node);
}
function getTargetModuleKind(node: CloneNode): AddModuleKind | null {
if (node.kind === "media" || getPresetMode(node)) return null;
if (getDraftString(node, "action") === "TEXT_RESOURCE" || getDraftString(node, "scriptRole") === "resource") {
@ -2360,8 +2365,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
}, []);
const isBusy = isLoading || isProjectLoading;
const selectedPresetControlNode =
selectedNode?.kind === "media" && selectedNode.inputType !== "audio" ? selectedNode : null;
const selectedPresetControlNode = isOfficialImageControlNode(selectedNode) ? selectedNode : null;
const selectedPresetMode = getPresetMode(selectedPresetControlNode);
const selectedTargetModuleKind = selectedNode ? getTargetModuleKind(selectedNode) : null;
const selectedPresetAnchor = useMemo<PresetControlAnchor | null>(() => {
@ -2370,6 +2374,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
bottomY: Math.round(viewport.y + (selectedPresetControlNode.y + selectedPresetControlNode.height) * viewport.zoom),
centerX: Math.round(viewport.x + (selectedPresetControlNode.x + selectedPresetControlNode.width / 2) * viewport.zoom),
topY: Math.round(viewport.y + selectedPresetControlNode.y * viewport.zoom),
zoom: viewport.zoom,
};
}, [selectedPresetControlNode, viewport.x, viewport.y, viewport.zoom]);
@ -2483,10 +2488,10 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
/>
) : null}
{selectedPresetMode && selectedPresetAnchor && selectedPresetControlNode ? (
{selectedPresetAnchor && selectedPresetControlNode ? (
<PresetWorkflowControls
anchor={selectedPresetAnchor}
mode={selectedPresetMode}
mode={selectedPresetMode ?? "character-three-view"}
nodes={nodes}
onComposerSubmit={(payload) => submitSelectedImagePrompt(selectedPresetControlNode.id, payload)}
onImageToolAction={(action, option) => runSelectedImageToolAction(selectedPresetControlNode.id, action, option)}
@ -2546,7 +2551,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib
/>
) : null}
{selectedNode && !selectedPresetMode && !selectedTargetModuleKind ? (
{selectedNode && !selectedPresetControlNode && !selectedTargetModuleKind ? (
<InspectorPanel
node={selectedNode}
onChangeProperty={updateNodeDraft}
@ -3156,7 +3161,7 @@ function CharacterPresetToolbar({
? "origin-bottom -translate-x-1/2 -translate-y-full scale-[0.7]"
: "left-1/2 top-[168px] origin-top -translate-x-1/2 scale-[0.7]"
)}
style={anchor ? { left: anchor.centerX, top: anchor.topY - 14 } : undefined}
style={anchor ? { left: anchor.centerX, top: anchor.topY - (24 * anchor.zoom + 10) } : undefined}
>
<SceneTool active={toolbarMenu === "panorama"} kind="panorama" label="全景" badge="NEW" onClick={() => setToolbarMenu((current) => current === "panorama" ? null : "panorama")} />
<SceneTool active={toolbarMenu === "orbit"} kind="orbit" label="多角度" onClick={() => setToolbarMenu((current) => current === "orbit" ? null : "orbit")} />
@ -3510,10 +3515,10 @@ function PresetComposerPanel({
className={cn(
"pointer-events-auto absolute h-[238px] w-[895px] rounded-[18px] border border-white/8 bg-[#262626]/98 p-5 text-white shadow-[0_24px_84px_rgba(0,0,0,0.48)]",
anchor
? "origin-top -translate-x-1/2 scale-[0.5]"
: "bottom-[64px] left-1/2 origin-bottom -translate-x-1/2 scale-[0.5]"
? "origin-top -translate-x-1/2 scale-[0.47]"
: "bottom-[64px] left-1/2 origin-bottom -translate-x-1/2 scale-[0.47]"
)}
style={anchor ? { left: anchor.centerX, top: anchor.bottomY + 18 } : undefined}
style={anchor ? { left: anchor.centerX, top: anchor.bottomY + 10 } : undefined}
>
<button className="absolute right-5 top-5 text-[26px] text-white/45" onClick={() => toast.info("展开提示词编辑器待接入。")} type="button">↗</button>
<div className="mb-5 flex items-center gap-3">
@ -3846,10 +3851,10 @@ function PromptComposer({
className={cn(
"pointer-events-auto absolute h-[286px] w-[895px] rounded-[18px] border border-white/8 bg-[#262626]/98 p-5 text-white shadow-[0_24px_84px_rgba(0,0,0,0.48)]",
anchor
? "origin-top -translate-x-1/2 scale-[0.5]"
: "bottom-[64px] left-1/2 origin-bottom -translate-x-1/2 scale-[0.5]"
? "origin-top -translate-x-1/2 scale-[0.47]"
: "bottom-[64px] left-1/2 origin-bottom -translate-x-1/2 scale-[0.47]"
)}
style={anchor ? { left: anchor.centerX, top: anchor.bottomY + 18 } : undefined}
style={anchor ? { left: anchor.centerX, top: anchor.bottomY + 10 } : undefined}
>
<button className="absolute right-5 top-5 text-[26px] text-white/45" onClick={() => toast.info("展开提示词编辑器待接入。")} type="button">↗</button>
<div className="flex items-center gap-3">