import type { ShaderGraphIR, ShaderSocketIR } from "./shader-graph"; const input = (id: string, name: string, dataType: ShaderSocketIR["dataType"], defaultValue?: ShaderSocketIR["defaultValue"]): ShaderSocketIR => ({ id, name, direction: "INPUT", dataType, ...(defaultValue === undefined ? {} : { defaultValue }) }); const output = (id: string, name: string, dataType: ShaderSocketIR["dataType"]): ShaderSocketIR => ({ id, name, direction: "OUTPUT", dataType }); /** Build a valid bounded graph for the source-backed Principled writer. */ export const shaderGraphCommands = Object.freeze({ setPrincipledGraph(materialId: string, baseColor: readonly number[], roughness: number, metallic: number): ShaderGraphIR { const principled = "shader:principled"; const materialOutput = "shader:material-output"; return { schemaVersion: 1, id: `shader-graph:${materialId}`, materialId, nodes: [ { id: principled, type: "PRINCIPLED", name: "Principled BSDF", sockets: [ input("Base Color", "Base Color", "COLOR", [...baseColor].slice(0, 4)), input("Metallic", "Metallic", "VALUE", metallic), input("Roughness", "Roughness", "VALUE", roughness), output("BSDF", "BSDF", "SHADER"), ] }, { id: materialOutput, type: "MATERIAL_OUTPUT", name: "Material Output", sockets: [input("Surface", "Surface", "SHADER")] }, ], links: [{ fromNodeId: principled, fromSocketId: "BSDF", toNodeId: materialOutput, toSocketId: "Surface" }], outputNodeId: materialOutput, }; }, } as const);