diff --git a/types/tsl-textures/.npmignore b/types/tsl-textures/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/tsl-textures/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/tsl-textures/index.d.cts b/types/tsl-textures/index.d.cts new file mode 100644 index 00000000000000..dc5f9d4ac5c95a --- /dev/null +++ b/types/tsl-textures/index.d.cts @@ -0,0 +1,673 @@ +// CommonJS type declarations for tsl-textures. +// +// tsl-textures ships both an ESM build (`dist/tsl-textures.js`, used by the +// `import` condition) and a CommonJS build (`dist/cjs/tsl-textures.cjs`, used by +// the `require` condition). This file describes the CommonJS build and holds the +// declarations shared by both entry points; the ESM entry point (index.d.ts) +// re-exports everything here and adds a few extra re-exports. +// +// The CommonJS build does NOT expose the noise/fractal/voronoi helpers that the +// ESM build re-exports from 'three/tsl' (e.g. `noise`, `voronoi`). Those are +// value re-exports from an ESM-only module ('three/tsl' has no CommonJS export +// in @types/three), which a CommonJS module cannot re-export, and the bundled +// CommonJS build drops them as well. They are therefore only declared in the ESM +// entry point (index.d.ts). + +// 'three/webgpu' is ESM-only, so resolving it from this CommonJS declaration +// file requires an explicit resolution-mode. The import is type-only and erased. +import type { Color, Node, Vector2, Vector3 } from "three/webgpu" with { "resolution-mode": "import" }; + +// Parameter input aliases. Each texture passes its params straight into a TSL Fn +// (via setLayout), which coerces every argument — so a param typed with one of +// these accepts either a plain JS value or a TSL node of that type (e.g. a +// uniform() or an animated time node), letting the texture be configured +// statically or driven by a node graph. The plain boolean flags (e.g. +// GridParams.equirectangular) are the exception and stay JS booleans. +export type FloatInput = Node<"float"> | number; +export type Vec2Input = Node<"vec2"> | Vector2; +export type Vec3Input = Node<"vec3"> | Vector3; +export type ColorInput = Node<"color"> | Color; + +// === Utility functions === + +export function approximateNormal(pos: Vec3Input, posU: Vec3Input, posV: Vec3Input): Node<"vec3">; +export function showFallbackWarning(): Promise; +export function hideFallbackWarning(): void; +export function remapExp( + x: FloatInput, + fromMin: FloatInput, + fromMax: FloatInput, + toMin: FloatInput, + toMax: FloatInput, +): Node<"float">; +export function hsl(col: Vec3Input): Node<"vec3">; +export function toHsl(rgb: Vec3Input): Node<"vec3">; +export function rotatePivot(vector: Vec3Input, pivot: Vec3Input, angle: Vec3Input): Node<"vec3">; +export function vnoise(v: Vec3Input): Node<"float">; +export function spherical(phi: FloatInput, theta: FloatInput): Node<"vec3">; +export function selectPlanar( + pos: Vec3Input, + selAngles: Vec2Input, + selCenter: Vec3Input, + selWidth: FloatInput, +): Node<"float">; + +// === Texture param interfaces === + +export interface BrainParams { + position?: Vec3Input; + scale?: FloatInput; + smooth?: FloatInput; + wave?: FloatInput; + speed?: FloatInput; + time?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface BricksParams { + position?: Vec3Input; + scale?: FloatInput; + brickSize?: Vec3Input; + brickShift?: FloatInput; + jointSize?: FloatInput; + jointSpan?: FloatInput; + jointJitter?: FloatInput; + jointBlur?: FloatInput; + noiseSize?: FloatInput; + noiseStrength?: FloatInput; + colorShade?: FloatInput; + color?: ColorInput; + additional?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface CamouflageParams { + position?: Vec3Input; + scale?: FloatInput; + colorA?: ColorInput; + colorB?: ColorInput; + colorC?: ColorInput; + colorD?: ColorInput; + seed?: FloatInput; +} + +export interface CausticsParams { + position?: Vec3Input; + scale?: FloatInput; + speed?: FloatInput; + time?: FloatInput; + color?: ColorInput; + seed?: FloatInput; +} + +export interface CaveArtParams { + position?: Vec3Input; + scale?: FloatInput; + thinness?: FloatInput; + noise?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface CircleDecorParams { + position?: Vec3Input; + scale?: FloatInput; + grains?: FloatInput; + complexity?: FloatInput; + blur?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface CirclesParams { + position?: Vec3Input; + scale?: FloatInput; + variety?: FloatInput; + color?: ColorInput; + seed?: FloatInput; +} + +export interface CloudsParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + opacity?: FloatInput; + color?: ColorInput; + subcolor?: ColorInput; + seed?: FloatInput; +} + +export interface ConcreteParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + bump?: FloatInput; + seed?: FloatInput; +} + +export interface CorkParams { + position?: Vec3Input; + scale?: FloatInput; + straight?: FloatInput; + noise?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface CrumpledFabricParams { + position?: Vec3Input; + scale?: FloatInput; + pinch?: FloatInput; + color?: ColorInput; + subcolor?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface DalmatianSpotsParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface DarthMaulParams { + position?: Vec3Input; + scale?: FloatInput; + shift?: Vec3Input; + complexity?: FloatInput; + angle?: FloatInput; + distance?: FloatInput; + color?: ColorInput; + background?: ColorInput; + balance?: FloatInput; + seed?: FloatInput; +} + +export interface DysonSphereParams { + position?: Vec3Input; + scale?: FloatInput; + complexity?: FloatInput; + variation?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface EntangledParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface ForditeParams { + position?: Vec3Input; + scale?: FloatInput; + color?: ColorInput; + seed?: FloatInput; +} + +export interface GasGiantParams { + position?: Vec3Input; + scale?: FloatInput; + turbulence?: FloatInput; + blur?: FloatInput; + colorA?: ColorInput; + colorB?: ColorInput; + colorC?: ColorInput; + seed?: FloatInput; +} + +export interface GridParams { + uvs?: Vec2Input; + countU?: FloatInput; + countV?: FloatInput; + aspect?: FloatInput; + thinness?: FloatInput; + equirectangular?: boolean; + color?: ColorInput; + background?: ColorInput; +} + +export interface HalftoneParams { + position?: Vec2Input; + scale?: FloatInput; + radius?: FloatInput; + pattern?: FloatInput; + attenuation?: FloatInput; + near?: FloatInput; + far?: FloatInput; + color?: Vec3Input | ColorInput; + positionView?: Vec3Input; +} + +export interface IsolayersParams { + position?: Vec3Input; + scale?: FloatInput; + layers?: FloatInput; + edge?: FloatInput; + darkness?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface IsolinesParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + blur?: FloatInput; + thinness?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface KarstRockParams { + position?: Vec3Input; + scale?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface MarbleParams { + position?: Vec3Input; + scale?: FloatInput; + thinness?: FloatInput; + noise?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface NeonLightsParams { + position?: Vec3Input; + scale?: FloatInput; + thinness?: FloatInput; + mode?: FloatInput; + colorA?: ColorInput; + colorB?: ColorInput; + colorC?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface PerlinNoiseParams { + position?: Vec3Input; + scale?: FloatInput; + balance?: FloatInput; + contrast?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface PhotosphereParams { + position?: Vec3Input; + scale?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface PlanetParams { + position?: Vec3Input; + scale?: FloatInput; + iterations?: FloatInput; + levelSea?: FloatInput; + levelMountain?: FloatInput; + balanceWater?: FloatInput; + balanceSand?: FloatInput; + balanceSnow?: FloatInput; + colorDeep?: ColorInput; + colorShallow?: ColorInput; + colorBeach?: ColorInput; + colorGrass?: ColorInput; + colorForest?: ColorInput; + colorSnow?: ColorInput; + seed?: FloatInput; +} + +export interface PolkaDotsParams { + position?: Vec3Input; + count?: FloatInput; + size?: FloatInput; + blur?: FloatInput; + color?: ColorInput; + background?: ColorInput; + flat?: FloatInput; +} + +export interface ProcessedWoodParams { + position?: Vec3Input; + scale?: FloatInput; + lengths?: FloatInput; + strength?: FloatInput; + angle?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface ProtozoaParams { + position?: Vec3Input; + matcap?: Vec2Input; + scale?: FloatInput; + fat?: FloatInput; + amount?: FloatInput; + color?: ColorInput; + subcolor?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface ReticularVeinsParams { + position?: Vec3Input; + scale?: FloatInput; + reticulation?: FloatInput; + strength?: FloatInput; + organelles?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface RomanPavingParams { + position?: Vec3Input; + scale?: FloatInput; + depth?: FloatInput; + seed?: FloatInput; +} + +export interface RotatorParams { + angles?: Vec3Input; + center?: Vec3Input; + selectorCenter?: Vec3Input; + selectorAngles?: Vec2Input; + selectorWidth?: FloatInput; +} + +export interface RoughClayParams { + position?: Vec3Input; + scale?: FloatInput; + bump?: FloatInput; + curvature?: FloatInput; + seed?: FloatInput; +} + +export interface RunnyEggsParams { + position?: Vec3Input; + scale?: FloatInput; + sizeYolk?: FloatInput; + sizeWhite?: FloatInput; + colorYolk?: ColorInput; + colorWhite?: ColorInput; + colorBackground?: ColorInput; + seed?: FloatInput; +} + +export interface RustParams { + position?: Vec3Input; + scale?: FloatInput; + iterations?: FloatInput; + amount?: FloatInput; + opacity?: FloatInput; + noise?: FloatInput; + noiseScale?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface SatinParams { + position?: Vec3Input; + scale?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface ScalerParams { + scales?: Vec3Input; + center?: Vec3Input; + selectorCenter?: Vec3Input; + selectorAngles?: Vec2Input; + selectorWidth?: FloatInput; +} + +export interface ScepterHeadParams { + position?: Vec3Input; + xFactor?: FloatInput; + yFactor?: FloatInput; + zFactor?: FloatInput; + colorRim?: ColorInput; + colorA?: ColorInput; + colorB?: ColorInput; +} + +export interface ScreamParams { + position?: Vec3Input; + scale?: FloatInput; + variety?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface StarsParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + variation?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface StaticNoiseParams { + position?: Vec2Input; + time?: FloatInput; + scale?: FloatInput; + balance?: FloatInput; + contrast?: FloatInput; + delay?: FloatInput; + seed?: FloatInput; +} + +export interface SupersphereParams { + exponent?: FloatInput; +} + +export interface TigerFurParams { + position?: Vec3Input; + scale?: FloatInput; + lengths?: FloatInput; + blur?: FloatInput; + strength?: FloatInput; + hairs?: FloatInput; + color?: ColorInput; + bottomColor?: ColorInput; + seed?: FloatInput; +} + +export interface TranslatorParams { + distance?: Vec3Input; + selectorCenter?: Vec3Input; + selectorAngles?: Vec2Input; + selectorWidth?: FloatInput; +} + +export interface TurbulentSmokeParams { + position?: Vec3Input; + scale?: FloatInput; + speed?: FloatInput; + details?: FloatInput; + time?: FloatInput; + seed?: FloatInput; +} + +export interface VoronoiCellsParams { + position?: Vec3Input; + scale?: FloatInput; + variation?: FloatInput; + facet?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface WaterDropsParams { + position?: Vec3Input; + scale?: FloatInput; + density?: FloatInput; + bump?: FloatInput; + seed?: FloatInput; +} + +export interface WatermelonParams { + position?: Vec3Input; + uvs?: Vec2Input; + scale?: FloatInput; + stripes?: FloatInput; + variation?: FloatInput; + noise?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface WavesParams { + position?: Vec3Input; + scale?: FloatInput; + speed?: FloatInput; + time?: FloatInput; + level?: FloatInput; + rough?: FloatInput; + height?: FloatInput; + foamSize?: FloatInput; + foamEdge?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface WoodParams { + position?: Vec3Input; + scale?: FloatInput; + rings?: FloatInput; + lengths?: FloatInput; + angle?: FloatInput; + fibers?: FloatInput; + fibersDensity?: FloatInput; + color?: ColorInput; + background?: ColorInput; + seed?: FloatInput; +} + +export interface ZebraLinesParams { + position?: Vec3Input; + scale?: FloatInput; + thinness?: FloatInput; + phi?: FloatInput; + theta?: FloatInput; + color?: ColorInput; + background?: ColorInput; + flat?: FloatInput; +} + +// === Texture function types === + +// Simple texture: callable + .defaults +export interface SimpleTexture

{ + (params?: P): Node<"vec3">; + defaults: P; +} + +// Texture with a .normal() method +export interface TextureWithNormal

{ + (params?: P): Node<"vec3">; + normal(params?: P): Node<"vec3">; + defaults: P; +} + +// Texture with an .opacity() method +export interface TextureWithOpacity

{ + (params?: P): Node<"vec3">; + opacity(params?: P): Node<"float">; + defaults: P; +} + +// runnyEggs: both .normal() and .roughness() +export interface RunnyEggsTexture { + (params?: RunnyEggsParams): Node<"vec3">; + normal(params?: RunnyEggsParams): Node<"vec3">; + roughness(params?: RunnyEggsParams): Node<"float">; + defaults: RunnyEggsParams; +} + +// === Exports === + +export const brain: TextureWithNormal; +export const bricks: SimpleTexture; +export const camouflage: SimpleTexture; +export const caustics: SimpleTexture; +export const caveArt: SimpleTexture; +export const circleDecor: SimpleTexture; +export const circles: SimpleTexture; +export const clouds: TextureWithOpacity; +export const concrete: SimpleTexture; +export const cork: SimpleTexture; +export const crumpledFabric: SimpleTexture; +export const dalmatianSpots: SimpleTexture; +export const darthMaul: SimpleTexture; +export const dysonSphere: SimpleTexture; +export const entangled: SimpleTexture; +export const fordite: SimpleTexture; +export const gasGiant: SimpleTexture; +export const grid: SimpleTexture; +export const halftone: SimpleTexture; +export const isolayers: SimpleTexture; +export const isolines: SimpleTexture; +export const karstRock: SimpleTexture; +export const marble: SimpleTexture; +export const neonLights: SimpleTexture; +export const perlinNoise: SimpleTexture; +export const photosphere: SimpleTexture; +export const planet: SimpleTexture; +export const polkaDots: SimpleTexture; +export const processedWood: SimpleTexture; +export const protozoa: SimpleTexture; +export const reticularVeins: SimpleTexture; +export const romanPaving: SimpleTexture; +export const rotator: TextureWithNormal; +export const roughClay: SimpleTexture; +export const runnyEggs: RunnyEggsTexture; +export const rust: TextureWithOpacity; +export const satin: SimpleTexture; +export const scaler: TextureWithNormal; +export const scepterHead: SimpleTexture; +export const scream: SimpleTexture; +export const stars: SimpleTexture; +export const staticNoise: SimpleTexture; +export const supersphere: TextureWithNormal; +export const tigerFur: SimpleTexture; +export const translator: TextureWithNormal; +export const turbulentSmoke: SimpleTexture; +export const voronoiCells: SimpleTexture; +export const waterDrops: SimpleTexture; +export const watermelon: SimpleTexture; +export const waves: TextureWithOpacity; +export const wood: SimpleTexture; +export const zebraLines: SimpleTexture; diff --git a/types/tsl-textures/index.d.ts b/types/tsl-textures/index.d.ts new file mode 100644 index 00000000000000..03a3a33b9cd634 --- /dev/null +++ b/types/tsl-textures/index.d.ts @@ -0,0 +1,27 @@ +// ESM type declarations for tsl-textures (the `import` condition). +// +// tsl-textures ships both an ESM build (`dist/tsl-textures.js`) and a CommonJS +// build (`dist/cjs/tsl-textures.cjs`). The shared API is declared in the +// CommonJS declaration file (index.d.cts) and re-exported here; this file adds +// the noise/fractal/voronoi helpers, which the ESM build re-exports from +// 'three/tsl'. Those are value re-exports from an ESM-only module, so they are +// only valid from an ES module — they exist in the ESM build (and here) but not +// in the CommonJS build (index.d.cts). +// +// To update tsl-textures type definition, please make changes to the repository +// at: https://github.com/HannahLilyW/tsl-textures-ts-types. +// Periodically, the updates from the repository are pushed to DefinitelyTyped +// and released in the @types/tsl-textures npm package. + +export * from "./index.cjs"; + +// Noise / fractal / voronoi re-exported from three/tsl +export { + mx_fractal_noise_float as fractal, + mx_fractal_noise_vec3 as fractal3, + mx_noise_float as noise, + mx_noise_vec3 as noise3, + mx_worley_noise_float as voronoi, + mx_worley_noise_vec2 as voronoi2, + mx_worley_noise_vec3 as voronoi3, +} from "three/tsl"; diff --git a/types/tsl-textures/package.json b/types/tsl-textures/package.json new file mode 100644 index 00000000000000..a166a06213f192 --- /dev/null +++ b/types/tsl-textures/package.json @@ -0,0 +1,35 @@ +{ + "private": true, + "name": "@types/tsl-textures", + "version": "3.0.9999", + "type": "module", + "projects": [ + "https://boytchev.github.io/tsl-textures/" + ], + "exports": { + ".": { + "import": "./index.d.ts", + "require": "./index.d.cts" + }, + "./tsl-textures.js": { + "import": "./index.d.ts", + "require": "./index.d.cts" + } + }, + "dependencies": { + "@types/three": "*" + }, + "devDependencies": { + "@types/tsl-textures": "workspace:." + }, + "owners": [ + { + "name": "Hannah Watsky", + "githubUsername": "HannahLilyW" + }, + { + "name": "Pavel Boytchev", + "githubUsername": "boytchev" + } + ] +} diff --git a/types/tsl-textures/tsconfig.json b/types/tsl-textures/tsconfig.json new file mode 100644 index 00000000000000..f03b31ae905434 --- /dev/null +++ b/types/tsl-textures/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6", + "dom" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "index.d.cts", + "tsl-textures-tests.ts" + ] +} diff --git a/types/tsl-textures/tsl-textures-tests.ts b/types/tsl-textures/tsl-textures-tests.ts new file mode 100644 index 00000000000000..84afca94c8ec50 --- /dev/null +++ b/types/tsl-textures/tsl-textures-tests.ts @@ -0,0 +1,243 @@ +import { float, uniform, vec2, vec3 } from "three/tsl"; +import { Color, Node, Vector2, Vector3 } from "three/webgpu"; + +import { + approximateNormal, + brain, + bricks, + camouflage, + clouds, + ColorInput, + FloatInput, + fractal, + fractal3, + grid, + halftone, + hideFallbackWarning, + hsl, + noise, + noise3, + planet, + polkaDots, + remapExp, + rotatePivot, + rotator, + runnyEggs, + RunnyEggsParams, + RunnyEggsTexture, + rust, + scaler, + selectPlanar, + showFallbackWarning, + SimpleTexture, + spherical, + supersphere, + TextureWithNormal, + TextureWithOpacity, + toHsl, + translator, + Vec2Input, + Vec3Input, + vnoise, + voronoi, + voronoi2, + voronoi3, + waves, +} from "tsl-textures"; + +// Sample node values of each supported kind, used as inputs below. +const f: Node<"float"> = float(1); +const v2node: Node<"vec2"> = vec2(0, 1); +const v3node: Node<"vec3"> = vec3(0, 1, 2); + +const col = new Color(0xff0000); +const p2 = new Vector2(0.5, 0.5); +const p3 = new Vector3(0, 1, 0); + +// === Utility functions === + +// $ExpectType Node<"vec3"> +approximateNormal(v3node, p3, v3node); + +// remapExp: float-ish args (numbers or float nodes) -> float node. +// $ExpectType Node<"float"> +remapExp(0.5, 0, 1, 1, 10); +// $ExpectType Node<"float"> +remapExp(f, f, 1, 0, f); + +// hsl / toHsl convert vec3 <-> vec3. +// $ExpectType Node<"vec3"> +hsl(v3node); +// $ExpectType Node<"vec3"> +toHsl(p3); + +// $ExpectType Node<"vec3"> +rotatePivot(v3node, p3, v3node); +// $ExpectType Node<"float"> +vnoise(v3node); +// $ExpectType Node<"vec3"> +spherical(f, 0.25); +// $ExpectType Node<"float"> +selectPlanar(v3node, p2, p3, 0.5); + +// Fallback-warning helpers. +// $ExpectType Promise +showFallbackWarning(); +// $ExpectType void +hideFallbackWarning(); + +// === Re-exported noise functions === +// These come straight from three/tsl; just confirm they are exported and callable. +noise(v3node); +noise3(v3node); +fractal(v3node); +fractal3(v3node); +voronoi(v3node); +voronoi2(v3node); +voronoi3(v3node); + +// === Simple textures === + +// Callable with no arguments. +// $ExpectType Node<"vec3"> +bricks(); + +// Partial params; F accepts numbers or float nodes, C accepts Color or color +// nodes, V3 accepts Vector3 or vec3 nodes. +// $ExpectType Node<"vec3"> +bricks({ scale: 2, brickSize: p3, jointSize: f, color: col, seed: 7 }); + +// camouflage exposes several color slots. +// $ExpectType Node<"vec3"> +camouflage({ colorA: col, colorB: col, colorC: col, colorD: col, seed: 1 }); + +// grid uses uv (vec2) inputs and a boolean flag. +// $ExpectType Node<"vec3"> +grid({ uvs: v2node, countU: 32, countV: 16, equirectangular: true, color: col }); + +// halftone uses a vec2 position and accepts a vec3 OR color for `color`. +// $ExpectType Node<"vec3"> +halftone({ position: p2, radius: 0.5, color: v3node }); +// $ExpectType Node<"vec3"> +halftone({ position: vec2(0, 0), color: col, positionView: p3 }); + +// planet has many balance/color knobs. +// $ExpectType Node<"vec3"> +planet({ iterations: 10, levelSea: 0.5, colorDeep: col, colorSnow: col }); + +// polkaDots uses a `flat` flag-like float. +// $ExpectType Node<"vec3"> +polkaDots({ count: 4, size: 0.3, blur: f, flat: 1 }); + +// `.defaults` is exposed and shaped like the params object. +// $ExpectType BricksParams +bricks.defaults; +// $ExpectType GridParams +grid.defaults; +// $ExpectType HalftoneParams +halftone.defaults; + +// === Textures with a .normal() channel === +// $ExpectType Node<"vec3"> +brain({ color: col, background: col }); +// $ExpectType Node<"vec3"> +brain.normal({ wave: 0.5, speed: 2.5, time: f }); + +// rotator / scaler / translator / supersphere share params across channels. +// $ExpectType Node<"vec3"> +rotator.normal({ angles: p3, center: p3, selectorWidth: 0.5 }); +// $ExpectType Node<"vec3"> +scaler.normal({ scales: p3, selectorAngles: p2 }); +// $ExpectType Node<"vec3"> +translator.normal({ distance: p3, selectorCenter: p3 }); +// $ExpectType Node<"vec3"> +supersphere.normal({ exponent: 3 }); + +// === Textures with an .opacity() channel === + +// $ExpectType Node<"vec3"> +clouds({ density: 0.5, color: col, subcolor: col }); +// $ExpectType Node<"float"> +clouds.opacity({ density: 0.5, opacity: 0.8 }); + +// $ExpectType Node<"float"> +rust.opacity({ amount: 0.5, opacity: 0.5 }); +// $ExpectType Node<"float"> +waves.opacity({ level: 0.5, foamEdge: 0.1 }); + +// The same config object can be fed to every channel of a texture. +const cloudConfig = { scale: 3, density: 0.7, opacity: 0.8, color: col, seed: 5 }; +// $ExpectType Node<"vec3"> +clouds(cloudConfig); +// $ExpectType Node<"float"> +clouds.opacity(cloudConfig); + +// === runnyEggs: both .normal() and .roughness() === + +// $ExpectType Node<"vec3"> +runnyEggs({ sizeYolk: 0.2, sizeWhite: 0.7, colorYolk: col }); +// $ExpectType Node<"vec3"> +runnyEggs.normal({ sizeWhite: 0.7 }); +// $ExpectType Node<"float"> +runnyEggs.roughness({ sizeYolk: 0.2 }); + +// The full params object is the superset and works on every channel. +const eggConfig: RunnyEggsParams = { sizeYolk: 0.2, sizeWhite: 0.7, colorWhite: col }; +// $ExpectType Node<"vec3"> +runnyEggs(eggConfig); +// $ExpectType Node<"vec3"> +runnyEggs.normal(eggConfig); +// $ExpectType Node<"float"> +runnyEggs.roughness(eggConfig); + +// === uniform() inputs === +// Params are commonly driven by uniform nodes so they can be animated at runtime. +// $ExpectType Node<"vec3"> +clouds({ density: uniform(0.25), opacity: 0.2, color: uniform(col), seed: uniform(0) }); + +// === Public helper types === +// The input aliases and texture-shape interfaces are exported so consumers can +// build their own params/helpers on top of them. + +// Input aliases accept either a plain JS value or a matching TSL node. +const floatIn: FloatInput = f; +const floatInNum: FloatInput = 0.5; +const colorIn: ColorInput = col; +const vec2In: Vec2Input = p2; +const vec3In: Vec3Input = v3node; +// $ExpectType Node<"vec3"> +bricks({ scale: floatIn, color: colorIn, brickSize: vec3In }); +// $ExpectType Node<"vec3"> +halftone({ position: vec2In, radius: floatInNum }); + +// Texture-shape interfaces describe the callable + channel structure. +const simple: SimpleTexture = bricks; +// $ExpectType Node<"vec3"> +simple(); +const withNormal: TextureWithNormal = rotator; +// $ExpectType Node<"vec3"> +withNormal.normal(); +const withOpacity: TextureWithOpacity = clouds; +// $ExpectType Node<"float"> +withOpacity.opacity(); +const eggs: RunnyEggsTexture = runnyEggs; +// $ExpectType Node<"float"> +eggs.roughness(); + +// === Negative tests === + +// A simple texture has no extra channels. +// @ts-expect-error - bricks is a plain texture without a .normal() method. +bricks.normal(); + +// @ts-expect-error - clouds has .opacity(), not .normal(). +clouds.normal(); + +// @ts-expect-error - scale must be a number or float node, not a string. +brain({ scale: "large" }); + +// @ts-expect-error - `nope` is not a known parameter. +grid({ nope: true }); + +// @ts-expect-error - a color slot does not accept a bare number. +camouflage({ colorA: 123 });