6d964937db
补齐普通生图参考图来源菜单和画布选择流程 接入UI设计图与视频生成面板的提交链路 让生成引用上传目标支持多种生成面板 统一图片信息弹窗断言并补充相关测试 修复图标按钮浮层锚点ref与视频生成类型契约
288 lines
10 KiB
TypeScript
288 lines
10 KiB
TypeScript
import {
|
|
type Dispatch,
|
|
type MutableRefObject,
|
|
type RefObject,
|
|
type SetStateAction,
|
|
useCallback,
|
|
} from 'react';
|
|
|
|
import { ImageCanvasGenerationComposerView } from './ImageCanvasGenerationComposerView';
|
|
import {
|
|
resolveCharacterAnimationPanelStyle,
|
|
resolveGenerationAnchor,
|
|
resolveGenerationComposerStyle,
|
|
resolveIconComposerStyle,
|
|
resolveQuickEditPanelStyle,
|
|
} from './ImageCanvasOverlayModel';
|
|
import type {
|
|
CanvasGenerationDialogState,
|
|
CanvasLayer,
|
|
CanvasTool,
|
|
CanvasViewport,
|
|
GenerateDialogState,
|
|
ImageContextMenuState,
|
|
SidebarPanel,
|
|
UploadTarget,
|
|
} from './ImageCanvasEditorTypes';
|
|
import { useImageCanvasGenerationWorkflow } from './useImageCanvasGenerationWorkflow';
|
|
|
|
type CanvasGenerationDialogUpdater = (
|
|
dialog: CanvasGenerationDialogState,
|
|
) => CanvasGenerationDialogState | null;
|
|
|
|
type ImageCanvasGenerationSurfaceOptions = {
|
|
layers: CanvasLayer[];
|
|
canvasSize: { width: number; height: number };
|
|
viewport: CanvasViewport;
|
|
setViewport: Dispatch<SetStateAction<CanvasViewport>>;
|
|
layerCounterRef: MutableRefObject<number>;
|
|
specToolWrapRef: RefObject<HTMLSpanElement | null>;
|
|
characterSpecButtonRef: RefObject<HTMLButtonElement | null>;
|
|
characterReferenceButtonRef: RefObject<HTMLButtonElement | null>;
|
|
iconSpecButtonRef: RefObject<HTMLButtonElement | null>;
|
|
generationReferenceButtonRef: RefObject<HTMLButtonElement | null>;
|
|
generateDialog: GenerateDialogState | null;
|
|
setGenerateDialog: Dispatch<SetStateAction<GenerateDialogState | null>>;
|
|
activeCanvasGenerationDialog: CanvasGenerationDialogState | null;
|
|
canvasGenerationDialogs: CanvasGenerationDialogState[];
|
|
openCanvasGenerationDialog: (
|
|
dialog: Omit<CanvasGenerationDialogState, 'id'>,
|
|
) => void;
|
|
updateCanvasGenerationDialogById: (
|
|
dialogId: string,
|
|
updater: CanvasGenerationDialogUpdater,
|
|
) => void;
|
|
removeCanvasGenerationDialogById: (dialogId: string) => void;
|
|
removeCanvasGenerationDialogsByLayerId: (targetLayerId: string) => void;
|
|
getGeneratingDialogPlaceholder: (
|
|
dialog: GenerateDialogState,
|
|
) => GenerateDialogState['placeholder'];
|
|
appendCanvasLayersWithResources: (nextLayers: CanvasLayer[]) => void;
|
|
selectSingleLayer: (layerId: string | null) => void;
|
|
fitLayers: (targetLayers?: CanvasLayer[]) => void;
|
|
setActiveTool: Dispatch<SetStateAction<CanvasTool>>;
|
|
setActiveSidebarPanel: Dispatch<SetStateAction<SidebarPanel | null>>;
|
|
setMetadataLayer: Dispatch<SetStateAction<CanvasLayer | null>>;
|
|
setImageContextMenu: Dispatch<SetStateAction<ImageContextMenuState | null>>;
|
|
requestUpload: (target: UploadTarget) => void;
|
|
};
|
|
|
|
export function useImageCanvasGenerationSurface({
|
|
layers,
|
|
canvasSize,
|
|
viewport,
|
|
setViewport,
|
|
layerCounterRef,
|
|
specToolWrapRef,
|
|
characterSpecButtonRef,
|
|
characterReferenceButtonRef,
|
|
iconSpecButtonRef,
|
|
generationReferenceButtonRef,
|
|
generateDialog,
|
|
setGenerateDialog,
|
|
activeCanvasGenerationDialog,
|
|
canvasGenerationDialogs,
|
|
openCanvasGenerationDialog,
|
|
updateCanvasGenerationDialogById,
|
|
removeCanvasGenerationDialogById,
|
|
removeCanvasGenerationDialogsByLayerId,
|
|
getGeneratingDialogPlaceholder,
|
|
appendCanvasLayersWithResources,
|
|
selectSingleLayer,
|
|
fitLayers,
|
|
setActiveTool,
|
|
setActiveSidebarPanel,
|
|
setMetadataLayer,
|
|
setImageContextMenu,
|
|
requestUpload,
|
|
}: ImageCanvasGenerationSurfaceOptions) {
|
|
const generationWorkflow = useImageCanvasGenerationWorkflow({
|
|
layers,
|
|
canvasSize,
|
|
viewport,
|
|
setViewport,
|
|
canvasGenerationDialogs,
|
|
layerCounterRef,
|
|
generateDialog,
|
|
setGenerateDialog,
|
|
openCanvasGenerationDialog,
|
|
updateCanvasGenerationDialogById,
|
|
removeCanvasGenerationDialogById,
|
|
removeCanvasGenerationDialogsByLayerId,
|
|
getGeneratingDialogPlaceholder,
|
|
appendCanvasLayersWithResources,
|
|
selectSingleLayer,
|
|
fitLayers,
|
|
setActiveTool,
|
|
setActiveSidebarPanel,
|
|
setMetadataLayer,
|
|
setImageContextMenu,
|
|
});
|
|
|
|
const activeGenerationLayer =
|
|
activeCanvasGenerationDialog?.generatedLayerId
|
|
? (layers.find(
|
|
(layer) => layer.id === activeCanvasGenerationDialog.generatedLayerId,
|
|
) ?? null)
|
|
: null;
|
|
const generationAnchor = resolveGenerationAnchor({
|
|
dialog: activeCanvasGenerationDialog,
|
|
generatedLayer: activeGenerationLayer,
|
|
});
|
|
const generationComposerStyle = resolveGenerationComposerStyle({
|
|
dialog: activeCanvasGenerationDialog,
|
|
anchor: generationAnchor,
|
|
viewport,
|
|
});
|
|
const iconComposerStyle = resolveIconComposerStyle({
|
|
dialog: activeCanvasGenerationDialog,
|
|
composerStyle: generationComposerStyle,
|
|
iconDescriptionCount: generationWorkflow.iconDescriptionValues.length,
|
|
});
|
|
const quickEditPanelStyle = resolveQuickEditPanelStyle({
|
|
panel: generationWorkflow.quickEditPanel,
|
|
sourceLayer: generationWorkflow.quickEditSourceLayer,
|
|
viewport,
|
|
canvasSize,
|
|
});
|
|
const characterAnimationPanelStyle = resolveCharacterAnimationPanelStyle({
|
|
panel: generationWorkflow.characterAnimationPanel,
|
|
sourceLayer: generationWorkflow.characterAnimationSourceLayer,
|
|
viewport,
|
|
canvasSize,
|
|
});
|
|
|
|
const switchGenerationTool = useCallback(
|
|
(tool: CanvasTool) => {
|
|
if (tool === 'generate') {
|
|
generationWorkflow.openGenerateDialog();
|
|
return true;
|
|
}
|
|
if (tool === 'spec') {
|
|
generationWorkflow.setIsSpecMenuOpen((open) => !open);
|
|
setActiveTool('spec');
|
|
return true;
|
|
}
|
|
if (tool === 'character') {
|
|
generationWorkflow.openCharacterGenerationDialog();
|
|
return true;
|
|
}
|
|
if (tool === 'icon') {
|
|
generationWorkflow.openIconGenerationDialog();
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
[generationWorkflow, setActiveTool],
|
|
);
|
|
|
|
const generationComposerNode = (
|
|
<ImageCanvasGenerationComposerView
|
|
specToolWrapRef={specToolWrapRef}
|
|
characterSpecButtonRef={characterSpecButtonRef}
|
|
characterReferenceButtonRef={characterReferenceButtonRef}
|
|
generationReferenceButtonRef={generationReferenceButtonRef}
|
|
iconSpecButtonRef={iconSpecButtonRef}
|
|
isSpecMenuOpen={generationWorkflow.isSpecMenuOpen}
|
|
isGenerationReferenceMenuOpen={
|
|
generationWorkflow.isGenerationReferenceMenuOpen
|
|
}
|
|
isCharacterSpecMenuOpen={generationWorkflow.isCharacterSpecMenuOpen}
|
|
isCharacterReferenceMenuOpen={
|
|
generationWorkflow.isCharacterReferenceMenuOpen
|
|
}
|
|
isIconSpecMenuOpen={generationWorkflow.isIconSpecMenuOpen}
|
|
isUiDesignSpecMenuOpen={generationWorkflow.isUiDesignSpecMenuOpen}
|
|
isPickingGenerationReferenceFromCanvas={
|
|
generationWorkflow.isPickingGenerationReferenceFromCanvas
|
|
}
|
|
isPickingCharacterSpecFromCanvas={
|
|
generationWorkflow.isPickingCharacterSpecFromCanvas
|
|
}
|
|
isPickingCharacterReferenceFromCanvas={
|
|
generationWorkflow.isPickingCharacterReferenceFromCanvas
|
|
}
|
|
isPickingIconSpecFromCanvas={
|
|
generationWorkflow.isPickingIconSpecFromCanvas
|
|
}
|
|
isPickingUiDesignSpecFromCanvas={
|
|
generationWorkflow.isPickingUiDesignSpecFromCanvas
|
|
}
|
|
generateDialog={generateDialog}
|
|
generationComposerStyle={generationComposerStyle}
|
|
iconComposerStyle={iconComposerStyle}
|
|
quickEditPanel={generationWorkflow.quickEditPanel}
|
|
quickEditSourceLayer={generationWorkflow.quickEditSourceLayer}
|
|
quickEditPanelStyle={quickEditPanelStyle}
|
|
quickEditSizeOptions={generationWorkflow.quickEditSizeOptions}
|
|
quickEditModelOptions={generationWorkflow.quickEditModelOptions}
|
|
characterAnimationPanel={generationWorkflow.characterAnimationPanel}
|
|
characterAnimationSourceLayer={
|
|
generationWorkflow.characterAnimationSourceLayer
|
|
}
|
|
characterAnimationPanelStyle={characterAnimationPanelStyle}
|
|
characterAnimationPrice={generationWorkflow.characterAnimationPrice}
|
|
setGenerateDialog={setGenerateDialog}
|
|
setQuickEditPanel={generationWorkflow.setQuickEditPanel}
|
|
setCharacterAnimationPanel={
|
|
generationWorkflow.setCharacterAnimationPanel
|
|
}
|
|
setIsCharacterSpecMenuOpen={
|
|
generationWorkflow.setIsCharacterSpecMenuOpen
|
|
}
|
|
setIsCharacterReferenceMenuOpen={
|
|
generationWorkflow.setIsCharacterReferenceMenuOpen
|
|
}
|
|
setIsGenerationReferenceMenuOpen={
|
|
generationWorkflow.setIsGenerationReferenceMenuOpen
|
|
}
|
|
setIsIconSpecMenuOpen={generationWorkflow.setIsIconSpecMenuOpen}
|
|
setIsUiDesignSpecMenuOpen={
|
|
generationWorkflow.setIsUiDesignSpecMenuOpen
|
|
}
|
|
setIsPickingGenerationReferenceFromCanvas={
|
|
generationWorkflow.setIsPickingGenerationReferenceFromCanvas
|
|
}
|
|
setIsPickingCharacterSpecFromCanvas={
|
|
generationWorkflow.setIsPickingCharacterSpecFromCanvas
|
|
}
|
|
setIsPickingCharacterReferenceFromCanvas={
|
|
generationWorkflow.setIsPickingCharacterReferenceFromCanvas
|
|
}
|
|
setIsPickingIconSpecFromCanvas={
|
|
generationWorkflow.setIsPickingIconSpecFromCanvas
|
|
}
|
|
setIsPickingUiDesignSpecFromCanvas={
|
|
generationWorkflow.setIsPickingUiDesignSpecFromCanvas
|
|
}
|
|
onOpenSpecDialog={generationWorkflow.openSpecDialog}
|
|
onRequestUpload={requestUpload}
|
|
onSubmitImageGeneration={(dialog) =>
|
|
void generationWorkflow.submitImageGeneration(dialog)
|
|
}
|
|
onSubmitIconSpritesheetGeneration={(dialog) =>
|
|
void generationWorkflow.submitIconSpritesheetGeneration(dialog)
|
|
}
|
|
onSubmitQuickEdit={() => void generationWorkflow.submitQuickEdit()}
|
|
onSubmitCharacterAnimation={() =>
|
|
void generationWorkflow.submitCharacterAnimation()
|
|
}
|
|
onCloseGenerateComposer={generationWorkflow.closeGenerateComposer}
|
|
onUpdateSpecFormValue={generationWorkflow.updateSpecFormValue}
|
|
onUpdateIconDescription={generationWorkflow.updateIconDescription}
|
|
onAddIconDescription={generationWorkflow.addIconDescription}
|
|
onUpdateCharacterAnimationDuration={
|
|
generationWorkflow.updateCharacterAnimationDuration
|
|
}
|
|
onRememberImageModel={generationWorkflow.rememberImageModel}
|
|
/>
|
|
);
|
|
|
|
return {
|
|
...generationWorkflow,
|
|
generationComposerStyle,
|
|
generationComposerNode,
|
|
switchGenerationTool,
|
|
};
|
|
}
|