lecodes-sdk 2.4.8 → 2.4.10
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/global.d.ts +4 -0
- package/dist/host.d.ts +13 -2
- package/dist/types/gl/Light.d.ts +7 -2
- package/dist/types/gl/Lightmap.d.ts +45 -25
- package/dist/types/gl/Material.d.ts +16 -2
- package/dist/types/gl/Particles.d.ts +1 -1
- package/dist/types/inject.d.ts +1 -0
- package/dist/types/scene/defineScene.d.ts +15 -54
- package/dist/types/version.d.ts +1 -1
- package/dist/types.json +1 -1
- package/package.json +1 -1
- package/src/compile/assetMacro.ts +2 -2
- package/src/compile/bakeMacro.ts +243 -0
- package/src/compile/bundler.ts +38 -6
- package/src/compile/compileProject.ts +13 -7
- package/src/compile/index.ts +2 -1
- package/src/compile/resourceSlots.ts +4 -3
- package/src/gl/Light.ts +280 -274
- package/src/gl/Lightmap.ts +123 -81
- package/src/gl/Material.ts +36 -2
- package/src/gl/Particles.ts +1 -1
- package/src/host.d.ts +13 -2
- package/src/inject.ts +1 -0
- package/src/scene/defineScene.ts +26 -59
- package/src/version.ts +1 -1
package/src/scene/defineScene.ts
CHANGED
|
@@ -52,11 +52,11 @@ import { Mesh } from "../gl/Mesh"
|
|
|
52
52
|
import { Model } from "../gl/Model"
|
|
53
53
|
import { Physics } from "../gl/physics/Physics"
|
|
54
54
|
import { CharacterController } from "../gl/physics/CharacterController"
|
|
55
|
-
import { Lightmap, type
|
|
55
|
+
import { Lightmap, type LightmapDef } from "../gl/Lightmap"
|
|
56
56
|
import { Foliage, type FoliageOptions } from "../gl/Foliage"
|
|
57
57
|
import { NavMesh } from "../gl/nav/NavMesh"
|
|
58
58
|
import { Terrain, type TerrainLayer, type TerrainRegion, type TerrainOptions } from "../gl/terrain/Terrain"
|
|
59
|
-
import { Light, type SunOptions } from "../gl/Light"
|
|
59
|
+
import { Light, type PointOptions, type SpotOptions, type SunOptions } from "../gl/Light"
|
|
60
60
|
import { Material } from "../gl/Material"
|
|
61
61
|
import { assignMaterialDef, MaterialHandle, resolveMaterialDef, type MaterialDef } from "./material"
|
|
62
62
|
import type { CapsuleOptions, CylinderOptions, PlaneOptions, SphereOptions } from "../gl/Geometry"
|
|
@@ -71,7 +71,13 @@ export type MeshDef =
|
|
|
71
71
|
| ({ kind: "capsule" } & CapsuleOptions)
|
|
72
72
|
| ({ kind: "plane" } & PlaneOptions)
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
/** The `light: {}` source block, by `kind` — `Light.sun` / `Light.point` / `Light.spot` with the node's transform: a
|
|
75
|
+
* point light's `bakeArea` panel lies in the node's local XZ plane and emits along its local -Y, so `eulerAngles`
|
|
76
|
+
* tilts it; a spot shines along the node's -Z (`direction` aims it, as a sun's does). */
|
|
77
|
+
export type LightDef =
|
|
78
|
+
| ({ kind: "sun" } & SunOptions)
|
|
79
|
+
| ({ kind: "point" } & PointOptions)
|
|
80
|
+
| ({ kind: "spot" } & SpotOptions)
|
|
75
81
|
|
|
76
82
|
/** A stamp: the terrain conforms to another node of this file (a road) at load — see Terrain.conform. */
|
|
77
83
|
export type TerrainStampDef = {
|
|
@@ -192,7 +198,7 @@ export type SceneNodeDef = {
|
|
|
192
198
|
* `'cube'` = a static whose every mesh bakes as AMBIENT CUBES instead of atlas texels — an occluder (its shadow and
|
|
193
199
|
* bounce stay in the bake) lit where it stands, the way the bake treats small and thin props on its own: a pipe run, a
|
|
194
200
|
* fence, a prop whose lightmap seams show. A prefab marked `'cube'` bakes its statics that way too. By name for a whole
|
|
195
|
-
* kit: `env.lightmap
|
|
201
|
+
* kit: the `cube` option of `env.lightmap`'s `bake()`. */
|
|
196
202
|
lightmap?: boolean | "cube"
|
|
197
203
|
/** `model` nodes: vegetation — load through the FOLIAGE tier (wind, touch bending, per-copy tint; see
|
|
198
204
|
* `Foliage`). `{ fade: [start, end] }` also thins the cards out over that distance range (m) and drops the
|
|
@@ -215,55 +221,6 @@ export type SceneCameraDef = CameraProjectionDef & {
|
|
|
215
221
|
target?: Vec3Like
|
|
216
222
|
}
|
|
217
223
|
|
|
218
|
-
/** `env.lightmap` — the level's baked lighting (engines/bake): the files `lecodes lightmap bake`
|
|
219
|
-
* writes. Absent = real-time only. */
|
|
220
|
-
export type SceneLightmapDef = {
|
|
221
|
-
/** `asset('./assets/lightmap/level.bake')` */
|
|
222
|
-
data: string
|
|
223
|
-
/** `asset('./assets/lightmap/level-light.ktx2')` — or, for a bake that took more than one atlas PAGE
|
|
224
|
-
* (`lecodes lightmap bake --pages`), every page in order: `[asset('x-light.ktx2'), asset('x-light_1.ktx2')]`. */
|
|
225
|
-
light: string | string[]
|
|
226
|
-
/** `asset('./assets/lightmap/level-aux.ktx2')` (pages like `light`) — sun / sky visibility + light direction. */
|
|
227
|
-
aux: string | string[]
|
|
228
|
-
/** DEBUG: the page sets a `lecodes lightmap bake --split` wrote (`<stem>-direct[_n].ktx2`, `<stem>-indirect[_n].ktx2`),
|
|
229
|
-
* pages like `light` — the `Lightmap.debug("direct" | "indirect")` views bind them in place of `light`. */
|
|
230
|
-
direct?: string | string[]
|
|
231
|
-
indirect?: string | string[]
|
|
232
|
-
/** `asset('./assets/lightmap/level-probes.ktx2')` — the bake's reflection probes (one prefiltered cubemap of the level's
|
|
233
|
-
* radiance per probe; every static reflects the nearest). Absent = statics reflect the sky's SH alone. */
|
|
234
|
-
probes?: string
|
|
235
|
-
/** FOR THE BAKE: the radiance in cd / m² of emission 1.0 on this level (emissive factor x strength x map) - every lit
|
|
236
|
-
* region of an emissive surface bakes as a rectangle lamp. An imported pack's emission is a LOOK (the school's panels
|
|
237
|
-
* say 10); this is where the level says what they give: a 1.3 m ceiling panel of ~8000 lm is ~1600 nits. Default: what
|
|
238
|
-
* the camera makes of 1.0 (`1.2 x 2^EV100`). 0 = emissive surfaces light nothing. `--emissive-nits` overrides. */
|
|
239
|
-
emissiveNits?: number
|
|
240
|
-
/** `false` = the emissive surfaces light nothing in the bake - the level is lit by its lamps (`Light.point` with a
|
|
241
|
-
* `bakeArea` next to every panel, the Unity packs' way) and the panels are decoration; `emissiveNits` then only says how
|
|
242
|
-
* bright their glow is DRAWN (scene-referred: nits through the camera's exposure). Default true. */
|
|
243
|
-
emissiveBake?: boolean
|
|
244
|
-
/** FOR THE BAKE: materials that let light THROUGH them, by glTF material name (`"name*"` = every name with that start) →
|
|
245
|
-
* the share of a shadow ray that passes, tinted by the material's base colour x map: `{ mat_awning: 0.3 }` puts the
|
|
246
|
-
* awning's warm, patterned light on the sand. The surface stays opaque - baked, drawn as before, a shadow caster.
|
|
247
|
-
* `{ through, diffuse }` splits it: `through` goes straight (the picture of the map), `diffuse` is scattered by the
|
|
248
|
-
* fibres (the underside glows, a soft fill with no picture) - dense canvas: `{ through: 0.08, diffuse: 0.25 }`. */
|
|
249
|
-
transmit?: Record<string, LightmapTransmit>
|
|
250
|
-
/** FOR THE BAKE: CUBES BY NAME — regular expressions (ECMAScript, case-sensitive) searched in every baked mesh's key
|
|
251
|
-
* (`<node path>@<ordinal>`): `['SM_pipe', 'SM_fence']` bakes every pipe and fence node as ambient cubes instead of atlas
|
|
252
|
-
* texels, like a node's `lightmap: 'cube'`. The CLI's `--cube` adds to these. */
|
|
253
|
-
cube?: string[]
|
|
254
|
-
/** `asset('./assets/lightmap/level.lgrid')` — THE LIGHT GRID for movers: every node a Physics aspect or a
|
|
255
|
-
* CharacterController moves (and what code marks with `Lightmap.track`) takes its ambient light from the bake at the
|
|
256
|
-
* place it is at, whatever its shader. Absent = movers keep the scene's IBL. */
|
|
257
|
-
volume?: string
|
|
258
|
-
/** `asset('./assets/lightmap/level-uv1.bin')` — THE PACKED LIGHTMAP UV1 the bake's rects map: it packs every mesh's
|
|
259
|
-
* lightmap charts into a square of their own instead of the unwrap's (once per mesh, whatever model holds it), and the
|
|
260
|
-
* engine swaps this into the models' TEXCOORD_1 before the rects go on. Required when the bake wrote one (the .bake's `uv1`): without it the statics
|
|
261
|
-
* read the wrong texels, so the bake is not applied. */
|
|
262
|
-
uv1?: string
|
|
263
|
-
/** A DEBUG multiplier on the atlas' lux (default 1). */
|
|
264
|
-
lightScale?: number
|
|
265
|
-
}
|
|
266
|
-
|
|
267
224
|
/** `env.navmesh` — the level's navigation mesh (see navmesh.md): the file `lecodes navmesh bake`
|
|
268
225
|
* writes, the agent size it is built for, and the named areas. Absent = no navigation. */
|
|
269
226
|
export type SceneNavmeshDef = {
|
|
@@ -276,7 +233,9 @@ export type SceneNavmeshDef = {
|
|
|
276
233
|
}
|
|
277
234
|
|
|
278
235
|
export type SceneDef = {
|
|
279
|
-
|
|
236
|
+
/** `lightmap` = the level's baked lighting (engines/bake): `bake('./assets/lightmap/level.bake', { …options })`, the
|
|
237
|
+
* macro that reads the bake's manifest at compile time (`LightmapDef`). Absent = real-time only. */
|
|
238
|
+
env?: SceneOptions & { lightmap?: LightmapDef, navmesh?: SceneNavmeshDef, foliage?: FoliageOptions }
|
|
280
239
|
camera?: SceneCameraDef
|
|
281
240
|
nodes?: Record<string, SceneNodeDef>
|
|
282
241
|
}
|
|
@@ -503,12 +462,23 @@ export const createSource = (path: string, def: SceneNodeDef, lightmap: boolean)
|
|
|
503
462
|
if (def.model !== undefined) return loadModel(def.model, lightmap, !!def.foliage)
|
|
504
463
|
if (def.mesh !== undefined) return createMesh(def.mesh, def.material)
|
|
505
464
|
if (def.terrain !== undefined) return createTerrain(def.terrain, lightmap)
|
|
506
|
-
if (def.light !== undefined)
|
|
465
|
+
if (def.light !== undefined) return createLight(path, def.light)
|
|
507
466
|
// make/prefab/camera/group nodes are plain wrappers — make/prefab subtrees mount under them
|
|
508
467
|
// during the build (attachPrefab) or in phase 2 (attachMake); a camera node drives scene.camera
|
|
509
468
|
return new Node()
|
|
510
469
|
}
|
|
511
470
|
|
|
471
|
+
/** A `light:` block by its kind. The node IS the light: its transform (applyNode) aims a sun / spot and turns a
|
|
472
|
+
* point light's `bakeArea` panel (local XZ, emitting along local -Y). */
|
|
473
|
+
const createLight = (path: string, def: LightDef): Light => {
|
|
474
|
+
switch (def.kind) {
|
|
475
|
+
case "sun": { const { kind: _k, ...opts } = def; return Light.sun(opts) }
|
|
476
|
+
case "point": { const { kind: _k, ...opts } = def; return Light.point(opts) }
|
|
477
|
+
case "spot": { const { kind: _k, ...opts } = def; return Light.spot(opts) }
|
|
478
|
+
}
|
|
479
|
+
throw new Error(`Scene node "${path}": light kind "${String((def as { kind?: unknown }).kind)}" is not sun, point or spot`)
|
|
480
|
+
}
|
|
481
|
+
|
|
512
482
|
/** Edit mode: play the preview pose on a model node (`editor: { clip, time }`) — idempotent, the
|
|
513
483
|
* harness re-applies it on inspector edits. No clip = back to the rest pose. */
|
|
514
484
|
export const applyEditorPose = (node: Node, pose: { clip?: string, time?: number } | undefined): void => {
|
|
@@ -1034,10 +1004,7 @@ const instantiate = async (def: SceneDef, editorRuns: EditorRun[]): Promise<{ sc
|
|
|
1034
1004
|
}
|
|
1035
1005
|
|
|
1036
1006
|
// the level is complete: apply the bake — or, under `lecodes lightmap bake`, run it
|
|
1037
|
-
if (lm && lightmap)
|
|
1038
|
-
await Lightmap.load(scene, { data: lightmap.data, light: lightmap.light, aux: lightmap.aux, direct: lightmap.direct, indirect: lightmap.indirect, probes: lightmap.probes, volume: lightmap.volume, uv1: lightmap.uv1 },
|
|
1039
|
-
{ lightScale: lightmap.lightScale, emissiveNits: lightmap.emissiveNits, emissiveBake: lightmap.emissiveBake, transmit: lightmap.transmit, cube: lightmap.cube })
|
|
1040
|
-
}
|
|
1007
|
+
if (lm && lightmap) await Lightmap.load(scene, lightmap)
|
|
1041
1008
|
// navigation: load the baked mesh — or, under `lecodes navmesh bake`, dump the level's collision
|
|
1042
1009
|
// geometry for it (the static bodies exist by now; edit mode never loads it — v1)
|
|
1043
1010
|
if (navmesh && !(EDITOR && isEditMode())) {
|
package/src/version.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// same manifest). Its MAJOR is the bundle ↔ runtime contract: a bundle's `// sdk:` header line
|
|
5
5
|
// and a host's embedded version must agree on the major for the host to run the bundle; minor
|
|
6
6
|
// and patch never gate anything (features are detected, never versioned).
|
|
7
|
-
export const SDK_VERSION = "2.4.
|
|
7
|
+
export const SDK_VERSION = "2.4.10"
|
|
8
8
|
|
|
9
9
|
/** The major of a semver string, or null when it is not one. */
|
|
10
10
|
export const sdkMajor = (version: string | null | undefined): number | null => {
|