@vgai/engine 0.2.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.
Files changed (147) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +35 -0
  3. package/package.json +55 -0
  4. package/src/adapter/authoring.ts +402 -0
  5. package/src/adapter/colyseus-networking-adapter.ts +72 -0
  6. package/src/adapter/first-party-systems.ts +103 -0
  7. package/src/adapter/game-adapter.ts +151 -0
  8. package/src/adapter/host-context.ts +77 -0
  9. package/src/adapter/index.ts +85 -0
  10. package/src/adapter/ingest/game-contract.ts +59 -0
  11. package/src/adapter/ingest/overlay-applier.ts +207 -0
  12. package/src/adapter/ingest/overlay-apply.ts +124 -0
  13. package/src/adapter/ingest/overlay-file.ts +126 -0
  14. package/src/adapter/ingest/overlay-report.ts +176 -0
  15. package/src/adapter/ingest/scene-capture.ts +307 -0
  16. package/src/adapter/ingest/upstream-pin.ts +52 -0
  17. package/src/adapter/loop-gate-report.ts +54 -0
  18. package/src/adapter/rapier-physics-adapter.ts +56 -0
  19. package/src/adapter/system-adapter.ts +154 -0
  20. package/src/adapter/transform.ts +18 -0
  21. package/src/adapter/vgai-scene-game-adapter.ts +886 -0
  22. package/src/adapter/world-kind.ts +34 -0
  23. package/src/ai/navigation.ts +164 -0
  24. package/src/animation/anim-graph-types.ts +56 -0
  25. package/src/animation/anim-graph.ts +406 -0
  26. package/src/animation/anim-system.ts +28 -0
  27. package/src/animation/blend-node.ts +119 -0
  28. package/src/animation/property-track.ts +178 -0
  29. package/src/animation/schema.ts +204 -0
  30. package/src/assets.ts +80 -0
  31. package/src/audio/ambient.ts +300 -0
  32. package/src/audio/impacts.ts +212 -0
  33. package/src/audio/index.ts +7 -0
  34. package/src/audio/movement.ts +140 -0
  35. package/src/audio/musical.ts +200 -0
  36. package/src/audio/ui-sounds.ts +171 -0
  37. package/src/audio/vehicle.ts +235 -0
  38. package/src/audio/weapons.ts +152 -0
  39. package/src/core/game-loop.ts +127 -0
  40. package/src/core/system-runner.ts +298 -0
  41. package/src/core/types.ts +58 -0
  42. package/src/dev/console-bridge.ts +83 -0
  43. package/src/dev/debug-draw.ts +80 -0
  44. package/src/dev/logger.ts +119 -0
  45. package/src/ecs/component-manager.ts +748 -0
  46. package/src/ecs/game-component.ts +147 -0
  47. package/src/ecs/hmr-swap-report.ts +65 -0
  48. package/src/input/input-manager.ts +439 -0
  49. package/src/input/input-types.ts +19 -0
  50. package/src/input/schema.ts +129 -0
  51. package/src/loader.ts +70 -0
  52. package/src/manifest/index.ts +24 -0
  53. package/src/manifest/load-file.ts +16 -0
  54. package/src/manifest/load.ts +378 -0
  55. package/src/manifest/schema.ts +375 -0
  56. package/src/physics/collision-system.ts +76 -0
  57. package/src/physics/physics-registry.ts +83 -0
  58. package/src/physics/transform-writer.ts +41 -0
  59. package/src/physics/trigger-dispatch.ts +97 -0
  60. package/src/react/game-state.tsx +172 -0
  61. package/src/render/auto-batcher.ts +169 -0
  62. package/src/render/render-batch-system.ts +268 -0
  63. package/src/render/render-features.ts +146 -0
  64. package/src/render/render-settings.ts +72 -0
  65. package/src/runtime/create-runtime.ts +1152 -0
  66. package/src/runtime/frame-selector-cache.ts +81 -0
  67. package/src/runtime/game.ts +1003 -0
  68. package/src/runtime/input-router.ts +213 -0
  69. package/src/runtime/mount-game.ts +269 -0
  70. package/src/runtime/mount-manifest.ts +361 -0
  71. package/src/runtime/scene-ui-bridge.ts +86 -0
  72. package/src/runtime/scene-ui-data.ts +119 -0
  73. package/src/runtime/state-bridge.ts +79 -0
  74. package/src/runtime/types.ts +196 -0
  75. package/src/scene/asset-loaders.ts +195 -0
  76. package/src/scene/asset-paths.ts +123 -0
  77. package/src/scene/asset-registry.ts +67 -0
  78. package/src/scene/collider-dimensions.ts +125 -0
  79. package/src/scene/component-registry.ts +40 -0
  80. package/src/scene/defaults.ts +164 -0
  81. package/src/scene/geometries/index.ts +7 -0
  82. package/src/scene/geometries/terrain.ts +42 -0
  83. package/src/scene/geometry-registry.ts +42 -0
  84. package/src/scene/instance-registry.ts +84 -0
  85. package/src/scene/instancers/grid.ts +38 -0
  86. package/src/scene/instancers/index.ts +7 -0
  87. package/src/scene/light-camera-factory.ts +97 -0
  88. package/src/scene/material-factory.ts +211 -0
  89. package/src/scene/material-registry.ts +73 -0
  90. package/src/scene/materials/index.ts +7 -0
  91. package/src/scene/materials/water.ts +56 -0
  92. package/src/scene/parse.ts +71 -0
  93. package/src/scene/particles-factory.ts +383 -0
  94. package/src/scene/scene-apply.ts +356 -0
  95. package/src/scene/scene-diff-schema.ts +115 -0
  96. package/src/scene/scene-diff-types.ts +29 -0
  97. package/src/scene/scene-loader.ts +1533 -0
  98. package/src/scene/scene-query.ts +63 -0
  99. package/src/scene/scene-types.ts +34 -0
  100. package/src/scene/scene-version.ts +40 -0
  101. package/src/scene/schema/animation.ts +95 -0
  102. package/src/scene/schema/audio.ts +25 -0
  103. package/src/scene/schema/camera.ts +21 -0
  104. package/src/scene/schema/collider.ts +69 -0
  105. package/src/scene/schema/entity-ref.ts +78 -0
  106. package/src/scene/schema/entity.ts +169 -0
  107. package/src/scene/schema/environment.ts +384 -0
  108. package/src/scene/schema/index.ts +95 -0
  109. package/src/scene/schema/instances.ts +35 -0
  110. package/src/scene/schema/joint.ts +26 -0
  111. package/src/scene/schema/light.ts +38 -0
  112. package/src/scene/schema/material.ts +113 -0
  113. package/src/scene/schema/mesh.ts +108 -0
  114. package/src/scene/schema/particles.ts +398 -0
  115. package/src/scene/schema/physics.ts +49 -0
  116. package/src/scene/schema/scene-file.ts +299 -0
  117. package/src/scene/schema/shadow.ts +24 -0
  118. package/src/scene/schema/spline.ts +21 -0
  119. package/src/scene/schema/tuples.ts +21 -0
  120. package/src/scene/schema/ui.ts +602 -0
  121. package/src/scene/user-data.ts +203 -0
  122. package/src/setup/setup-audio.ts +60 -0
  123. package/src/setup/setup-particles.ts +23 -0
  124. package/src/setup/setup-physics.ts +67 -0
  125. package/src/setup/setup-renderer.ts +529 -0
  126. package/src/types-n8ao.d.ts +37 -0
  127. package/src/types-realism-effects.d.ts +61 -0
  128. package/src/world2d/authoring-2d.ts +208 -0
  129. package/src/world2d/capture-to-scene2d.ts +52 -0
  130. package/src/world2d/collision-2d.ts +106 -0
  131. package/src/world2d/components-2d.ts +86 -0
  132. package/src/world2d/index.ts +66 -0
  133. package/src/world2d/ingest-iframe-2d.ts +255 -0
  134. package/src/world2d/ingest2d.ts +131 -0
  135. package/src/world2d/physics2d-registry.ts +49 -0
  136. package/src/world2d/pixi-game-adapter.ts +325 -0
  137. package/src/world2d/pixi-surface.ts +78 -0
  138. package/src/world2d/scene-capture-2d.ts +117 -0
  139. package/src/world2d/scene2d-loader.ts +308 -0
  140. package/src/world2d/schema/entity2d.ts +145 -0
  141. package/src/world2d/schema/physics2d.ts +53 -0
  142. package/src/world2d/schema/sprite.ts +71 -0
  143. package/src/world2d/schema/tilemap.ts +22 -0
  144. package/src/world2d/schema/tuples2d.ts +25 -0
  145. package/src/world2d/system-adapters-2d.ts +49 -0
  146. package/src/world2d/transform-writer-2d.ts +24 -0
  147. package/src/world2d/types.ts +55 -0
@@ -0,0 +1,146 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * The render-feature registry — single source of truth for every togglable render
5
+ * setting. The scene schema (`SceneEnvironment.rendering`, `SceneEntity.render`),
6
+ * the cascade resolver (`resolveRenderSettings`), the editor UI, and the stats
7
+ * overlay are all derived from this list, so "everything togglable" stays
8
+ * consistent by construction (same posture as the component/material/instancer
9
+ * registries). Adding a feature here gives it a schema field + cascade entry for
10
+ * free. See docs/research/RENDER-SETTINGS-UX.md.
11
+ */
12
+
13
+ export type RenderFeatureValue = boolean | number | string;
14
+
15
+ export interface RenderFeature {
16
+ /** Stable key used in schema, cascade, and UI. */
17
+ key: string;
18
+ /** Editor display label. */
19
+ label: string;
20
+ /** Schema `.describe()` text (powers JSON Schema / inspector docs). */
21
+ description: string;
22
+ /** Control shape. */
23
+ kind: 'toggle' | 'number' | 'enum';
24
+ /** Engine default — the "fast by default" baseline. */
25
+ default: RenderFeatureValue;
26
+ /**
27
+ * `live` re-applies on change; `reload` needs a renderer re-init (e.g. backend,
28
+ * antialias). The editor badges `reload` features and re-inits the viewport.
29
+ */
30
+ apply: 'live' | 'reload';
31
+ /** Whether this feature may be overridden per-entity (the entity cascade layer). */
32
+ perEntity: boolean;
33
+ /** Allowed values for `enum` kind. */
34
+ options?: readonly string[];
35
+ /** [min, max] for `number` kind. */
36
+ range?: readonly [number, number];
37
+ }
38
+
39
+ export const RENDER_FEATURES: readonly RenderFeature[] = [
40
+ {
41
+ key: 'autoBatch',
42
+ label: 'Auto-batching',
43
+ description:
44
+ 'Automatically batch entities sharing geometry+material into one draw call (InstancedMesh/BatchedMesh) while keeping each Object3D as the handle. The headline perf win; opt out per-entity for custom-shader/skinned meshes.',
45
+ kind: 'toggle',
46
+ default: true,
47
+ apply: 'live',
48
+ perEntity: true,
49
+ },
50
+ {
51
+ key: 'frustumCulling',
52
+ label: 'Frustum culling',
53
+ description: 'Per-instance frustum culling for batched content.',
54
+ kind: 'toggle',
55
+ default: true,
56
+ apply: 'live',
57
+ perEntity: true,
58
+ },
59
+ {
60
+ key: 'lod',
61
+ label: 'Level of detail',
62
+ description: 'Distance-based geometry swap (LOD) for eligible entities.',
63
+ kind: 'toggle',
64
+ default: true,
65
+ apply: 'live',
66
+ perEntity: true,
67
+ },
68
+ {
69
+ key: 'shadows',
70
+ label: 'Shadows',
71
+ description: 'Enable the shadow map. Per-entity cast/receive still applies.',
72
+ kind: 'toggle',
73
+ default: true,
74
+ apply: 'live',
75
+ perEntity: true,
76
+ },
77
+ {
78
+ key: 'postProcessing',
79
+ label: 'Post-processing',
80
+ description:
81
+ 'Master switch for the post-processing stack (individual effects nest beneath it).',
82
+ kind: 'toggle',
83
+ default: true,
84
+ apply: 'live',
85
+ perEntity: false,
86
+ },
87
+ {
88
+ key: 'resolutionScale',
89
+ label: 'Resolution scale',
90
+ description: 'Device-pixel-ratio multiplier (1.0 = native). The cheapest perf dial.',
91
+ kind: 'number',
92
+ default: 1,
93
+ apply: 'live',
94
+ perEntity: false,
95
+ range: [0.25, 2],
96
+ },
97
+ {
98
+ key: 'antialias',
99
+ label: 'Antialiasing',
100
+ description: 'MSAA via renderer construction. Applies on reload (renderer re-init).',
101
+ kind: 'toggle',
102
+ default: true,
103
+ apply: 'reload',
104
+ perEntity: false,
105
+ },
106
+ {
107
+ key: 'backend',
108
+ label: 'Renderer backend',
109
+ description: 'GPU backend: auto picks WebGPU when available, else WebGL2. Applies on reload.',
110
+ kind: 'enum',
111
+ default: 'auto',
112
+ apply: 'reload',
113
+ perEntity: false,
114
+ options: ['auto', 'webgl', 'webgpu'],
115
+ },
116
+ ];
117
+
118
+ /** Map for O(1) lookup by key. */
119
+ export const RENDER_FEATURE_BY_KEY: ReadonlyMap<string, RenderFeature> = new Map(
120
+ RENDER_FEATURES.map((f) => [f.key, f]),
121
+ );
122
+
123
+ /**
124
+ * Build a Zod object for the render settings, derived from the registry so the
125
+ * schema can never drift from the feature list. All fields optional — absence
126
+ * means "inherit" in the cascade. `perEntityOnly` builds the per-entity override
127
+ * schema (only features whose `perEntity` is true).
128
+ */
129
+ export function buildRenderingZod(opts: { perEntityOnly?: boolean } = {}): z.ZodTypeAny {
130
+ const shape: Record<string, z.ZodTypeAny> = {};
131
+ for (const f of RENDER_FEATURES) {
132
+ if (opts.perEntityOnly && !f.perEntity) continue;
133
+ let base: z.ZodTypeAny;
134
+ if (f.kind === 'toggle') base = z.boolean();
135
+ else if (f.kind === 'number') base = z.number();
136
+ else base = z.enum(f.options as [string, ...string[]]);
137
+ shape[f.key] = base.optional().describe(f.description);
138
+ }
139
+ return z
140
+ .object(shape)
141
+ .describe(
142
+ opts.perEntityOnly
143
+ ? 'Per-entity render overrides (omit a field to inherit from the scene/engine default)'
144
+ : 'Scene render settings (omit a field to inherit the engine default)',
145
+ );
146
+ }
@@ -0,0 +1,72 @@
1
+ import { RENDER_FEATURES, type RenderFeatureValue } from './render-features';
2
+
3
+ /**
4
+ * Cascade resolution for render settings: engine default → scene → entity, with
5
+ * tri-state inherit (an absent value inherits from the next level up). See
6
+ * docs/research/RENDER-SETTINGS-UX.md.
7
+ */
8
+
9
+ /** A partial override map (scene-level or entity-level). Absent key = inherit. */
10
+ export type RenderScope = Partial<Record<string, RenderFeatureValue>>;
11
+
12
+ /** Fully-resolved settings: every registry key present. */
13
+ export type ResolvedRenderSettings = Record<string, RenderFeatureValue>;
14
+
15
+ /**
16
+ * Resolve effective settings. `entity` overrides only apply to features whose
17
+ * `perEntity` flag is set; non-per-entity features resolve across engine→scene
18
+ * only. `??` walks up the chain on `undefined` (inherit) but lets an explicit
19
+ * `false`/`0` override (they are not nullish).
20
+ */
21
+ export function resolveRenderSettings(
22
+ scene?: RenderScope,
23
+ entity?: RenderScope,
24
+ ): ResolvedRenderSettings {
25
+ const out: ResolvedRenderSettings = {};
26
+ for (const f of RENDER_FEATURES) {
27
+ const entityVal = f.perEntity ? entity?.[f.key] : undefined;
28
+ out[f.key] = entityVal ?? scene?.[f.key] ?? f.default;
29
+ }
30
+ return out;
31
+ }
32
+
33
+ /**
34
+ * A small observable holding the live scene-level resolved settings. Live
35
+ * features re-apply when a value changes (subscribers are notified with the
36
+ * changed key). This is the seam a future player-facing graphics menu would
37
+ * drive — for now it backs the editor toggles + the runtime systems.
38
+ */
39
+ export class RenderSettings {
40
+ private values: ResolvedRenderSettings;
41
+ private listeners = new Set<(key: string, value: RenderFeatureValue) => void>();
42
+
43
+ constructor(scene?: RenderScope) {
44
+ this.values = resolveRenderSettings(scene);
45
+ }
46
+
47
+ get(key: string): RenderFeatureValue {
48
+ return this.values[key]!;
49
+ }
50
+
51
+ /** Set a scene-level value; notifies subscribers if it changed. */
52
+ set(key: string, value: RenderFeatureValue): void {
53
+ if (this.values[key] === value) return;
54
+ this.values[key] = value;
55
+ for (const fn of this.listeners) fn(key, value);
56
+ }
57
+
58
+ /** Resolve the effective value for an entity (entity override → scene → default). */
59
+ forEntity(key: string, entity?: RenderScope): RenderFeatureValue {
60
+ const f = entity?.[key];
61
+ return f ?? this.values[key]!;
62
+ }
63
+
64
+ subscribe(fn: (key: string, value: RenderFeatureValue) => void): () => void {
65
+ this.listeners.add(fn);
66
+ return () => this.listeners.delete(fn);
67
+ }
68
+
69
+ snapshot(): ResolvedRenderSettings {
70
+ return { ...this.values };
71
+ }
72
+ }