@babylonjs/inspector 8.41.0 → 8.41.1-preview

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.
@@ -0,0 +1,545 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { b as Button, c as TextInputPropertyLine, d as SpinButtonPropertyLine, e as CheckboxPropertyLine, V as Vector3PropertyLine, f as ShellServiceIdentity, g as SceneContextIdentity, u as useObservableState, A as Accordion, h as AccordionSection } from './index-BUtV9Nch.js';
3
+ import { Settings20Regular, CollectionsAdd20Regular } from '@fluentui/react-icons';
4
+ import '@babylonjs/core/Particles/webgl2ParticleSystem.js';
5
+ import { MeshBuilder } from '@babylonjs/core/Meshes/meshBuilder.js';
6
+ import { useState, useRef } from 'react';
7
+ import { Popover, PopoverTrigger, PopoverSurface, makeStyles, tokens } from '@fluentui/react-components';
8
+ import { FilesInput } from '@babylonjs/core/Misc/filesInput.js';
9
+ import { NodeMaterial } from '@babylonjs/core/Materials/Node/nodeMaterial.js';
10
+ import { PBRMaterial } from '@babylonjs/core/Materials/PBR/pbrMaterial.js';
11
+ import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial.js';
12
+ import { PointLight } from '@babylonjs/core/Lights/pointLight.js';
13
+ import { DirectionalLight } from '@babylonjs/core/Lights/directionalLight.js';
14
+ import { SpotLight } from '@babylonjs/core/Lights/spotLight.js';
15
+ import { Vector3 } from '@babylonjs/core/Maths/math.vector.js';
16
+ import { ArcRotateCamera } from '@babylonjs/core/Cameras/arcRotateCamera.js';
17
+ import { UniversalCamera } from '@babylonjs/core/Cameras/universalCamera.js';
18
+ import { ParticleSystem } from '@babylonjs/core/Particles/particleSystem.js';
19
+ import { GPUParticleSystem } from '@babylonjs/core/Particles/gpuParticleSystem.js';
20
+ import { NodeParticleSystemSet } from '@babylonjs/core/Particles/Node/nodeParticleSystemSet.js';
21
+ import { Texture } from '@babylonjs/core/Materials/Textures/texture.js';
22
+ import '@babylonjs/core/Maths/math.color.js';
23
+ import '@babylonjs/core/Misc/observable.js';
24
+ import '@fluentui/react-motion-components-preview';
25
+ import '@babylonjs/core/Misc/typeStore.js';
26
+ import 'usehooks-ts';
27
+ import '@babylonjs/core/Misc/asyncLock.js';
28
+ import '@babylonjs/core/Misc/deferred.js';
29
+ import '@babylonjs/core/Maths/math.scalar.functions.js';
30
+ import '@fluentui-contrib/react-virtualizer';
31
+ import '@babylonjs/addons/msdfText/fontAsset.js';
32
+ import '@babylonjs/addons/msdfText/textRenderer.js';
33
+ import '@babylonjs/core/Debug/physicsViewer.js';
34
+ import '@babylonjs/core/Materials/materialFlags.js';
35
+ import '@babylonjs/core/Meshes/Builders/groundBuilder.js';
36
+ import '@babylonjs/core/Misc/tools.js';
37
+ import '@babylonjs/core/Rendering/utilityLayerRenderer.js';
38
+ import '@babylonjs/materials/grid/gridMaterial.js';
39
+ import '@babylonjs/core/Misc/dataStorage.js';
40
+ import '@babylonjs/core/Instrumentation/engineInstrumentation.js';
41
+ import '@babylonjs/core/Instrumentation/sceneInstrumentation.js';
42
+ import '@babylonjs/core/Engines/AbstractEngine/abstractEngine.timeQuery.js';
43
+ import '@babylonjs/core/Engines/Extensions/engine.query.js';
44
+ import '@babylonjs/core/Engines/WebGPU/Extensions/engine.query.js';
45
+ import '@babylonjs/core/Misc/PerformanceViewer/performanceViewerCollectionStrategies.js';
46
+ import '@babylonjs/core/Misc/PerformanceViewer/performanceViewerSceneExtension.js';
47
+ import '@babylonjs/core/Misc/pressureObserverWrapper.js';
48
+ import '@babylonjs/core/Engines/abstractEngine.js';
49
+ import '@babylonjs/core/Misc/logger.js';
50
+ import 'react-dom/client';
51
+ import '@babylonjs/core/FrameGraph/frameGraphUtils.js';
52
+ import '@babylonjs/core/Gizmos/cameraGizmo.js';
53
+ import '@babylonjs/core/Gizmos/lightGizmo.js';
54
+ import '@babylonjs/core/Bones/bone.js';
55
+ import '@babylonjs/core/Cameras/camera.js';
56
+ import '@babylonjs/core/Gizmos/gizmoManager.js';
57
+ import '@babylonjs/core/Lights/light.js';
58
+ import '@babylonjs/core/Meshes/abstractMesh.js';
59
+ import '@babylonjs/core/node.js';
60
+ import '@babylonjs/core/Animations/animationGroup.js';
61
+ import '@babylonjs/core/Animations/animationPropertiesOverride.js';
62
+ import '@babylonjs/addons/atmosphere/atmosphere.js';
63
+ import '@babylonjs/core/Cameras/followCamera.js';
64
+ import '@babylonjs/core/Cameras/freeCamera.js';
65
+ import '@babylonjs/core/Cameras/targetCamera.js';
66
+ import '@babylonjs/core/scene.js';
67
+ import '@babylonjs/core/FrameGraph/frameGraph.js';
68
+ import '@babylonjs/core/Lights/hemisphericLight.js';
69
+ import '@babylonjs/core/Lights/rectAreaLight.js';
70
+ import '@babylonjs/core/Lights/shadowLight.js';
71
+ import '@babylonjs/core/Lights/Shadows/cascadedShadowGenerator.js';
72
+ import '@babylonjs/core/Lights/Shadows/shadowGenerator.js';
73
+ import '@babylonjs/core/Lights/Shadows/shadowGeneratorSceneComponent.js';
74
+ import '@babylonjs/core/Materials/material.js';
75
+ import '@babylonjs/core/Materials/multiMaterial.js';
76
+ import '@babylonjs/core/Materials/PBR/pbrBaseMaterial.js';
77
+ import '@babylonjs/core/Materials/PBR/pbrBaseSimpleMaterial.js';
78
+ import '@babylonjs/core/Materials/PBR/openpbrMaterial.js';
79
+ import '@babylonjs/materials/sky/skyMaterial.js';
80
+ import '@babylonjs/core/Engines/constants.js';
81
+ import '@babylonjs/core/Engines/engine.js';
82
+ import '@babylonjs/core/Misc/fileTools.js';
83
+ import '@babylonjs/core/Meshes/mesh.js';
84
+ import '@babylonjs/core/Debug/skeletonViewer.js';
85
+ import '@babylonjs/core/Meshes/buffer.js';
86
+ import '@babylonjs/core/Meshes/Builders/linesBuilder.js';
87
+ import '@babylonjs/core/Meshes/instancedMesh.js';
88
+ import '@babylonjs/core/Rendering/renderingManager.js';
89
+ import '@babylonjs/core/Rendering/edgesRenderer.js';
90
+ import '@babylonjs/core/Rendering/outlineRenderer.js';
91
+ import '@babylonjs/core/Meshes/GaussianSplatting/gaussianSplattingMesh.js';
92
+ import '@babylonjs/core/Misc/gradients.js';
93
+ import '@babylonjs/core/Materials/Node/Blocks/gradientBlock.js';
94
+ import '@babylonjs/core/Particles/attractor.js';
95
+ import '@babylonjs/core/Meshes/Builders/sphereBuilder.js';
96
+ import '@babylonjs/core/Meshes/transformNode.js';
97
+ import '@babylonjs/core/Physics/v2/IPhysicsEnginePlugin.js';
98
+ import '@babylonjs/core/Physics/v2/physicsEngineComponent.js';
99
+ import '@babylonjs/core/PostProcesses/postProcess.js';
100
+ import '@babylonjs/core/Materials/Textures/cubeTexture.js';
101
+ import '@babylonjs/core/Materials/imageProcessingConfiguration.js';
102
+ import '@babylonjs/core/Bones/skeleton.js';
103
+ import '@babylonjs/core/Sprites/sprite.js';
104
+ import '@babylonjs/core/Sprites/spriteManager.js';
105
+ import '@babylonjs/core/Materials/Textures/baseTexture.js';
106
+ import '@babylonjs/core/Materials/Textures/multiRenderTarget.js';
107
+ import '@babylonjs/core/Materials/Textures/renderTargetTexture.js';
108
+ import '@babylonjs/core/Materials/Textures/thinTexture.js';
109
+ import '@babylonjs/core/Misc/textureTools.js';
110
+ import '@babylonjs/core/Lights/Clustered/clusteredLightContainer.js';
111
+ import '@babylonjs/core/Rendering/boundingBoxRenderer.js';
112
+ import '@babylonjs/core/PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSceneComponent.js';
113
+ import '@babylonjs/core/Sprites/spriteSceneComponent.js';
114
+ import '@babylonjs/core/Materials/Textures/dynamicTexture.js';
115
+ import '@babylonjs/core/Events/pointerEvents.js';
116
+ import '@babylonjs/core/Engines/engineStore.js';
117
+ import '@babylonjs/core/Misc/uniqueIdGenerator.js';
118
+ import '@babylonjs/core/Debug/debugLayer.js';
119
+ import '@babylonjs/core/Misc/lazy.js';
120
+
121
+ /**
122
+ * Settings popover component, can be updated to use shared popover once it exists
123
+ * @param props
124
+ * @returns
125
+ */
126
+ const SettingsPopover = (props) => {
127
+ const { children } = props;
128
+ const [popoverOpen, setPopoverOpen] = useState(false);
129
+ return (jsxs(Popover, { open: popoverOpen, onOpenChange: (_, data) => setPopoverOpen(data.open), positioning: "below-start", trapFocus: true, children: [jsx(PopoverTrigger, { disableButtonEnhancement: true, children: jsx("button", { type: "button", onClick: () => setPopoverOpen(true), style: {
130
+ display: "inline-flex",
131
+ alignItems: "center",
132
+ justifyContent: "center",
133
+ border: "none",
134
+ background: "transparent",
135
+ cursor: "pointer",
136
+ padding: "5px 8px",
137
+ borderRadius: "4px",
138
+ }, children: jsx(Settings20Regular, {}) }) }), jsx(PopoverSurface, { children: jsx("div", { style: { display: "flex", flexDirection: "column", gap: 12, padding: 16, minWidth: 300, maxWidth: 400 }, children: children }) })] }));
139
+ };
140
+
141
+ const useStyles$4 = makeStyles({
142
+ section: {
143
+ display: "flex",
144
+ flexDirection: "column",
145
+ rowGap: tokens.spacingVerticalM,
146
+ },
147
+ row: { display: "flex", alignItems: "center", gap: "4px" },
148
+ });
149
+ const SetCamera = function (scene) {
150
+ const camera = scene.activeCamera;
151
+ if (camera && camera.radius !== undefined) {
152
+ camera.radius = 5;
153
+ }
154
+ };
155
+ /**
156
+ * @internal
157
+ */
158
+ const MeshesContent = ({ scene }) => {
159
+ const classes = useStyles$4();
160
+ const [sphereParams, setSphereParams] = useState({
161
+ name: "Sphere",
162
+ segments: 32,
163
+ diameter: 1,
164
+ diameterX: 1,
165
+ diameterY: 1,
166
+ diameterZ: 1,
167
+ arc: 1,
168
+ slice: 1,
169
+ uniform: true,
170
+ });
171
+ const handleSphereParamChange = (key, value) => {
172
+ setSphereParams((prev) => ({
173
+ ...prev,
174
+ [key]: value,
175
+ }));
176
+ };
177
+ const [boxParams, setBoxParams] = useState({
178
+ name: "Box",
179
+ size: 1,
180
+ width: 1,
181
+ height: 1,
182
+ depth: 1,
183
+ });
184
+ const handleBoxParamChange = (key, value) => {
185
+ setBoxParams((prev) => ({
186
+ ...prev,
187
+ [key]: value,
188
+ }));
189
+ };
190
+ const [cylinderParams, setCylinderParams] = useState({
191
+ name: "Cylinder",
192
+ height: 2,
193
+ diameterTop: 1,
194
+ diameterBottom: 1,
195
+ diameter: 1,
196
+ tessellation: 32,
197
+ subdivisions: 1,
198
+ arc: 1,
199
+ });
200
+ const handleCylinderParamChange = (key, value) => {
201
+ setCylinderParams((prev) => ({
202
+ ...prev,
203
+ [key]: value,
204
+ }));
205
+ };
206
+ const [coneParams, setConeParams] = useState({
207
+ name: "Cone",
208
+ height: 2,
209
+ diameter: 1,
210
+ diameterTop: 0,
211
+ diameterBottom: 1,
212
+ tessellation: 32,
213
+ subdivisions: 1,
214
+ arc: 1,
215
+ });
216
+ const [coneUp, setConeUp] = useState(true);
217
+ const handleConeParamChange = (key, value) => {
218
+ setConeParams((prev) => ({
219
+ ...prev,
220
+ [key]: value,
221
+ }));
222
+ };
223
+ const [groundParams, setGroundParams] = useState({
224
+ name: "Ground",
225
+ width: 10,
226
+ height: 10,
227
+ subdivisions: 1,
228
+ subdivisionsX: 1,
229
+ subdivisionsY: 1,
230
+ });
231
+ const handleGroundParamChange = (key, value) => {
232
+ setGroundParams((prev) => ({
233
+ ...prev,
234
+ [key]: value,
235
+ }));
236
+ };
237
+ const fileInputRef = useRef(null);
238
+ const [importMeshName, setImportMeshName] = useState("ImportedMesh");
239
+ const handleLocalMeshImport = (event) => {
240
+ const files = event.target.files;
241
+ if (!files || files.length === 0) {
242
+ return;
243
+ }
244
+ const filesArray = Array.from(files);
245
+ if (importMeshName.trim().length > 0 && filesArray.length > 0) {
246
+ const originalFile = filesArray[0];
247
+ const extensionIndex = originalFile.name.lastIndexOf(".");
248
+ const extension = extensionIndex >= 0 ? originalFile.name.substring(extensionIndex) : "";
249
+ const sanitizedName = importMeshName.trim();
250
+ const desiredFileName = sanitizedName.toLowerCase().endsWith(extension.toLowerCase()) ? sanitizedName : `${sanitizedName}${extension}`;
251
+ filesArray[0] = new File([originalFile], desiredFileName, { type: originalFile.type, lastModified: originalFile.lastModified });
252
+ }
253
+ const filesInput = new FilesInput(scene.getEngine(), scene, null, null, null, null, null, null, (_sceneFile, _scene, message) => {
254
+ alert(message ? `Failed to import mesh: ${message}` : "Failed to import mesh.");
255
+ }, true);
256
+ filesInput.displayLoadingUI = false;
257
+ filesInput.loadFiles({ target: { files: filesArray } });
258
+ filesInput.dispose();
259
+ event.target.value = "";
260
+ };
261
+ return (jsxs("div", { className: classes.section, children: [jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
262
+ MeshBuilder.CreateSphere("Sphere", {}, scene);
263
+ SetCamera(scene);
264
+ }, label: "Sphere" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: sphereParams.name, onChange: (val) => handleSphereParamChange("name", val) }), jsx(SpinButtonPropertyLine, { label: "Segments", value: sphereParams.segments, min: 0, onChange: (val) => handleSphereParamChange("segments", val) }), jsx(SpinButtonPropertyLine, { label: "Diameter", value: sphereParams.diameter, min: 0, step: 0.1, onChange: (val) => handleSphereParamChange("diameter", val), disabled: !sphereParams.uniform }), jsx(CheckboxPropertyLine, { label: "Uniform", value: sphereParams.uniform, onChange: (checked) => handleSphereParamChange("uniform", checked) }), jsx(SpinButtonPropertyLine, { label: "Diameter X", value: sphereParams.diameterX, min: 0, step: 0.1, onChange: (val) => handleSphereParamChange("diameterX", val), disabled: sphereParams.uniform }), jsx(SpinButtonPropertyLine, { label: "Diameter Y", value: sphereParams.diameterY, min: 0, step: 0.1, onChange: (val) => handleSphereParamChange("diameterY", val), disabled: sphereParams.uniform }), jsx(SpinButtonPropertyLine, { label: "Diameter Z", value: sphereParams.diameterZ, min: 0, step: 0.1, onChange: (val) => handleSphereParamChange("diameterZ", val), disabled: sphereParams.uniform }), jsx(SpinButtonPropertyLine, { label: "Arc", value: sphereParams.arc, min: 0, max: 1, step: 0.1, onChange: (val) => handleSphereParamChange("arc", val) }), jsx(SpinButtonPropertyLine, { label: "Slice", value: sphereParams.slice, min: 0, max: 1, step: 0.1, onChange: (val) => handleSphereParamChange("slice", val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: jsx(Button, { appearance: "primary", onClick: () => {
265
+ // Create params object based on uniform checkbox
266
+ const createParams = {
267
+ segments: sphereParams.segments,
268
+ arc: sphereParams.arc,
269
+ slice: sphereParams.slice,
270
+ };
271
+ if (sphereParams.uniform) {
272
+ // If uniform is checked, use diameter
273
+ createParams.diameter = sphereParams.diameter;
274
+ }
275
+ else {
276
+ // If uniform is unchecked, use individual diameters
277
+ createParams.diameterX = sphereParams.diameterX;
278
+ createParams.diameterY = sphereParams.diameterY;
279
+ createParams.diameterZ = sphereParams.diameterZ;
280
+ }
281
+ MeshBuilder.CreateSphere(sphereParams.name, createParams, scene);
282
+ SetCamera(scene);
283
+ }, label: "Create" }) })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
284
+ MeshBuilder.CreateBox("Box", {}, scene);
285
+ SetCamera(scene);
286
+ }, label: "Box" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: boxParams.name, onChange: (val) => handleBoxParamChange("name", val) }), jsx(SpinButtonPropertyLine, { label: "Size", value: boxParams.size, min: 0, step: 0.1, onChange: (val) => handleBoxParamChange("size", val) }), jsx(SpinButtonPropertyLine, { label: "Width", value: boxParams.width, min: 0, step: 0.1, onChange: (val) => handleBoxParamChange("width", val) }), jsx(SpinButtonPropertyLine, { label: "Height", value: boxParams.height, min: 0, step: 0.1, onChange: (val) => handleBoxParamChange("height", val) }), jsx(SpinButtonPropertyLine, { label: "Depth", value: boxParams.depth, min: 0, step: 0.1, onChange: (val) => handleBoxParamChange("depth", val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: jsx(Button, { appearance: "primary", onClick: () => {
287
+ MeshBuilder.CreateBox(boxParams.name, boxParams, scene);
288
+ SetCamera(scene);
289
+ }, label: "Create" }) })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
290
+ MeshBuilder.CreateCylinder("Cylinder", {}, scene);
291
+ SetCamera(scene);
292
+ }, label: "Cylinder" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: cylinderParams.name, onChange: (val) => handleCylinderParamChange("name", val) }), jsx(SpinButtonPropertyLine, { label: "Height", value: cylinderParams.height, min: 0, step: 0.1, onChange: (val) => handleCylinderParamChange("height", val) }), jsx(SpinButtonPropertyLine, { label: "Diameter Top", value: cylinderParams.diameterTop, min: 0, step: 0.1, onChange: (val) => handleCylinderParamChange("diameterTop", val) }), jsx(SpinButtonPropertyLine, { label: "Diameter Bottom", value: cylinderParams.diameterBottom, min: 0, step: 0.1, onChange: (val) => handleCylinderParamChange("diameterBottom", val) }), jsx(SpinButtonPropertyLine, { label: "Diameter", value: cylinderParams.diameter, min: 0, step: 0.1, onChange: (val) => handleCylinderParamChange("diameter", val) }), jsx(SpinButtonPropertyLine, { label: "Tessellation", value: cylinderParams.tessellation, min: 3, onChange: (val) => handleCylinderParamChange("tessellation", val) }), jsx(SpinButtonPropertyLine, { label: "Subdivisions", value: cylinderParams.subdivisions, min: 1, onChange: (val) => handleCylinderParamChange("subdivisions", val) }), jsx(SpinButtonPropertyLine, { label: "Arc", value: cylinderParams.arc, min: 0, max: 1, step: 0.1, onChange: (val) => handleCylinderParamChange("arc", val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: jsx(Button, { appearance: "primary", onClick: () => {
293
+ MeshBuilder.CreateCylinder(cylinderParams.name, cylinderParams, scene);
294
+ SetCamera(scene);
295
+ }, label: "Create" }) })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
296
+ MeshBuilder.CreateCylinder("Cone", { diameterTop: 0 }, scene);
297
+ SetCamera(scene);
298
+ }, label: "Cone" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: coneParams.name, onChange: (val) => handleConeParamChange("name", val) }), jsx(SpinButtonPropertyLine, { label: "Height", value: coneParams.height, min: 0, step: 0.1, onChange: (val) => handleConeParamChange("height", val) }), jsx(SpinButtonPropertyLine, { label: "Diameter", value: coneParams.diameter, min: 0, step: 0.1, onChange: (val) => handleConeParamChange("diameter", val) }), jsx(SpinButtonPropertyLine, { label: "Tessellation", value: coneParams.tessellation, min: 3, onChange: (val) => handleConeParamChange("tessellation", val) }), jsx(SpinButtonPropertyLine, { label: "Subdivisions", value: coneParams.subdivisions, min: 1, onChange: (val) => handleConeParamChange("subdivisions", val) }), jsx(SpinButtonPropertyLine, { label: "Arc", value: coneParams.arc, min: 0, max: 1, step: 0.1, onChange: (val) => handleConeParamChange("arc", val) }), jsx(CheckboxPropertyLine, { label: "Up", value: coneUp, onChange: (val) => setConeUp(val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: jsx(Button, { appearance: "primary", onClick: () => {
299
+ const coneParamsToUse = {
300
+ ...coneParams,
301
+ diameterTop: coneUp ? 0 : coneParams.diameterTop,
302
+ diameterBottom: coneUp ? coneParams.diameterBottom : 0,
303
+ };
304
+ MeshBuilder.CreateCylinder(coneParams.name, coneParamsToUse, scene);
305
+ SetCamera(scene);
306
+ }, label: "Create" }) })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
307
+ MeshBuilder.CreateGround("Ground", {}, scene);
308
+ SetCamera(scene);
309
+ }, label: "Ground" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: groundParams.name, onChange: (val) => handleGroundParamChange("name", val) }), jsx(SpinButtonPropertyLine, { label: "Width", value: groundParams.width, min: 0, step: 0.1, onChange: (val) => handleGroundParamChange("width", val) }), jsx(SpinButtonPropertyLine, { label: "Height", value: groundParams.height, min: 0, step: 0.1, onChange: (val) => handleGroundParamChange("height", val) }), jsx(SpinButtonPropertyLine, { label: "Subdivisions", value: groundParams.subdivisions, min: 1, onChange: (val) => handleGroundParamChange("subdivisions", val) }), jsx(SpinButtonPropertyLine, { label: "Subdivisions X", value: groundParams.subdivisionsX, min: 1, onChange: (val) => handleGroundParamChange("subdivisionsX", val) }), jsx(SpinButtonPropertyLine, { label: "Subdivisions Y", value: groundParams.subdivisionsY, min: 1, onChange: (val) => handleGroundParamChange("subdivisionsY", val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8, marginTop: 16 }, children: jsx(Button, { appearance: "primary", onClick: () => {
310
+ MeshBuilder.CreateGround(groundParams.name, groundParams, scene);
311
+ SetCamera(scene);
312
+ }, label: "Create" }) })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: () => {
313
+ fileInputRef.current?.click();
314
+ }, label: "Import Mesh" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: importMeshName, onChange: (val) => setImportMeshName(val) }), jsx("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: jsx(Button, { appearance: "primary", onClick: () => {
315
+ fileInputRef.current?.click();
316
+ }, label: "Import" }) })] }), jsx("input", { ref: fileInputRef, type: "file", accept: ".babylon,.glb,.gltf,.obj,.stl,.ply,.mesh,.babylonmeshdata", multiple: true, style: { display: "none" }, onChange: handleLocalMeshImport })] })] }));
317
+ };
318
+
319
+ const useStyles$3 = makeStyles({
320
+ section: {
321
+ display: "flex",
322
+ flexDirection: "column",
323
+ rowGap: tokens.spacingVerticalM,
324
+ },
325
+ row: { display: "flex", alignItems: "center", gap: "4px" },
326
+ });
327
+ /**
328
+ * Materials content component
329
+ * @param props - Component props
330
+ * @returns React component
331
+ */
332
+ const MaterialsContent = ({ scene }) => {
333
+ const classes = useStyles$3();
334
+ // Node Material state
335
+ const [nodeMaterialName, setNodeMaterialName] = useState("Node Material");
336
+ const [nodeMaterialSnippetId, setNodeMaterialSnippetId] = useState("");
337
+ // PBR Material state
338
+ const [pbrMaterialName, setPbrMaterialName] = useState("PBR Material");
339
+ // Standard Material state
340
+ const [standardMaterialName, setStandardMaterialName] = useState("Standard Material");
341
+ const handleCreateNodeMaterialAsync = async () => {
342
+ if (nodeMaterialSnippetId) {
343
+ try {
344
+ const nodeMaterial = await NodeMaterial.ParseFromSnippetAsync(nodeMaterialSnippetId, scene);
345
+ nodeMaterial.name = nodeMaterialName;
346
+ }
347
+ catch (e) {
348
+ alert("Failed to load Node Material from snippet: " + e);
349
+ }
350
+ }
351
+ else {
352
+ const nodeMaterial = new NodeMaterial(nodeMaterialName, scene);
353
+ nodeMaterial.build();
354
+ }
355
+ };
356
+ const handleCreatePBRMaterial = () => {
357
+ new PBRMaterial(pbrMaterialName, scene);
358
+ };
359
+ const handleCreateStandardMaterial = () => {
360
+ new StandardMaterial(standardMaterialName, scene);
361
+ };
362
+ return (jsxs("div", { className: classes.section, children: [jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateNodeMaterialAsync, label: "Node Material" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: nodeMaterialName, onChange: (value) => setNodeMaterialName(value) }), jsx(TextInputPropertyLine, { label: "Snippet ID", value: nodeMaterialSnippetId, onChange: (value) => setNodeMaterialSnippetId(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateNodeMaterialAsync, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreatePBRMaterial, label: "PBR Material" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: pbrMaterialName, onChange: (value) => setPbrMaterialName(value) }), jsx(Button, { appearance: "primary", onClick: handleCreatePBRMaterial, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateStandardMaterial, label: "Standard Material" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: standardMaterialName, onChange: (value) => setStandardMaterialName(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateStandardMaterial, label: "Create" })] })] })] }));
363
+ };
364
+
365
+ const useStyles$2 = makeStyles({
366
+ section: {
367
+ display: "flex",
368
+ flexDirection: "column",
369
+ rowGap: tokens.spacingVerticalM,
370
+ },
371
+ row: { display: "flex", alignItems: "center", gap: "4px" },
372
+ });
373
+ /**
374
+ * Lights content component
375
+ * @param props - Component props
376
+ * @returns React component
377
+ */
378
+ const LightsContent = ({ scene }) => {
379
+ const classes = useStyles$2();
380
+ // Point Light state
381
+ const [pointLightName, setPointLightName] = useState("Point Light");
382
+ const [pointLightPosition, setPointLightPosition] = useState(new Vector3(0, 5, 0));
383
+ // Directional Light state
384
+ const [directionalLightName, setDirectionalLightName] = useState("Directional Light");
385
+ const [directionalLightDirection, setDirectionalLightDirection] = useState(new Vector3(1, -1, 0));
386
+ // Spotlight state
387
+ const [spotlightName, setSpotlightName] = useState("Spotlight");
388
+ const [spotlightPosition, setSpotlightPosition] = useState(new Vector3(0, 5, 0));
389
+ const [spotlightDirection, setSpotlightDirection] = useState(new Vector3(0, -1, 0));
390
+ const [spotlightAngle, setSpotlightAngle] = useState(1);
391
+ const [spotlightExponent, setSpotlightExponent] = useState(1);
392
+ const handleCreatePointLight = () => {
393
+ const light = new PointLight(pointLightName, pointLightPosition, scene);
394
+ light.intensity = 1.0;
395
+ };
396
+ const handleCreateDirectionalLight = () => {
397
+ const dirLight = new DirectionalLight(directionalLightName, directionalLightDirection, scene);
398
+ dirLight.intensity = 1.0;
399
+ };
400
+ const handleCreateSpotlight = () => {
401
+ const spotlight = new SpotLight(spotlightName, spotlightPosition, spotlightDirection, spotlightAngle, spotlightExponent, scene);
402
+ spotlight.intensity = 1.0;
403
+ };
404
+ return (jsxs("div", { className: classes.section, children: [jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreatePointLight, label: "Point Light" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: pointLightName, onChange: (value) => setPointLightName(value) }), jsx(Vector3PropertyLine, { label: "Position", value: pointLightPosition, onChange: (value) => setPointLightPosition(value) }), jsx(Button, { appearance: "primary", onClick: handleCreatePointLight, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateDirectionalLight, label: "Directional Light" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: directionalLightName, onChange: (value) => setDirectionalLightName(value) }), jsx(Vector3PropertyLine, { label: "Direction", value: directionalLightDirection, onChange: (value) => setDirectionalLightDirection(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateDirectionalLight, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateSpotlight, label: "Spotlight" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: spotlightName, onChange: (value) => setSpotlightName(value) }), jsx(Vector3PropertyLine, { label: "Position", value: spotlightPosition, onChange: (value) => setSpotlightPosition(value) }), jsx(Vector3PropertyLine, { label: "Direction", value: spotlightDirection, onChange: (value) => setSpotlightDirection(value) }), jsx(SpinButtonPropertyLine, { label: "Angle", value: spotlightAngle, onChange: (value) => setSpotlightAngle(value), min: 0, max: Math.PI, step: 0.1 }), jsx(SpinButtonPropertyLine, { label: "Exponent", value: spotlightExponent, onChange: (value) => setSpotlightExponent(value), min: 0, max: 10, step: 0.1 }), jsx(Button, { appearance: "primary", onClick: handleCreateSpotlight, label: "Create" })] })] })] }));
405
+ };
406
+
407
+ const useStyles$1 = makeStyles({
408
+ section: {
409
+ display: "flex",
410
+ flexDirection: "column",
411
+ rowGap: tokens.spacingVerticalM,
412
+ },
413
+ row: { display: "flex", alignItems: "center", gap: "4px" },
414
+ });
415
+ /**
416
+ * Cameras content component
417
+ * @param props - Component props
418
+ * @returns React component
419
+ */
420
+ const CamerasContent = ({ scene }) => {
421
+ const classes = useStyles$1();
422
+ // ArcRotate Camera state
423
+ const [arcRotateCameraName, setArcRotateCameraName] = useState("ArcRotate Camera");
424
+ const [arcRotateCameraTarget, setArcRotateCameraTarget] = useState(new Vector3(0, 0, 0));
425
+ const [arcRotateCameraRadius, setArcRotateCameraRadius] = useState(10);
426
+ const [arcRotateCameraAlpha, setArcRotateCameraAlpha] = useState(0);
427
+ const [arcRotateCameraBeta, setArcRotateCameraBeta] = useState(45);
428
+ const [arcRotateCameraUseRadians, setArcRotateCameraUseRadians] = useState(false);
429
+ // Universal Camera state
430
+ const [universalCameraName, setUniversalCameraName] = useState("Universal Camera");
431
+ const [universalCameraPosition, setUniversalCameraPosition] = useState(new Vector3(0, 1, -10));
432
+ const handleCreateArcRotateCamera = () => {
433
+ const alpha = arcRotateCameraUseRadians ? arcRotateCameraAlpha : (arcRotateCameraAlpha * Math.PI) / 180;
434
+ const beta = arcRotateCameraUseRadians ? arcRotateCameraBeta : (arcRotateCameraBeta * Math.PI) / 180;
435
+ const camera = new ArcRotateCamera(arcRotateCameraName, alpha, beta, arcRotateCameraRadius, arcRotateCameraTarget, scene);
436
+ camera.attachControl(scene.getEngine().getRenderingCanvas(), true);
437
+ if (!scene.activeCamera) {
438
+ scene.activeCamera = camera;
439
+ }
440
+ };
441
+ const handleCreateUniversalCamera = () => {
442
+ const camera = new UniversalCamera(universalCameraName, universalCameraPosition, scene);
443
+ camera.attachControl(scene.getEngine().getRenderingCanvas(), true);
444
+ if (!scene.activeCamera) {
445
+ scene.activeCamera = camera;
446
+ }
447
+ };
448
+ return (jsxs("div", { className: classes.section, children: [jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateArcRotateCamera, label: "ArcRotate Camera" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: arcRotateCameraName, onChange: (value) => setArcRotateCameraName(value) }), jsx(Vector3PropertyLine, { label: "Target", value: arcRotateCameraTarget, onChange: (value) => setArcRotateCameraTarget(value) }), jsx(SpinButtonPropertyLine, { label: "Radius", value: arcRotateCameraRadius, onChange: (value) => setArcRotateCameraRadius(value), min: 0.1, max: 1000, step: 0.5 }), jsx(SpinButtonPropertyLine, { label: `Alpha ${arcRotateCameraUseRadians ? "(rad)" : "(deg)"}`, value: arcRotateCameraAlpha, onChange: (value) => setArcRotateCameraAlpha(value), min: arcRotateCameraUseRadians ? -Math.PI * 2 : -360, max: arcRotateCameraUseRadians ? Math.PI * 2 : 360, step: arcRotateCameraUseRadians ? 0.1 : 5 }), jsx(SpinButtonPropertyLine, { label: `Beta ${arcRotateCameraUseRadians ? "(rad)" : "(deg)"}`, value: arcRotateCameraBeta, onChange: (value) => setArcRotateCameraBeta(value), min: arcRotateCameraUseRadians ? 0 : 0, max: arcRotateCameraUseRadians ? Math.PI : 180, step: arcRotateCameraUseRadians ? 0.1 : 5 }), jsx(CheckboxPropertyLine, { label: "Use Radians", value: arcRotateCameraUseRadians, onChange: (value) => setArcRotateCameraUseRadians(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateArcRotateCamera, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateUniversalCamera, label: "Universal Camera" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: universalCameraName, onChange: (value) => setUniversalCameraName(value) }), jsx(Vector3PropertyLine, { label: "Position", value: universalCameraPosition, onChange: (value) => setUniversalCameraPosition(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateUniversalCamera, label: "Create" })] })] })] }));
449
+ };
450
+
451
+ const useStyles = makeStyles({
452
+ section: {
453
+ display: "flex",
454
+ flexDirection: "column",
455
+ rowGap: tokens.spacingVerticalM,
456
+ },
457
+ row: { display: "flex", alignItems: "center", gap: "4px" },
458
+ });
459
+ /**
460
+ * Particles content component
461
+ * @param props - Component props
462
+ * @returns React component
463
+ */
464
+ const ParticlesContent = ({ scene }) => {
465
+ const classes = useStyles();
466
+ // CPU Particle System state
467
+ const [cpuParticleSystemName, setCpuParticleSystemName] = useState("Particle System");
468
+ const [cpuParticleSystemCapacity, setCpuParticleSystemCapacity] = useState(2000);
469
+ // GPU Particle System state
470
+ const [gpuParticleSystemName, setGpuParticleSystemName] = useState("GPU Particle System");
471
+ const [gpuParticleSystemCapacity, setGpuParticleSystemCapacity] = useState(2000);
472
+ // Node Particle System state
473
+ const [nodeParticleSystemName, setNodeParticleSystemName] = useState("Node Particle System");
474
+ const [nodeParticleSystemSnippetId, setNodeParticleSystemSnippetId] = useState("");
475
+ const handleCreateCPUParticleSystem = () => {
476
+ setTimeout(() => {
477
+ const system = new ParticleSystem(cpuParticleSystemName, cpuParticleSystemCapacity, scene);
478
+ system.particleTexture = new Texture("https://assets.babylonjs.com/textures/flare.png", scene);
479
+ system.start();
480
+ }, 0);
481
+ };
482
+ const handleCreateGPUParticleSystem = () => {
483
+ if (GPUParticleSystem.IsSupported) {
484
+ setTimeout(() => {
485
+ const system = new GPUParticleSystem(gpuParticleSystemName, { capacity: gpuParticleSystemCapacity }, scene);
486
+ system.particleTexture = new Texture("https://assets.babylonjs.com/textures/flare.png", scene);
487
+ system.start();
488
+ }, 0);
489
+ }
490
+ else {
491
+ alert("GPU Particle System is not supported.");
492
+ }
493
+ };
494
+ const handleCreateNodeParticleSystemAsync = async () => {
495
+ try {
496
+ let nodeParticleSet;
497
+ const snippetId = nodeParticleSystemSnippetId.trim();
498
+ if (snippetId) {
499
+ nodeParticleSet = await NodeParticleSystemSet.ParseFromSnippetAsync(snippetId);
500
+ nodeParticleSet.name = nodeParticleSystemName;
501
+ }
502
+ else {
503
+ nodeParticleSet = NodeParticleSystemSet.CreateDefault(nodeParticleSystemName);
504
+ }
505
+ const particleSystemSet = await nodeParticleSet.buildAsync(scene);
506
+ for (const system of particleSystemSet.systems) {
507
+ system.name = nodeParticleSystemName;
508
+ }
509
+ particleSystemSet.start();
510
+ }
511
+ catch (e) {
512
+ global.console.error("Error creating Node Particle System:", e);
513
+ alert("Failed to create Node Particle System: " + e);
514
+ }
515
+ };
516
+ return (jsxs("div", { className: classes.section, children: [jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateCPUParticleSystem, label: "CPU Particle System" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: cpuParticleSystemName, onChange: (value) => setCpuParticleSystemName(value) }), jsx(SpinButtonPropertyLine, { label: "Capacity", value: cpuParticleSystemCapacity, onChange: (value) => setCpuParticleSystemCapacity(value), min: 1, max: 100000, step: 100 }), jsx(Button, { appearance: "primary", onClick: handleCreateCPUParticleSystem, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateGPUParticleSystem, label: "GPU Particle System" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: gpuParticleSystemName, onChange: (value) => setGpuParticleSystemName(value) }), jsx(SpinButtonPropertyLine, { label: "Capacity", value: gpuParticleSystemCapacity, onChange: (value) => setGpuParticleSystemCapacity(value), min: 1, max: 1000000, step: 1000 }), jsx(Button, { appearance: "primary", onClick: handleCreateGPUParticleSystem, label: "Create" })] })] }), jsxs("div", { className: classes.row, children: [jsx(Button, { onClick: handleCreateNodeParticleSystemAsync, label: "Node Particle System" }), jsxs(SettingsPopover, { children: [jsx(TextInputPropertyLine, { label: "Name", value: nodeParticleSystemName, onChange: (value) => setNodeParticleSystemName(value) }), jsx(TextInputPropertyLine, { label: "Snippet ID", value: nodeParticleSystemSnippetId, onChange: (value) => setNodeParticleSystemSnippetId(value) }), jsx(Button, { appearance: "primary", onClick: handleCreateNodeParticleSystemAsync, label: "Create" })] })] })] }));
517
+ };
518
+
519
+ // TODO: This is just a placeholder for a dynamically installed extension that brings in asset creation tools (node materials, etc.).
520
+ const CreateToolsServiceDefinition = {
521
+ friendlyName: "Creation Tools",
522
+ consumes: [ShellServiceIdentity, SceneContextIdentity],
523
+ factory: (shellService, sceneContext) => {
524
+ const registration = shellService.addSidePane({
525
+ key: "Create",
526
+ title: "Creation Tools",
527
+ icon: CollectionsAdd20Regular,
528
+ horizontalLocation: "left",
529
+ verticalLocation: "top",
530
+ content: () => {
531
+ const scene = useObservableState(() => sceneContext.currentScene, sceneContext.currentSceneObservable);
532
+ return (scene && (jsx(Fragment, { children: jsxs(Accordion, { children: [jsx(AccordionSection, { title: "Meshes", children: jsx(MeshesContent, { scene: scene }) }), jsx(AccordionSection, { title: "Materials", children: jsx(MaterialsContent, { scene: scene }) }), jsx(AccordionSection, { title: "Lights", children: jsx(LightsContent, { scene: scene }) }), jsx(AccordionSection, { title: "Particles", children: jsx(ParticlesContent, { scene: scene }) }), jsx(AccordionSection, { title: "Cameras", children: jsx(CamerasContent, { scene: scene }) })] }) })));
533
+ },
534
+ });
535
+ return {
536
+ dispose: () => registration.dispose(),
537
+ };
538
+ },
539
+ };
540
+ var quickCreateToolsService = {
541
+ serviceDefinitions: [CreateToolsServiceDefinition],
542
+ };
543
+
544
+ export { CreateToolsServiceDefinition, quickCreateToolsService as default };
545
+ //# sourceMappingURL=quickCreateToolsService-C-yzV033.js.map