@babylonjs/inspector 9.3.0 → 9.3.2
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/bin/inspector-bridge.mjs +11 -2
- package/bin/inspector-cli.mjs +19 -31
- package/lib/{extensionsListService-DPHWDyzb.js → extensionsListService-0lDnbVBc.js} +2 -2
- package/lib/{extensionsListService-DPHWDyzb.js.map → extensionsListService-0lDnbVBc.js.map} +1 -1
- package/lib/{index-BaFR1FRV.js → index-DYOMPcC7.js} +343 -301
- package/lib/index-DYOMPcC7.js.map +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/inspectable.d.ts +20 -23
- package/lib/inspector.d.ts +7 -2
- package/lib/{quickCreateToolsService-DJ1GVvH-.js → quickCreateToolsService-7_2Rei48.js} +2 -2
- package/lib/{quickCreateToolsService-DJ1GVvH-.js.map → quickCreateToolsService-7_2Rei48.js.map} +1 -1
- package/lib/{reflectorService-Cd41l6Tr.js → reflectorService-DiamgYXJ.js} +2 -2
- package/lib/{reflectorService-Cd41l6Tr.js.map → reflectorService-DiamgYXJ.js.map} +1 -1
- package/lib/services/cli/entityQueryService.d.ts +2 -2
- package/lib/services/cli/perfTraceCommandService.d.ts +2 -2
- package/lib/services/cli/screenshotCommandService.d.ts +2 -2
- package/lib/services/cli/shaderCommandService.d.ts +2 -2
- package/lib/services/cli/statsCommandService.d.ts +2 -2
- package/lib/services/cliConnectionStatusService.d.ts +1 -1
- package/package.json +1 -1
- package/readme.md +1 -1
- package/lib/cli/protocol.d.ts +0 -202
- package/lib/index-BaFR1FRV.js.map +0 -1
- package/lib/services/cli/cliConnectionStatus.d.ts +0 -25
- package/lib/services/cli/inspectableBridgeService.d.ts +0 -28
- package/lib/services/cli/inspectableCommandRegistry.d.ts +0 -69
|
@@ -8034,7 +8034,7 @@ class ExtensionManager {
|
|
|
8034
8034
|
// Register the ServiceDefinitions.
|
|
8035
8035
|
let servicesRegistrationToken = null;
|
|
8036
8036
|
if (installedExtension.extensionModule.default.serviceDefinitions) {
|
|
8037
|
-
servicesRegistrationToken =
|
|
8037
|
+
servicesRegistrationToken = this._serviceContainer.addServices(...installedExtension.extensionModule.default.serviceDefinitions);
|
|
8038
8038
|
}
|
|
8039
8039
|
// Create a registration token to for dispose.
|
|
8040
8040
|
installedExtension.registrationToken = {
|
|
@@ -8155,17 +8155,15 @@ class ServiceContainer {
|
|
|
8155
8155
|
_parent?._children.add(this);
|
|
8156
8156
|
}
|
|
8157
8157
|
/**
|
|
8158
|
-
* Adds a set of service definitions
|
|
8158
|
+
* Adds a set of service definitions to the service container.
|
|
8159
8159
|
* The services are sorted based on their dependencies.
|
|
8160
|
-
* @param
|
|
8161
|
-
* @returns A disposable that will remove the service
|
|
8160
|
+
* @param serviceDefinitions The service definitions to register.
|
|
8161
|
+
* @returns A disposable that will remove the service definitions from the service container.
|
|
8162
8162
|
*/
|
|
8163
|
-
|
|
8163
|
+
addServices(...serviceDefinitions) {
|
|
8164
8164
|
if (this._isDisposed) {
|
|
8165
8165
|
throw new Error("ServiceContainer is disposed.");
|
|
8166
8166
|
}
|
|
8167
|
-
const abortSignal = args[args.length - 1] instanceof AbortSignal ? args.pop() : undefined;
|
|
8168
|
-
const serviceDefinitions = args;
|
|
8169
8167
|
const sortedServiceDefinitions = SortServiceDefinitions(serviceDefinitions);
|
|
8170
8168
|
const dispose = () => {
|
|
8171
8169
|
for (const serviceDefinition of sortedServiceDefinitions.reverse()) {
|
|
@@ -8174,9 +8172,7 @@ class ServiceContainer {
|
|
|
8174
8172
|
};
|
|
8175
8173
|
try {
|
|
8176
8174
|
for (const serviceDefinition of sortedServiceDefinitions) {
|
|
8177
|
-
|
|
8178
|
-
// eslint-disable-next-line no-await-in-loop
|
|
8179
|
-
await this._addServiceAsync(serviceDefinition, abortSignal);
|
|
8175
|
+
this._addService(serviceDefinition);
|
|
8180
8176
|
}
|
|
8181
8177
|
}
|
|
8182
8178
|
catch (error) {
|
|
@@ -8190,18 +8186,12 @@ class ServiceContainer {
|
|
|
8190
8186
|
/**
|
|
8191
8187
|
* Registers a service definition in the service container.
|
|
8192
8188
|
* @param serviceDefinition The service definition to register.
|
|
8193
|
-
* @param abortSignal An optional abort signal.
|
|
8194
8189
|
* @returns A disposable that will remove the service definition from the service container.
|
|
8195
8190
|
*/
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
return await this.addServicesAsync(serviceDefinition, abortSignal);
|
|
8199
|
-
}
|
|
8200
|
-
else {
|
|
8201
|
-
return await this.addServicesAsync(serviceDefinition);
|
|
8202
|
-
}
|
|
8191
|
+
addService(serviceDefinition) {
|
|
8192
|
+
return this.addServices(serviceDefinition);
|
|
8203
8193
|
}
|
|
8204
|
-
|
|
8194
|
+
_addService(service) {
|
|
8205
8195
|
if (this._isDisposed) {
|
|
8206
8196
|
throw new Error(`'${this._friendlyName}' container is disposed.`);
|
|
8207
8197
|
}
|
|
@@ -8214,7 +8204,7 @@ class ServiceContainer {
|
|
|
8214
8204
|
this._serviceDefinitions.set(contract, service);
|
|
8215
8205
|
});
|
|
8216
8206
|
const dependencies = service.consumes?.map((contract) => this._resolveDependency(contract, service)) ?? [];
|
|
8217
|
-
this._serviceInstances.set(service,
|
|
8207
|
+
this._serviceInstances.set(service, service.factory(...dependencies));
|
|
8218
8208
|
}
|
|
8219
8209
|
/**
|
|
8220
8210
|
* Resolves a dependency by contract identity for a consuming service.
|
|
@@ -8227,15 +8217,15 @@ class ServiceContainer {
|
|
|
8227
8217
|
_resolveDependency(contract, consumer) {
|
|
8228
8218
|
const definition = this._serviceDefinitions.get(contract);
|
|
8229
8219
|
if (definition) {
|
|
8220
|
+
const instance = this._serviceInstances.get(definition);
|
|
8221
|
+
if (!instance) {
|
|
8222
|
+
throw new Error(`Service '${contract.toString()}' has not been instantiated in the '${this._friendlyName}' container.`);
|
|
8223
|
+
}
|
|
8230
8224
|
let dependentDefinitions = this._serviceDependents.get(definition);
|
|
8231
8225
|
if (!dependentDefinitions) {
|
|
8232
8226
|
this._serviceDependents.set(definition, (dependentDefinitions = new Set()));
|
|
8233
8227
|
}
|
|
8234
8228
|
dependentDefinitions.add(consumer);
|
|
8235
|
-
const instance = this._serviceInstances.get(definition);
|
|
8236
|
-
if (!instance) {
|
|
8237
|
-
throw new Error(`Service '${contract.toString()}' has not been instantiated in the '${this._friendlyName}' container.`);
|
|
8238
|
-
}
|
|
8239
8229
|
return instance;
|
|
8240
8230
|
}
|
|
8241
8231
|
if (this._parent) {
|
|
@@ -8389,6 +8379,8 @@ function MakeModularTool(options) {
|
|
|
8389
8379
|
if (themeMode) {
|
|
8390
8380
|
settingsStore.writeSetting(ThemeModeSettingDescriptor, themeMode);
|
|
8391
8381
|
}
|
|
8382
|
+
// This deferred resolves once the React effect cleanup (which disposes the ServiceContainer) is complete.
|
|
8383
|
+
const disposeDeferred = new Deferred();
|
|
8392
8384
|
const modularToolRootComponent = () => {
|
|
8393
8385
|
const classes = useStyles$H();
|
|
8394
8386
|
const [extensionManagerContext, setExtensionManagerContext] = useState();
|
|
@@ -8421,13 +8413,13 @@ function MakeModularTool(options) {
|
|
|
8421
8413
|
const initializeExtensionManagerAsync = async () => {
|
|
8422
8414
|
const serviceContainer = new ServiceContainer("ModularToolContainer", parentContainer);
|
|
8423
8415
|
// Expose the settings store as a service so other services can read/write settings.
|
|
8424
|
-
|
|
8416
|
+
serviceContainer.addService({
|
|
8425
8417
|
friendlyName: "Settings Store",
|
|
8426
8418
|
produces: [SettingsStoreIdentity],
|
|
8427
8419
|
factory: () => settingsStore,
|
|
8428
8420
|
});
|
|
8429
8421
|
// Expose the react context service so other services can add React context providers.
|
|
8430
|
-
|
|
8422
|
+
serviceContainer.addService({
|
|
8431
8423
|
friendlyName: "React Context Service",
|
|
8432
8424
|
produces: [ReactContextServiceIdentity],
|
|
8433
8425
|
factory: () => ({
|
|
@@ -8446,7 +8438,7 @@ function MakeModularTool(options) {
|
|
|
8446
8438
|
}),
|
|
8447
8439
|
});
|
|
8448
8440
|
// Expose the toast service so non-React code (e.g. Observable callbacks) can show toasts.
|
|
8449
|
-
|
|
8441
|
+
serviceContainer.addService({
|
|
8450
8442
|
friendlyName: "Toast Service",
|
|
8451
8443
|
produces: [ToastServiceIdentity],
|
|
8452
8444
|
factory: () => ({
|
|
@@ -8456,9 +8448,9 @@ function MakeModularTool(options) {
|
|
|
8456
8448
|
}),
|
|
8457
8449
|
});
|
|
8458
8450
|
// Register the shell service (top level toolbar/side pane UI layout).
|
|
8459
|
-
|
|
8451
|
+
serviceContainer.addService(MakeShellServiceDefinition(options));
|
|
8460
8452
|
// Register a service that simply consumes the services we need before first render.
|
|
8461
|
-
|
|
8453
|
+
serviceContainer.addService({
|
|
8462
8454
|
friendlyName: "Service Bootstrapper",
|
|
8463
8455
|
consumes: [RootComponentServiceIdentity],
|
|
8464
8456
|
factory: (rootComponent) => {
|
|
@@ -8470,18 +8462,18 @@ function MakeModularTool(options) {
|
|
|
8470
8462
|
},
|
|
8471
8463
|
});
|
|
8472
8464
|
// Register the theme service (exposes the current theme to other services).
|
|
8473
|
-
|
|
8465
|
+
serviceContainer.addService(ThemeServiceDefinition);
|
|
8474
8466
|
// Register the theme selector service (for selecting the theme) if theming is configured.
|
|
8475
8467
|
if (showThemeSelector) {
|
|
8476
|
-
|
|
8468
|
+
serviceContainer.addService(ThemeSelectorServiceDefinition);
|
|
8477
8469
|
}
|
|
8478
8470
|
// Register the extension list service (for browsing/installing extensions) if extension feeds are provided.
|
|
8479
8471
|
if (extensionFeeds.length > 0) {
|
|
8480
|
-
const { ExtensionListServiceDefinition } = await import('./extensionsListService-
|
|
8481
|
-
|
|
8472
|
+
const { ExtensionListServiceDefinition } = await import('./extensionsListService-0lDnbVBc.js');
|
|
8473
|
+
serviceContainer.addService(ExtensionListServiceDefinition);
|
|
8482
8474
|
}
|
|
8483
8475
|
// Register all external services (that make up a unique tool).
|
|
8484
|
-
|
|
8476
|
+
serviceContainer.addServices(...serviceDefinitions);
|
|
8485
8477
|
// Create the extension manager, passing along the registry for runtime changes to the registered services.
|
|
8486
8478
|
const extensionManager = await ExtensionManager.CreateAsync(namespace, serviceContainer, extensionFeeds, setExtensionInstallError);
|
|
8487
8479
|
// Check query params for required extensions. This lets users share links with sets of extensions.
|
|
@@ -8529,7 +8521,8 @@ function MakeModularTool(options) {
|
|
|
8529
8521
|
// eslint-disable-next-line github/no-then
|
|
8530
8522
|
.catch((error) => {
|
|
8531
8523
|
Logger.Error(`Failed to dispose of the modular tool: ${error}`);
|
|
8532
|
-
})
|
|
8524
|
+
})
|
|
8525
|
+
.finally(() => disposeDeferred.resolve());
|
|
8533
8526
|
};
|
|
8534
8527
|
}, []);
|
|
8535
8528
|
const onAcceptRequiredExtensions = useCallback(() => {
|
|
@@ -8561,6 +8554,7 @@ function MakeModularTool(options) {
|
|
|
8561
8554
|
reactRoot.render(createElement(modularToolRootComponent));
|
|
8562
8555
|
let disposed = false;
|
|
8563
8556
|
return {
|
|
8557
|
+
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
8564
8558
|
dispose: () => {
|
|
8565
8559
|
// Unmount and restore the original container element display.
|
|
8566
8560
|
if (!disposed) {
|
|
@@ -8568,6 +8562,9 @@ function MakeModularTool(options) {
|
|
|
8568
8562
|
reactRoot.unmount();
|
|
8569
8563
|
containerElement.style.display = originalContainerElementDisplay;
|
|
8570
8564
|
}
|
|
8565
|
+
// The promise resolves once the React effect cleanup
|
|
8566
|
+
// (which disposes the ServiceContainer) has completed.
|
|
8567
|
+
return disposeDeferred.promise;
|
|
8571
8568
|
},
|
|
8572
8569
|
};
|
|
8573
8570
|
}
|
|
@@ -8593,21 +8590,270 @@ const DefaultInspectorExtensionFeed = new BuiltInsExtensionFeed("Inspector", [
|
|
|
8593
8590
|
description: "Adds a new panel for easy creation of various Babylon assets. This is a WIP extension...expect changes!",
|
|
8594
8591
|
keywords: ["creation", "tools"],
|
|
8595
8592
|
...BabylonWebResources,
|
|
8596
|
-
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-
|
|
8593
|
+
getExtensionModuleAsync: async () => await import('./quickCreateToolsService-7_2Rei48.js'),
|
|
8597
8594
|
},
|
|
8598
8595
|
{
|
|
8599
8596
|
name: "Reflector",
|
|
8600
8597
|
description: "Connects to the Reflector Bridge for real-time scene synchronization with the Babylon.js Sandbox.",
|
|
8601
8598
|
keywords: ["reflector", "bridge", "sync", "sandbox", "tools"],
|
|
8602
8599
|
...BabylonWebResources,
|
|
8603
|
-
getExtensionModuleAsync: async () => await import('./reflectorService-
|
|
8600
|
+
getExtensionModuleAsync: async () => await import('./reflectorService-DiamgYXJ.js'),
|
|
8604
8601
|
},
|
|
8605
8602
|
]);
|
|
8606
8603
|
|
|
8607
8604
|
/**
|
|
8608
|
-
* The service identity for the
|
|
8605
|
+
* The service identity for the CLI connection status.
|
|
8606
|
+
* @experimental
|
|
8607
|
+
* @internal
|
|
8608
|
+
*/
|
|
8609
|
+
const CliConnectionStatusIdentity = Symbol("CliConnectionStatus");
|
|
8610
|
+
|
|
8611
|
+
/**
|
|
8612
|
+
* The service identity for the bridge command registry.
|
|
8613
|
+
* @experimental
|
|
8614
|
+
* @internal
|
|
8615
|
+
*/
|
|
8616
|
+
const BridgeCommandRegistryIdentity = Symbol("BridgeCommandRegistry");
|
|
8617
|
+
|
|
8618
|
+
/**
|
|
8619
|
+
* Creates the service definition for the CLI Bridge Service.
|
|
8620
|
+
* @param options The options for connecting to the bridge.
|
|
8621
|
+
* @returns A service definition that produces an IBridgeCommandRegistry and ICliConnectionStatus.
|
|
8622
|
+
* @experimental
|
|
8623
|
+
* @internal
|
|
8609
8624
|
*/
|
|
8610
|
-
|
|
8625
|
+
function MakeBridgeServiceDefinition(options) {
|
|
8626
|
+
return {
|
|
8627
|
+
friendlyName: "CLI Bridge Service",
|
|
8628
|
+
produces: [BridgeCommandRegistryIdentity, CliConnectionStatusIdentity],
|
|
8629
|
+
factory: () => {
|
|
8630
|
+
const commands = new Map();
|
|
8631
|
+
let ws = null;
|
|
8632
|
+
let reconnectTimer = null;
|
|
8633
|
+
let disposed = false;
|
|
8634
|
+
let enabled = options.autoEnable;
|
|
8635
|
+
let connected = false;
|
|
8636
|
+
const onConnectionStatusChanged = new Observable();
|
|
8637
|
+
function notifyStatusChanged() {
|
|
8638
|
+
onConnectionStatusChanged.notifyObservers();
|
|
8639
|
+
}
|
|
8640
|
+
function setConnected(value) {
|
|
8641
|
+
if (connected !== value) {
|
|
8642
|
+
connected = value;
|
|
8643
|
+
notifyStatusChanged();
|
|
8644
|
+
}
|
|
8645
|
+
}
|
|
8646
|
+
function sendToBridge(message) {
|
|
8647
|
+
ws?.send(JSON.stringify(message));
|
|
8648
|
+
}
|
|
8649
|
+
function connect() {
|
|
8650
|
+
if (disposed || !enabled) {
|
|
8651
|
+
return;
|
|
8652
|
+
}
|
|
8653
|
+
// Close any existing WebSocket to avoid orphaned connections that
|
|
8654
|
+
// keep a stale session alive on the bridge.
|
|
8655
|
+
if (ws) {
|
|
8656
|
+
const oldWs = ws;
|
|
8657
|
+
oldWs.onopen = null;
|
|
8658
|
+
oldWs.onclose = null;
|
|
8659
|
+
oldWs.onmessage = null;
|
|
8660
|
+
oldWs.onerror = null;
|
|
8661
|
+
oldWs.close();
|
|
8662
|
+
ws = null;
|
|
8663
|
+
}
|
|
8664
|
+
try {
|
|
8665
|
+
// NOTE: The browser unconditionally logs a console error for failed WebSocket
|
|
8666
|
+
// connections at the network level. This cannot be suppressed from JavaScript.
|
|
8667
|
+
ws = new WebSocket(`ws://127.0.0.1:${options.port}`);
|
|
8668
|
+
}
|
|
8669
|
+
catch {
|
|
8670
|
+
ws = null;
|
|
8671
|
+
setConnected(false);
|
|
8672
|
+
Logger.Warn(`CLIBridgeService: Failed to create WebSocket connection on port ${options.port}.`);
|
|
8673
|
+
scheduleReconnect();
|
|
8674
|
+
return;
|
|
8675
|
+
}
|
|
8676
|
+
ws.onopen = () => {
|
|
8677
|
+
setConnected(true);
|
|
8678
|
+
sendToBridge({ type: "register", name: options.name });
|
|
8679
|
+
};
|
|
8680
|
+
ws.onmessage = (event) => {
|
|
8681
|
+
try {
|
|
8682
|
+
const message = JSON.parse(event.data);
|
|
8683
|
+
void handleMessage(message);
|
|
8684
|
+
}
|
|
8685
|
+
catch {
|
|
8686
|
+
Logger.Warn("CLIBridgeService: Failed to parse message from bridge.");
|
|
8687
|
+
}
|
|
8688
|
+
};
|
|
8689
|
+
ws.onclose = () => {
|
|
8690
|
+
ws = null;
|
|
8691
|
+
setConnected(false);
|
|
8692
|
+
scheduleReconnect();
|
|
8693
|
+
};
|
|
8694
|
+
ws.onerror = () => {
|
|
8695
|
+
// onclose will fire after onerror, which handles reconnection.
|
|
8696
|
+
};
|
|
8697
|
+
}
|
|
8698
|
+
function disconnect() {
|
|
8699
|
+
if (reconnectTimer !== null) {
|
|
8700
|
+
clearTimeout(reconnectTimer);
|
|
8701
|
+
reconnectTimer = null;
|
|
8702
|
+
}
|
|
8703
|
+
if (ws) {
|
|
8704
|
+
ws.onclose = null;
|
|
8705
|
+
ws.close();
|
|
8706
|
+
ws = null;
|
|
8707
|
+
}
|
|
8708
|
+
setConnected(false);
|
|
8709
|
+
}
|
|
8710
|
+
function scheduleReconnect() {
|
|
8711
|
+
if (disposed || !enabled || reconnectTimer !== null) {
|
|
8712
|
+
return;
|
|
8713
|
+
}
|
|
8714
|
+
reconnectTimer = setTimeout(() => {
|
|
8715
|
+
reconnectTimer = null;
|
|
8716
|
+
connect();
|
|
8717
|
+
}, 3000);
|
|
8718
|
+
}
|
|
8719
|
+
async function handleMessage(message) {
|
|
8720
|
+
switch (message.type) {
|
|
8721
|
+
case "listCommands": {
|
|
8722
|
+
const commandList = Array.from(commands.values()).map((cmd) => ({
|
|
8723
|
+
id: cmd.id,
|
|
8724
|
+
description: cmd.description,
|
|
8725
|
+
args: cmd.args,
|
|
8726
|
+
}));
|
|
8727
|
+
sendToBridge({
|
|
8728
|
+
type: "commandListResponse",
|
|
8729
|
+
requestId: message.requestId,
|
|
8730
|
+
commands: commandList,
|
|
8731
|
+
});
|
|
8732
|
+
break;
|
|
8733
|
+
}
|
|
8734
|
+
case "getInfo": {
|
|
8735
|
+
sendToBridge({
|
|
8736
|
+
type: "infoResponse",
|
|
8737
|
+
requestId: message.requestId,
|
|
8738
|
+
name: options.name,
|
|
8739
|
+
});
|
|
8740
|
+
break;
|
|
8741
|
+
}
|
|
8742
|
+
case "execCommand": {
|
|
8743
|
+
const command = commands.get(message.commandId);
|
|
8744
|
+
if (!command) {
|
|
8745
|
+
sendToBridge({
|
|
8746
|
+
type: "commandResponse",
|
|
8747
|
+
requestId: message.requestId,
|
|
8748
|
+
error: `Unknown command: ${message.commandId}`,
|
|
8749
|
+
});
|
|
8750
|
+
break;
|
|
8751
|
+
}
|
|
8752
|
+
try {
|
|
8753
|
+
const result = await command.executeAsync(message.args);
|
|
8754
|
+
sendToBridge({
|
|
8755
|
+
type: "commandResponse",
|
|
8756
|
+
requestId: message.requestId,
|
|
8757
|
+
result,
|
|
8758
|
+
});
|
|
8759
|
+
}
|
|
8760
|
+
catch (error) {
|
|
8761
|
+
sendToBridge({
|
|
8762
|
+
type: "commandResponse",
|
|
8763
|
+
requestId: message.requestId,
|
|
8764
|
+
error: String(error),
|
|
8765
|
+
});
|
|
8766
|
+
}
|
|
8767
|
+
break;
|
|
8768
|
+
}
|
|
8769
|
+
}
|
|
8770
|
+
}
|
|
8771
|
+
if (enabled) {
|
|
8772
|
+
connect();
|
|
8773
|
+
}
|
|
8774
|
+
const registry = {
|
|
8775
|
+
addCommand(descriptor) {
|
|
8776
|
+
if (commands.has(descriptor.id)) {
|
|
8777
|
+
throw new Error(`Command '${descriptor.id}' is already registered.`);
|
|
8778
|
+
}
|
|
8779
|
+
commands.set(descriptor.id, descriptor);
|
|
8780
|
+
return {
|
|
8781
|
+
dispose: () => {
|
|
8782
|
+
commands.delete(descriptor.id);
|
|
8783
|
+
},
|
|
8784
|
+
};
|
|
8785
|
+
},
|
|
8786
|
+
get isEnabled() {
|
|
8787
|
+
return enabled;
|
|
8788
|
+
},
|
|
8789
|
+
set isEnabled(value) {
|
|
8790
|
+
if (enabled !== value) {
|
|
8791
|
+
enabled = value;
|
|
8792
|
+
if (enabled) {
|
|
8793
|
+
connect();
|
|
8794
|
+
}
|
|
8795
|
+
else {
|
|
8796
|
+
disconnect();
|
|
8797
|
+
}
|
|
8798
|
+
notifyStatusChanged();
|
|
8799
|
+
}
|
|
8800
|
+
},
|
|
8801
|
+
get isConnected() {
|
|
8802
|
+
return connected;
|
|
8803
|
+
},
|
|
8804
|
+
onConnectionStatusChanged,
|
|
8805
|
+
dispose: () => {
|
|
8806
|
+
disposed = true;
|
|
8807
|
+
enabled = false;
|
|
8808
|
+
disconnect();
|
|
8809
|
+
commands.clear();
|
|
8810
|
+
onConnectionStatusChanged.clear();
|
|
8811
|
+
},
|
|
8812
|
+
};
|
|
8813
|
+
return registry;
|
|
8814
|
+
},
|
|
8815
|
+
};
|
|
8816
|
+
}
|
|
8817
|
+
|
|
8818
|
+
const DefaultPort$1 = 4400;
|
|
8819
|
+
/**
|
|
8820
|
+
* Creates a headless {@link ServiceContainer} that hosts a bridge service.
|
|
8821
|
+
*
|
|
8822
|
+
* The returned token owns the container. Dispose it to tear down the bridge.
|
|
8823
|
+
*
|
|
8824
|
+
* @param options Optional configuration for the bridge.
|
|
8825
|
+
* @returns A {@link ModularBridgeToken} that owns the container.
|
|
8826
|
+
* @experimental
|
|
8827
|
+
* @internal
|
|
8828
|
+
*/
|
|
8829
|
+
function MakeModularBridge(options) {
|
|
8830
|
+
const serviceContainer = new ServiceContainer("ModularBridgeContainer");
|
|
8831
|
+
const bridgeDefinition = MakeBridgeServiceDefinition({
|
|
8832
|
+
port: options?.port ?? DefaultPort$1,
|
|
8833
|
+
get name() {
|
|
8834
|
+
return options?.name ?? (typeof document !== "undefined" ? document.title : "Babylon.js Scene");
|
|
8835
|
+
},
|
|
8836
|
+
autoEnable: options?.autoEnable ?? true,
|
|
8837
|
+
});
|
|
8838
|
+
const allDefinitions = [bridgeDefinition];
|
|
8839
|
+
if (options?.serviceDefinitions) {
|
|
8840
|
+
allDefinitions.push(...options.serviceDefinitions);
|
|
8841
|
+
}
|
|
8842
|
+
serviceContainer.addServices(...allDefinitions);
|
|
8843
|
+
let disposed = false;
|
|
8844
|
+
return {
|
|
8845
|
+
get serviceContainer() {
|
|
8846
|
+
return serviceContainer;
|
|
8847
|
+
},
|
|
8848
|
+
get isDisposed() {
|
|
8849
|
+
return disposed;
|
|
8850
|
+
},
|
|
8851
|
+
dispose() {
|
|
8852
|
+
disposed = true;
|
|
8853
|
+
serviceContainer.dispose();
|
|
8854
|
+
},
|
|
8855
|
+
};
|
|
8856
|
+
}
|
|
8611
8857
|
|
|
8612
8858
|
const UniqueIdArg = {
|
|
8613
8859
|
name: "uniqueId",
|
|
@@ -8681,7 +8927,7 @@ function MakeQueryCommand(collection, sceneContext) {
|
|
|
8681
8927
|
*/
|
|
8682
8928
|
const EntityQueryServiceDefinition = {
|
|
8683
8929
|
friendlyName: "Entity Query Service",
|
|
8684
|
-
consumes: [
|
|
8930
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
8685
8931
|
factory: (commandRegistry, sceneContext) => {
|
|
8686
8932
|
const collections = [
|
|
8687
8933
|
{
|
|
@@ -8846,205 +9092,13 @@ const EntityQueryServiceDefinition = {
|
|
|
8846
9092
|
},
|
|
8847
9093
|
};
|
|
8848
9094
|
|
|
8849
|
-
/**
|
|
8850
|
-
* The service identity for the CLI connection status.
|
|
8851
|
-
*/
|
|
8852
|
-
const CliConnectionStatusIdentity = Symbol("CliConnectionStatus");
|
|
8853
|
-
|
|
8854
|
-
/**
|
|
8855
|
-
* Creates the service definition for the InspectableBridgeService.
|
|
8856
|
-
* @param options The options for connecting to the bridge.
|
|
8857
|
-
* @returns A service definition that produces an IInspectableCommandRegistry.
|
|
8858
|
-
*/
|
|
8859
|
-
function MakeInspectableBridgeServiceDefinition(options) {
|
|
8860
|
-
return {
|
|
8861
|
-
friendlyName: "Inspectable Bridge Service",
|
|
8862
|
-
produces: [InspectableCommandRegistryIdentity, CliConnectionStatusIdentity],
|
|
8863
|
-
factory: () => {
|
|
8864
|
-
const commands = new Map();
|
|
8865
|
-
let ws = null;
|
|
8866
|
-
let reconnectTimer = null;
|
|
8867
|
-
let disposed = false;
|
|
8868
|
-
let enabled = options.autoStart;
|
|
8869
|
-
let connected = false;
|
|
8870
|
-
const onConnectionStatusChanged = new Observable();
|
|
8871
|
-
function notifyStatusChanged() {
|
|
8872
|
-
onConnectionStatusChanged.notifyObservers();
|
|
8873
|
-
}
|
|
8874
|
-
function setConnected(value) {
|
|
8875
|
-
if (connected !== value) {
|
|
8876
|
-
connected = value;
|
|
8877
|
-
notifyStatusChanged();
|
|
8878
|
-
}
|
|
8879
|
-
}
|
|
8880
|
-
function sendToBridge(message) {
|
|
8881
|
-
ws?.send(JSON.stringify(message));
|
|
8882
|
-
}
|
|
8883
|
-
function connect() {
|
|
8884
|
-
if (disposed || !enabled) {
|
|
8885
|
-
return;
|
|
8886
|
-
}
|
|
8887
|
-
try {
|
|
8888
|
-
// NOTE: The browser unconditionally logs a console error for failed WebSocket
|
|
8889
|
-
// connections at the network level. This cannot be suppressed from JavaScript.
|
|
8890
|
-
ws = new WebSocket(`ws://127.0.0.1:${options.port}`);
|
|
8891
|
-
}
|
|
8892
|
-
catch {
|
|
8893
|
-
ws = null;
|
|
8894
|
-
setConnected(false);
|
|
8895
|
-
Logger.Warn(`InspectableBridgeService: Failed to create WebSocket connection on port ${options.port}.`);
|
|
8896
|
-
scheduleReconnect();
|
|
8897
|
-
return;
|
|
8898
|
-
}
|
|
8899
|
-
ws.onopen = () => {
|
|
8900
|
-
setConnected(true);
|
|
8901
|
-
sendToBridge({ type: "register", name: options.name });
|
|
8902
|
-
};
|
|
8903
|
-
ws.onmessage = (event) => {
|
|
8904
|
-
try {
|
|
8905
|
-
const message = JSON.parse(event.data);
|
|
8906
|
-
void handleMessage(message);
|
|
8907
|
-
}
|
|
8908
|
-
catch {
|
|
8909
|
-
Logger.Warn("InspectableBridgeService: Failed to parse message from bridge.");
|
|
8910
|
-
}
|
|
8911
|
-
};
|
|
8912
|
-
ws.onclose = () => {
|
|
8913
|
-
ws = null;
|
|
8914
|
-
setConnected(false);
|
|
8915
|
-
scheduleReconnect();
|
|
8916
|
-
};
|
|
8917
|
-
ws.onerror = () => {
|
|
8918
|
-
// onclose will fire after onerror, which handles reconnection.
|
|
8919
|
-
};
|
|
8920
|
-
}
|
|
8921
|
-
function disconnect() {
|
|
8922
|
-
if (reconnectTimer !== null) {
|
|
8923
|
-
clearTimeout(reconnectTimer);
|
|
8924
|
-
reconnectTimer = null;
|
|
8925
|
-
}
|
|
8926
|
-
if (ws) {
|
|
8927
|
-
ws.onclose = null;
|
|
8928
|
-
ws.close();
|
|
8929
|
-
ws = null;
|
|
8930
|
-
}
|
|
8931
|
-
setConnected(false);
|
|
8932
|
-
}
|
|
8933
|
-
function scheduleReconnect() {
|
|
8934
|
-
if (disposed || !enabled || reconnectTimer !== null) {
|
|
8935
|
-
return;
|
|
8936
|
-
}
|
|
8937
|
-
reconnectTimer = setTimeout(() => {
|
|
8938
|
-
reconnectTimer = null;
|
|
8939
|
-
connect();
|
|
8940
|
-
}, 3000);
|
|
8941
|
-
}
|
|
8942
|
-
async function handleMessage(message) {
|
|
8943
|
-
switch (message.type) {
|
|
8944
|
-
case "listCommands": {
|
|
8945
|
-
const commandList = Array.from(commands.values()).map((cmd) => ({
|
|
8946
|
-
id: cmd.id,
|
|
8947
|
-
description: cmd.description,
|
|
8948
|
-
args: cmd.args,
|
|
8949
|
-
}));
|
|
8950
|
-
sendToBridge({
|
|
8951
|
-
type: "commandListResponse",
|
|
8952
|
-
requestId: message.requestId,
|
|
8953
|
-
commands: commandList,
|
|
8954
|
-
});
|
|
8955
|
-
break;
|
|
8956
|
-
}
|
|
8957
|
-
case "getInfo": {
|
|
8958
|
-
sendToBridge({
|
|
8959
|
-
type: "infoResponse",
|
|
8960
|
-
requestId: message.requestId,
|
|
8961
|
-
name: options.name,
|
|
8962
|
-
});
|
|
8963
|
-
break;
|
|
8964
|
-
}
|
|
8965
|
-
case "execCommand": {
|
|
8966
|
-
const command = commands.get(message.commandId);
|
|
8967
|
-
if (!command) {
|
|
8968
|
-
sendToBridge({
|
|
8969
|
-
type: "commandResponse",
|
|
8970
|
-
requestId: message.requestId,
|
|
8971
|
-
error: `Unknown command: ${message.commandId}`,
|
|
8972
|
-
});
|
|
8973
|
-
break;
|
|
8974
|
-
}
|
|
8975
|
-
try {
|
|
8976
|
-
const result = await command.executeAsync(message.args);
|
|
8977
|
-
sendToBridge({
|
|
8978
|
-
type: "commandResponse",
|
|
8979
|
-
requestId: message.requestId,
|
|
8980
|
-
result,
|
|
8981
|
-
});
|
|
8982
|
-
}
|
|
8983
|
-
catch (error) {
|
|
8984
|
-
sendToBridge({
|
|
8985
|
-
type: "commandResponse",
|
|
8986
|
-
requestId: message.requestId,
|
|
8987
|
-
error: String(error),
|
|
8988
|
-
});
|
|
8989
|
-
}
|
|
8990
|
-
break;
|
|
8991
|
-
}
|
|
8992
|
-
}
|
|
8993
|
-
}
|
|
8994
|
-
if (enabled) {
|
|
8995
|
-
connect();
|
|
8996
|
-
}
|
|
8997
|
-
const registry = {
|
|
8998
|
-
addCommand(descriptor) {
|
|
8999
|
-
if (commands.has(descriptor.id)) {
|
|
9000
|
-
throw new Error(`Command '${descriptor.id}' is already registered.`);
|
|
9001
|
-
}
|
|
9002
|
-
commands.set(descriptor.id, descriptor);
|
|
9003
|
-
return {
|
|
9004
|
-
dispose: () => {
|
|
9005
|
-
commands.delete(descriptor.id);
|
|
9006
|
-
},
|
|
9007
|
-
};
|
|
9008
|
-
},
|
|
9009
|
-
get isEnabled() {
|
|
9010
|
-
return enabled;
|
|
9011
|
-
},
|
|
9012
|
-
set isEnabled(value) {
|
|
9013
|
-
if (enabled !== value) {
|
|
9014
|
-
enabled = value;
|
|
9015
|
-
if (enabled) {
|
|
9016
|
-
connect();
|
|
9017
|
-
}
|
|
9018
|
-
else {
|
|
9019
|
-
disconnect();
|
|
9020
|
-
}
|
|
9021
|
-
notifyStatusChanged();
|
|
9022
|
-
}
|
|
9023
|
-
},
|
|
9024
|
-
get isConnected() {
|
|
9025
|
-
return connected;
|
|
9026
|
-
},
|
|
9027
|
-
onConnectionStatusChanged,
|
|
9028
|
-
dispose: () => {
|
|
9029
|
-
disposed = true;
|
|
9030
|
-
enabled = false;
|
|
9031
|
-
disconnect();
|
|
9032
|
-
commands.clear();
|
|
9033
|
-
onConnectionStatusChanged.clear();
|
|
9034
|
-
},
|
|
9035
|
-
};
|
|
9036
|
-
return registry;
|
|
9037
|
-
},
|
|
9038
|
-
};
|
|
9039
|
-
}
|
|
9040
|
-
|
|
9041
9095
|
/**
|
|
9042
9096
|
* Service that registers CLI commands for performance tracing using the PerformanceViewerCollector.
|
|
9043
9097
|
* start-perf-trace begins collecting data, stop-perf-trace stops and returns the collected data as JSON.
|
|
9044
9098
|
*/
|
|
9045
9099
|
const PerfTraceCommandServiceDefinition = {
|
|
9046
9100
|
friendlyName: "Perf Trace Command Service",
|
|
9047
|
-
consumes: [
|
|
9101
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9048
9102
|
factory: (commandRegistry, sceneContext) => {
|
|
9049
9103
|
let perfCollector;
|
|
9050
9104
|
const startReg = commandRegistry.addCommand({
|
|
@@ -9111,7 +9165,7 @@ const PerfTraceCommandServiceDefinition = {
|
|
|
9111
9165
|
*/
|
|
9112
9166
|
const ScreenshotCommandServiceDefinition = {
|
|
9113
9167
|
friendlyName: "Screenshot Command Service",
|
|
9114
|
-
consumes: [
|
|
9168
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9115
9169
|
factory: (commandRegistry, sceneContext) => {
|
|
9116
9170
|
const registration = commandRegistry.addCommand({
|
|
9117
9171
|
id: "take-screenshot",
|
|
@@ -9201,7 +9255,7 @@ const ScreenshotCommandServiceDefinition = {
|
|
|
9201
9255
|
*/
|
|
9202
9256
|
const ShaderCommandServiceDefinition = {
|
|
9203
9257
|
friendlyName: "Shader Command Service",
|
|
9204
|
-
consumes: [
|
|
9258
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9205
9259
|
factory: (commandRegistry, sceneContext) => {
|
|
9206
9260
|
const registration = commandRegistry.addCommand({
|
|
9207
9261
|
id: "get-shader-code",
|
|
@@ -9273,7 +9327,7 @@ const ShaderCommandServiceDefinition = {
|
|
|
9273
9327
|
*/
|
|
9274
9328
|
const StatsCommandServiceDefinition = {
|
|
9275
9329
|
friendlyName: "Stats Command Service",
|
|
9276
|
-
consumes: [
|
|
9330
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9277
9331
|
factory: (commandRegistry, sceneContext) => {
|
|
9278
9332
|
let sceneInstrumentation;
|
|
9279
9333
|
let engineInstrumentation;
|
|
@@ -9439,15 +9493,32 @@ const InspectableStates = new Map();
|
|
|
9439
9493
|
function _StartInspectable(scene, options) {
|
|
9440
9494
|
let state = InspectableStates.get(scene);
|
|
9441
9495
|
if (!state) {
|
|
9442
|
-
const
|
|
9496
|
+
const disposeActions = [];
|
|
9497
|
+
// When a bridgeToken is provided, use its container as the parent and skip bridge creation.
|
|
9498
|
+
// When not, create an internal bridge container via MakeModularBridge.
|
|
9499
|
+
let bridgeToken;
|
|
9500
|
+
if (options?.bridgeToken) {
|
|
9501
|
+
bridgeToken = options.bridgeToken;
|
|
9502
|
+
}
|
|
9503
|
+
else {
|
|
9504
|
+
bridgeToken = MakeModularBridge({
|
|
9505
|
+
port: options?.port ?? DefaultPort,
|
|
9506
|
+
name: options?.name,
|
|
9507
|
+
autoEnable: options?.autoEnable,
|
|
9508
|
+
});
|
|
9509
|
+
disposeActions.push(() => bridgeToken.dispose());
|
|
9510
|
+
}
|
|
9511
|
+
const serviceContainer = new ServiceContainer("InspectableContainer", bridgeToken.serviceContainer);
|
|
9512
|
+
disposeActions.push(() => serviceContainer.dispose());
|
|
9443
9513
|
let fullyDisposed = false;
|
|
9444
9514
|
const fullyDispose = () => {
|
|
9445
9515
|
InspectableStates.delete(scene);
|
|
9446
9516
|
fullyDisposed = true;
|
|
9447
|
-
|
|
9448
|
-
|
|
9517
|
+
for (const action of disposeActions.reverse()) {
|
|
9518
|
+
action();
|
|
9519
|
+
}
|
|
9449
9520
|
};
|
|
9450
|
-
// Initialize the service container
|
|
9521
|
+
// Initialize the service container.
|
|
9451
9522
|
const sceneContextServiceDefinition = {
|
|
9452
9523
|
friendlyName: "Inspectable Scene Context",
|
|
9453
9524
|
produces: [SceneContextIdentity],
|
|
@@ -9456,46 +9527,25 @@ function _StartInspectable(scene, options) {
|
|
|
9456
9527
|
currentSceneObservable: new Observable(),
|
|
9457
9528
|
}),
|
|
9458
9529
|
};
|
|
9459
|
-
|
|
9460
|
-
await serviceContainer.addServicesAsync(sceneContextServiceDefinition, MakeInspectableBridgeServiceDefinition({
|
|
9461
|
-
port: options?.port ?? DefaultPort,
|
|
9462
|
-
get name() {
|
|
9463
|
-
return options?.name ?? (typeof document !== "undefined" ? document.title : "Babylon.js Scene");
|
|
9464
|
-
},
|
|
9465
|
-
autoStart: options?.autoStart ?? false,
|
|
9466
|
-
}), EntityQueryServiceDefinition, ScreenshotCommandServiceDefinition, ShaderCommandServiceDefinition, StatsCommandServiceDefinition, PerfTraceCommandServiceDefinition);
|
|
9467
|
-
})();
|
|
9530
|
+
serviceContainer.addServices(sceneContextServiceDefinition, EntityQueryServiceDefinition, ScreenshotCommandServiceDefinition, ShaderCommandServiceDefinition, StatsCommandServiceDefinition, PerfTraceCommandServiceDefinition);
|
|
9468
9531
|
state = {
|
|
9469
9532
|
refCount: 0,
|
|
9470
9533
|
get fullyDisposed() {
|
|
9471
9534
|
return fullyDisposed;
|
|
9472
9535
|
},
|
|
9473
9536
|
serviceContainer,
|
|
9474
|
-
sceneDisposeObserver: { remove: () => { } },
|
|
9475
9537
|
fullyDispose,
|
|
9476
|
-
readyPromise,
|
|
9477
9538
|
};
|
|
9478
9539
|
const capturedState = state;
|
|
9479
9540
|
InspectableStates.set(scene, state);
|
|
9480
|
-
// Auto-dispose when the scene is disposed.
|
|
9481
|
-
|
|
9541
|
+
// Auto-dispose when the scene is disposed. Use insertFirst so that
|
|
9542
|
+
// callbacks registered later (e.g. ShowInspector) fire before this one,
|
|
9543
|
+
// ensuring child containers are disposed before this parent container.
|
|
9544
|
+
const sceneDisposeObserver = scene.onDisposeObservable.add(() => {
|
|
9482
9545
|
capturedState.refCount = 0;
|
|
9483
9546
|
capturedState.fullyDispose();
|
|
9484
|
-
});
|
|
9485
|
-
|
|
9486
|
-
// Handle initialization failure (guard against already-disposed state).
|
|
9487
|
-
void (async () => {
|
|
9488
|
-
try {
|
|
9489
|
-
await readyPromise;
|
|
9490
|
-
}
|
|
9491
|
-
catch (error) {
|
|
9492
|
-
if (InspectableStates.has(scene)) {
|
|
9493
|
-
Logger.Error(`Failed to initialize Inspectable: ${error}`);
|
|
9494
|
-
capturedState.refCount = 0;
|
|
9495
|
-
capturedState.fullyDispose();
|
|
9496
|
-
}
|
|
9497
|
-
}
|
|
9498
|
-
})();
|
|
9547
|
+
}, undefined, true, undefined, true);
|
|
9548
|
+
disposeActions.push(() => sceneDisposeObserver.remove());
|
|
9499
9549
|
}
|
|
9500
9550
|
state.refCount++;
|
|
9501
9551
|
const { serviceContainer } = state;
|
|
@@ -9503,21 +9553,9 @@ function _StartInspectable(scene, options) {
|
|
|
9503
9553
|
// If additional service definitions were provided, add them in a separate call
|
|
9504
9554
|
// so they can be independently removed when this token is disposed.
|
|
9505
9555
|
let extraServicesDisposable;
|
|
9506
|
-
const extraAbortController = new AbortController();
|
|
9507
9556
|
const extraServiceDefinitions = options?.serviceDefinitions;
|
|
9508
9557
|
if (extraServiceDefinitions && extraServiceDefinitions.length > 0) {
|
|
9509
|
-
|
|
9510
|
-
void (async () => {
|
|
9511
|
-
try {
|
|
9512
|
-
await owningState.readyPromise;
|
|
9513
|
-
extraServicesDisposable = await serviceContainer.addServicesAsync(...extraServiceDefinitions, extraAbortController.signal);
|
|
9514
|
-
}
|
|
9515
|
-
catch (error) {
|
|
9516
|
-
if (!extraAbortController.signal.aborted) {
|
|
9517
|
-
Logger.Error(`Failed to add extra inspectable services: ${error}`);
|
|
9518
|
-
}
|
|
9519
|
-
}
|
|
9520
|
-
})();
|
|
9558
|
+
extraServicesDisposable = serviceContainer.addServices(...extraServiceDefinitions);
|
|
9521
9559
|
}
|
|
9522
9560
|
let disposed = false;
|
|
9523
9561
|
const token = {
|
|
@@ -9532,8 +9570,7 @@ function _StartInspectable(scene, options) {
|
|
|
9532
9570
|
return;
|
|
9533
9571
|
}
|
|
9534
9572
|
disposed = true;
|
|
9535
|
-
//
|
|
9536
|
-
extraAbortController.abort();
|
|
9573
|
+
// Remove extra services that were added for this token.
|
|
9537
9574
|
extraServicesDisposable?.dispose();
|
|
9538
9575
|
owningState.refCount--;
|
|
9539
9576
|
if (owningState.refCount <= 0) {
|
|
@@ -9545,9 +9582,12 @@ function _StartInspectable(scene, options) {
|
|
|
9545
9582
|
}
|
|
9546
9583
|
/**
|
|
9547
9584
|
* Makes a scene inspectable by connecting it to the Inspector CLI bridge.
|
|
9548
|
-
* This creates a headless {@link ServiceContainer} (no UI)
|
|
9549
|
-
*
|
|
9550
|
-
*
|
|
9585
|
+
* This creates a headless {@link ServiceContainer} (no UI) that registers
|
|
9586
|
+
* scene-specific CLI command services (entity query, screenshot, shader, stats, etc.).
|
|
9587
|
+
*
|
|
9588
|
+
* When {@link InspectableOptions.bridgeToken} is provided, the inspectable container
|
|
9589
|
+
* is created as a child of the CLI container, inheriting the bridge and command registry.
|
|
9590
|
+
* When not provided, a bridge container is created internally via {@link MakeModularBridge}.
|
|
9551
9591
|
*
|
|
9552
9592
|
* Multiple callers may call this for the same scene. Each returned token is
|
|
9553
9593
|
* ref-counted — the underlying connection is only torn down when all tokens
|
|
@@ -23225,7 +23265,7 @@ const InspectorLock = new AsyncLock();
|
|
|
23225
23265
|
*/
|
|
23226
23266
|
function ShowInspector(scene, options = {}) {
|
|
23227
23267
|
// Dispose of any existing inspector for this scene.
|
|
23228
|
-
InspectorTokens.get(scene)?.dispose();
|
|
23268
|
+
void InspectorTokens.get(scene)?.dispose();
|
|
23229
23269
|
// Default the dispose logic to a no-op until we know that we are actually going
|
|
23230
23270
|
// to show the Inspector and there will be cleanup work to do.
|
|
23231
23271
|
let disposeAsync = async () => await Promise.resolve();
|
|
@@ -23234,9 +23274,9 @@ function ShowInspector(scene, options = {}) {
|
|
|
23234
23274
|
let isDisposed = false;
|
|
23235
23275
|
const onDisposed = new Observable();
|
|
23236
23276
|
const inspectorToken = {
|
|
23237
|
-
|
|
23238
|
-
|
|
23239
|
-
InspectorLock.lockAsync(async () => {
|
|
23277
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
23278
|
+
async dispose() {
|
|
23279
|
+
await InspectorLock.lockAsync(async () => {
|
|
23240
23280
|
await disposeAsync();
|
|
23241
23281
|
isDisposed = true;
|
|
23242
23282
|
onDisposed.notifyObservers();
|
|
@@ -23258,9 +23298,9 @@ function ShowInspector(scene, options = {}) {
|
|
|
23258
23298
|
layoutMode: "overlay",
|
|
23259
23299
|
...options,
|
|
23260
23300
|
};
|
|
23261
|
-
// Sequentialize showing the inspector (e.g. don't start showing until after a previous hide
|
|
23301
|
+
// Sequentialize showing the inspector (e.g. don't start showing until after a previous hide is finished).
|
|
23262
23302
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
23263
|
-
InspectorLock.lockAsync(
|
|
23303
|
+
InspectorLock.lockAsync(() => {
|
|
23264
23304
|
let parentElement = options.containerElement ?? null;
|
|
23265
23305
|
// If a container element was not found, find an appropriate one above the engine's rendering canvas.
|
|
23266
23306
|
if (!parentElement) {
|
|
@@ -23320,8 +23360,8 @@ function ShowInspector(scene, options = {}) {
|
|
|
23320
23360
|
const serviceDefinitions = [];
|
|
23321
23361
|
// Ensure the inspectable bridge is running for this scene. The inspector's
|
|
23322
23362
|
// ServiceContainer will use the inspectable container as a parent, inheriting
|
|
23323
|
-
// services like ISceneContext and
|
|
23324
|
-
const inspectableToken = _StartInspectable(scene);
|
|
23363
|
+
// services like ISceneContext and IBridgeCommandRegistry.
|
|
23364
|
+
const inspectableToken = _StartInspectable(scene, { autoEnable: false });
|
|
23325
23365
|
disposeActions.push(() => inspectableToken.dispose());
|
|
23326
23366
|
// Create a container element for the inspector UI.
|
|
23327
23367
|
// This element will become the root React node, so it must be a new empty node
|
|
@@ -23431,10 +23471,12 @@ function ShowInspector(scene, options = {}) {
|
|
|
23431
23471
|
leftPaneDefaultCollapsed: options.leftPaneDefaultCollapsed,
|
|
23432
23472
|
rightPaneDefaultCollapsed: options.rightPaneDefaultCollapsed,
|
|
23433
23473
|
});
|
|
23434
|
-
disposeActions.push(() => modularTool.dispose());
|
|
23435
|
-
|
|
23436
|
-
|
|
23437
|
-
|
|
23474
|
+
disposeActions.push(async () => await modularTool.dispose());
|
|
23475
|
+
// Use insertFirst so this fires before StartInspectable's scene-dispose
|
|
23476
|
+
// callback, ensuring the UI child container is torn down first.
|
|
23477
|
+
const sceneDisposedObserver = scene.onDisposeObservable.add(() => {
|
|
23478
|
+
void inspectorToken.dispose();
|
|
23479
|
+
}, undefined, true, undefined, true);
|
|
23438
23480
|
disposeActions.push(() => sceneDisposedObserver.remove());
|
|
23439
23481
|
disposeActions.push(() => {
|
|
23440
23482
|
InspectorTokens.delete(scene);
|
|
@@ -23920,7 +23962,7 @@ class Inspector {
|
|
|
23920
23962
|
this._CurrentInstance.disposeToken.onDisposed.addOnce(() => (this._CurrentInstance = null));
|
|
23921
23963
|
}
|
|
23922
23964
|
static Hide() {
|
|
23923
|
-
this._CurrentInstance?.disposeToken.dispose();
|
|
23965
|
+
void this._CurrentInstance?.disposeToken.dispose();
|
|
23924
23966
|
}
|
|
23925
23967
|
// @ts-expect-error TS6133: This is private, but used by debugLayer (same as Inspector v1).
|
|
23926
23968
|
static _SetNewScene(scene) {
|
|
@@ -24251,5 +24293,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
24251
24293
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
24252
24294
|
AttachDebugLayer();
|
|
24253
24295
|
|
|
24254
|
-
export {
|
|
24255
|
-
//# sourceMappingURL=index-
|
|
24296
|
+
export { GetPropertyDescriptor as $, Accordion as A, Button as B, CheckboxPropertyLine as C, Color4PropertyLine as D, ColorPickerPopup as E, ColorStepGradientComponent as F, ComboBox as G, ComboBoxPropertyLine as H, ConstructorFactory as I, ConvertOptions as J, DebugServiceIdentity as K, Link as L, MessageBar as M, NumberInputPropertyLine as N, DetachDebugLayer as O, Popover as P, DraggableLine as Q, Dropdown as R, ShellServiceIdentity as S, TextInputPropertyLine as T, EntitySelector as U, Vector3PropertyLine as V, ErrorBoundary as W, ExtensibleAccordion as X, FactorGradientComponent as Y, FactorGradientList as Z, FileUploadLine as _, useToast as a, ThemeServiceIdentity as a$, GizmoServiceIdentity as a0, HexPropertyLine as a1, InfoLabel as a2, InputHexField as a3, InputHsvField as a4, Inspector as a5, InterceptFunction as a6, InterceptProperty as a7, IsPropertyReadonly as a8, LineContainer as a9, SearchBox as aA, SelectionServiceDefinition as aB, SettingsServiceIdentity as aC, SettingsStore as aD, SettingsStoreIdentity as aE, ShowInspector as aF, SidePaneContainer as aG, SkeletonSelector as aH, Slider as aI, SpinButton as aJ, StartInspectable as aK, StatsServiceIdentity as aL, StringDropdown as aM, StringDropdownPropertyLine as aN, StringifiedPropertyLine as aO, Switch as aP, SwitchPropertyLine as aQ, SyncedSliderInput as aR, SyncedSliderPropertyLine as aS, TeachingMoment as aT, TextAreaPropertyLine as aU, TextInput as aV, TextPropertyLine as aW, Textarea as aX, TextureSelector as aY, TextureUpload as aZ, Theme as a_, LinkPropertyLine as aa, LinkToEntityPropertyLine as ab, List as ac, MakeDialogTeachingMoment as ad, MakeLazyComponent as ae, MakeModularBridge as af, MakeModularTool as ag, MakePopoverTeachingMoment as ah, MakePropertyHook as ai, MakeTeachingMoment as aj, MaterialSelector as ak, NodeSelector as al, NumberDropdown as am, NumberDropdownPropertyLine as an, ObservableCollection as ao, Pane as ap, PlaceholderPropertyLine as aq, PositionedPopover as ar, PropertiesServiceIdentity as as, Property as at, PropertyContext as au, PropertyLine as av, QuaternionPropertyLine as aw, RotationVectorPropertyLine as ax, SceneExplorerServiceIdentity as ay, SearchBar as az, useInterceptObservable as b, ToastProvider as b0, ToggleButton as b1, Tooltip as b2, UploadButton as b3, Vector2PropertyLine as b4, Vector4PropertyLine as b5, WatcherServiceIdentity as b6, useAngleConverters as b7, useAsyncResource as b8, useColor3Property as b9, useColor4Property as ba, useEventListener as bb, useEventfulState as bc, useKeyListener as bd, useKeyState as be, useObservableCollection as bf, useOrderedObservableCollection as bg, usePollingObservable as bh, usePropertyChangedNotifier as bi, useQuaternionProperty as bj, useResource as bk, useTheme as bl, useThemeMode as bm, useVector3Property as bn, LinkToEntity as c, SpinButtonPropertyLine as d, useProperty as e, SceneContextIdentity as f, SelectionServiceIdentity as g, useObservableState as h, AccordionSection as i, ButtonLine as j, ToolsServiceIdentity as k, AccordionSectionItem as l, AttachDebugLayer as m, BooleanBadgePropertyLine as n, BoundProperty as o, BridgeCommandRegistryIdentity as p, BuiltInsExtensionFeed as q, Checkbox as r, ChildWindow as s, Collapse as t, useExtensionManager as u, Color3GradientComponent as v, Color3GradientList as w, Color3PropertyLine as x, Color4GradientComponent as y, Color4GradientList as z };
|
|
24297
|
+
//# sourceMappingURL=index-DYOMPcC7.js.map
|