@galfus/engine 0.0.0-stage → 0.31.0-alpha
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/README.md +190 -2
- package/package.json +59 -4
- package/src/anchors/cache.ts +101 -0
- package/src/anchors/component.ts +123 -0
- package/src/anchors/hierarchy.ts +192 -0
- package/src/anchors/index.ts +8 -0
- package/src/anchors/solver.ts +247 -0
- package/src/anchors/strategy.ts +142 -0
- package/src/animation/blending.ts +163 -0
- package/src/animation/clip.ts +132 -0
- package/src/animation/coordinator.ts +568 -0
- package/src/animation/index.ts +7 -0
- package/src/animation/native-targets.ts +37 -0
- package/src/animation/player.ts +287 -0
- package/src/audio/index.ts +4 -0
- package/src/audio/manager.ts +371 -0
- package/src/collision/components.ts +211 -0
- package/src/collision/index.ts +16 -0
- package/src/collision/query2d.ts +167 -0
- package/src/collision/query3d.ts +170 -0
- package/src/ecs/component.ts +130 -0
- package/src/ecs/entity.ts +75 -0
- package/src/ecs/index.ts +9 -0
- package/src/ecs/intent.ts +162 -0
- package/src/ecs/metadata.ts +44 -0
- package/src/ecs/system.ts +224 -0
- package/src/ecs/world.ts +291 -0
- package/src/index.ts +19 -0
- package/src/interaction/focus.ts +327 -0
- package/src/interaction/index.ts +9 -0
- package/src/interaction/listener.ts +58 -0
- package/src/interaction/snapshot2d.ts +210 -0
- package/src/interaction/snapshot3d.ts +214 -0
- package/src/interaction/system.ts +544 -0
- package/src/interaction/types.ts +27 -0
- package/src/math/common.ts +67 -0
- package/src/math/index.ts +17 -0
- package/src/math/mat2d.ts +320 -0
- package/src/math/mat4.ts +576 -0
- package/src/math/quat.ts +438 -0
- package/src/math/vec2.ts +161 -0
- package/src/math/vec3.ts +242 -0
- package/src/math/vec4.ts +171 -0
- package/src/multiverse/coordinator.ts +540 -0
- package/src/multiverse/index.ts +13 -0
- package/src/multiverse/presentation-graph.ts +306 -0
- package/src/multiverse/presentation-links.ts +134 -0
- package/src/multiverse/realm.ts +49 -0
- package/src/platform/index.ts +2 -0
- package/src/platform/platform.ts +149 -0
- package/src/platform/window.ts +181 -0
- package/src/realm2d/components.ts +254 -0
- package/src/realm2d/index.ts +12 -0
- package/src/realm2d/presets/index.ts +36 -0
- package/src/realm2d/realm.ts +522 -0
- package/src/realm2d/sync.ts +284 -0
- package/src/realm2d/utils/index.ts +32 -0
- package/src/realm3d/components.ts +341 -0
- package/src/realm3d/geometry.ts +224 -0
- package/src/realm3d/index.ts +12 -0
- package/src/realm3d/presets/index.ts +67 -0
- package/src/realm3d/realm.ts +588 -0
- package/src/realm3d/resource-ids.ts +62 -0
- package/src/realm3d/skinning.ts +128 -0
- package/src/realm3d/sync.ts +442 -0
- package/src/realm3d/utils/index.ts +26 -0
- package/src/resources/index.ts +4 -0
- package/src/resources/manager.ts +92 -0
- package/src/runtime.ts +588 -0
- package/src/spatial/dirty_registry.ts +217 -0
- package/src/spatial/flags.ts +14 -0
- package/src/spatial/index.ts +6 -0
- package/src/spatial/metrics.ts +124 -0
- package/src/text/editor.ts +224 -0
- package/src/text/encoding.ts +38 -0
- package/src/text/index.ts +13 -0
- package/src/text/input.ts +160 -0
- package/src/text/keyboard.ts +50 -0
- package/src/text/svg-decorations.ts +147 -0
- package/src/types.ts +85 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WindowManager coordinates native OS and browser canvas display surfaces.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { GalfusEngine, WindowConfig, WindowState } from '@galfus/transport-types';
|
|
6
|
+
import { IdAllocator, type WindowId } from '../types';
|
|
7
|
+
|
|
8
|
+
export type CursorGrabMode = 'none' | 'confined' | 'locked';
|
|
9
|
+
|
|
10
|
+
export type CursorIconName =
|
|
11
|
+
'default' | 'pointer' | 'grab' | 'grabbing' | 'crosshair' | 'text' | 'move' | 'wait';
|
|
12
|
+
|
|
13
|
+
const CURSOR_GRAB_MAP: Record<CursorGrabMode, number> = {
|
|
14
|
+
none: 0,
|
|
15
|
+
confined: 1,
|
|
16
|
+
locked: 2
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const CURSOR_ICON_MAP: Record<CursorIconName, number> = {
|
|
20
|
+
default: 0,
|
|
21
|
+
pointer: 1,
|
|
22
|
+
grab: 2,
|
|
23
|
+
grabbing: 3,
|
|
24
|
+
crosshair: 4,
|
|
25
|
+
text: 5,
|
|
26
|
+
move: 6,
|
|
27
|
+
wait: 7
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export interface WindowCreateOptions {
|
|
31
|
+
title?: string;
|
|
32
|
+
size?: [number, number];
|
|
33
|
+
position?: [number, number];
|
|
34
|
+
resizable?: boolean;
|
|
35
|
+
decorations?: boolean;
|
|
36
|
+
transparent?: boolean;
|
|
37
|
+
initialState?: WindowState;
|
|
38
|
+
canvasId?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class WindowManager {
|
|
42
|
+
private _engine: GalfusEngine | null = null;
|
|
43
|
+
private readonly _idAllocator = new IdAllocator<WindowId>(1);
|
|
44
|
+
private readonly _openWindows = new Set<WindowId>();
|
|
45
|
+
private readonly _lifecycleListeners = new Set<(windowId: WindowId, opened: boolean) => void>();
|
|
46
|
+
|
|
47
|
+
/** Observes actual window creation and closure, independent of close requests. */
|
|
48
|
+
onLifecycle(listener: (windowId: WindowId, opened: boolean) => void): () => void {
|
|
49
|
+
this._lifecycleListeners.add(listener);
|
|
50
|
+
return () => {
|
|
51
|
+
this._lifecycleListeners.delete(listener);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
bindEngine(engine: GalfusEngine): void {
|
|
56
|
+
this._engine = engine;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Creates an OS window or binds a browser canvas, returning a strongly-typed WindowId.
|
|
61
|
+
*/
|
|
62
|
+
create(options: WindowCreateOptions = {}): WindowId {
|
|
63
|
+
const windowId = this._idAllocator.allocate('WindowId');
|
|
64
|
+
if (this._engine) {
|
|
65
|
+
const config: WindowConfig = {
|
|
66
|
+
id: windowId,
|
|
67
|
+
title: options.title ?? 'Galfus Engine',
|
|
68
|
+
size: options.size,
|
|
69
|
+
position: options.position,
|
|
70
|
+
resizable: options.resizable ?? true,
|
|
71
|
+
decorations: options.decorations ?? true,
|
|
72
|
+
transparent: options.transparent ?? false,
|
|
73
|
+
initialState: options.initialState ?? 'windowed',
|
|
74
|
+
canvasId: options.canvasId
|
|
75
|
+
};
|
|
76
|
+
this._engine.windowCreate(config);
|
|
77
|
+
}
|
|
78
|
+
this._openWindows.add(windowId);
|
|
79
|
+
for (const listener of this._lifecycleListeners) listener(windowId, true);
|
|
80
|
+
return windowId;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Closes and destroys an open window surface.
|
|
85
|
+
*/
|
|
86
|
+
close(windowId: WindowId): void {
|
|
87
|
+
if (!this._openWindows.has(windowId)) return;
|
|
88
|
+
if (this._engine) {
|
|
89
|
+
this._engine.windowClose(windowId);
|
|
90
|
+
}
|
|
91
|
+
this._openWindows.delete(windowId);
|
|
92
|
+
for (const listener of this._lifecycleListeners) listener(windowId, false);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Updates the window title bar.
|
|
97
|
+
*/
|
|
98
|
+
setTitle(windowId: WindowId, title: string): void {
|
|
99
|
+
if (this._engine) {
|
|
100
|
+
this._engine.windowSetTitle(windowId, title);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Enables or disables input method composition for a window. */
|
|
105
|
+
setImeAllowed(windowId: WindowId, allowed: boolean): void {
|
|
106
|
+
if (this._openWindows.has(windowId))
|
|
107
|
+
this._engine?.windowSetImeAllowed(windowId, allowed ? 1 : 0);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** @internal Controls whether the platform captures Tab navigation for this window. */
|
|
111
|
+
setTabCapture(windowId: WindowId, enabled: boolean): void {
|
|
112
|
+
this._engine?.windowSetTabCapture?.(windowId, enabled ? 1 : 0);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** @internal Requests keyboard focus for the platform input surface. */
|
|
116
|
+
requestInputFocus(windowId: WindowId): void {
|
|
117
|
+
this._engine?.windowRequestInputFocus?.(windowId);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Sets the input method candidate area in physical window pixels. */
|
|
121
|
+
setImeCursorArea(windowId: WindowId, x: number, y: number, width: number, height: number): void {
|
|
122
|
+
this._engine?.windowSetImeCursorArea(windowId, x, y, width, height);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Retrieves the physical inner surface dimensions [width, height].
|
|
127
|
+
*/
|
|
128
|
+
getSize(windowId: WindowId): [number, number] {
|
|
129
|
+
if (this._engine && this._engine.platformGetWindowSize) {
|
|
130
|
+
return this._engine.platformGetWindowSize(windowId);
|
|
131
|
+
}
|
|
132
|
+
return [0, 0];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Explicitly updates the window / swapchain surface size in the Multiverse.
|
|
137
|
+
*/
|
|
138
|
+
updateSize(windowId: WindowId, width: number, height: number): void {
|
|
139
|
+
if (this._engine) {
|
|
140
|
+
this._engine.multiverseUpdateWindowSize(windowId, width, height);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Updates cursor grab mode ('none' | 'confined' | 'locked').
|
|
146
|
+
* 'locked' enables Pointer Lock for FPS and orbit cameras.
|
|
147
|
+
*/
|
|
148
|
+
setCursorGrab(windowId: WindowId, mode: CursorGrabMode | number): void {
|
|
149
|
+
const numericMode = typeof mode === 'string' ? (CURSOR_GRAB_MAP[mode] ?? 0) : mode;
|
|
150
|
+
if (this._engine) {
|
|
151
|
+
this._engine.windowSetCursorGrab(windowId, numericMode);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Updates cursor visual appearance icon ('default' | 'pointer' | 'grab' | 'grabbing' | 'crosshair' | 'text' | 'move' | 'wait').
|
|
157
|
+
*/
|
|
158
|
+
setCursorIcon(windowId: WindowId, icon: CursorIconName | number): void {
|
|
159
|
+
const numericIcon = typeof icon === 'string' ? (CURSOR_ICON_MAP[icon] ?? 0) : icon;
|
|
160
|
+
if (this._engine) {
|
|
161
|
+
this._engine.windowSetCursorIcon(windowId, numericIcon);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Sets the visual application icon of this window using raw image bytes (ICO, PNG, WebP, JPEG).
|
|
167
|
+
* Follows payload-first convention: (windowId, data).
|
|
168
|
+
*/
|
|
169
|
+
setIcon(windowId: WindowId, data: Uint8Array): void {
|
|
170
|
+
if (this._engine && this._engine.windowSetIcon) {
|
|
171
|
+
this._engine.windowSetIcon(windowId, data, data.byteLength);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Disposes and closes all active windows.
|
|
177
|
+
*/
|
|
178
|
+
dispose(): void {
|
|
179
|
+
for (const windowId of [...this._openWindows]) this.close(windowId);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realm 2D component declarations.
|
|
3
|
+
* Incorporates spatial Model2D with contiguous local/world matrices and SpatialDirtyFlags.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
Camera2DDesc,
|
|
8
|
+
Light2DDesc,
|
|
9
|
+
ParticleEmitter2DDesc,
|
|
10
|
+
Shape2DDesc,
|
|
11
|
+
Sprite2DDesc,
|
|
12
|
+
Svg2DDesc
|
|
13
|
+
} from '@galfus/transport-types';
|
|
14
|
+
import type { Component } from '../ecs/component';
|
|
15
|
+
import { mat2d, type Mat2d, vec2, type Vec2 } from '../math/index';
|
|
16
|
+
import { SpatialDirtyFlags } from '../spatial/flags';
|
|
17
|
+
|
|
18
|
+
const SCRATCH_P2D = vec2.create();
|
|
19
|
+
const SCRATCH_S2D = vec2.create();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 2D Spatial node component holding dual 2D affine matrices (local and resolved world)
|
|
23
|
+
* and a two-stage dirty flag state machine (LocalDirty -> WorldDirty -> Clean).
|
|
24
|
+
*/
|
|
25
|
+
export class Model2DComponent implements Component {
|
|
26
|
+
readonly type = 'Model2D' as const;
|
|
27
|
+
readonly modelId: number;
|
|
28
|
+
readonly localMatrix: Mat2d;
|
|
29
|
+
readonly worldMatrix: Mat2d;
|
|
30
|
+
private _zLayer = 0;
|
|
31
|
+
private _drawOrder = 0;
|
|
32
|
+
flags: SpatialDirtyFlags;
|
|
33
|
+
|
|
34
|
+
constructor(modelId: number, initialLocal?: Float32Array | number[]) {
|
|
35
|
+
this.modelId = modelId;
|
|
36
|
+
this.localMatrix = mat2d.create();
|
|
37
|
+
this.worldMatrix = mat2d.create();
|
|
38
|
+
if (initialLocal) {
|
|
39
|
+
this.localMatrix.set(initialLocal);
|
|
40
|
+
this.worldMatrix.set(initialLocal);
|
|
41
|
+
}
|
|
42
|
+
this.flags = SpatialDirtyFlags.LocalDirty | SpatialDirtyFlags.WorldDirty;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get zLayer(): number {
|
|
46
|
+
return this._zLayer;
|
|
47
|
+
}
|
|
48
|
+
set zLayer(value: number) {
|
|
49
|
+
if (value !== this._zLayer) {
|
|
50
|
+
this._zLayer = value;
|
|
51
|
+
this.flags |= SpatialDirtyFlags.WorldDirty;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
get drawOrder(): number {
|
|
55
|
+
return this._drawOrder;
|
|
56
|
+
}
|
|
57
|
+
set drawOrder(value: number) {
|
|
58
|
+
if (value !== this._drawOrder) {
|
|
59
|
+
this._drawOrder = value;
|
|
60
|
+
this.flags |= SpatialDirtyFlags.WorldDirty;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setPosition(x: number, y: number): this;
|
|
65
|
+
setPosition(position: [number, number] | Vec2): this;
|
|
66
|
+
setPosition(xOrPos: number | [number, number] | Vec2, y?: number): this {
|
|
67
|
+
if (typeof xOrPos === 'number') {
|
|
68
|
+
this.localMatrix[4] = xOrPos;
|
|
69
|
+
this.localMatrix[5] = y ?? 0;
|
|
70
|
+
} else {
|
|
71
|
+
this.localMatrix[4] = xOrPos[0];
|
|
72
|
+
this.localMatrix[5] = xOrPos[1];
|
|
73
|
+
}
|
|
74
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setRotation(rad: number): this {
|
|
79
|
+
vec2.set(SCRATCH_P2D, this.localMatrix[4], this.localMatrix[5]);
|
|
80
|
+
const sx = Math.hypot(this.localMatrix[0], this.localMatrix[1]);
|
|
81
|
+
const sy =
|
|
82
|
+
Math.hypot(this.localMatrix[2], this.localMatrix[3]) *
|
|
83
|
+
(this.localMatrix[0] * this.localMatrix[3] - this.localMatrix[1] * this.localMatrix[2] < 0
|
|
84
|
+
? -1
|
|
85
|
+
: 1);
|
|
86
|
+
vec2.set(SCRATCH_S2D, sx, sy);
|
|
87
|
+
mat2d.fromRotationTranslationScale(this.localMatrix, SCRATCH_P2D, rad, SCRATCH_S2D);
|
|
88
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
setScale(x: number, y: number): this;
|
|
93
|
+
setScale(scale: [number, number] | Vec2): this;
|
|
94
|
+
setScale(xOrScale: number | [number, number] | Vec2, y?: number): this {
|
|
95
|
+
const x = typeof xOrScale === 'number' ? xOrScale : xOrScale[0];
|
|
96
|
+
const sy = typeof xOrScale === 'number' ? (y ?? 1) : xOrScale[1];
|
|
97
|
+
const rotation = Math.atan2(this.localMatrix[1], this.localMatrix[0]);
|
|
98
|
+
vec2.set(SCRATCH_P2D, this.localMatrix[4], this.localMatrix[5]);
|
|
99
|
+
vec2.set(SCRATCH_S2D, x, sy);
|
|
100
|
+
mat2d.fromRotationTranslationScale(this.localMatrix, SCRATCH_P2D, rotation, SCRATCH_S2D);
|
|
101
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
setTRS(
|
|
106
|
+
position?: [number, number] | Vec2,
|
|
107
|
+
rotationRad = 0,
|
|
108
|
+
scale?: [number, number] | Vec2
|
|
109
|
+
): this {
|
|
110
|
+
const p = (position ?? [0, 0]) as unknown as Vec2;
|
|
111
|
+
const s = (scale ?? [1, 1]) as unknown as Vec2;
|
|
112
|
+
mat2d.fromRotationTranslationScale(this.localMatrix, p, rotationRad, s);
|
|
113
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
114
|
+
return this;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setLocalMatrix(mat: Float32Array | number[]): this {
|
|
118
|
+
this.localMatrix.set(mat);
|
|
119
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
setWorldMatrix(mat: Float32Array | number[]): this {
|
|
124
|
+
this.worldMatrix.set(mat);
|
|
125
|
+
this.flags |= SpatialDirtyFlags.WorldDirty;
|
|
126
|
+
return this;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
markLocalDirty(): void {
|
|
130
|
+
this.flags |= SpatialDirtyFlags.LocalDirty;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
markWorldDirty(): void {
|
|
134
|
+
this.flags |= SpatialDirtyFlags.WorldDirty;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
get isDirty(): boolean {
|
|
138
|
+
return this.flags !== SpatialDirtyFlags.Clean;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
set isDirty(val: boolean) {
|
|
142
|
+
if (val) {
|
|
143
|
+
this.flags |= SpatialDirtyFlags.WorldDirty;
|
|
144
|
+
} else {
|
|
145
|
+
this.flags = SpatialDirtyFlags.Clean;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function createModel2D(
|
|
151
|
+
modelId: number,
|
|
152
|
+
initialLocal?: Float32Array | number[]
|
|
153
|
+
): Model2DComponent {
|
|
154
|
+
return new Model2DComponent(modelId, initialLocal);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface Sprite2DComponent extends Component {
|
|
158
|
+
readonly type: 'Sprite2D';
|
|
159
|
+
readonly spriteId: number;
|
|
160
|
+
desc: Sprite2DDesc;
|
|
161
|
+
isDirty: boolean;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function createSprite2D(spriteId: number, desc: Sprite2DDesc): Sprite2DComponent {
|
|
165
|
+
return {
|
|
166
|
+
type: 'Sprite2D',
|
|
167
|
+
spriteId,
|
|
168
|
+
desc,
|
|
169
|
+
isDirty: true
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface Shape2DComponent extends Component {
|
|
174
|
+
readonly type: 'Shape2D';
|
|
175
|
+
readonly shapeId: number;
|
|
176
|
+
desc: Shape2DDesc;
|
|
177
|
+
isDirty: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function createShape2D(shapeId: number, desc: Shape2DDesc): Shape2DComponent {
|
|
181
|
+
return {
|
|
182
|
+
type: 'Shape2D',
|
|
183
|
+
shapeId,
|
|
184
|
+
desc,
|
|
185
|
+
isDirty: true
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export interface Light2DComponent extends Component {
|
|
190
|
+
readonly type: 'Light2D';
|
|
191
|
+
readonly lightId: number;
|
|
192
|
+
desc: Light2DDesc;
|
|
193
|
+
isDirty: boolean;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function createLight2D(lightId: number, desc: Light2DDesc): Light2DComponent {
|
|
197
|
+
return {
|
|
198
|
+
type: 'Light2D',
|
|
199
|
+
lightId,
|
|
200
|
+
desc,
|
|
201
|
+
isDirty: true
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface Camera2DComponent extends Component {
|
|
206
|
+
readonly type: 'Camera2D';
|
|
207
|
+
readonly cameraId: number;
|
|
208
|
+
desc: Camera2DDesc;
|
|
209
|
+
isDirty: boolean;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export function createCamera2D(cameraId: number, desc: Camera2DDesc): Camera2DComponent {
|
|
213
|
+
return {
|
|
214
|
+
type: 'Camera2D',
|
|
215
|
+
cameraId,
|
|
216
|
+
desc,
|
|
217
|
+
isDirty: true
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export interface Svg2DComponent extends Component {
|
|
222
|
+
readonly type: 'Svg2D';
|
|
223
|
+
readonly svgId: number;
|
|
224
|
+
desc: Svg2DDesc;
|
|
225
|
+
isDirty: boolean;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function createSvg2D(svgId: number, desc: Svg2DDesc): Svg2DComponent {
|
|
229
|
+
return {
|
|
230
|
+
type: 'Svg2D',
|
|
231
|
+
svgId,
|
|
232
|
+
desc,
|
|
233
|
+
isDirty: true
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface ParticleEmitter2DComponent extends Component {
|
|
238
|
+
readonly type: 'ParticleEmitter2D';
|
|
239
|
+
readonly emitterId: number;
|
|
240
|
+
desc: ParticleEmitter2DDesc;
|
|
241
|
+
isDirty: boolean;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export function createParticleEmitter2D(
|
|
245
|
+
emitterId: number,
|
|
246
|
+
desc: ParticleEmitter2DDesc
|
|
247
|
+
): ParticleEmitter2DComponent {
|
|
248
|
+
return {
|
|
249
|
+
type: 'ParticleEmitter2D',
|
|
250
|
+
emitterId,
|
|
251
|
+
desc,
|
|
252
|
+
isDirty: true
|
|
253
|
+
};
|
|
254
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realm 2D module.
|
|
3
|
+
*/
|
|
4
|
+
export * from './components';
|
|
5
|
+
export * from './presets/index';
|
|
6
|
+
export * as presets2D from './presets/index';
|
|
7
|
+
export * from './realm';
|
|
8
|
+
export * from './sync';
|
|
9
|
+
export * from './utils/index';
|
|
10
|
+
export * as utils2D from './utils/index';
|
|
11
|
+
|
|
12
|
+
export { Collider2DComponent, createCollider2D } from '../collision/components';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Realm 2D presets for quick entity and camera setup.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Camera2DDesc, Light2DDesc } from '@galfus/transport-types';
|
|
6
|
+
|
|
7
|
+
export function createOrthoCamera2DPreset(
|
|
8
|
+
options: {
|
|
9
|
+
orthoScale?: number;
|
|
10
|
+
near?: number;
|
|
11
|
+
far?: number;
|
|
12
|
+
cameraSlot?: number;
|
|
13
|
+
} = {}
|
|
14
|
+
): Camera2DDesc {
|
|
15
|
+
return {
|
|
16
|
+
orthoScale: options.orthoScale ?? 1.0,
|
|
17
|
+
near: options.near ?? 0.0,
|
|
18
|
+
far: options.far ?? 1000.0,
|
|
19
|
+
cameraSlot: options.cameraSlot ?? 0,
|
|
20
|
+
active: true
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createPointLight2DPreset(
|
|
25
|
+
options: {
|
|
26
|
+
color?: [number, number, number];
|
|
27
|
+
intensity?: number;
|
|
28
|
+
range?: number;
|
|
29
|
+
} = {}
|
|
30
|
+
): Light2DDesc {
|
|
31
|
+
return {
|
|
32
|
+
color: options.color ?? [1.0, 1.0, 1.0],
|
|
33
|
+
intensity: options.intensity ?? 1.0,
|
|
34
|
+
range: options.range ?? 200.0
|
|
35
|
+
};
|
|
36
|
+
}
|