import { ENTERPRISE_DEFAULT_VIDEO_MODEL, ENTERPRISE_DEFAULT_VIDEO_RESOLUTION, ENTERPRISE_VIDEO_MODEL_OPTIONS, ENTERPRISE_VIDEO_RESOLUTION_OPTIONS, } from "../../utils/enterpriseVideoPolicy"; import type { CanvasNodeKind, CanvasNodeSize, CanvasOption, CanvasStylePickerTab, CanvasVideoMode, } from "./canvasTypes"; // --- Connector follow behavior --- export const connectorFollowRadius = 96; export const connectorFollowStrength = 1; export const connectorMaxFollowOffset = 62; export const connectorAnchorOutset = 9; // --- Interaction thresholds --- export const canvasNodeClickMoveThreshold = 5; // --- Auto-save timing --- export const canvasAutoSaveDebounceMs = 2_000; export const canvasAutoSaveIdleTimeoutMs = 800; // --- Viewport zoom limits --- export const canvasViewportMinZoom = 0.25; export const canvasViewportMaxZoom = 2.6; // --- Node sizes --- export const canvasNodeDefaultSizes: Record = { text: { width: 380, height: 260 }, image: { width: 460, height: 290 }, video: { width: 560, height: 315 }, }; export const canvasNodeMinSizes: Record = { text: { width: 300, height: 220 }, image: { width: 340, height: 220 }, video: { width: 420, height: 236 }, }; export const canvasNodeMaxSizes: Record = { text: { width: 720, height: 520 }, image: { width: 860, height: 620 }, video: { width: 960, height: 540 }, }; // --- Text model options --- export const textModelOptions = [ { id: "gemini-3.1-pro", label: "Gemini 3.1 Pro", description: "默认文本生成模型", speed: "20s" }, { id: "gemini-2.5-pro", label: "Gemini 2.5 Pro", description: "通用文本生成模型", speed: "20s" }, { id: "gpt-4o", label: "GPT-4o", description: "通用文本生成模型", speed: "20s" }, ]; export const defaultTextModelId = textModelOptions[0].id; // --- Image model options --- export const imageModelOptions: CanvasOption[] = [ { value: "wan2.7-image", label: "wan 2.7" }, { value: "wan2.7-image-pro", label: "wan 2.7 Pro" }, { value: "gpt-image-2", label: "omni-GPT" }, { value: "gpt-image-2-vip", label: "omni-GPT VIP" }, { value: "nano-banana-pro", label: "omni-水果 Pro" }, { value: "nano-banana-2", label: "omni-水果 2" }, { value: "nano-banana-fast", label: "omni-水果" }, ]; export const imageRatioOptions: CanvasOption[] = [ { value: "16:9", label: "16:9" }, { value: "9:16", label: "9:16" }, { value: "1:1", label: "1:1" }, { value: "4:3", label: "4:3" }, { value: "3:4", label: "3:4" }, ]; export const imageFocusRatioOptions: CanvasOption[] = [ { value: "16:9", label: "16:9" }, { value: "3:2", label: "3:2" }, { value: "4:3", label: "4:3" }, { value: "1:1", label: "1:1" }, { value: "3:4", label: "3:4" }, { value: "2:3", label: "2:3" }, { value: "9:16", label: "9:16" }, ]; export const imageQualityOptions: CanvasOption[] = [ { value: "1K", label: "1K" }, { value: "2K", label: "2K" }, { value: "4K", label: "4K" }, ]; // --- Style picker --- export const canvasStylePickerTabs: Array<{ key: CanvasStylePickerTab; label: string }> = [ { key: "square", label: "广场" }, { key: "favorites", label: "我的收藏" }, { key: "recent", label: "最近使用" }, ]; export const canvasStylePickerCategories = [ "推荐", "摄影写真", "电商营销", "动漫游戏", "风格插画", "平面设计", "建筑及室内设计", "创意玩法", "文创周边", "小说推文", ]; // --- 4K capable image models --- export const image4kCapableModels = new Set([ "wan2.7-image-pro", "nano-banana-2", "nano-banana-pro", "nano-banana-pro-4k", "nano-banana-pro-4k-vip", "gpt-image-2-vip", ]); // --- Video model options --- export const videoModelOptions: CanvasOption[] = [ ...ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => ({ value: option.value, label: option.label, })), ]; // --- Video ratio & duration options --- export const videoRatioOptions: CanvasOption[] = [ { value: "21:9", label: "21:9" }, { value: "16:9", label: "16:9" }, { value: "4:3", label: "4:3" }, { value: "1:1", label: "1:1" }, { value: "3:4", label: "3:4" }, { value: "9:16", label: "9:16" }, ]; export const videoDurationOptions: CanvasOption[] = [ { value: "5", label: "5s" }, { value: "6", label: "6s" }, { value: "7", label: "7s" }, { value: "8", label: "8s" }, { value: "9", label: "9s" }, { value: "10", label: "10s" }, { value: "11", label: "11s" }, { value: "12", label: "12s" }, { value: "13", label: "13s" }, { value: "14", label: "14s" }, { value: "15", label: "15s" }, ]; // --- Video quality & resolution by model --- export const fallbackVideoQualityOptions: CanvasOption[] = [ ...ENTERPRISE_VIDEO_RESOLUTION_OPTIONS.map((option) => ({ value: option.value, label: option.label, })), ]; export const videoResolutionByModel: Record = { ...Object.fromEntries(ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => [option.value, fallbackVideoQualityOptions])), }; export const videoDefaultQualityByModel: Record = { ...Object.fromEntries(ENTERPRISE_VIDEO_MODEL_OPTIONS.map((option) => [option.value, ENTERPRISE_DEFAULT_VIDEO_RESOLUTION])), }; // --- Defaults --- export const defaultImageModel = "nano-banana-pro"; export const defaultVideoModel = ENTERPRISE_DEFAULT_VIDEO_MODEL; export const canvasVideoModes: CanvasVideoMode[] = ["text2video", "img2video", "firstlast"]; // --- Poll constants --- export const imageNodeTaskPollIntervalMs = 3000; export const imageNodeTaskPollAttempts = 180; export const videoNodeTaskPollIntervalMs = 5000; export const videoNodeTaskPollAttempts = 360; // --- Asset library --- export const assetTypePromptLabel: Record = { character: "角色主体", scene: "环境场景", prop: "关键道具", video: "动态镜头", image: "图片素材", asset: "通用素材", other: "其他素材", }; export const assetLibraryCategories = [ { key: "character", label: "人物" }, { key: "scene", label: "场景" }, { key: "prop", label: "物品" }, { key: "video", label: "视频" }, { key: "image", label: "图片" }, { key: "asset", label: "素材" }, { key: "other", label: "其他" }, ] satisfies Array<{ key: import("../assets/localAssetStore").AssetLibraryCategory; label: string }>;