@vulfram/engine 0.5.6-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/package.json +17 -0
- package/src/engine/api.ts +282 -0
- package/src/engine/bridge/dispatch.ts +115 -0
- package/src/engine/bridge/guards.ts +28 -0
- package/src/engine/bridge/protocol.ts +130 -0
- package/src/engine/ecs/index.ts +516 -0
- package/src/engine/errors.ts +10 -0
- package/src/engine/state.ts +135 -0
- package/src/engine/systems/command-intent.ts +74 -0
- package/src/engine/systems/core-command-builder.ts +265 -0
- package/src/engine/systems/diagnostics.ts +42 -0
- package/src/engine/systems/index.ts +7 -0
- package/src/engine/systems/input-mirror.ts +152 -0
- package/src/engine/systems/resource-upload.ts +143 -0
- package/src/engine/systems/response-decode.ts +28 -0
- package/src/engine/systems/utils.ts +147 -0
- package/src/engine/systems/world-lifecycle.ts +164 -0
- package/src/engine/world/entities.ts +516 -0
- package/src/index.ts +9 -0
- package/src/types/cmds/camera.ts +76 -0
- package/src/types/cmds/environment.ts +45 -0
- package/src/types/cmds/geometry.ts +144 -0
- package/src/types/cmds/gizmo.ts +18 -0
- package/src/types/cmds/index.ts +231 -0
- package/src/types/cmds/light.ts +69 -0
- package/src/types/cmds/material.ts +98 -0
- package/src/types/cmds/model.ts +59 -0
- package/src/types/cmds/shadow.ts +22 -0
- package/src/types/cmds/system.ts +15 -0
- package/src/types/cmds/texture.ts +63 -0
- package/src/types/cmds/window.ts +263 -0
- package/src/types/events/gamepad.ts +34 -0
- package/src/types/events/index.ts +19 -0
- package/src/types/events/keyboard.ts +225 -0
- package/src/types/events/pointer.ts +105 -0
- package/src/types/events/system.ts +13 -0
- package/src/types/events/window.ts +96 -0
- package/src/types/index.ts +3 -0
- package/src/types/kinds.ts +111 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import type { ShadowConfig } from '../../types/cmds/shadow';
|
|
2
|
+
import type { EnvironmentConfig } from '../../types/cmds/environment';
|
|
3
|
+
import type { NotificationLevel, UserAttentionType } from '../../types/kinds';
|
|
4
|
+
import { getWorldOrThrow, requireInitialized } from '../bridge/guards';
|
|
5
|
+
import type {
|
|
6
|
+
CameraProps,
|
|
7
|
+
CreateWindowProps,
|
|
8
|
+
GeometryProps,
|
|
9
|
+
InputStateComponent,
|
|
10
|
+
Intent,
|
|
11
|
+
LightProps,
|
|
12
|
+
MaterialProps,
|
|
13
|
+
ModelProps,
|
|
14
|
+
TagProps,
|
|
15
|
+
TextureProps,
|
|
16
|
+
TransformProps,
|
|
17
|
+
WindowProps,
|
|
18
|
+
WindowStateComponent,
|
|
19
|
+
} from '../ecs';
|
|
20
|
+
import { engineState } from '../state';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Emits an intent to the specified world.
|
|
24
|
+
* Intents are processed by systems at the beginning of each tick.
|
|
25
|
+
*/
|
|
26
|
+
export function emitIntent(worldId: number, intent: Intent): void {
|
|
27
|
+
requireInitialized();
|
|
28
|
+
const world = getWorldOrThrow(worldId);
|
|
29
|
+
world.pendingIntents.push(intent);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Emits an intent to create a window in the core.
|
|
34
|
+
*/
|
|
35
|
+
export function createWindow(worldId: number, props: CreateWindowProps): void {
|
|
36
|
+
emitIntent(worldId, {
|
|
37
|
+
type: 'create-window',
|
|
38
|
+
props,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Emits an intent to close the window associated with this world.
|
|
44
|
+
*/
|
|
45
|
+
export function closeWindow(worldId: number): void {
|
|
46
|
+
emitIntent(worldId, {
|
|
47
|
+
type: 'close-window',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Updates window properties.
|
|
53
|
+
*/
|
|
54
|
+
export function updateWindow(worldId: number, props: WindowProps): void {
|
|
55
|
+
emitIntent(worldId, {
|
|
56
|
+
type: 'update-window',
|
|
57
|
+
props,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Requests user attention for the window.
|
|
63
|
+
*/
|
|
64
|
+
export function requestAttention(
|
|
65
|
+
worldId: number,
|
|
66
|
+
attentionType?: UserAttentionType,
|
|
67
|
+
): void {
|
|
68
|
+
emitIntent(worldId, {
|
|
69
|
+
type: 'request-attention',
|
|
70
|
+
attentionType,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Focuses the window.
|
|
76
|
+
*/
|
|
77
|
+
export function focusWindow(worldId: number): void {
|
|
78
|
+
emitIntent(worldId, {
|
|
79
|
+
type: 'focus-window',
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Requests a list of resources from the engine for debugging.
|
|
85
|
+
*/
|
|
86
|
+
export function requestResourceList(
|
|
87
|
+
worldId: number,
|
|
88
|
+
resourceType:
|
|
89
|
+
| 'model'
|
|
90
|
+
| 'material'
|
|
91
|
+
| 'texture'
|
|
92
|
+
| 'geometry'
|
|
93
|
+
| 'light'
|
|
94
|
+
| 'camera',
|
|
95
|
+
): void {
|
|
96
|
+
emitIntent(worldId, {
|
|
97
|
+
type: 'request-resource-list',
|
|
98
|
+
resourceType,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Disposes a material.
|
|
104
|
+
*/
|
|
105
|
+
export function disposeMaterial(worldId: number, resourceId: number): void {
|
|
106
|
+
emitIntent(worldId, { type: 'dispose-material', resourceId });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Disposes a texture.
|
|
111
|
+
*/
|
|
112
|
+
export function disposeTexture(worldId: number, resourceId: number): void {
|
|
113
|
+
emitIntent(worldId, { type: 'dispose-texture', resourceId });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Disposes a geometry.
|
|
118
|
+
*/
|
|
119
|
+
export function disposeGeometry(worldId: number, resourceId: number): void {
|
|
120
|
+
emitIntent(worldId, { type: 'dispose-geometry', resourceId });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sends a system notification.
|
|
125
|
+
*/
|
|
126
|
+
export function sendNotification(
|
|
127
|
+
worldId: number,
|
|
128
|
+
props: {
|
|
129
|
+
level: NotificationLevel;
|
|
130
|
+
title: string;
|
|
131
|
+
message: string;
|
|
132
|
+
},
|
|
133
|
+
): void {
|
|
134
|
+
emitIntent(worldId, {
|
|
135
|
+
type: 'send-notification',
|
|
136
|
+
level: props.level,
|
|
137
|
+
title: props.title,
|
|
138
|
+
message: props.message,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Configures shadow settings for the world.
|
|
144
|
+
*/
|
|
145
|
+
export function configureShadows(worldId: number, config: ShadowConfig): void {
|
|
146
|
+
emitIntent(worldId, {
|
|
147
|
+
type: 'configure-shadows',
|
|
148
|
+
config,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Configures environment settings for the world.
|
|
154
|
+
*/
|
|
155
|
+
export function configureEnvironment(
|
|
156
|
+
worldId: number,
|
|
157
|
+
config: EnvironmentConfig,
|
|
158
|
+
): void {
|
|
159
|
+
emitIntent(worldId, {
|
|
160
|
+
type: 'configure-environment',
|
|
161
|
+
config,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Draws a debug gizmo line for one frame.
|
|
167
|
+
*/
|
|
168
|
+
export function drawGizmoLine(
|
|
169
|
+
worldId: number,
|
|
170
|
+
props: {
|
|
171
|
+
start: [number, number, number];
|
|
172
|
+
end: [number, number, number];
|
|
173
|
+
color?: [number, number, number, number];
|
|
174
|
+
},
|
|
175
|
+
): void {
|
|
176
|
+
emitIntent(worldId, {
|
|
177
|
+
type: 'gizmo-draw-line',
|
|
178
|
+
start: props.start,
|
|
179
|
+
end: props.end,
|
|
180
|
+
color: props.color || [1, 1, 1, 1],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Draws a debug gizmo AABB for one frame.
|
|
186
|
+
*/
|
|
187
|
+
export function drawGizmoAabb(
|
|
188
|
+
worldId: number,
|
|
189
|
+
props: {
|
|
190
|
+
min: [number, number, number];
|
|
191
|
+
max: [number, number, number];
|
|
192
|
+
color?: [number, number, number, number];
|
|
193
|
+
},
|
|
194
|
+
): void {
|
|
195
|
+
emitIntent(worldId, {
|
|
196
|
+
type: 'gizmo-draw-aabb',
|
|
197
|
+
min: props.min,
|
|
198
|
+
max: props.max,
|
|
199
|
+
color: props.color || [1, 1, 1, 1],
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Creates a new entity in the specified world.
|
|
205
|
+
* Returns the entity ID immediately, but the entity is actually created in the next tick.
|
|
206
|
+
*/
|
|
207
|
+
export function createEntity(worldId: number): number {
|
|
208
|
+
requireInitialized();
|
|
209
|
+
const entityId = engineState.nextEntityId++;
|
|
210
|
+
|
|
211
|
+
emitIntent(worldId, {
|
|
212
|
+
type: 'create-entity',
|
|
213
|
+
worldId,
|
|
214
|
+
entityId,
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return entityId;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Removes an entity and all its components in the next tick.
|
|
222
|
+
*/
|
|
223
|
+
export function removeEntity(worldId: number, entityId: number): void {
|
|
224
|
+
emitIntent(worldId, {
|
|
225
|
+
type: 'remove-entity',
|
|
226
|
+
entityId,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Attaches a camera component to an entity via Intent.
|
|
232
|
+
*/
|
|
233
|
+
export function createCamera(
|
|
234
|
+
worldId: number,
|
|
235
|
+
entityId: number,
|
|
236
|
+
props: CameraProps = {},
|
|
237
|
+
): void {
|
|
238
|
+
emitIntent(worldId, {
|
|
239
|
+
type: 'attach-camera',
|
|
240
|
+
entityId,
|
|
241
|
+
props,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Attaches a light component to an entity via Intent.
|
|
247
|
+
*/
|
|
248
|
+
export function createLight(
|
|
249
|
+
worldId: number,
|
|
250
|
+
entityId: number,
|
|
251
|
+
props: LightProps = {},
|
|
252
|
+
): void {
|
|
253
|
+
emitIntent(worldId, {
|
|
254
|
+
type: 'attach-light',
|
|
255
|
+
entityId,
|
|
256
|
+
props,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Attaches a model component to an entity via Intent.
|
|
262
|
+
*/
|
|
263
|
+
export function createModel(
|
|
264
|
+
worldId: number,
|
|
265
|
+
entityId: number,
|
|
266
|
+
props: ModelProps,
|
|
267
|
+
): void {
|
|
268
|
+
emitIntent(worldId, {
|
|
269
|
+
type: 'attach-model',
|
|
270
|
+
entityId,
|
|
271
|
+
props,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Updates an entity's transform via Intent.
|
|
277
|
+
*/
|
|
278
|
+
export function updateTransform(
|
|
279
|
+
worldId: number,
|
|
280
|
+
entityId: number,
|
|
281
|
+
props: TransformProps,
|
|
282
|
+
): void {
|
|
283
|
+
emitIntent(worldId, {
|
|
284
|
+
type: 'update-transform',
|
|
285
|
+
entityId,
|
|
286
|
+
props,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Attaches a tag component to an entity via Intent.
|
|
292
|
+
*/
|
|
293
|
+
export function createTag(
|
|
294
|
+
worldId: number,
|
|
295
|
+
entityId: number,
|
|
296
|
+
props: TagProps,
|
|
297
|
+
): void {
|
|
298
|
+
emitIntent(worldId, {
|
|
299
|
+
type: 'attach-tag',
|
|
300
|
+
entityId,
|
|
301
|
+
props,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Sets the parent of an entity via Intent.
|
|
307
|
+
*/
|
|
308
|
+
export function setParent(
|
|
309
|
+
worldId: number,
|
|
310
|
+
entityId: number,
|
|
311
|
+
parentId: number | null,
|
|
312
|
+
): void {
|
|
313
|
+
emitIntent(worldId, {
|
|
314
|
+
type: 'set-parent',
|
|
315
|
+
entityId,
|
|
316
|
+
parentId,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Resources (Material, Geometry, Texture)
|
|
322
|
+
*/
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Creates a material resource and returns its ID.
|
|
326
|
+
*/
|
|
327
|
+
export function createMaterial(worldId: number, props: MaterialProps): number {
|
|
328
|
+
requireInitialized();
|
|
329
|
+
const world = getWorldOrThrow(worldId);
|
|
330
|
+
const resourceId = world.nextCoreId++;
|
|
331
|
+
|
|
332
|
+
emitIntent(worldId, {
|
|
333
|
+
type: 'create-material',
|
|
334
|
+
resourceId,
|
|
335
|
+
props,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
return resourceId;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Creates a geometry resource and returns its ID.
|
|
343
|
+
*/
|
|
344
|
+
export function createGeometry(worldId: number, props: GeometryProps): number {
|
|
345
|
+
requireInitialized();
|
|
346
|
+
const world = getWorldOrThrow(worldId);
|
|
347
|
+
const resourceId = world.nextCoreId++;
|
|
348
|
+
|
|
349
|
+
emitIntent(worldId, {
|
|
350
|
+
type: 'create-geometry',
|
|
351
|
+
resourceId,
|
|
352
|
+
props,
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
return resourceId;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Creates a texture resource and returns its ID.
|
|
360
|
+
*/
|
|
361
|
+
export function createTexture(worldId: number, props: TextureProps): number {
|
|
362
|
+
requireInitialized();
|
|
363
|
+
const world = getWorldOrThrow(worldId);
|
|
364
|
+
const resourceId = world.nextCoreId++;
|
|
365
|
+
|
|
366
|
+
emitIntent(worldId, {
|
|
367
|
+
type: 'create-texture',
|
|
368
|
+
resourceId,
|
|
369
|
+
props,
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return resourceId;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Input & Window State Queries
|
|
377
|
+
*/
|
|
378
|
+
|
|
379
|
+
const WORLD_ENTITY_ID = 0;
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Gets the InputState component for a world.
|
|
383
|
+
* Returns undefined if the system hasn't run yet.
|
|
384
|
+
*/
|
|
385
|
+
function getInputState(worldId: number): InputStateComponent | undefined {
|
|
386
|
+
requireInitialized();
|
|
387
|
+
const world = getWorldOrThrow(worldId);
|
|
388
|
+
const worldStore = world.components.get(WORLD_ENTITY_ID);
|
|
389
|
+
return worldStore?.get('InputState') as InputStateComponent | undefined;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Gets the WindowState component for a world.
|
|
394
|
+
* Returns undefined if the system hasn't run yet.
|
|
395
|
+
*/
|
|
396
|
+
function getWindowState(worldId: number): WindowStateComponent | undefined {
|
|
397
|
+
requireInitialized();
|
|
398
|
+
const world = getWorldOrThrow(worldId);
|
|
399
|
+
const worldStore = world.components.get(WORLD_ENTITY_ID);
|
|
400
|
+
return worldStore?.get('WindowState') as WindowStateComponent | undefined;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Checks if a key is currently pressed.
|
|
405
|
+
*/
|
|
406
|
+
export function isKeyPressed(worldId: number, keyCode: number): boolean {
|
|
407
|
+
const state = getInputState(worldId);
|
|
408
|
+
return state?.keysPressed.has(keyCode) ?? false;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Checks if a key was just pressed this frame.
|
|
413
|
+
*/
|
|
414
|
+
export function isKeyJustPressed(worldId: number, keyCode: number): boolean {
|
|
415
|
+
const state = getInputState(worldId);
|
|
416
|
+
return state?.keysJustPressed.has(keyCode) ?? false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Checks if a key was just released this frame.
|
|
421
|
+
*/
|
|
422
|
+
export function isKeyJustReleased(worldId: number, keyCode: number): boolean {
|
|
423
|
+
const state = getInputState(worldId);
|
|
424
|
+
return state?.keysJustReleased.has(keyCode) ?? false;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Gets the current mouse position.
|
|
429
|
+
*/
|
|
430
|
+
export function getMousePosition(worldId: number): [number, number] {
|
|
431
|
+
const state = getInputState(worldId);
|
|
432
|
+
return state?.mousePosition ?? [0, 0];
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Gets the mouse movement delta for this frame.
|
|
437
|
+
*/
|
|
438
|
+
export function getMouseDelta(worldId: number): [number, number] {
|
|
439
|
+
const state = getInputState(worldId);
|
|
440
|
+
return state?.mouseDelta ?? [0, 0];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Checks if a mouse button is currently pressed.
|
|
445
|
+
*/
|
|
446
|
+
export function isMouseButtonPressed(worldId: number, button: number): boolean {
|
|
447
|
+
const state = getInputState(worldId);
|
|
448
|
+
return state?.mouseButtons.has(button) ?? false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Checks if a mouse button was just pressed this frame.
|
|
453
|
+
*/
|
|
454
|
+
export function isMouseButtonJustPressed(
|
|
455
|
+
worldId: number,
|
|
456
|
+
button: number,
|
|
457
|
+
): boolean {
|
|
458
|
+
const state = getInputState(worldId);
|
|
459
|
+
return state?.mouseJustPressed.has(button) ?? false;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Gets the scroll delta for this frame.
|
|
464
|
+
*/
|
|
465
|
+
export function getScrollDelta(worldId: number): [number, number] {
|
|
466
|
+
const state = getInputState(worldId);
|
|
467
|
+
return state?.scrollDelta ?? [0, 0];
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Gets the current window size.
|
|
472
|
+
*/
|
|
473
|
+
export function getWindowSize(worldId: number): [number, number] {
|
|
474
|
+
const state = getWindowState(worldId);
|
|
475
|
+
return state?.size ?? [800, 600];
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Gets the current window position.
|
|
480
|
+
*/
|
|
481
|
+
export function getWindowPosition(worldId: number): [number, number] {
|
|
482
|
+
const state = getWindowState(worldId);
|
|
483
|
+
return state?.position ?? [0, 0];
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Checks if the window is focused.
|
|
488
|
+
*/
|
|
489
|
+
export function isWindowFocused(worldId: number): boolean {
|
|
490
|
+
const state = getWindowState(worldId);
|
|
491
|
+
return state?.focused ?? false;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Checks if a close was requested this frame.
|
|
496
|
+
*/
|
|
497
|
+
export function isWindowCloseRequested(worldId: number): boolean {
|
|
498
|
+
const state = getWindowState(worldId);
|
|
499
|
+
return state?.closeRequested ?? false;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Checks if the window was resized this frame.
|
|
504
|
+
*/
|
|
505
|
+
export function wasWindowResized(worldId: number): boolean {
|
|
506
|
+
const state = getWindowState(worldId);
|
|
507
|
+
return state?.resizedThisFrame ?? false;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* Gets the window scale factor (DPI scaling).
|
|
512
|
+
*/
|
|
513
|
+
export function getWindowScaleFactor(worldId: number): number {
|
|
514
|
+
const state = getWindowState(worldId);
|
|
515
|
+
return state?.scaleFactor ?? 1.0;
|
|
516
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { CameraKind } from '../kinds';
|
|
2
|
+
|
|
3
|
+
/** Viewport value expressed as relative (0..1) or absolute pixels. */
|
|
4
|
+
export interface ViewValue {
|
|
5
|
+
type: 'relative' | 'absolute';
|
|
6
|
+
value: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Viewport definition relative to the window. */
|
|
10
|
+
export interface ViewPosition {
|
|
11
|
+
anchor: { x: ViewValue; y: ViewValue };
|
|
12
|
+
size: { width: ViewValue; height: ViewValue };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Command payload for creating a camera. */
|
|
16
|
+
export interface CmdCameraCreateArgs {
|
|
17
|
+
windowId: number;
|
|
18
|
+
cameraId: number;
|
|
19
|
+
label?: string;
|
|
20
|
+
transform: number[]; // Mat4 (16 elements)
|
|
21
|
+
kind: CameraKind;
|
|
22
|
+
flags: number;
|
|
23
|
+
nearFar: [number, number]; // Vec2
|
|
24
|
+
layerMask: number;
|
|
25
|
+
order: number;
|
|
26
|
+
viewPosition?: ViewPosition;
|
|
27
|
+
orthoScale: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Result payload for camera create. */
|
|
31
|
+
export interface CmdResultCameraCreate {
|
|
32
|
+
success: boolean;
|
|
33
|
+
message: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Command payload for updating a camera. */
|
|
37
|
+
export interface CmdCameraUpdateArgs {
|
|
38
|
+
windowId: number;
|
|
39
|
+
cameraId: number;
|
|
40
|
+
transform?: number[];
|
|
41
|
+
kind?: CameraKind;
|
|
42
|
+
flags?: number;
|
|
43
|
+
layerMask?: number;
|
|
44
|
+
order?: number;
|
|
45
|
+
nearFar?: [number, number];
|
|
46
|
+
viewPosition?: ViewPosition;
|
|
47
|
+
orthoScale?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Result payload for camera update. */
|
|
51
|
+
export interface CmdResultCameraUpdate {
|
|
52
|
+
success: boolean;
|
|
53
|
+
message: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Command payload for disposing a camera. */
|
|
57
|
+
export interface CmdCameraDisposeArgs {
|
|
58
|
+
windowId: number;
|
|
59
|
+
cameraId: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Result payload for camera dispose. */
|
|
63
|
+
export interface CmdResultCameraDispose {
|
|
64
|
+
success: boolean;
|
|
65
|
+
message: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** Command payload for listing cameras. */
|
|
69
|
+
export interface CmdCameraListArgs {}
|
|
70
|
+
|
|
71
|
+
/** Result payload for camera list. */
|
|
72
|
+
export interface CmdResultCameraList {
|
|
73
|
+
success: boolean;
|
|
74
|
+
message: string;
|
|
75
|
+
content: number[]; // List of camera IDs
|
|
76
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { SkyboxMode } from '../kinds';
|
|
2
|
+
|
|
3
|
+
/** MSAA configuration for the renderer. */
|
|
4
|
+
export interface MsaaConfig {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
sampleCount: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Skybox configuration for the environment. */
|
|
10
|
+
export interface SkyboxConfig {
|
|
11
|
+
mode: SkyboxMode;
|
|
12
|
+
intensity: number;
|
|
13
|
+
rotation: number;
|
|
14
|
+
tint: [number, number, number];
|
|
15
|
+
cubemapTextureId?: number | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Environment configuration for a window. */
|
|
19
|
+
export interface EnvironmentConfig {
|
|
20
|
+
msaa: MsaaConfig;
|
|
21
|
+
skybox: SkyboxConfig;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Command payload for creating environment settings. */
|
|
25
|
+
export interface CmdEnvironmentCreateArgs {
|
|
26
|
+
windowId: number;
|
|
27
|
+
config: EnvironmentConfig;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Command payload for updating environment settings. */
|
|
31
|
+
export interface CmdEnvironmentUpdateArgs {
|
|
32
|
+
windowId: number;
|
|
33
|
+
config: EnvironmentConfig;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Command payload for disposing environment settings. */
|
|
37
|
+
export interface CmdEnvironmentDisposeArgs {
|
|
38
|
+
windowId: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Result payload for environment commands. */
|
|
42
|
+
export interface CmdResultEnvironment {
|
|
43
|
+
success: boolean;
|
|
44
|
+
message: string;
|
|
45
|
+
}
|