Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 97 additions & 5 deletions website/src/content/docs/api/headless.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ dispose(); // always call on cleanup

---

## `parseVox(buffer, options?)`

Parses a MagicaVoxel `.vox` file into greedy colored polygon quads. The result also carries `voxelSource` metadata used by the vanilla baked-mode voxel fast path when the mesh remains eligible.

```ts
import { parseVox } from "@layoutit/polycss-core";

const buf = await fetch("/model.vox").then(r => r.arrayBuffer());
const { polygons, voxelSource } = parseVox(buf, {
targetSize: 60,
paletteMergeDistance: 10,
});
```

**Options:** See [`VoxParseOptions`](/api/types/#voxparseoptions).

---

## `parseMtl(text)`

Parses an MTL file text string into a material map.
Expand Down Expand Up @@ -147,7 +165,7 @@ const cam = createIsometricCamera({

Attach pointer drag, wheel zoom, and an optional autorotate loop to a scene returned by `createPolyScene`. Pure additive layer: the renderer stays free of input concerns. Modelled on Three.js `OrbitControls`.

Use `createPolyMapControls(scene, options?)` instead when you want map/pan-style drag (pointer pans the camera across a flat surface rather than orbiting the scene center).
Use `createPolyMapControls(scene, options?)` instead when you want map/pan-style drag (pointer pans the camera across a flat surface rather than orbiting the scene center). Use `createPolyFirstPersonControls(scene, options?)` for pointer-lock mouselook and keyboard movement.

```ts
import { createPolyCamera, createPolyScene, createPolyOrbitControls, loadMesh } from "@layoutit/polycss";
Expand Down Expand Up @@ -218,6 +236,72 @@ Anything that satisfies that subset works, so layered helpers can compose multip

---

## `createPolyFirstPersonControls(scene, options?)`

Adds pointer-lock mouselook, WASD / arrow movement, Space jump, and Ctrl crouch to an imperative scene. The handle can be paused/resumed, pointer-locked programmatically from a user gesture, and teleported with `setOrigin()`.

```ts
import {
createPolyPerspectiveCamera,
createPolyScene,
createPolyFirstPersonControls,
} from "@layoutit/polycss";

const camera = createPolyPerspectiveCamera({ rotX: 90, rotY: 0, perspective: 1200 });
const scene = createPolyScene(host, { camera });
const fpv = createPolyFirstPersonControls(scene, {
moveSpeed: 8,
eyeHeight: 1.7,
});

button.addEventListener("click", () => fpv.lock());
fpv.setOrigin([10, 5, 1.7]);
```

---

## `createSelect(scene, options?)`

Adds mesh selection to an imperative scene. It tracks selected `PolyMeshHandle`s, supports optional multi-select, background clearing, and a DOM bbox fallback for clicks that do not land on a polygon leaf directly.

```ts
import { createSelect } from "@layoutit/polycss";

const selection = createSelect(scene, {
multiple: true,
onChange(meshes) {
console.log(meshes.map((mesh) => mesh.id));
},
});

selection.set([meshHandle]);
selection.clear();
```

---

## `createTransformControls(scene, options?)`

Adds a translate / rotate gizmo for a mesh handle. The gizmo mutates the attached mesh with `setTransform()` and emits object-change callbacks so application state can mirror the transform.

```ts
import { createTransformControls } from "@layoutit/polycss";

const transform = createTransformControls(scene, {
mode: "translate",
translationSnap: 10,
onObjectChange(event) {
console.log(event.position, event.rotation);
},
});

transform.attach(meshHandle);
transform.setMode("rotate");
transform.detach();
```

---

## `collectPolyRenderStats(root, options?)`

Reads an already-rendered polycss DOM subtree and returns a one-shot diagnostic snapshot. It counts mounted polygon leaves, shadow leaves, surface leaf categories, and bucket wrappers; it does not observe changes or mutate the scene.
Expand All @@ -240,7 +324,7 @@ console.log(stats.mountedPolygonLeafCount, stats.surfaceLeafCounts);

## Custom elements (vanilla)

Register `<poly-camera>`, `<poly-scene>`, `<poly-mesh>`, `<poly-polygon>`, `<poly-orbit-controls>`, and `<poly-map-controls>` custom elements by importing the side-effect entry point:
Register the custom elements by importing the side-effect entry point:

```html
<script type="module" src="https://esm.sh/@layoutit/polycss/elements"></script>
Expand All @@ -255,14 +339,22 @@ Register `<poly-camera>`, `<poly-scene>`, `<poly-mesh>`, `<poly-polygon>`, `<pol

See the [polycss README](https://github.com/LayoutitStudio/polycss/tree/main/packages/polycss) for the full custom element attribute reference.

Registered element families include:

- Cameras: `<poly-camera>`, `<poly-orthographic-camera>`, `<poly-perspective-camera>`.
- Scene and geometry: `<poly-scene>`, `<poly-mesh>`, `<poly-polygon>`.
- Controls: `<poly-orbit-controls>`, `<poly-map-controls>`, `<poly-first-person-controls>`, `<poly-transform-controls>`, `<poly-select>`.
- Helpers: `<poly-axes-helper>`, `<poly-directional-light-helper>`.
- Shapes: `<poly-box>`, `<poly-plane>`, `<poly-ring>`, `<poly-sphere>`, `<poly-tetrahedron>`, `<poly-octahedron>`, `<poly-icosahedron>`, `<poly-dodecahedron>`, `<poly-cylinder>`, `<poly-cone>`, `<poly-torus>`.

---

## Package Exports

| Import path | Contents |
|---|---|
| `@layoutit/polycss-react` | React components: `PolyScene`, `PolyMesh`, `Poly`, `PolyCamera`, hooks, render diagnostics |
| `@layoutit/polycss-vue` | Vue components: `PolyScene`, `PolyMesh`, `Poly`, `PolyCamera`, render diagnostics |
| `@layoutit/polycss` | Vanilla imperative API + custom element classes + render diagnostics |
| `@layoutit/polycss-react` | React components, hooks, controls, selection, animation, core re-exports, render diagnostics |
| `@layoutit/polycss-vue` | Vue components, composables, controls, selection, animation, core re-exports, render diagnostics |
| `@layoutit/polycss` | Vanilla imperative API + custom element classes + controls + selection + render diagnostics |
| `@layoutit/polycss/elements` | Side-effect: registers the polycss custom elements |
| `@layoutit/polycss-core` | Pure parsers / math, zero DOM: `parseObj`, `parseGltf`, `parseVox`, `loadMesh`, types |
135 changes: 131 additions & 4 deletions website/src/content/docs/api/types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Core parser and math types are exported from `@layoutit/polycss-react`, `@layout

## `Polygon`

The atomic renderable primitive. Each polygon becomes one atlas-backed `<i>` DOM element for textured and flat-color faces.
The atomic renderable primitive. Each visible polygon becomes one renderer-owned DOM leaf. The exact tag is an internal strategy choice: solid CSS primitives where possible, atlas slices for textured or irregular faces.

```ts
interface Polygon {
Expand Down Expand Up @@ -80,14 +80,26 @@ interface PolyAmbientLight {

## `PolyTextureLightingMode`

Controls how texture lighting is applied to atlas-backed polygons.
Controls whether polygon lighting is baked into generated paint output or evaluated through CSS variables at runtime.

```ts
type PolyTextureLightingMode = "baked" | "dynamic";
```

---

## `PolyRenderStrategiesOption`

Diagnostic render-strategy override accepted by scenes and atlas renderers. Disabled strategies fall through to the atlas path; `<s>` is the universal fallback and cannot be disabled.

```ts
type PolyRenderStrategy = "b" | "i" | "u";

interface PolyRenderStrategiesOption {
disable?: PolyRenderStrategy[];
}
```

## `PolyRenderStats`

One-shot DOM diagnostic snapshot returned by `collectPolyRenderStats`.
Expand Down Expand Up @@ -161,6 +173,8 @@ Unified return shape from all mesh parsers (`parseObj`, `parseGltf`, `parseVox`,
interface ParseResult {
/** Parsed and validated polygon array, ready for rendering. */
polygons: Polygon[];
/** Optional raw voxel source for .vox fast paths; polygon fallback remains authoritative. */
voxelSource?: PolyVoxelSource;
/** Blob URLs minted during parse (e.g. embedded GLB textures).
* Revoked when dispose() is called. */
objectUrls: string[];
Expand All @@ -177,12 +191,102 @@ interface ParseResult {
materials?: string[];
animations?: ParseAnimationClip[];
sourceBytes?: number;
voxelCount?: number;
};
}
```

---

## `PolyVoxelSource`

Raw `.vox` metadata preserved by `parseVox` for renderer fast paths. The polygon list remains the fallback and public geometry.

```ts
interface PolyVoxelCell {
x: number;
y: number;
z: number;
color: string;
}

interface PolyVoxelSource {
kind: "magica-vox";
cells: PolyVoxelCell[];
rows: number;
cols: number;
depth: number;
scale: number;
gridShift: number;
sourceBytes: number;
}
```

---

## `ParseAnimationController`

glTF / GLB parses can expose a lightweight sampler for animation clips. Framework hooks and the core animation mixer consume this controller.

```ts
interface ParseAnimationClip {
index: number;
name: string;
duration: number;
channelCount: number;
}

interface ParseAnimationController {
clips: ParseAnimationClip[];
sample: (clip: number | string, timeSeconds: number) => Polygon[];
}
```

---

## `PolyAnimationMixer`

Core animation API used by `usePolyAnimation` and vanilla animation loops.

```ts
interface PolyAnimationTarget {
setPolygons(polygons: Polygon[]): void;
}

interface PolyAnimationAction {
play(): PolyAnimationAction;
stop(): PolyAnimationAction;
reset(): PolyAnimationAction;
fadeIn(durationSeconds: number): PolyAnimationAction;
fadeOut(durationSeconds: number): PolyAnimationAction;
crossFadeTo(target: PolyAnimationAction, durationSeconds: number): PolyAnimationAction;
crossFadeFrom(from: PolyAnimationAction, durationSeconds: number): PolyAnimationAction;
setLoop(mode: LoopMode, repetitions: number): PolyAnimationAction;
setEffectiveTimeScale(scale: number): PolyAnimationAction;
setEffectiveWeight(weight: number): PolyAnimationAction;
clampWhenFinished: boolean;
timeScale: number;
weight: number;
time: number;
enabled: boolean;
paused: boolean;
readonly isRunning: boolean;
}

interface PolyAnimationMixer {
clipAction(clip: number | string): PolyAnimationAction;
existingAction(clip: number | string): PolyAnimationAction | null;
update(deltaSeconds: number): void;
stopAllAction(): void;
uncacheClip(clip: number | string): void;
uncacheRoot(): void;
}
```

`LoopOnce`, `LoopRepeat`, and `LoopPingPong` are exported constants matching three.js loop modes.

---

## `LoadMeshOptions`

Options for the high-level `loadMesh` dispatcher. Format-specific parser settings are nested under the matching key.
Expand All @@ -199,13 +303,32 @@ interface LoadMeshOptions {
gltfOptions?: GltfParseOptions;
/** Forwarded to parseVox. */
voxOptions?: VoxParseOptions;
/** Convert uniform texture-backed faces into solid-color polygons before optimization. */
solidTextureSamples?: boolean | SolidTextureSampleOptions;
/** Shared mesh-resolution optimizer. Defaults to "lossy", including bounded seam repair. */
meshResolution?: "lossless" | "lossy";
}
```

---

## `SolidTextureSampleOptions`

Optional `loadMesh` optimization that converts texture-backed faces whose sampled UV region is effectively a uniform color into solid-color polygons before culling and merging.

```ts
interface SolidTextureSampleOptions {
/** Set false to keep every textured polygon texture-backed. */
enabled?: boolean;
/** Per-channel tolerance for declaring sampled texels uniform. Default: 2. */
colorTolerance?: number;
/** Skip decoding very large textures for this optimization. Default: 16 MP. */
maxTexturePixels?: number;
}
```

---

## `NormalizeResult`

Return type of `normalizePolygons`.
Expand All @@ -229,7 +352,7 @@ interface ObjParseOptions {
targetSize?: number;
/** Shift all vertices by this amount after scaling. */
gridShift?: number;
/** Fallback color for un-colored faces (default: "#cccccc"). */
/** Fallback color for un-colored faces (default: "#888888"). */
defaultColor?: string;
/** Override per-material colors (material name → CSS color). */
materialColors?: Record<string, string>;
Expand All @@ -256,6 +379,10 @@ interface VoxParseOptions {
targetSize?: number;
/** Shift all vertices by this amount after scaling. Default: 0. */
gridShift?: number;
/** Lossy RGB distance for folding nearby opaque palette colors before greedy meshing. Default: disabled. */
paletteMergeDistance?: number;
/** Lossy RGB distance for recoloring small local color islands/streaks before greedy meshing. Default: disabled. */
colorRegionMergeDistance?: number;
}
```

Expand All @@ -271,7 +398,7 @@ interface GltfParseOptions {
targetSize?: number;
/** Shift all vertices by this amount after scaling. */
gridShift?: number;
/** Fallback color for un-colored faces. */
/** Fallback color for un-colored faces (default: "#888888"). */
defaultColor?: string;
/** Override per-material colors. */
materialColors?: Record<string, string>;
Expand Down
Loading
Loading