@babylonjs/inspector 9.2.2 → 9.3.1
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 +29 -2
- package/bin/inspector-cli.mjs +17 -2
- package/lib/{extensionsListService-B_R2ChvJ.js → extensionsListService-DA8_rCpk.js} +2 -2
- package/lib/{extensionsListService-B_R2ChvJ.js.map → extensionsListService-DA8_rCpk.js.map} +1 -1
- package/lib/{index-DB_fpb1t.js → index-nEGqYbP2.js} +348 -293
- package/lib/index-nEGqYbP2.js.map +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/lib/inspectable.d.ts +27 -10
- package/lib/inspector.d.ts +7 -2
- package/lib/{quickCreateToolsService-DaBqYmZw.js → quickCreateToolsService-_L22btR5.js} +2 -2
- package/lib/{quickCreateToolsService-DaBqYmZw.js.map → quickCreateToolsService-_L22btR5.js.map} +1 -1
- package/lib/{reflectorService-5IVRhqd-.js → reflectorService-BMLxtZT7.js} +2 -2
- package/lib/{reflectorService-5IVRhqd-.js.map → reflectorService-BMLxtZT7.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/lib/cli/protocol.d.ts +0 -180
- package/lib/index-DB_fpb1t.js.map +0 -1
- package/lib/services/cli/cliConnectionStatus.d.ts +0 -25
- package/lib/services/cli/inspectableBridgeService.d.ts +0 -26
- package/lib/services/cli/inspectableCommandRegistry.d.ts +0 -58
|
@@ -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-DA8_rCpk.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-_L22btR5.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-BMLxtZT7.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.autoStart;
|
|
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
|
+
autoStart: options?.autoStart ?? false,
|
|
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,197 +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 "execCommand": {
|
|
8958
|
-
const command = commands.get(message.commandId);
|
|
8959
|
-
if (!command) {
|
|
8960
|
-
sendToBridge({
|
|
8961
|
-
type: "commandResponse",
|
|
8962
|
-
requestId: message.requestId,
|
|
8963
|
-
error: `Unknown command: ${message.commandId}`,
|
|
8964
|
-
});
|
|
8965
|
-
break;
|
|
8966
|
-
}
|
|
8967
|
-
try {
|
|
8968
|
-
const result = await command.executeAsync(message.args);
|
|
8969
|
-
sendToBridge({
|
|
8970
|
-
type: "commandResponse",
|
|
8971
|
-
requestId: message.requestId,
|
|
8972
|
-
result,
|
|
8973
|
-
});
|
|
8974
|
-
}
|
|
8975
|
-
catch (error) {
|
|
8976
|
-
sendToBridge({
|
|
8977
|
-
type: "commandResponse",
|
|
8978
|
-
requestId: message.requestId,
|
|
8979
|
-
error: String(error),
|
|
8980
|
-
});
|
|
8981
|
-
}
|
|
8982
|
-
break;
|
|
8983
|
-
}
|
|
8984
|
-
}
|
|
8985
|
-
}
|
|
8986
|
-
if (enabled) {
|
|
8987
|
-
connect();
|
|
8988
|
-
}
|
|
8989
|
-
const registry = {
|
|
8990
|
-
addCommand(descriptor) {
|
|
8991
|
-
if (commands.has(descriptor.id)) {
|
|
8992
|
-
throw new Error(`Command '${descriptor.id}' is already registered.`);
|
|
8993
|
-
}
|
|
8994
|
-
commands.set(descriptor.id, descriptor);
|
|
8995
|
-
return {
|
|
8996
|
-
dispose: () => {
|
|
8997
|
-
commands.delete(descriptor.id);
|
|
8998
|
-
},
|
|
8999
|
-
};
|
|
9000
|
-
},
|
|
9001
|
-
get isEnabled() {
|
|
9002
|
-
return enabled;
|
|
9003
|
-
},
|
|
9004
|
-
set isEnabled(value) {
|
|
9005
|
-
if (enabled !== value) {
|
|
9006
|
-
enabled = value;
|
|
9007
|
-
if (enabled) {
|
|
9008
|
-
connect();
|
|
9009
|
-
}
|
|
9010
|
-
else {
|
|
9011
|
-
disconnect();
|
|
9012
|
-
}
|
|
9013
|
-
notifyStatusChanged();
|
|
9014
|
-
}
|
|
9015
|
-
},
|
|
9016
|
-
get isConnected() {
|
|
9017
|
-
return connected;
|
|
9018
|
-
},
|
|
9019
|
-
onConnectionStatusChanged,
|
|
9020
|
-
dispose: () => {
|
|
9021
|
-
disposed = true;
|
|
9022
|
-
enabled = false;
|
|
9023
|
-
disconnect();
|
|
9024
|
-
commands.clear();
|
|
9025
|
-
onConnectionStatusChanged.clear();
|
|
9026
|
-
},
|
|
9027
|
-
};
|
|
9028
|
-
return registry;
|
|
9029
|
-
},
|
|
9030
|
-
};
|
|
9031
|
-
}
|
|
9032
|
-
|
|
9033
9095
|
/**
|
|
9034
9096
|
* Service that registers CLI commands for performance tracing using the PerformanceViewerCollector.
|
|
9035
9097
|
* start-perf-trace begins collecting data, stop-perf-trace stops and returns the collected data as JSON.
|
|
9036
9098
|
*/
|
|
9037
9099
|
const PerfTraceCommandServiceDefinition = {
|
|
9038
9100
|
friendlyName: "Perf Trace Command Service",
|
|
9039
|
-
consumes: [
|
|
9101
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9040
9102
|
factory: (commandRegistry, sceneContext) => {
|
|
9041
9103
|
let perfCollector;
|
|
9042
9104
|
const startReg = commandRegistry.addCommand({
|
|
@@ -9103,7 +9165,7 @@ const PerfTraceCommandServiceDefinition = {
|
|
|
9103
9165
|
*/
|
|
9104
9166
|
const ScreenshotCommandServiceDefinition = {
|
|
9105
9167
|
friendlyName: "Screenshot Command Service",
|
|
9106
|
-
consumes: [
|
|
9168
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9107
9169
|
factory: (commandRegistry, sceneContext) => {
|
|
9108
9170
|
const registration = commandRegistry.addCommand({
|
|
9109
9171
|
id: "take-screenshot",
|
|
@@ -9193,7 +9255,7 @@ const ScreenshotCommandServiceDefinition = {
|
|
|
9193
9255
|
*/
|
|
9194
9256
|
const ShaderCommandServiceDefinition = {
|
|
9195
9257
|
friendlyName: "Shader Command Service",
|
|
9196
|
-
consumes: [
|
|
9258
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9197
9259
|
factory: (commandRegistry, sceneContext) => {
|
|
9198
9260
|
const registration = commandRegistry.addCommand({
|
|
9199
9261
|
id: "get-shader-code",
|
|
@@ -9265,7 +9327,7 @@ const ShaderCommandServiceDefinition = {
|
|
|
9265
9327
|
*/
|
|
9266
9328
|
const StatsCommandServiceDefinition = {
|
|
9267
9329
|
friendlyName: "Stats Command Service",
|
|
9268
|
-
consumes: [
|
|
9330
|
+
consumes: [BridgeCommandRegistryIdentity, SceneContextIdentity],
|
|
9269
9331
|
factory: (commandRegistry, sceneContext) => {
|
|
9270
9332
|
let sceneInstrumentation;
|
|
9271
9333
|
let engineInstrumentation;
|
|
@@ -9431,15 +9493,32 @@ const InspectableStates = new Map();
|
|
|
9431
9493
|
function _StartInspectable(scene, options) {
|
|
9432
9494
|
let state = InspectableStates.get(scene);
|
|
9433
9495
|
if (!state) {
|
|
9434
|
-
const
|
|
9435
|
-
|
|
9436
|
-
|
|
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
|
+
autoStart: options?.autoStart,
|
|
9508
|
+
});
|
|
9509
|
+
disposeActions.push(() => bridgeToken.dispose());
|
|
9510
|
+
}
|
|
9511
|
+
const serviceContainer = new ServiceContainer("InspectableContainer", bridgeToken.serviceContainer);
|
|
9512
|
+
disposeActions.push(() => serviceContainer.dispose());
|
|
9513
|
+
let fullyDisposed = false;
|
|
9437
9514
|
const fullyDispose = () => {
|
|
9438
9515
|
InspectableStates.delete(scene);
|
|
9439
|
-
|
|
9440
|
-
|
|
9516
|
+
fullyDisposed = true;
|
|
9517
|
+
for (const action of disposeActions.reverse()) {
|
|
9518
|
+
action();
|
|
9519
|
+
}
|
|
9441
9520
|
};
|
|
9442
|
-
// Initialize the service container
|
|
9521
|
+
// Initialize the service container.
|
|
9443
9522
|
const sceneContextServiceDefinition = {
|
|
9444
9523
|
friendlyName: "Inspectable Scene Context",
|
|
9445
9524
|
produces: [SceneContextIdentity],
|
|
@@ -9448,41 +9527,25 @@ function _StartInspectable(scene, options) {
|
|
|
9448
9527
|
currentSceneObservable: new Observable(),
|
|
9449
9528
|
}),
|
|
9450
9529
|
};
|
|
9451
|
-
|
|
9452
|
-
await serviceContainer.addServicesAsync(sceneContextServiceDefinition, MakeInspectableBridgeServiceDefinition({
|
|
9453
|
-
port,
|
|
9454
|
-
name,
|
|
9455
|
-
autoStart: options?.autoStart ?? false,
|
|
9456
|
-
}), EntityQueryServiceDefinition, ScreenshotCommandServiceDefinition, ShaderCommandServiceDefinition, StatsCommandServiceDefinition, PerfTraceCommandServiceDefinition);
|
|
9457
|
-
})();
|
|
9530
|
+
serviceContainer.addServices(sceneContextServiceDefinition, EntityQueryServiceDefinition, ScreenshotCommandServiceDefinition, ShaderCommandServiceDefinition, StatsCommandServiceDefinition, PerfTraceCommandServiceDefinition);
|
|
9458
9531
|
state = {
|
|
9459
9532
|
refCount: 0,
|
|
9533
|
+
get fullyDisposed() {
|
|
9534
|
+
return fullyDisposed;
|
|
9535
|
+
},
|
|
9460
9536
|
serviceContainer,
|
|
9461
|
-
sceneDisposeObserver: { remove: () => { } },
|
|
9462
9537
|
fullyDispose,
|
|
9463
|
-
readyPromise,
|
|
9464
9538
|
};
|
|
9465
9539
|
const capturedState = state;
|
|
9466
9540
|
InspectableStates.set(scene, state);
|
|
9467
|
-
// Auto-dispose when the scene is disposed.
|
|
9468
|
-
|
|
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(() => {
|
|
9469
9545
|
capturedState.refCount = 0;
|
|
9470
9546
|
capturedState.fullyDispose();
|
|
9471
|
-
});
|
|
9472
|
-
|
|
9473
|
-
// Handle initialization failure (guard against already-disposed state).
|
|
9474
|
-
void (async () => {
|
|
9475
|
-
try {
|
|
9476
|
-
await readyPromise;
|
|
9477
|
-
}
|
|
9478
|
-
catch (error) {
|
|
9479
|
-
if (InspectableStates.has(scene)) {
|
|
9480
|
-
Logger.Error(`Failed to initialize Inspectable: ${error}`);
|
|
9481
|
-
capturedState.refCount = 0;
|
|
9482
|
-
capturedState.fullyDispose();
|
|
9483
|
-
}
|
|
9484
|
-
}
|
|
9485
|
-
})();
|
|
9547
|
+
}, undefined, true, undefined, true);
|
|
9548
|
+
disposeActions.push(() => sceneDisposeObserver.remove());
|
|
9486
9549
|
}
|
|
9487
9550
|
state.refCount++;
|
|
9488
9551
|
const { serviceContainer } = state;
|
|
@@ -9490,26 +9553,14 @@ function _StartInspectable(scene, options) {
|
|
|
9490
9553
|
// If additional service definitions were provided, add them in a separate call
|
|
9491
9554
|
// so they can be independently removed when this token is disposed.
|
|
9492
9555
|
let extraServicesDisposable;
|
|
9493
|
-
const extraAbortController = new AbortController();
|
|
9494
9556
|
const extraServiceDefinitions = options?.serviceDefinitions;
|
|
9495
9557
|
if (extraServiceDefinitions && extraServiceDefinitions.length > 0) {
|
|
9496
|
-
|
|
9497
|
-
void (async () => {
|
|
9498
|
-
try {
|
|
9499
|
-
await owningState.readyPromise;
|
|
9500
|
-
extraServicesDisposable = await serviceContainer.addServicesAsync(...extraServiceDefinitions, extraAbortController.signal);
|
|
9501
|
-
}
|
|
9502
|
-
catch (error) {
|
|
9503
|
-
if (!extraAbortController.signal.aborted) {
|
|
9504
|
-
Logger.Error(`Failed to add extra inspectable services: ${error}`);
|
|
9505
|
-
}
|
|
9506
|
-
}
|
|
9507
|
-
})();
|
|
9558
|
+
extraServicesDisposable = serviceContainer.addServices(...extraServiceDefinitions);
|
|
9508
9559
|
}
|
|
9509
9560
|
let disposed = false;
|
|
9510
9561
|
const token = {
|
|
9511
9562
|
get isDisposed() {
|
|
9512
|
-
return disposed;
|
|
9563
|
+
return disposed || owningState.fullyDisposed;
|
|
9513
9564
|
},
|
|
9514
9565
|
get serviceContainer() {
|
|
9515
9566
|
return serviceContainer;
|
|
@@ -9519,8 +9570,7 @@ function _StartInspectable(scene, options) {
|
|
|
9519
9570
|
return;
|
|
9520
9571
|
}
|
|
9521
9572
|
disposed = true;
|
|
9522
|
-
//
|
|
9523
|
-
extraAbortController.abort();
|
|
9573
|
+
// Remove extra services that were added for this token.
|
|
9524
9574
|
extraServicesDisposable?.dispose();
|
|
9525
9575
|
owningState.refCount--;
|
|
9526
9576
|
if (owningState.refCount <= 0) {
|
|
@@ -9532,9 +9582,12 @@ function _StartInspectable(scene, options) {
|
|
|
9532
9582
|
}
|
|
9533
9583
|
/**
|
|
9534
9584
|
* Makes a scene inspectable by connecting it to the Inspector CLI bridge.
|
|
9535
|
-
* This creates a headless {@link ServiceContainer} (no UI)
|
|
9536
|
-
*
|
|
9537
|
-
*
|
|
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}.
|
|
9538
9591
|
*
|
|
9539
9592
|
* Multiple callers may call this for the same scene. Each returned token is
|
|
9540
9593
|
* ref-counted — the underlying connection is only torn down when all tokens
|
|
@@ -23212,7 +23265,7 @@ const InspectorLock = new AsyncLock();
|
|
|
23212
23265
|
*/
|
|
23213
23266
|
function ShowInspector(scene, options = {}) {
|
|
23214
23267
|
// Dispose of any existing inspector for this scene.
|
|
23215
|
-
InspectorTokens.get(scene)?.dispose();
|
|
23268
|
+
void InspectorTokens.get(scene)?.dispose();
|
|
23216
23269
|
// Default the dispose logic to a no-op until we know that we are actually going
|
|
23217
23270
|
// to show the Inspector and there will be cleanup work to do.
|
|
23218
23271
|
let disposeAsync = async () => await Promise.resolve();
|
|
@@ -23221,9 +23274,9 @@ function ShowInspector(scene, options = {}) {
|
|
|
23221
23274
|
let isDisposed = false;
|
|
23222
23275
|
const onDisposed = new Observable();
|
|
23223
23276
|
const inspectorToken = {
|
|
23224
|
-
|
|
23225
|
-
|
|
23226
|
-
InspectorLock.lockAsync(async () => {
|
|
23277
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
23278
|
+
async dispose() {
|
|
23279
|
+
await InspectorLock.lockAsync(async () => {
|
|
23227
23280
|
await disposeAsync();
|
|
23228
23281
|
isDisposed = true;
|
|
23229
23282
|
onDisposed.notifyObservers();
|
|
@@ -23245,9 +23298,9 @@ function ShowInspector(scene, options = {}) {
|
|
|
23245
23298
|
layoutMode: "overlay",
|
|
23246
23299
|
...options,
|
|
23247
23300
|
};
|
|
23248
|
-
// 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).
|
|
23249
23302
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
23250
|
-
InspectorLock.lockAsync(
|
|
23303
|
+
InspectorLock.lockAsync(() => {
|
|
23251
23304
|
let parentElement = options.containerElement ?? null;
|
|
23252
23305
|
// If a container element was not found, find an appropriate one above the engine's rendering canvas.
|
|
23253
23306
|
if (!parentElement) {
|
|
@@ -23307,7 +23360,7 @@ function ShowInspector(scene, options = {}) {
|
|
|
23307
23360
|
const serviceDefinitions = [];
|
|
23308
23361
|
// Ensure the inspectable bridge is running for this scene. The inspector's
|
|
23309
23362
|
// ServiceContainer will use the inspectable container as a parent, inheriting
|
|
23310
|
-
// services like ISceneContext and
|
|
23363
|
+
// services like ISceneContext and IBridgeCommandRegistry.
|
|
23311
23364
|
const inspectableToken = _StartInspectable(scene);
|
|
23312
23365
|
disposeActions.push(() => inspectableToken.dispose());
|
|
23313
23366
|
// Create a container element for the inspector UI.
|
|
@@ -23418,10 +23471,12 @@ function ShowInspector(scene, options = {}) {
|
|
|
23418
23471
|
leftPaneDefaultCollapsed: options.leftPaneDefaultCollapsed,
|
|
23419
23472
|
rightPaneDefaultCollapsed: options.rightPaneDefaultCollapsed,
|
|
23420
23473
|
});
|
|
23421
|
-
disposeActions.push(() => modularTool.dispose());
|
|
23422
|
-
|
|
23423
|
-
|
|
23424
|
-
|
|
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);
|
|
23425
23480
|
disposeActions.push(() => sceneDisposedObserver.remove());
|
|
23426
23481
|
disposeActions.push(() => {
|
|
23427
23482
|
InspectorTokens.delete(scene);
|
|
@@ -23907,7 +23962,7 @@ class Inspector {
|
|
|
23907
23962
|
this._CurrentInstance.disposeToken.onDisposed.addOnce(() => (this._CurrentInstance = null));
|
|
23908
23963
|
}
|
|
23909
23964
|
static Hide() {
|
|
23910
|
-
this._CurrentInstance?.disposeToken.dispose();
|
|
23965
|
+
void this._CurrentInstance?.disposeToken.dispose();
|
|
23911
23966
|
}
|
|
23912
23967
|
// @ts-expect-error TS6133: This is private, but used by debugLayer (same as Inspector v1).
|
|
23913
23968
|
static _SetNewScene(scene) {
|
|
@@ -24238,5 +24293,5 @@ const TextAreaPropertyLine = (props) => {
|
|
|
24238
24293
|
// Attach Inspector v2 to Scene.debugLayer as a side effect for back compat.
|
|
24239
24294
|
AttachDebugLayer();
|
|
24240
24295
|
|
|
24241
|
-
export {
|
|
24242
|
-
//# 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-nEGqYbP2.js.map
|