@certe/atmos-core 0.1.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 (48) hide show
  1. package/LICENCE +674 -0
  2. package/README.md +171 -0
  3. package/dist/component-registry.d.ts +60 -0
  4. package/dist/component-registry.d.ts.map +1 -0
  5. package/dist/component-registry.js +14 -0
  6. package/dist/component-registry.js.map +1 -0
  7. package/dist/component.d.ts +19 -0
  8. package/dist/component.d.ts.map +1 -0
  9. package/dist/component.js +23 -0
  10. package/dist/component.js.map +1 -0
  11. package/dist/engine.d.ts +32 -0
  12. package/dist/engine.d.ts.map +1 -0
  13. package/dist/engine.js +75 -0
  14. package/dist/engine.js.map +1 -0
  15. package/dist/game-object.d.ts +23 -0
  16. package/dist/game-object.d.ts.map +1 -0
  17. package/dist/game-object.js +65 -0
  18. package/dist/game-object.js.map +1 -0
  19. package/dist/index.d.ts +15 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +11 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/input.d.ts +48 -0
  24. package/dist/input.d.ts.map +1 -0
  25. package/dist/input.js +102 -0
  26. package/dist/input.js.map +1 -0
  27. package/dist/register-builtins.d.ts +2 -0
  28. package/dist/register-builtins.d.ts.map +1 -0
  29. package/dist/register-builtins.js +13 -0
  30. package/dist/register-builtins.js.map +1 -0
  31. package/dist/scene-serializer.d.ts +46 -0
  32. package/dist/scene-serializer.d.ts.map +1 -0
  33. package/dist/scene-serializer.js +197 -0
  34. package/dist/scene-serializer.js.map +1 -0
  35. package/dist/scene.d.ts +38 -0
  36. package/dist/scene.d.ts.map +1 -0
  37. package/dist/scene.js +142 -0
  38. package/dist/scene.js.map +1 -0
  39. package/dist/time.d.ts +9 -0
  40. package/dist/time.d.ts.map +1 -0
  41. package/dist/time.js +24 -0
  42. package/dist/time.js.map +1 -0
  43. package/dist/transform.d.ts +27 -0
  44. package/dist/transform.d.ts.map +1 -0
  45. package/dist/transform.js +121 -0
  46. package/dist/transform.js.map +1 -0
  47. package/package.json +27 -0
  48. package/src/index.ts +33 -0
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # 🧩 @certe/atmos-core
2
+
3
+ The heart of the Atmos Engine — game loop, scene graph, component model, input, and serialization. This package has no rendering or physics code; it defines the contracts that all other packages build on.
4
+
5
+ ---
6
+
7
+ ## 🔑 Key Concepts
8
+
9
+ ### Component Lifecycle
10
+
11
+ Every component follows a strict lifecycle:
12
+
13
+ ```
14
+ onAwake() → onStart() → onUpdate(dt) → onRender() → onDestroy()
15
+ once once every frame every frame once
16
+ ```
17
+
18
+ ```ts
19
+ import { Component } from '@certe/atmos-core';
20
+
21
+ class Rotator extends Component {
22
+ speed = 1;
23
+
24
+ onUpdate(dt: number) {
25
+ const r = this.gameObject.transform.rotation;
26
+ Quat.rotateY(r, r, this.speed * dt);
27
+ this.gameObject.transform.rotation = r; // triggers dirty flag
28
+ }
29
+ }
30
+ ```
31
+
32
+ ### GameObject & Transform
33
+
34
+ Every `GameObject` has a unique ID and always carries a `Transform`:
35
+
36
+ ```ts
37
+ const cube = new GameObject('Cube');
38
+ cube.transform.setPosition(0, 5, 0);
39
+ cube.transform.setScale(2, 2, 2);
40
+
41
+ const child = new GameObject('Child');
42
+ child.setParent(cube); // inherits parent's world matrix
43
+ ```
44
+
45
+ Transform uses a **dirty flag system** — local matrix recomputes only when TRS changes, and world matrix propagates through the parent chain.
46
+
47
+ ---
48
+
49
+ ## 🚀 Quick Start
50
+
51
+ ```ts
52
+ import { Engine, Scene, GameObject, Time, Input } from '@certe/atmos-core';
53
+
54
+ const scene = new Scene();
55
+ const player = new GameObject('Player');
56
+ player.addComponent(MyController);
57
+ scene.add(player);
58
+
59
+ const engine = new Engine();
60
+ engine.start(scene);
61
+ ```
62
+
63
+ ---
64
+
65
+ ## 📖 API Overview
66
+
67
+ ### Engine
68
+
69
+ The main loop orchestrator. Frame order:
70
+
71
+ ```
72
+ Input.endFrame() → Physics.step() → Scene.updateAll(dt) → Render
73
+ ```
74
+
75
+ | Method / Property | Description |
76
+ |---|---|
77
+ | `start(scene)` | Begin the game loop |
78
+ | `stop()` | Stop the loop |
79
+ | `paused` | Get/set — skips physics & scripts when true |
80
+ | `scene` | Set to swap scenes at runtime |
81
+ | `setRenderer(r)` | Provide a renderer implementation |
82
+ | `setPhysics(p)` | Provide a physics stepper |
83
+
84
+ ### Scene
85
+
86
+ Container for GameObjects. Manages lifecycle propagation.
87
+
88
+ | Method | Description |
89
+ |---|---|
90
+ | `add(obj)` | Add a GameObject (and children) |
91
+ | `remove(obj)` | Remove and call onDestroy on all components |
92
+ | `getAllObjects()` | `ReadonlySet<GameObject>` |
93
+ | `findAll<T>(Ctor)` | Find all components of a type |
94
+ | `awakeAll()` / `startAll()` / `updateAll(dt)` / `renderAll()` | Lifecycle phases |
95
+
96
+ ### Input
97
+
98
+ Keyboard and mouse state, frame-deterministic:
99
+
100
+ ```ts
101
+ if (Input.getKeyDown('Space')) jump();
102
+ if (Input.getKey('KeyW')) moveForward(dt);
103
+ const { x, y } = input.mousePosition;
104
+ ```
105
+
106
+ ### Time
107
+
108
+ ```ts
109
+ Time.deltaTime // seconds since last frame (clamped to 100ms)
110
+ Time.time // accumulated seconds
111
+ Time.frameCount // integer frame counter
112
+ ```
113
+
114
+ ### Component Registry
115
+
116
+ Register components at startup so the editor and serializer know about them:
117
+
118
+ ```ts
119
+ import { registerComponent } from '@certe/atmos-core';
120
+
121
+ registerComponent(Rotator, {
122
+ name: 'Rotator',
123
+ properties: [
124
+ { key: 'speed', type: 'number', default: 1, min: 0, max: 10 },
125
+ ],
126
+ });
127
+ ```
128
+
129
+ ### Scene Serialization
130
+
131
+ ```ts
132
+ import { serializeScene, deserializeScene } from '@certe/atmos-core';
133
+
134
+ const data = serializeScene(scene); // → JSON-safe SceneData
135
+ const restored = deserializeScene(data, ctx); // → new Scene
136
+ ```
137
+
138
+ The serializer handles Transform, parent-child relationships, component data, and `gameObjectRef` resolution across a 3-pass process.
139
+
140
+ ---
141
+
142
+ ## 🧠 Design Principles
143
+
144
+ - **No circular dependencies** — Component ↔ Scene link uses late binding
145
+ - **Deterministic execution** — fixed update order, frame-deterministic input
146
+ - **Composition over inheritance** — components attached to GameObjects
147
+ - **Strict TypeScript** — no `any`, all public APIs typed
148
+
149
+ ---
150
+
151
+ ## 📁 Structure
152
+
153
+ ```
154
+ packages/core/src/
155
+ index.ts # Public API
156
+ component.ts # Abstract Component base class
157
+ game-object.ts # GameObject with Transform
158
+ transform.ts # TRS + dirty flags + hierarchy
159
+ scene.ts # Scene graph + lifecycle
160
+ engine.ts # Main loop
161
+ input.ts # Keyboard/mouse
162
+ time.ts # Frame timing
163
+ component-registry.ts # Property metadata
164
+ scene-serializer.ts # Save/load scenes
165
+ ```
166
+
167
+ ---
168
+
169
+ ## 🔗 Dependencies
170
+
171
+ - `@certe/atmos-math` — Vec3, Mat4, Quat for Transform
@@ -0,0 +1,60 @@
1
+ export type PropertyType = 'number' | 'string' | 'boolean' | 'vec3' | 'quat' | 'color' | 'enum' | 'gameObjectRef' | 'materialAsset';
2
+ export interface PropertyDefBase {
3
+ visibleWhen?: (target: unknown) => boolean;
4
+ }
5
+ export interface NumberPropertyDef extends PropertyDefBase {
6
+ key: string;
7
+ type: 'number';
8
+ min?: number;
9
+ max?: number;
10
+ step?: number;
11
+ }
12
+ export interface Vec3PropertyDef extends PropertyDefBase {
13
+ key: string;
14
+ type: 'vec3';
15
+ }
16
+ export interface QuatPropertyDef extends PropertyDefBase {
17
+ key: string;
18
+ type: 'quat';
19
+ }
20
+ export interface ColorPropertyDef extends PropertyDefBase {
21
+ key: string;
22
+ type: 'color';
23
+ }
24
+ export interface EnumPropertyDef extends PropertyDefBase {
25
+ key: string;
26
+ type: 'enum';
27
+ options: string[];
28
+ /** When present, inspector uses this instead of static `options` for dynamic enum values. */
29
+ optionsFrom?: (target: unknown) => string[];
30
+ }
31
+ export interface StringPropertyDef extends PropertyDefBase {
32
+ key: string;
33
+ type: 'string';
34
+ }
35
+ export interface BooleanPropertyDef extends PropertyDefBase {
36
+ key: string;
37
+ type: 'boolean';
38
+ }
39
+ export interface GameObjectRefPropertyDef extends PropertyDefBase {
40
+ key: string;
41
+ type: 'gameObjectRef';
42
+ }
43
+ export interface MaterialAssetPropertyDef extends PropertyDefBase {
44
+ key: string;
45
+ type: 'materialAsset';
46
+ }
47
+ export type PropertyDef = NumberPropertyDef | Vec3PropertyDef | QuatPropertyDef | ColorPropertyDef | EnumPropertyDef | StringPropertyDef | BooleanPropertyDef | GameObjectRefPropertyDef | MaterialAssetPropertyDef;
48
+ export interface ComponentDef {
49
+ name: string;
50
+ properties: PropertyDef[];
51
+ /** When true, multiple instances of this component can be added to the same GameObject. */
52
+ allowMultiple?: boolean;
53
+ }
54
+ type ComponentConstructor = abstract new (...args: any[]) => any;
55
+ export declare function registerComponent(ctor: ComponentConstructor, def: ComponentDef): void;
56
+ export declare function getComponentDef(ctor: ComponentConstructor): ComponentDef | undefined;
57
+ export declare function getAllRegisteredComponents(): Map<ComponentConstructor, ComponentDef>;
58
+ export declare function clearRegistry(): void;
59
+ export {};
60
+ //# sourceMappingURL=component-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-registry.d.ts","sourceRoot":"","sources":["../src/component-registry.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,eAAe,CAAC;AAEpI,MAAM,WAAW,eAAe;IAC9B,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB;AAED,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,MAAM,WAAW,GACnB,iBAAiB,GACjB,eAAe,GACf,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,iBAAiB,GACjB,kBAAkB,GAClB,wBAAwB,GACxB,wBAAwB,CAAC;AAE7B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,WAAW,EAAE,CAAC;IAC1B,2FAA2F;IAC3F,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,KAAK,oBAAoB,GAAG,QAAQ,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;AAIjE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,oBAAoB,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAErF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,oBAAoB,GAAG,YAAY,GAAG,SAAS,CAEpF;AAED,wBAAgB,0BAA0B,IAAI,GAAG,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAEpF;AAED,wBAAgB,aAAa,IAAI,IAAI,CAEpC"}
@@ -0,0 +1,14 @@
1
+ const registry = new Map();
2
+ export function registerComponent(ctor, def) {
3
+ registry.set(ctor, def);
4
+ }
5
+ export function getComponentDef(ctor) {
6
+ return registry.get(ctor);
7
+ }
8
+ export function getAllRegisteredComponents() {
9
+ return new Map(registry);
10
+ }
11
+ export function clearRegistry() {
12
+ registry.clear();
13
+ }
14
+ //# sourceMappingURL=component-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-registry.js","sourceRoot":"","sources":["../src/component-registry.ts"],"names":[],"mappings":"AA8EA,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsC,CAAC;AAE/D,MAAM,UAAU,iBAAiB,CAAC,IAA0B,EAAE,GAAiB;IAC7E,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAA0B;IACxD,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { GameObject } from './game-object.js';
2
+ import type { Scene } from './scene.js';
3
+ export declare function _setSceneClass(cls: typeof Scene): void;
4
+ export declare abstract class Component {
5
+ gameObject: GameObject;
6
+ enabled: boolean;
7
+ onAwake?(): void;
8
+ onStart?(): void;
9
+ onUpdate?(dt: number): void;
10
+ onRender?(): void;
11
+ onDestroy?(): void;
12
+ /** Get a sibling component on the same GameObject. */
13
+ getComponent<T extends Component>(Ctor: new (...args: never[]) => T): T | null;
14
+ /** Get all sibling components of a given type on the same GameObject. */
15
+ getAllComponents<T extends Component>(Ctor: new (...args: never[]) => T): T[];
16
+ /** Find all components of a given type in the current scene. */
17
+ static findAll<T extends Component>(Ctor: new (...args: never[]) => T): T[];
18
+ }
19
+ //# sourceMappingURL=component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,KAAK,GAAG,IAAI,CAAuB;AAE9E,8BAAsB,SAAS;IAC7B,UAAU,EAAG,UAAU,CAAC;IACxB,OAAO,UAAQ;IAEf,OAAO,CAAC,IAAI,IAAI;IAChB,OAAO,CAAC,IAAI,IAAI;IAChB,QAAQ,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAC3B,QAAQ,CAAC,IAAI,IAAI;IACjB,SAAS,CAAC,IAAI,IAAI;IAElB,sDAAsD;IACtD,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI;IAI9E,yEAAyE;IACzE,gBAAgB,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE;IAI7E,gEAAgE;IAChE,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE;CAK5E"}
@@ -0,0 +1,23 @@
1
+ /** Set by Scene module at import time to break circular dependency. */
2
+ let _sceneClass = null;
3
+ export function _setSceneClass(cls) { _sceneClass = cls; }
4
+ export class Component {
5
+ gameObject;
6
+ enabled = true;
7
+ /** Get a sibling component on the same GameObject. */
8
+ getComponent(Ctor) {
9
+ return this.gameObject.getComponent(Ctor);
10
+ }
11
+ /** Get all sibling components of a given type on the same GameObject. */
12
+ getAllComponents(Ctor) {
13
+ return this.gameObject.getComponents().filter((c) => c instanceof Ctor);
14
+ }
15
+ /** Find all components of a given type in the current scene. */
16
+ static findAll(Ctor) {
17
+ const current = _sceneClass?.current;
18
+ if (!current)
19
+ return [];
20
+ return current.findAll(Ctor);
21
+ }
22
+ }
23
+ //# sourceMappingURL=component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAGA,uEAAuE;AACvE,IAAI,WAAW,GAAwB,IAAI,CAAC;AAC5C,MAAM,UAAU,cAAc,CAAC,GAAiB,IAAU,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC;AAE9E,MAAM,OAAgB,SAAS;IAC7B,UAAU,CAAc;IACxB,OAAO,GAAG,IAAI,CAAC;IAQf,sDAAsD;IACtD,YAAY,CAAsB,IAAiC;QACjE,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,yEAAyE;IACzE,gBAAgB,CAAsB,IAAiC;QACrE,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAU,EAAE,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC;IAClF,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,OAAO,CAAsB,IAAiC;QACnE,MAAM,OAAO,GAAG,WAAW,EAAE,OAAO,CAAC;QACrC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import { Scene } from './scene.js';
2
+ import { Time } from './time.js';
3
+ import { Input } from './input.js';
4
+ export interface Renderer {
5
+ beginFrame(): void;
6
+ endFrame(): void;
7
+ }
8
+ export interface PhysicsStepper {
9
+ step(dt: number): void;
10
+ }
11
+ export declare class Engine {
12
+ readonly time: Time;
13
+ readonly input: Input;
14
+ private _scene;
15
+ private _renderer;
16
+ private _physics;
17
+ private _running;
18
+ private _paused;
19
+ private _rafId;
20
+ setRenderer(renderer: Renderer): void;
21
+ setPhysics(physics: PhysicsStepper): void;
22
+ start(scene: Scene): void;
23
+ stop(): void;
24
+ get running(): boolean;
25
+ get paused(): boolean;
26
+ set paused(value: boolean);
27
+ set scene(s: Scene);
28
+ /** Exposed for testing: run a single frame tick manually */
29
+ tick(timestamp: number): void;
30
+ private _loop;
31
+ }
32
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,UAAU,IAAI,IAAI,CAAC;IACnB,QAAQ,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,qBAAa,MAAM;IACjB,QAAQ,CAAC,IAAI,OAAc;IAC3B,QAAQ,CAAC,KAAK,QAAe;IAE7B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAK;IAEnB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI;IAIrC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAIzC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAgBzB,IAAI,IAAI,IAAI;IAQZ,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,EAExB;IAED,IAAI,KAAK,CAAC,CAAC,EAAE,KAAK,EAIjB;IAED,4DAA4D;IAC5D,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAa7B,OAAO,CAAC,KAAK;CAKd"}
package/dist/engine.js ADDED
@@ -0,0 +1,75 @@
1
+ import { Scene } from './scene.js';
2
+ import { Time } from './time.js';
3
+ import { Input } from './input.js';
4
+ export class Engine {
5
+ time = new Time();
6
+ input = new Input();
7
+ _scene = null;
8
+ _renderer = null;
9
+ _physics = null;
10
+ _running = false;
11
+ _paused = false;
12
+ _rafId = 0;
13
+ setRenderer(renderer) {
14
+ this._renderer = renderer;
15
+ }
16
+ setPhysics(physics) {
17
+ this._physics = physics;
18
+ }
19
+ start(scene) {
20
+ if (this._running)
21
+ return;
22
+ this._scene = scene;
23
+ Scene.current = scene;
24
+ Input.current = this.input;
25
+ this._running = true;
26
+ this.time.reset();
27
+ if (!this._paused) {
28
+ scene.awakeAll();
29
+ scene.startAll();
30
+ }
31
+ this._rafId = requestAnimationFrame((ts) => this._loop(ts));
32
+ }
33
+ stop() {
34
+ this._running = false;
35
+ if (this._rafId) {
36
+ cancelAnimationFrame(this._rafId);
37
+ this._rafId = 0;
38
+ }
39
+ }
40
+ get running() {
41
+ return this._running;
42
+ }
43
+ get paused() {
44
+ return this._paused;
45
+ }
46
+ set paused(value) {
47
+ this._paused = value;
48
+ }
49
+ set scene(s) {
50
+ this._scene = s;
51
+ Scene.current = s;
52
+ Input.current = this.input;
53
+ }
54
+ /** Exposed for testing: run a single frame tick manually */
55
+ tick(timestamp) {
56
+ if (!this._scene)
57
+ return;
58
+ this.time.update(timestamp);
59
+ this.input.endFrame();
60
+ if (!this._paused) {
61
+ this._physics?.step(this.time.deltaTime);
62
+ this._scene.updateAll(this.time.deltaTime);
63
+ }
64
+ this._renderer?.beginFrame();
65
+ this._scene.renderAll();
66
+ this._renderer?.endFrame();
67
+ }
68
+ _loop(timestamp) {
69
+ if (!this._running)
70
+ return;
71
+ this.tick(timestamp);
72
+ this._rafId = requestAnimationFrame((ts) => this._loop(ts));
73
+ }
74
+ }
75
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { Component } from './component.js';
2
+ import { Transform } from './transform.js';
3
+ export declare class GameObject {
4
+ readonly id: number;
5
+ readonly transform: Transform;
6
+ name: string;
7
+ /** If true, this object and its children are skipped during serialization. */
8
+ transient: boolean;
9
+ private readonly _components;
10
+ private _parent;
11
+ private readonly _children;
12
+ constructor(name?: string);
13
+ get parent(): GameObject | null;
14
+ get children(): readonly GameObject[];
15
+ setParent(parent: GameObject | null): void;
16
+ addComponent<T extends Component>(Ctor: new () => T): T;
17
+ getComponent<T extends Component>(Ctor: new (...args: never[]) => T): T | null;
18
+ getComponents(): readonly Component[];
19
+ removeComponent(component: Component): void;
20
+ }
21
+ /** Reset ID counter (for testing only) */
22
+ export declare function resetGameObjectIds(): void;
23
+ //# sourceMappingURL=game-object.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-object.d.ts","sourceRoot":"","sources":["../src/game-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAI3C,qBAAa,UAAU;IACrB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,YAAmB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,SAAS,UAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmB;IAC/C,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAElC,IAAI,SAAe;IAK/B,IAAI,MAAM,IAAI,UAAU,GAAG,IAAI,CAE9B;IAED,IAAI,QAAQ,IAAI,SAAS,UAAU,EAAE,CAEpC;IAED,SAAS,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAa1C,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC;IAOvD,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI;IAO9E,aAAa,IAAI,SAAS,SAAS,EAAE;IAIrC,eAAe,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;CAO5C;AAED,0CAA0C;AAC1C,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,65 @@
1
+ import { Transform } from './transform.js';
2
+ let nextId = 1;
3
+ export class GameObject {
4
+ id;
5
+ transform = new Transform();
6
+ name;
7
+ /** If true, this object and its children are skipped during serialization. */
8
+ transient = false;
9
+ _components = [];
10
+ _parent = null;
11
+ _children = [];
12
+ constructor(name = 'GameObject') {
13
+ this.id = nextId++;
14
+ this.name = name;
15
+ }
16
+ get parent() {
17
+ return this._parent;
18
+ }
19
+ get children() {
20
+ return this._children;
21
+ }
22
+ setParent(parent) {
23
+ if (this._parent === parent)
24
+ return;
25
+ if (this._parent) {
26
+ const idx = this._parent._children.indexOf(this);
27
+ if (idx !== -1)
28
+ this._parent._children.splice(idx, 1);
29
+ }
30
+ this._parent = parent;
31
+ if (parent) {
32
+ parent._children.push(this);
33
+ }
34
+ this.transform.setParent(parent ? parent.transform : null);
35
+ }
36
+ addComponent(Ctor) {
37
+ const component = new Ctor();
38
+ component.gameObject = this;
39
+ this._components.push(component);
40
+ return component;
41
+ }
42
+ getComponent(Ctor) {
43
+ for (const c of this._components) {
44
+ if (c instanceof Ctor)
45
+ return c;
46
+ }
47
+ return null;
48
+ }
49
+ getComponents() {
50
+ return this._components;
51
+ }
52
+ removeComponent(component) {
53
+ const idx = this._components.indexOf(component);
54
+ if (idx !== -1) {
55
+ this._components.splice(idx, 1);
56
+ if (component.onDestroy)
57
+ component.onDestroy();
58
+ }
59
+ }
60
+ }
61
+ /** Reset ID counter (for testing only) */
62
+ export function resetGameObjectIds() {
63
+ nextId = 1;
64
+ }
65
+ //# sourceMappingURL=game-object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"game-object.js","sourceRoot":"","sources":["../src/game-object.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,IAAI,MAAM,GAAG,CAAC,CAAC;AAEf,MAAM,OAAO,UAAU;IACZ,EAAE,CAAS;IACX,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;IACrC,IAAI,CAAS;IACb,8EAA8E;IAC9E,SAAS,GAAG,KAAK,CAAC;IAED,WAAW,GAAgB,EAAE,CAAC;IACvC,OAAO,GAAsB,IAAI,CAAC;IACzB,SAAS,GAAiB,EAAE,CAAC;IAE9C,YAAY,IAAI,GAAG,YAAY;QAC7B,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,SAAS,CAAC,MAAyB;QACjC,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;YAAE,OAAO;QACpC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;IAED,YAAY,CAAsB,IAAiB;QACjD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAC7B,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,YAAY,CAAsB,IAAiC;QACjE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,IAAI,CAAC,YAAY,IAAI;gBAAE,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,eAAe,CAAC,SAAoB;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAChC,IAAI,SAAS,CAAC,SAAS;gBAAE,SAAS,CAAC,SAAS,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;CACF;AAED,0CAA0C;AAC1C,MAAM,UAAU,kBAAkB;IAChC,MAAM,GAAG,CAAC,CAAC;AACb,CAAC"}
@@ -0,0 +1,15 @@
1
+ export { Component } from './component.js';
2
+ export { GameObject, resetGameObjectIds } from './game-object.js';
3
+ export { Transform } from './transform.js';
4
+ export { Scene } from './scene.js';
5
+ export type { SceneLoader } from './scene.js';
6
+ export { Time } from './time.js';
7
+ export { Input } from './input.js';
8
+ export { Engine } from './engine.js';
9
+ export type { Renderer, PhysicsStepper } from './engine.js';
10
+ export { registerComponent, getComponentDef, getAllRegisteredComponents, clearRegistry, } from './component-registry.js';
11
+ export type { PropertyDef, PropertyDefBase, PropertyType, ComponentDef, NumberPropertyDef, Vec3PropertyDef, QuatPropertyDef, ColorPropertyDef, EnumPropertyDef, StringPropertyDef, BooleanPropertyDef, GameObjectRefPropertyDef, MaterialAssetPropertyDef, } from './component-registry.js';
12
+ export { registerCoreBuiltins } from './register-builtins.js';
13
+ export { serializeScene, deserializeScene, applyComponentData, serializePostProcess, applyPostProcess } from './scene-serializer.js';
14
+ export type { SceneData, GameObjectData, ComponentData, DeserializeContext, PostProcessData } from './scene-serializer.js';
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,aAAa,GACd,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,WAAW,EACX,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACrI,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,aAAa,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export { Component } from './component.js';
2
+ export { GameObject, resetGameObjectIds } from './game-object.js';
3
+ export { Transform } from './transform.js';
4
+ export { Scene } from './scene.js';
5
+ export { Time } from './time.js';
6
+ export { Input } from './input.js';
7
+ export { Engine } from './engine.js';
8
+ export { registerComponent, getComponentDef, getAllRegisteredComponents, clearRegistry, } from './component-registry.js';
9
+ export { registerCoreBuiltins } from './register-builtins.js';
10
+ export { serializeScene, deserializeScene, applyComponentData, serializePostProcess, applyPostProcess } from './scene-serializer.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,0BAA0B,EAC1B,aAAa,GACd,MAAM,yBAAyB,CAAC;AAgBjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,48 @@
1
+ export interface EventTarget {
2
+ addEventListener: (type: string, handler: (e: unknown) => void, options?: boolean | AddEventListenerOptions) => void;
3
+ removeEventListener: (type: string, handler: (e: unknown) => void, options?: boolean | EventListenerOptions) => void;
4
+ }
5
+ export interface CanvasLike {
6
+ getBoundingClientRect(): {
7
+ left: number;
8
+ top: number;
9
+ };
10
+ addEventListener: (type: string, handler: (e: unknown) => void) => void;
11
+ removeEventListener: (type: string, handler: (e: unknown) => void) => void;
12
+ }
13
+ export declare class Input {
14
+ /** The currently active Input instance, set automatically by Engine. */
15
+ static current: Input | null;
16
+ private readonly _keysDown;
17
+ private readonly _keysJustDown;
18
+ private readonly _keysJustUp;
19
+ private _mouseButtons;
20
+ private _detach;
21
+ /** Canvas-relative mouse position in CSS pixels. Updated on mousemove. */
22
+ readonly mousePosition: {
23
+ x: number;
24
+ y: number;
25
+ };
26
+ /** Accumulated mouse movement since last endFrame(). */
27
+ readonly mouseDelta: {
28
+ x: number;
29
+ y: number;
30
+ };
31
+ /** Bind keyboard + mouse listeners to a target (e.g., window). Optionally bind mouse position to a canvas. */
32
+ attach(target: EventTarget, canvas?: CanvasLike): () => void;
33
+ /** Remove previously attached listeners */
34
+ detach(): void;
35
+ /** True while key is held */
36
+ getKey(code: string): boolean;
37
+ /** True only on the frame the key was first pressed */
38
+ getKeyDown(code: string): boolean;
39
+ /** True only on the frame the key was first pressed (alias for getKeyDown). */
40
+ getKeyPressed(code: string): boolean;
41
+ /** True only on the frame the key was released */
42
+ getKeyUp(code: string): boolean;
43
+ /** True while mouse button is held (0=left, 1=middle, 2=right). */
44
+ getMouseButton(button: number): boolean;
45
+ /** Call at the end of each frame to reset per-frame state */
46
+ endFrame(): void;
47
+ }
48
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../src/input.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,KAAK,IAAI,CAAC;IACrH,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,KAAK,IAAI,CAAC;CACtH;AAED,MAAM,WAAW,UAAU;IACzB,qBAAqB,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IACxE,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;CAC5E;AAED,qBAAa,KAAK;IAChB,wEAAwE;IACxE,MAAM,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAQ;IAEpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA0B;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,OAAO,CAA6B;IAE5C,0EAA0E;IAC1E,QAAQ,CAAC,aAAa;;;MAAkB;IAExC,wDAAwD;IACxD,QAAQ,CAAC,UAAU;;;MAAkB;IAErC,8GAA8G;IAC9G,MAAM,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,IAAI;IA+D5D,2CAA2C;IAC3C,MAAM,IAAI,IAAI;IAId,6BAA6B;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI7B,uDAAuD;IACvD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,+EAA+E;IAC/E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI/B,mEAAmE;IACnE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAIvC,6DAA6D;IAC7D,QAAQ,IAAI,IAAI;CAMjB"}