Browse Source
- Fix 3D viewport not filling node by adding resize={{ offsetSize: true }} for correct measurement in CSS-transformed React Flow nodes
- Replace grid/axis indicators with spot light for cleaner scene
- Add labeled input (3D) and output (Image) handles matching generate node style
- Add native wheel event listener to prevent graph zoom/pan while scrolling to zoom 3D model
- Remove redundant CSS workarounds (absolute positioning style, extra relative wrapper)
- Add edge-to-edge viewport via contentClassName (removes default padding when GLB loaded)
- Overlay controls bar on viewport with gradient background
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
22 changed files with 504 additions and 104 deletions
@ -0,0 +1,86 @@ |
|||||
|
/** |
||||
|
* Central node dispatcher. |
||||
|
* |
||||
|
* Maps a node's type to the correct executor function, eliminating the |
||||
|
* duplicated switch/if-else chains that previously existed in |
||||
|
* executeWorkflow, regenerateNode, and executeSelectedNodes. |
||||
|
*/ |
||||
|
|
||||
|
import type { NodeExecutionContext } from "./types"; |
||||
|
import { |
||||
|
executeAnnotation, |
||||
|
executePrompt, |
||||
|
executePromptConstructor, |
||||
|
executeOutput, |
||||
|
executeOutputGallery, |
||||
|
executeImageCompare, |
||||
|
executeGlbViewer, |
||||
|
} from "./simpleNodeExecutors"; |
||||
|
import { executeNanoBanana } from "./nanoBananaExecutor"; |
||||
|
import { executeGenerateVideo } from "./generateVideoExecutor"; |
||||
|
import { executeLlmGenerate } from "./llmGenerateExecutor"; |
||||
|
import { executeSplitGrid } from "./splitGridExecutor"; |
||||
|
import { executeVideoStitch, executeEaseCurve } from "./videoProcessingExecutors"; |
||||
|
|
||||
|
export interface ExecuteNodeOptions { |
||||
|
/** When true, executors that support it will fall back to stored inputs. */ |
||||
|
useStoredFallback?: boolean; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute a single node by dispatching to the appropriate executor. |
||||
|
* |
||||
|
* Data-source node types (`imageInput`, `audioInput`) are no-ops. |
||||
|
*/ |
||||
|
export async function executeNode( |
||||
|
ctx: NodeExecutionContext, |
||||
|
options?: ExecuteNodeOptions, |
||||
|
): Promise<void> { |
||||
|
const regenOpts = options?.useStoredFallback ? { useStoredFallback: true } : undefined; |
||||
|
|
||||
|
switch (ctx.node.type) { |
||||
|
case "imageInput": |
||||
|
case "audioInput": |
||||
|
// Data source nodes — no execution needed
|
||||
|
break; |
||||
|
case "annotation": |
||||
|
await executeAnnotation(ctx); |
||||
|
break; |
||||
|
case "prompt": |
||||
|
await executePrompt(ctx); |
||||
|
break; |
||||
|
case "promptConstructor": |
||||
|
await executePromptConstructor(ctx); |
||||
|
break; |
||||
|
case "nanoBanana": |
||||
|
await executeNanoBanana(ctx, regenOpts); |
||||
|
break; |
||||
|
case "generateVideo": |
||||
|
await executeGenerateVideo(ctx, regenOpts); |
||||
|
break; |
||||
|
case "llmGenerate": |
||||
|
await executeLlmGenerate(ctx, regenOpts); |
||||
|
break; |
||||
|
case "splitGrid": |
||||
|
await executeSplitGrid(ctx); |
||||
|
break; |
||||
|
case "output": |
||||
|
await executeOutput(ctx); |
||||
|
break; |
||||
|
case "outputGallery": |
||||
|
await executeOutputGallery(ctx); |
||||
|
break; |
||||
|
case "imageCompare": |
||||
|
await executeImageCompare(ctx); |
||||
|
break; |
||||
|
case "videoStitch": |
||||
|
await executeVideoStitch(ctx); |
||||
|
break; |
||||
|
case "easeCurve": |
||||
|
await executeEaseCurve(ctx); |
||||
|
break; |
||||
|
case "glbViewer": |
||||
|
await executeGlbViewer(ctx); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue