ldr 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/model.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { parse, norm, type Doc, type M } from "./spec.js";
1
+ import { parse, norm, type Doc, type M, type LFile, type StepView } from "./spec.js";
2
2
  /** A placed part. `color` is an LDraw colour code (or direct colour 0x2RRGGBB); `m` is the 12-number LDraw matrix `x y z a b c d e f g h i`. */
3
3
  export interface PartInstance {
4
4
  part: string;
@@ -8,28 +8,55 @@ export interface PartInstance {
8
8
  step: number;
9
9
  /** Step path through nested submodels, e.g. [3, 1] = top step 3, submodel step 1. */
10
10
  steps: number[];
11
+ /** Step within the file that places this instance (the last entry of `steps`). */
12
+ localStep: number;
11
13
  /** Submodel path, e.g. "main.ldr/wheel.ldr". */
12
14
  path: string;
15
+ /** The part is defined inside the document (an MPD-embedded part, see `fileKind`), not taken from the library. */
16
+ embedded?: boolean;
17
+ /** Set for synthetic parts (a model file's own type 2-5 lines, named `<file>#<step>`): returns the part's LDraw source
18
+ * (`source.file` / `source.step` give the model file and step, see `looseFile`). */
19
+ source?: (() => string) & {
20
+ file?: LFile;
21
+ step?: number;
22
+ };
23
+ /** Only with `flatten(doc, { textures: true })`: the part is wrapped by a model-level `!TEXMAP`. `texPart` names the synthetic
24
+ * textured part (`<part>#tex-<hash>`, in packs built with `textures: true`) and `texSource` is its LDraw source; `part` stays the plain part. */
25
+ texPart?: string;
26
+ texSource?: string;
27
+ /** View rotation of this instance's step from `0 ROTSTEP` (absent = default view). See `fileStepViews`. */
28
+ view?: StepView;
13
29
  }
14
30
  export interface FlattenOptions {
15
31
  /** Resolve an external reference that is not a submodel of this document (e.g. a model file you loaded separately). Return null to treat it as a part. */
16
32
  resolveModel?: (name: string) => Doc | null;
17
33
  /** Max submodel nesting (cycle guard). Default 64. */
18
34
  maxDepth?: number;
35
+ /** Emit a model file's own type 2-5 lines as synthetic parts `<file>#<step>` (LDraw allows geometry in any file). Default true. */
36
+ looseGeometry?: boolean;
37
+ /** TEXMAP-aware view of the model: references wrapped by a model-level `!TEXMAP` get `texPart`, `0 !:` type-1 lines are
38
+ * included and `!TEXMAP FALLBACK` references are skipped. Use with packs built with `textures: true`. Default false. */
39
+ textures?: boolean;
19
40
  }
20
- /** Flatten a parsed LDraw document into part instances. Submodels (`0 FILE` blocks in an MPD) are expanded; everything else is treated as a part. */
41
+ /**
42
+ * Flatten a parsed LDraw document into part instances. Model files (`0 FILE` blocks in an MPD that `fileKind` calls models) are
43
+ * expanded; MPD-embedded parts and library references become instances. A model file's own geometry becomes synthetic parts.
44
+ */
21
45
  export declare function flatten(doc: Doc, opts?: FlattenOptions): PartInstance[];
22
46
  /** Parse LDraw text (.ldr/.mpd/.dat) and flatten it in one call. */
23
47
  export declare function parseModel(text: string, name?: string, opts?: FlattenOptions): PartInstance[];
24
48
  /**
25
49
  * Assign each instance a global sequential build-step index, ordering by the full nested step path
26
- * (so submodel steps become their own steps). Returns the number of steps.
50
+ * (so submodel steps become their own steps). Returns the number of steps and, per global step, its ROTSTEP view
51
+ * (null = default view; the view of the innermost file's step, see `fileStepViews`).
27
52
  */
28
53
  export declare function sequenceSteps<T extends {
29
54
  steps: number[];
55
+ view?: StepView;
30
56
  }>(insts: T[]): {
31
57
  count: number;
32
58
  stepOf: Int32Array;
59
+ views: (StepView | null)[];
33
60
  };
34
61
  /** Colour table entry. */
35
62
  export interface LDrawColor {
@@ -16,6 +16,15 @@ export interface BuildPackOptions {
16
16
  primitives?: "low" | "full";
17
17
  /** Weld + index vertices (smaller GPU buffers, faster). Default true. */
18
18
  weld?: boolean;
19
+ /** Keep type-5 conditional lines so the renderer can draw curved-surface silhouettes (pack v2). Off by default:
20
+ * Round 16 measured +7.5–13.6% zstd size and ~+25% build time on Datsville 10k/100k. Packs stay readable by ldr <= 0.2.0. */
21
+ cond?: boolean;
22
+ /** Keep textured (`!TEXMAP`) parts' TEXMAP-aware geometry + UVs and embed their PNGs (pack v2 "tex"). Off by default;
23
+ * packs without textured parts are byte-identical either way. Textures resolve from model `!DATA` blocks, then `textures/` in the library. */
24
+ textures?: boolean;
25
+ /** Render a model file's own type 2-5 lines (as synthetic parts `<file>#<step>`). Default true (LDraw allows geometry in any file);
26
+ * false reproduces packs from ldr <= 0.2.0, which dropped it. */
27
+ looseGeometry?: boolean;
19
28
  /** Embed the LDConfig colour table (code → hex) in the pack header. Default true. */
20
29
  colors?: boolean;
21
30
  onProgress?: (done: number, total: number) => void;
@@ -25,5 +34,7 @@ export interface BuildPackResult {
25
34
  parts: number;
26
35
  studKinds: number;
27
36
  missing: string[];
37
+ /** e.g. two models embedding different files under the same name (the first one is used). */
38
+ warnings?: string[];
28
39
  }
29
40
  export declare function buildPack(o: BuildPackOptions): BuildPackResult;
@@ -1,19 +1,32 @@
1
1
  import { Library } from './resolver.js';
2
+ /** `cond`: keep type-5 conditional lines (endpoints + control points) so the pack can draw them (pack v2). Default off.
3
+ * `tex`: also compile the TEXMAP-aware view of parts that use `!TEXMAP` (textured triangles with UVs + PNGs; pack v2 "tex"). Default off. */
2
4
  export type Opts = {
3
5
  studs: 'full' | 'low';
4
6
  prims: 'full' | 'low';
5
7
  weld: boolean;
6
8
  separateStuds: boolean;
9
+ cond?: boolean;
10
+ tex?: boolean;
7
11
  };
8
12
  export type Bucket = {
9
13
  pos: number[];
10
14
  col: number[];
11
15
  };
16
+ /** Textured triangles for one PNG: `uv` = 2 floats per vertex (LDraw !TEXMAP projection, v = 0 at the image's top row). */
17
+ export type TexBucket = Bucket & {
18
+ uv: number[];
19
+ wrapU?: boolean;
20
+ };
12
21
  export type Compiled = {
13
22
  body: Bucket;
14
23
  under: Bucket;
15
24
  edges: number[];
16
25
  condLines: number;
26
+ /** Type-5 lines in part space, stride 12 (p0, p1, control0, control1). Only filled when `opts.cond`.
27
+ * `cond` = lines of the body; `condUnder` = lines inside underside (tube / anti-stud) subfiles, drawn with the underside batch so they follow underside culling. */
28
+ cond?: number[];
29
+ condUnder?: number[];
17
30
  studs: {
18
31
  kind: string;
19
32
  color: string;
@@ -27,6 +40,10 @@ export type Compiled = {
27
40
  nz: number;
28
41
  bits: number[];
29
42
  };
43
+ /** Only with `opts.tex`, for parts whose tree uses !TEXMAP: the untextured body a TEXMAP-aware renderer draws instead of
44
+ * `body` (FALLBACK geometry dropped, `0 !:` geometry kept), plus textured triangles per texture name. Under/studs/edges are shared. */
45
+ tbody?: Bucket;
46
+ texb?: Map<string, TexBucket>;
30
47
  };
31
48
  export declare function loadColors(root: string): Map<string, number[]>;
32
49
  export declare class Compiler {
@@ -37,7 +54,17 @@ export declare class Compiler {
37
54
  constructor(lib: Library, opts: Opts);
38
55
  resolve(ref: string, isStud: boolean): string | null;
39
56
  compile(key: string, separateStuds?: boolean): Compiled;
57
+ private texMemo;
58
+ /** True if `key` or any file it references contains a `!TEXMAP` meta. */
59
+ hasTex(key: string): boolean;
60
+ /** Texture PNG bytes by !TEXMAP name: `textures/<name>` under parts/, p/, models/, then `<name>` (case-insensitive). */
61
+ texture(name: string): Uint8Array | null;
62
+ private texPass;
40
63
  }
41
- export declare function writePack(file: string, parts: Map<string, Compiled>, studKinds: Map<string, Compiled>, weld: boolean, extra?: Record<string, unknown>): void;
64
+ export declare function writePack(file: string, parts: Map<string, Compiled>, studKinds: Map<string, Compiled>, weld: boolean, extra?: Record<string, unknown>, options?: EncodeOptions): void;
65
+ /** `texture(name)`: PNG bytes for a !TEXMAP name used by a compiled part (e.g. `compiler.texture`, or an MPD `!DATA` block). */
66
+ export type EncodeOptions = {
67
+ texture?: (name: string) => Uint8Array | null;
68
+ };
42
69
  /** Serialize compiled parts into the binary pack format read by `decodePack`/`loadPack`. `extra` keys are merged into the JSON header (e.g. `colors`). */
43
- export declare function encodePack(parts: Map<string, Compiled>, studKinds: Map<string, Compiled>, weld: boolean, extra?: Record<string, unknown>): Uint8Array;
70
+ export declare function encodePack(parts: Map<string, Compiled>, studKinds: Map<string, Compiled>, weld: boolean, extra?: Record<string, unknown>, options?: EncodeOptions): Uint8Array;