|
| 1 | +// eslint-disable-next-line import/no-internal-modules |
| 2 | +import { AccordionPane } from "../accordionPane"; |
| 3 | +import { SwitchPropertyLine } from "shared-ui-components/fluent/hoc/switchPropertyLine"; |
| 4 | +import { FontAsset } from "addons/msdfText/fontAsset"; |
| 5 | +import { TextRenderer } from "addons/msdfText/textRenderer"; |
| 6 | +import { Matrix } from "core/Maths/math.vector"; |
| 7 | +import { PhysicsViewer } from "core/Debug/physicsViewer"; |
| 8 | +import type { Mesh } from "core/Meshes/mesh"; |
| 9 | +import type { AbstractMesh } from "core/Meshes/abstractMesh"; |
| 10 | +import { UtilityLayerRenderer } from "core/Rendering/utilityLayerRenderer"; |
| 11 | +import { CreateGround } from "core/Meshes/Builders/groundBuilder"; |
| 12 | +import { GridMaterial } from "materials/grid/gridMaterial"; |
| 13 | +import { Tools } from "core/Misc/tools"; |
| 14 | +import { Color3 } from "core/Maths/math.color"; |
| 15 | +import { Texture } from "core/Materials/Textures/texture"; |
| 16 | +import { StandardMaterial } from "core/Materials/standardMaterial"; |
| 17 | +import type { Scene } from "core/scene"; |
| 18 | +import { MaterialFlags } from "core/Materials/materialFlags"; |
| 19 | +import { BoundPropertyLine } from "../properties/boundPropertyLine"; |
| 20 | +import { Accordion, AccordionSection } from "shared-ui-components/fluent/primitives/accordion"; |
| 21 | + |
| 22 | +const SwitchGrid = function (renderScene: Scene) { |
| 23 | + const scene = UtilityLayerRenderer.DefaultKeepDepthUtilityLayer.utilityLayerScene; |
| 24 | + |
| 25 | + if (!renderScene.reservedDataStore.gridMesh) { |
| 26 | + const extend = renderScene.getWorldExtends(); |
| 27 | + const width = (extend.max.x - extend.min.x) * 5.0; |
| 28 | + const depth = (extend.max.z - extend.min.z) * 5.0; |
| 29 | + |
| 30 | + renderScene.reservedDataStore.gridMesh = CreateGround("grid", { width: 1.0, height: 1.0, subdivisions: 1 }, scene); |
| 31 | + const gridMesh = renderScene.reservedDataStore.gridMesh as AbstractMesh; |
| 32 | + if (!gridMesh.reservedDataStore) { |
| 33 | + gridMesh.reservedDataStore = {}; |
| 34 | + } |
| 35 | + gridMesh.scaling.x = Math.max(width, depth); |
| 36 | + gridMesh.scaling.z = gridMesh.scaling.x; |
| 37 | + gridMesh.reservedDataStore.isInspectorGrid = true; |
| 38 | + gridMesh.isPickable = false; |
| 39 | + |
| 40 | + const groundMaterial = new GridMaterial("GridMaterial", scene); |
| 41 | + groundMaterial.majorUnitFrequency = 10; |
| 42 | + groundMaterial.minorUnitVisibility = 0.3; |
| 43 | + groundMaterial.gridRatio = 0.01; |
| 44 | + groundMaterial.backFaceCulling = false; |
| 45 | + groundMaterial.mainColor = new Color3(1, 1, 1); |
| 46 | + groundMaterial.lineColor = new Color3(1.0, 1.0, 1.0); |
| 47 | + groundMaterial.opacity = 0.8; |
| 48 | + groundMaterial.zOffset = 1.0; |
| 49 | + const textureUrl = Tools.GetAssetUrl("https://assets.babylonjs.com/core/environments/backgroundGround.png"); |
| 50 | + groundMaterial.opacityTexture = new Texture(textureUrl, scene); |
| 51 | + |
| 52 | + gridMesh.material = groundMaterial; |
| 53 | + return; |
| 54 | + } |
| 55 | + const gridMesh = renderScene.reservedDataStore.gridMesh as AbstractMesh; |
| 56 | + gridMesh.dispose(true, true); |
| 57 | + renderScene.reservedDataStore.gridMesh = null; |
| 58 | +}; |
| 59 | + |
| 60 | +const SwitchPhysicsViewers = function (scene: Scene) { |
| 61 | + if (!scene.reservedDataStore.physicsViewer) { |
| 62 | + const physicsViewer = new PhysicsViewer(scene); |
| 63 | + scene.reservedDataStore.physicsViewer = physicsViewer; |
| 64 | + |
| 65 | + for (const mesh of scene.meshes) { |
| 66 | + if (mesh.physicsImpostor) { |
| 67 | + const debugMesh = physicsViewer.showImpostor(mesh.physicsImpostor, mesh as Mesh); |
| 68 | + |
| 69 | + if (debugMesh) { |
| 70 | + debugMesh.reservedDataStore = { hidden: true }; |
| 71 | + debugMesh.material!.reservedDataStore = { hidden: true }; |
| 72 | + } |
| 73 | + } else if (mesh.physicsBody) { |
| 74 | + const debugMesh = physicsViewer.showBody(mesh.physicsBody); |
| 75 | + |
| 76 | + if (debugMesh) { |
| 77 | + debugMesh.reservedDataStore = { hidden: true }; |
| 78 | + debugMesh.material!.reservedDataStore = { hidden: true }; |
| 79 | + } |
| 80 | + } |
| 81 | + } |
| 82 | + |
| 83 | + for (const transformNode of scene.transformNodes) { |
| 84 | + if (transformNode.physicsBody) { |
| 85 | + const debugMesh = physicsViewer.showBody(transformNode.physicsBody); |
| 86 | + |
| 87 | + if (debugMesh) { |
| 88 | + debugMesh.reservedDataStore = { hidden: true }; |
| 89 | + debugMesh.material!.reservedDataStore = { hidden: true }; |
| 90 | + } |
| 91 | + } |
| 92 | + } |
| 93 | + } else { |
| 94 | + scene.reservedDataStore.physicsViewer.dispose(); |
| 95 | + scene.reservedDataStore.physicsViewer = null; |
| 96 | + } |
| 97 | +}; |
| 98 | + |
| 99 | +const SwitchNameViewerAsync = async function (scene: Scene) { |
| 100 | + if (!scene.reservedDataStore.textRenderersHook) { |
| 101 | + scene.reservedDataStore.textRenderers = []; |
| 102 | + if (!scene.reservedDataStore.fontAsset) { |
| 103 | + const sdfFontDefinition = await (await fetch("https://assets.babylonjs.com/fonts/roboto-regular.json")).text(); |
| 104 | + // eslint-disable-next-line require-atomic-updates |
| 105 | + scene.reservedDataStore.fontAsset = new FontAsset(sdfFontDefinition, "https://assets.babylonjs.com/fonts/roboto-regular.png"); |
| 106 | + } |
| 107 | + |
| 108 | + const textRendererPromises = scene.meshes.map(async (mesh) => { |
| 109 | + const textRenderer = await TextRenderer.CreateTextRendererAsync(scene.reservedDataStore.fontAsset!, scene.getEngine()); |
| 110 | + |
| 111 | + textRenderer.addParagraph(mesh.name); |
| 112 | + textRenderer.isBillboard = true; |
| 113 | + textRenderer.isBillboardScreenProjected = true; |
| 114 | + textRenderer.parent = mesh; |
| 115 | + textRenderer.ignoreDepthBuffer = true; |
| 116 | + textRenderer.transformMatrix = Matrix.Scaling(0.02, 0.02, 0.02); |
| 117 | + |
| 118 | + scene.reservedDataStore.textRenderers.push(textRenderer); |
| 119 | + }); |
| 120 | + |
| 121 | + await Promise.all(textRendererPromises); |
| 122 | + |
| 123 | + scene.reservedDataStore.textRenderersHook = scene.onAfterRenderObservable.add(() => { |
| 124 | + for (const textRenderer of scene.reservedDataStore.textRenderers) { |
| 125 | + if (!textRenderer.parent.isVisible || !textRenderer.parent.isEnabled()) { |
| 126 | + continue; |
| 127 | + } |
| 128 | + textRenderer.render(scene.getViewMatrix(), scene.getProjectionMatrix()); |
| 129 | + } |
| 130 | + }); |
| 131 | + } else { |
| 132 | + scene.onAfterRenderObservable.remove(scene.reservedDataStore.textRenderersHook); |
| 133 | + for (const textRenderer of scene.reservedDataStore.textRenderers) { |
| 134 | + textRenderer.dispose(); |
| 135 | + } |
| 136 | + scene.reservedDataStore.textRenderersHook = null; |
| 137 | + scene.reservedDataStore.textRenderers = null; |
| 138 | + } |
| 139 | +}; |
| 140 | + |
| 141 | +export const DebugPane: typeof AccordionPane<Scene> = (props) => { |
| 142 | + const scene = props.context; |
| 143 | + |
| 144 | + if (!scene.reservedDataStore) { |
| 145 | + scene.reservedDataStore = {}; |
| 146 | + } |
| 147 | + |
| 148 | + // Making sure we clean up when the scene is disposed |
| 149 | + scene.onDisposeObservable.addOnce(() => { |
| 150 | + if (scene.reservedDataStore.physicsViewer) { |
| 151 | + SwitchPhysicsViewers(scene); |
| 152 | + } |
| 153 | + |
| 154 | + if (scene.reservedDataStore.textRenderersHook) { |
| 155 | + void SwitchNameViewerAsync(scene); |
| 156 | + scene.reservedDataStore.fontAsset?.dispose(); |
| 157 | + } |
| 158 | + |
| 159 | + if (scene.reservedDataStore.gridMesh) { |
| 160 | + SwitchGrid(scene); |
| 161 | + } |
| 162 | + }); |
| 163 | + |
| 164 | + return ( |
| 165 | + <> |
| 166 | + <Accordion> |
| 167 | + <AccordionSection title="Helpers"> |
| 168 | + <SwitchPropertyLine label="Grid" description="Display a ground grid." value={!!scene.reservedDataStore.gridMesh} onChange={() => SwitchGrid(scene)} /> |
| 169 | + <SwitchPropertyLine |
| 170 | + label="Physics" |
| 171 | + description="Display physic debug info." |
| 172 | + value={!!scene.reservedDataStore.physicsViewer} |
| 173 | + onChange={() => SwitchPhysicsViewers(scene)} |
| 174 | + /> |
| 175 | + <SwitchPropertyLine |
| 176 | + label="Names" |
| 177 | + description="Display mesh names." |
| 178 | + value={!!scene.reservedDataStore.textRenderersHook} |
| 179 | + onChange={() => void SwitchNameViewerAsync(scene)} |
| 180 | + /> |
| 181 | + </AccordionSection> |
| 182 | + <AccordionSection title="Core texture channels"> |
| 183 | + <BoundPropertyLine component={SwitchPropertyLine} key="Diffuse" label="Diffuse" target={StandardMaterial} propertyKey="DiffuseTextureEnabled" /> |
| 184 | + <BoundPropertyLine component={SwitchPropertyLine} key="Ambient" label="Ambient" target={StandardMaterial} propertyKey="AmbientTextureEnabled" /> |
| 185 | + <BoundPropertyLine component={SwitchPropertyLine} key="Specular" label="Specular" target={StandardMaterial} propertyKey="SpecularTextureEnabled" /> |
| 186 | + <BoundPropertyLine component={SwitchPropertyLine} key="Emissive" label="Emissive" target={StandardMaterial} propertyKey="EmissiveTextureEnabled" /> |
| 187 | + <BoundPropertyLine component={SwitchPropertyLine} key="Bump" label="Bump" target={StandardMaterial} propertyKey="BumpTextureEnabled" /> |
| 188 | + <BoundPropertyLine component={SwitchPropertyLine} key="Opacity" label="Opacity" target={StandardMaterial} propertyKey="OpacityTextureEnabled" /> |
| 189 | + <BoundPropertyLine component={SwitchPropertyLine} key="Reflection" label="Reflection" target={StandardMaterial} propertyKey="ReflectionTextureEnabled" /> |
| 190 | + <BoundPropertyLine component={SwitchPropertyLine} key="ColorGrading" label="Color Grading" target={StandardMaterial} propertyKey="ColorGradingTextureEnabled" /> |
| 191 | + <BoundPropertyLine component={SwitchPropertyLine} key="Lightmap" label="Lightmap" target={StandardMaterial} propertyKey="LightmapTextureEnabled" /> |
| 192 | + <BoundPropertyLine component={SwitchPropertyLine} key="Fresnel" label="Fresnel" target={StandardMaterial} propertyKey="FresnelEnabled" /> |
| 193 | + <BoundPropertyLine component={SwitchPropertyLine} key="Detail" label="Detail" target={MaterialFlags} propertyKey="DetailTextureEnabled" /> |
| 194 | + <BoundPropertyLine component={SwitchPropertyLine} key="Decal" label="Decal" target={MaterialFlags} propertyKey="DecalMapEnabled" /> |
| 195 | + </AccordionSection> |
| 196 | + <AccordionSection title="Features"> |
| 197 | + <BoundPropertyLine component={SwitchPropertyLine} key="Animations" label="Animations" target={scene} propertyKey="animationsEnabled" /> |
| 198 | + <BoundPropertyLine component={SwitchPropertyLine} key="Physics" label="Physics" target={scene} propertyKey="physicsEnabled" /> |
| 199 | + <BoundPropertyLine component={SwitchPropertyLine} key="Collisions" label="Collisions" target={scene} propertyKey="collisionsEnabled" /> |
| 200 | + <BoundPropertyLine component={SwitchPropertyLine} key="Fog" label="Fog" target={scene} propertyKey="fogEnabled" /> |
| 201 | + <BoundPropertyLine component={SwitchPropertyLine} key="Lens flares" label="Lens flares" target={scene} propertyKey="lensFlaresEnabled" /> |
| 202 | + <BoundPropertyLine component={SwitchPropertyLine} key="Lights" label="Lights" target={scene} propertyKey="lightsEnabled" /> |
| 203 | + <BoundPropertyLine component={SwitchPropertyLine} key="Particles" label="Particles" target={scene} propertyKey="particlesEnabled" /> |
| 204 | + <BoundPropertyLine component={SwitchPropertyLine} key="Post-processes" label="Post-processes" target={scene} propertyKey="postProcessesEnabled" /> |
| 205 | + <BoundPropertyLine component={SwitchPropertyLine} key="Probes" label="Probes" target={scene} propertyKey="probesEnabled" /> |
| 206 | + <BoundPropertyLine component={SwitchPropertyLine} key="Textures" label="Textures" target={scene} propertyKey="texturesEnabled" /> |
| 207 | + <BoundPropertyLine |
| 208 | + component={SwitchPropertyLine} |
| 209 | + key="Procedural textures" |
| 210 | + label="Procedural textures" |
| 211 | + target={scene} |
| 212 | + propertyKey="proceduralTexturesEnabled" |
| 213 | + /> |
| 214 | + <BoundPropertyLine component={SwitchPropertyLine} key="Render targets" label="Render targets" target={scene} propertyKey="renderTargetsEnabled" /> |
| 215 | + <BoundPropertyLine component={SwitchPropertyLine} key="Shadows" label="Shadows" target={scene} propertyKey="shadowsEnabled" /> |
| 216 | + <BoundPropertyLine component={SwitchPropertyLine} key="Skeletons" label="Skeletons" target={scene} propertyKey="skeletonsEnabled" /> |
| 217 | + <BoundPropertyLine component={SwitchPropertyLine} key="Sprites" label="Sprites" target={scene} propertyKey="spritesEnabled" /> |
| 218 | + </AccordionSection> |
| 219 | + </Accordion> |
| 220 | + <AccordionPane {...props} /> |
| 221 | + </> |
| 222 | + ); |
| 223 | +}; |
0 commit comments