@3dsource/angular-unreal-module 0.0.97 → 0.0.99
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
CHANGED
|
@@ -10,6 +10,10 @@ This package provides:
|
|
|
10
10
|
- Communication bridge (commands, UI interactions, input data)
|
|
11
11
|
- NgRx state and effects for 3D stream lifecycle
|
|
12
12
|
- Config and utilities for telemetry, errors, and regions ping
|
|
13
|
+
- Auto-reconnection support for WebRTC/DataChannel failures
|
|
14
|
+
- File receiving from Unreal Engine
|
|
15
|
+
- Analytics, FPS monitoring, and stream status telemetry
|
|
16
|
+
- Playwright testing mode with mock services
|
|
13
17
|
|
|
14
18
|
## Installation
|
|
15
19
|
|
|
@@ -17,6 +21,8 @@ This package provides:
|
|
|
17
21
|
|
|
18
22
|
- Angular 18+
|
|
19
23
|
- NgRx store and effects (v18+)
|
|
24
|
+
- Angular CDK (v18+) — used for dialog overlays
|
|
25
|
+
- `provideHttpClient()` — required by internal services (telemetry, signalling, regions ping, error reporting)
|
|
20
26
|
|
|
21
27
|
### Peer Dependencies
|
|
22
28
|
|
|
@@ -48,11 +54,14 @@ The API is fully standalone (no NgModule). Use providers and components as shown
|
|
|
48
54
|
|
|
49
55
|
### 1) Provide the module services and store slice
|
|
50
56
|
|
|
51
|
-
Add providers in your application bootstrap (e.g., app.config.ts):
|
|
57
|
+
Add providers in your application bootstrap (e.g., `app.config.ts`):
|
|
58
|
+
|
|
59
|
+
> **⚠️ Important:** `UNREAL_CONFIG` is **required** — multiple internal services inject it without `{ optional: true }`. Omitting it will cause a `NullInjectorError` at runtime. You can provide it with an empty object `{}` as a minimum.
|
|
52
60
|
|
|
53
61
|
```ts
|
|
54
62
|
import { ApplicationConfig } from '@angular/core';
|
|
55
63
|
import { provideRouter } from '@angular/router';
|
|
64
|
+
import { provideHttpClient } from '@angular/common/http';
|
|
56
65
|
import { provideStore } from '@ngrx/store';
|
|
57
66
|
import { provideEffects } from '@ngrx/effects';
|
|
58
67
|
import { provideAngularUnrealModule, UNREAL_CONFIG } from '@3dsource/angular-unreal-module';
|
|
@@ -60,30 +69,49 @@ import { provideAngularUnrealModule, UNREAL_CONFIG } from '@3dsource/angular-unr
|
|
|
60
69
|
export const appConfig: ApplicationConfig = {
|
|
61
70
|
providers: [
|
|
62
71
|
provideRouter([]),
|
|
72
|
+
provideHttpClient(),
|
|
73
|
+
|
|
63
74
|
// Root NgRx (if not already added in your app)
|
|
64
75
|
provideStore(),
|
|
65
76
|
provideEffects(),
|
|
66
77
|
|
|
67
|
-
// Unreal
|
|
68
|
-
// Tip: pass { playwright: true } to switch to testing/dummy services
|
|
69
|
-
provideAngularUnrealModule({ playwright: false }),
|
|
70
|
-
|
|
71
|
-
// Optional initial config
|
|
78
|
+
// Required: Unreal initial configuration
|
|
72
79
|
{
|
|
73
80
|
provide: UNREAL_CONFIG,
|
|
74
81
|
useValue: {
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
//
|
|
80
|
-
|
|
82
|
+
customErrorsEndpoint: '', // Endpoint for custom error reporting
|
|
83
|
+
commandTelemetryReceiver: '', // Endpoint for command telemetry
|
|
84
|
+
regionsPingUrl: '', // URL prefix for regions latency ping
|
|
85
|
+
screenLockerContainerId: '', // DOM container id for screen locker overlay
|
|
86
|
+
dataChannelConnectionTimeout: 8000, // Timeout in ms for data channel connection (default: 8000)
|
|
87
|
+
playwright: false, // Mirrors the provider flag for services/effects
|
|
88
|
+
reconnect: {
|
|
89
|
+
// Auto-reconnection configuration
|
|
90
|
+
enabled: true, // Enable auto-reconnection (default: true)
|
|
91
|
+
maxAttempts: 3, // Max reconnection attempts (default: 3)
|
|
92
|
+
delayMs: 1000, // Delay between attempts in ms (default: 1000)
|
|
93
|
+
onIceFailure: true, // Reconnect on ICE connection failure (default: true)
|
|
94
|
+
onDataChannelClose: true, // Reconnect on DataChannel close (default: true)
|
|
95
|
+
},
|
|
81
96
|
},
|
|
82
97
|
},
|
|
98
|
+
|
|
99
|
+
// Unreal providers (adds feature state and effects internally)
|
|
100
|
+
// Tip: pass { playwright: true } to switch to testing/dummy services
|
|
101
|
+
provideAngularUnrealModule({ playwright: false }),
|
|
83
102
|
],
|
|
84
103
|
};
|
|
85
104
|
```
|
|
86
105
|
|
|
106
|
+
#### Minimal configuration
|
|
107
|
+
|
|
108
|
+
If you don't need custom endpoints, provide `UNREAL_CONFIG` with an empty object:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
{ provide: UNREAL_CONFIG, useValue: {} },
|
|
112
|
+
provideAngularUnrealModule(),
|
|
113
|
+
```
|
|
114
|
+
|
|
87
115
|
### 2) Use the Unreal scene component
|
|
88
116
|
|
|
89
117
|
Import the component into a standalone component and use it in the template.
|
|
@@ -96,7 +124,7 @@ import { UnrealSceneComponent } from '@3dsource/angular-unreal-module';
|
|
|
96
124
|
selector: 'app-root',
|
|
97
125
|
standalone: true,
|
|
98
126
|
imports: [UnrealSceneComponent],
|
|
99
|
-
template: ` <app-unreal-scene [isStudio]="false" [useContainerAsSizeProvider]="true" [studioResolutionSize]="{ width: 1920, height: 1080 }" (changeMouseOverScene)="onHover($event)"
|
|
127
|
+
template: ` <app-unreal-scene [isStudio]="false" [useContainerAsSizeProvider]="true" [studioResolutionSize]="{ width: 1920, height: 1080 }" (changeMouseOverScene)="onHover($event)"> </app-unreal-scene> `,
|
|
100
128
|
})
|
|
101
129
|
export class AppComponent {
|
|
102
130
|
onHover(isOver: boolean) {
|
|
@@ -105,25 +133,38 @@ export class AppComponent {
|
|
|
105
133
|
}
|
|
106
134
|
```
|
|
107
135
|
|
|
108
|
-
Component selector:
|
|
136
|
+
Component selector: `<app-unreal-scene>`
|
|
109
137
|
|
|
110
138
|
Inputs:
|
|
111
139
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
140
|
+
| Input | Type | Default |
|
|
141
|
+
| ---------------------------- | ----------------------------------- | ------------------------------- |
|
|
142
|
+
| `isStudio` | `boolean` | `false` |
|
|
143
|
+
| `useContainerAsSizeProvider` | `boolean` | `true` |
|
|
144
|
+
| `studioResolutionSize` | `{ width: number; height: number }` | `{ width: 1920, height: 1080 }` |
|
|
115
145
|
|
|
116
146
|
Outputs:
|
|
117
147
|
|
|
118
|
-
|
|
148
|
+
| Output | Type |
|
|
149
|
+
| ---------------------- | --------------------------- |
|
|
150
|
+
| `changeMouseOverScene` | `OutputEmitterRef<boolean>` |
|
|
119
151
|
|
|
120
152
|
### 3) Send commands / interactions to Unreal
|
|
121
153
|
|
|
122
154
|
Inject `UnrealCommunicatorService` to send commands or UI interactions. Types for command packets are provided by `@3dsource/types-unreal`.
|
|
123
155
|
|
|
156
|
+
There are three sending methods — choose based on your needs:
|
|
157
|
+
|
|
158
|
+
| Method | Description |
|
|
159
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
160
|
+
| `sendCommandToUnreal` | Full pipeline: adds `correlationId`, records telemetry, dispatches NgRx `commandStarted` action. **Recommended for application commands.** |
|
|
161
|
+
| `emitUIInteraction` | Sends the packet as a raw `UIInteraction` message. No telemetry or store dispatch. |
|
|
162
|
+
| `emitCommand` | Sends the packet as a raw `Command` message (for console commands, resolution changes, etc.). |
|
|
163
|
+
|
|
124
164
|
```ts
|
|
125
165
|
import { Component, inject } from '@angular/core';
|
|
126
166
|
import { UnrealCommunicatorService } from '@3dsource/angular-unreal-module';
|
|
167
|
+
import { MetaBoxCommand } from '@3dsource/types-unreal';
|
|
127
168
|
import type { MetaBoxCommandPacket } from '@3dsource/types-unreal';
|
|
128
169
|
|
|
129
170
|
@Component({ standalone: true, template: '' })
|
|
@@ -131,29 +172,126 @@ export class MyComponent {
|
|
|
131
172
|
private unreal = inject(UnrealCommunicatorService);
|
|
132
173
|
|
|
133
174
|
sendSomeCommand() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
175
|
+
// Recommended: use sendCommandToUnreal for full telemetry + store tracking
|
|
176
|
+
this.unreal.sendCommandToUnreal({
|
|
177
|
+
command: MetaBoxCommand.FChangeResolutionCommand,
|
|
178
|
+
payload: { resolution: { x: 1920, y: 1080 } },
|
|
179
|
+
});
|
|
180
|
+
}
|
|
140
181
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
182
|
+
sendRawUIInteraction() {
|
|
183
|
+
// Low-level: sends UIInteraction message without telemetry tracking
|
|
184
|
+
const packet = {
|
|
185
|
+
command: 'CustomCommand',
|
|
186
|
+
payload: { key: 'value' },
|
|
187
|
+
} as MetaBoxCommandPacket;
|
|
188
|
+
this.unreal.emitUIInteraction(packet);
|
|
146
189
|
}
|
|
147
190
|
}
|
|
148
191
|
```
|
|
149
192
|
|
|
193
|
+
### 4) Store integration (actions & selectors)
|
|
194
|
+
|
|
195
|
+
The module registers an NgRx feature state `unrealFeature`. You can dispatch actions and select state in your components:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import { inject } from '@angular/core';
|
|
199
|
+
import { Store } from '@ngrx/store';
|
|
200
|
+
import { startStream, setConfig, setOrchestrationContext, disconnectStream, selectTotalProgress, selectShowLoader, unrealFeature } from '@3dsource/angular-unreal-module';
|
|
201
|
+
|
|
202
|
+
// Dispatch actions
|
|
203
|
+
const store = inject(Store);
|
|
204
|
+
store.dispatch(startStream({ config: { autoStart: true, warnTimeout: 120 } }));
|
|
205
|
+
|
|
206
|
+
// Select state
|
|
207
|
+
const progress = store.selectSignal(selectTotalProgress);
|
|
208
|
+
const isVideoPlaying = store.selectSignal(unrealFeature.selectIsVideoPlaying);
|
|
209
|
+
const dataChannelConnected = store.selectSignal(unrealFeature.selectDataChannelConnected);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Key selectors:**
|
|
213
|
+
|
|
214
|
+
- `selectTotalProgress` — Scene load progress (0–1 float)
|
|
215
|
+
- `selectShowLoader` — Whether loader screen should be visible
|
|
216
|
+
- `selectShowReconnectPopup` — Whether reconnect popup should be shown
|
|
217
|
+
- `selectIsVideoPlayingAndDataChannelConnected` — Combined readiness check
|
|
218
|
+
- `selectStreamConfig` — Current stream configuration
|
|
219
|
+
- `unrealFeature.selectCirrusConnected` — Signalling server connection status
|
|
220
|
+
- `unrealFeature.selectDataChannelConnected` — Data channel status
|
|
221
|
+
- `unrealFeature.selectViewportReady` — Viewport readiness
|
|
222
|
+
|
|
223
|
+
**Key actions:**
|
|
224
|
+
|
|
225
|
+
- `startStream` — Start streaming with config
|
|
226
|
+
- `setConfig` — Update stream configuration
|
|
227
|
+
- `setOrchestrationContext` — Set orchestration URLs and environment
|
|
228
|
+
- `disconnectStream` — Disconnect with reason
|
|
229
|
+
- `destroyUnrealScene` — Full teardown
|
|
230
|
+
- `reconnectPeer` — Trigger peer reconnection
|
|
231
|
+
|
|
232
|
+
## Exported API
|
|
233
|
+
|
|
234
|
+
### Components
|
|
235
|
+
|
|
236
|
+
| Component | Selector | Description |
|
|
237
|
+
| -------------------------------- | ------------------ | -------------------------------------- |
|
|
238
|
+
| `UnrealSceneComponent` | `app-unreal-scene` | Main scene container with video stream |
|
|
239
|
+
| `AfkTimeoutModalComponent` | — | AFK timeout warning modal |
|
|
240
|
+
| `FreezeFrameComponent` | — | Freeze frame overlay |
|
|
241
|
+
| `LowBandwidthModalComponent` | — | Low bandwidth warning modal |
|
|
242
|
+
| `LowBandwidthIndicatorComponent` | — | Low bandwidth indicator |
|
|
243
|
+
| `ImageLoadingSrcComponent` | — | Loading image overlay |
|
|
244
|
+
| `IntroSrcComponent` | — | Intro image/video overlay |
|
|
245
|
+
| `VideoStatsComponent` | — | Video statistics display |
|
|
246
|
+
| `StatGraphComponent` | — | Statistics graph |
|
|
247
|
+
| `WebrtcErrorModalComponent` | — | WebRTC error modal |
|
|
248
|
+
|
|
249
|
+
### Services
|
|
250
|
+
|
|
251
|
+
| Service | Description |
|
|
252
|
+
| ------------------------------ | ---------------------------------------------- |
|
|
253
|
+
| `UnrealCommunicatorService` | Send commands and UI interactions to Unreal |
|
|
254
|
+
| `AggregatorService` | Aggregates data channel messages from Unreal |
|
|
255
|
+
| `SignallingService` | Manages WebSocket signalling connection |
|
|
256
|
+
| `VideoService` | Manages video element and stats |
|
|
257
|
+
| `WebRtcPlayerService` | Manages WebRTC peer connection |
|
|
258
|
+
| `FreezeFrameService` | Handles freeze frame images |
|
|
259
|
+
| `AFKService` | AFK (away from keyboard) detection and timeout |
|
|
260
|
+
| `DevModeService` | Toggle dev mode for debugging |
|
|
261
|
+
| `FileReceiverService` | Receives files from Unreal via data channel |
|
|
262
|
+
| `FileHandlerService` | Processes received files |
|
|
263
|
+
| `RegionsPingService` | Pings regions to determine latency |
|
|
264
|
+
| `CommandTelemetryService` | Records command telemetry |
|
|
265
|
+
| `StreamStatusTelemetryService` | Reports stream status telemetry |
|
|
266
|
+
| `AnalyticsService` | Analytics event tracking |
|
|
267
|
+
| `FpsMonitorService` | FPS monitoring |
|
|
268
|
+
|
|
269
|
+
### Pipes
|
|
270
|
+
|
|
271
|
+
| Pipe | Description |
|
|
272
|
+
| -------------- | ------------------------------- |
|
|
273
|
+
| `SafeHtmlPipe` | Bypasses Angular HTML sanitizer |
|
|
274
|
+
|
|
275
|
+
### Interfaces
|
|
276
|
+
|
|
277
|
+
| Interface | Description |
|
|
278
|
+
| ----------------------- | --------------------------------------------- |
|
|
279
|
+
| `UnrealInitialConfig` | Shape for `UNREAL_CONFIG` injection token |
|
|
280
|
+
| `ReconnectConfig` | Auto-reconnection behavior configuration |
|
|
281
|
+
| `StreamConfig` | Stream configuration (autoStart, warnTimeout) |
|
|
282
|
+
| `StreamResolutionProps` | Stream resolution width/height |
|
|
283
|
+
|
|
150
284
|
## Features
|
|
151
285
|
|
|
152
286
|
- Standalone Unreal Scene Component
|
|
153
|
-
- Command and UI Interaction API via UnrealCommunicatorService
|
|
154
|
-
- Event-driven status UI (freeze frame, video stats, play overlay)
|
|
287
|
+
- Command and UI Interaction API via `UnrealCommunicatorService`
|
|
288
|
+
- Event-driven status UI (freeze frame, video stats, play overlay, AFK, low bandwidth)
|
|
155
289
|
- NgRx-powered state management and effects
|
|
156
|
-
-
|
|
290
|
+
- **Required** initial configuration via `UNREAL_CONFIG` injection token
|
|
291
|
+
- Auto-reconnection on WebRTC/DataChannel failures (configurable)
|
|
292
|
+
- File receiving from Unreal Engine via data channel
|
|
293
|
+
- Analytics and FPS monitoring
|
|
294
|
+
- Playwright testing mode with mock service substitution
|
|
157
295
|
|
|
158
296
|
## Examples
|
|
159
297
|
|
|
@@ -163,6 +301,8 @@ Check the demo application for complete usage examples:
|
|
|
163
301
|
npm run demo:start
|
|
164
302
|
```
|
|
165
303
|
|
|
304
|
+
See also: `projects/demo/src/app/demo-layout/info-pages/unreal-scene-demo/constants/unreal.routes.ts` for a real-world provider configuration example.
|
|
305
|
+
|
|
166
306
|
## Engine requirements
|
|
167
307
|
|
|
168
308
|
- Node.js: >=20
|