super-three 0.184.0 → 0.185.0

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.
Files changed (366) hide show
  1. package/build/three.cjs +1260 -927
  2. package/build/three.core.js +1104 -829
  3. package/build/three.core.min.js +1 -1
  4. package/build/three.module.js +156 -98
  5. package/build/three.module.min.js +1 -1
  6. package/build/three.tsl.js +11 -4
  7. package/build/three.tsl.min.js +1 -1
  8. package/build/three.webgpu.js +7538 -3367
  9. package/build/three.webgpu.min.js +1 -1
  10. package/build/three.webgpu.nodes.js +7538 -3366
  11. package/build/three.webgpu.nodes.min.js +1 -1
  12. package/examples/jsm/Addons.js +3 -0
  13. package/examples/jsm/controls/ArcballControls.js +6 -2
  14. package/examples/jsm/controls/FirstPersonControls.js +79 -42
  15. package/examples/jsm/controls/TransformControls.js +68 -15
  16. package/examples/jsm/csm/CSMFrustum.js +31 -6
  17. package/examples/jsm/csm/CSMShadowNode.js +4 -1
  18. package/examples/jsm/effects/AsciiEffect.js +14 -1
  19. package/examples/jsm/exporters/DRACOExporter.js +27 -6
  20. package/examples/jsm/exporters/GLTFExporter.js +114 -12
  21. package/examples/jsm/exporters/PLYExporter.js +286 -73
  22. package/examples/jsm/exporters/USDZExporter.js +347 -112
  23. package/examples/jsm/generators/CityGenerator.js +346 -0
  24. package/examples/jsm/generators/ForestGenerator.js +347 -0
  25. package/examples/jsm/generators/TerrainGenerator.js +504 -0
  26. package/examples/jsm/generators/TreeGenerator.js +377 -0
  27. package/examples/jsm/generators/city/SidewalkGenerator.js +253 -0
  28. package/examples/jsm/generators/city/SkyscraperGenerator.js +1357 -0
  29. package/examples/jsm/geometries/LoftGeometry.js +355 -0
  30. package/examples/jsm/helpers/LightProbeGridHelper.js +1 -1
  31. package/examples/jsm/helpers/LightProbeHelper.js +5 -4
  32. package/examples/jsm/helpers/ViewHelper.js +16 -6
  33. package/examples/jsm/inspector/Inspector.js +53 -15
  34. package/examples/jsm/inspector/RendererInspector.js +152 -36
  35. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphEditor.js +1 -1
  36. package/examples/jsm/inspector/extensions/tsl-graph/TSLGraphLoader.js +1 -1
  37. package/examples/jsm/inspector/tabs/Console.js +200 -18
  38. package/examples/jsm/inspector/tabs/Memory.js +8 -0
  39. package/examples/jsm/inspector/tabs/Parameters.js +64 -4
  40. package/examples/jsm/inspector/tabs/Performance.js +21 -6
  41. package/examples/jsm/inspector/tabs/Settings.js +51 -9
  42. package/examples/jsm/inspector/tabs/Timeline.js +178 -93
  43. package/examples/jsm/inspector/tabs/Viewer.js +628 -16
  44. package/examples/jsm/inspector/ui/Graph.js +162 -25
  45. package/examples/jsm/inspector/ui/Item.js +92 -13
  46. package/examples/jsm/inspector/ui/List.js +1 -1
  47. package/examples/jsm/inspector/ui/Profiler.js +90 -45
  48. package/examples/jsm/inspector/ui/Style.js +1788 -1401
  49. package/examples/jsm/inspector/ui/Tab.js +5 -3
  50. package/examples/jsm/inspector/ui/Values.js +71 -6
  51. package/examples/jsm/inspector/ui/utils.js +130 -10
  52. package/examples/jsm/libs/basis/README.md +0 -1
  53. package/examples/jsm/libs/demuxer_mp4.js +3 -3
  54. package/examples/jsm/libs/draco/README.md +0 -1
  55. package/examples/jsm/libs/meshopt_clusterizer.module.js +421 -0
  56. package/examples/jsm/libs/meshopt_simplifier.module.js +627 -0
  57. package/examples/jsm/libs/mikktspace.module.js +34 -9
  58. package/examples/jsm/lighting/ClusteredLighting.js +55 -0
  59. package/examples/jsm/lighting/LightProbeGrid.js +106 -76
  60. package/examples/jsm/lines/LineMaterial.js +38 -15
  61. package/examples/jsm/lines/LineSegments2.js +8 -0
  62. package/examples/jsm/lines/webgpu/LineSegments2.js +8 -0
  63. package/examples/jsm/loaders/3DMLoader.js +1 -1
  64. package/examples/jsm/loaders/DRACOLoader.js +46 -13
  65. package/examples/jsm/loaders/EXRLoader.js +27 -55
  66. package/examples/jsm/loaders/HDRLoader.js +6 -28
  67. package/examples/jsm/loaders/KTX2Loader.js +31 -12
  68. package/examples/jsm/loaders/LDrawLoader.js +8 -8
  69. package/examples/jsm/loaders/LUT3dlLoader.js +2 -2
  70. package/examples/jsm/loaders/LUTCubeLoader.js +2 -2
  71. package/examples/jsm/loaders/LWOLoader.js +4 -0
  72. package/examples/jsm/loaders/LottieLoader.js +1 -1
  73. package/examples/jsm/loaders/MaterialXLoader.js +31 -9
  74. package/examples/jsm/loaders/NRRDLoader.js +3 -3
  75. package/examples/jsm/loaders/PCDLoader.js +7 -7
  76. package/examples/jsm/loaders/PLYLoader.js +218 -55
  77. package/examples/jsm/loaders/SVGLoader.js +547 -495
  78. package/examples/jsm/loaders/TTFLoader.js +1 -1
  79. package/examples/jsm/loaders/USDLoader.js +33 -9
  80. package/examples/jsm/loaders/VRMLLoader.js +1 -1
  81. package/examples/jsm/loaders/usd/USDAParser.js +93 -20
  82. package/examples/jsm/loaders/usd/USDCParser.js +1 -1
  83. package/examples/jsm/loaders/usd/USDComposer.js +52 -19
  84. package/examples/jsm/misc/TileCreasedNormalsPlugin.js +270 -0
  85. package/examples/jsm/misc/Volume.js +2 -2
  86. package/examples/jsm/objects/GroundedSkybox.js +1 -1
  87. package/examples/jsm/objects/Reflector.js +2 -3
  88. package/examples/jsm/objects/Water2Mesh.js +1 -1
  89. package/examples/jsm/physics/AmmoPhysics.js +15 -8
  90. package/examples/jsm/physics/RapierPhysics.js +27 -2
  91. package/examples/jsm/shaders/VolumeShader.js +31 -44
  92. package/examples/jsm/transpiler/GLSLDecoder.js +6 -6
  93. package/examples/jsm/transpiler/Linker.js +1 -1
  94. package/examples/jsm/tsl/display/BloomNode.js +59 -19
  95. package/examples/jsm/tsl/display/DepthOfFieldNode.js +2 -2
  96. package/examples/jsm/tsl/display/FXAANode.js +11 -12
  97. package/examples/jsm/tsl/display/GTAONode.js +34 -13
  98. package/examples/jsm/tsl/display/GodraysNode.js +1 -1
  99. package/examples/jsm/tsl/display/ImportanceSampledEnvironment.js +560 -0
  100. package/examples/jsm/tsl/display/PixelationPassNode.js +2 -2
  101. package/examples/jsm/tsl/display/RecurrentDenoiseNode.js +912 -0
  102. package/examples/jsm/tsl/display/SSAAPassNode.js +13 -25
  103. package/examples/jsm/tsl/display/SSGINode.js +89 -39
  104. package/examples/jsm/tsl/display/SSRNode.js +829 -132
  105. package/examples/jsm/tsl/display/SSSNode.js +2 -2
  106. package/examples/jsm/tsl/display/TemporalReprojectNode.js +1023 -0
  107. package/examples/jsm/tsl/lighting/ClusteredLightsNode.js +622 -0
  108. package/examples/jsm/tsl/lighting/DynamicLightsNode.js +1 -1
  109. package/examples/jsm/tsl/math/curlNoise.js +107 -0
  110. package/examples/jsm/tsl/shadows/TileShadowNode.js +1 -1
  111. package/examples/jsm/tsl/shadows/TileShadowNodeHelper.js +3 -3
  112. package/examples/jsm/tsl/utils/GroundedSkybox.js +62 -0
  113. package/examples/jsm/tsl/utils/RNoise.js +51 -0
  114. package/examples/jsm/tsl/utils/SpecularHelpers.js +325 -0
  115. package/examples/jsm/utils/BufferGeometryUtils.js +126 -59
  116. package/examples/jsm/utils/GeometryCompressionUtils.js +1 -1
  117. package/examples/jsm/utils/SceneOptimizer.js +1 -1
  118. package/examples/jsm/webxr/ARButton.js +1 -1
  119. package/examples/jsm/webxr/WebGLXRFallback.js +89 -0
  120. package/examples/jsm/webxr/XRControllerModelFactory.js +2 -2
  121. package/package.json +7 -7
  122. package/src/Three.TSL.js +10 -3
  123. package/src/Three.WebGPU.js +4 -0
  124. package/src/animation/AnimationAction.js +15 -11
  125. package/src/animation/AnimationClip.js +0 -139
  126. package/src/animation/KeyframeTrack.js +2 -2
  127. package/src/animation/PropertyBinding.js +2 -2
  128. package/src/cameras/Camera.js +2 -2
  129. package/src/cameras/StereoCamera.js +5 -2
  130. package/src/constants.js +1 -1
  131. package/src/core/BufferGeometry.js +29 -7
  132. package/src/core/Object3D.js +17 -7
  133. package/src/core/Raycaster.js +1 -1
  134. package/src/core/RenderTarget.js +15 -2
  135. package/src/extras/PMREMGenerator.js +6 -4
  136. package/src/extras/TextureUtils.js +1 -1
  137. package/src/extras/core/ShapePath.js +149 -160
  138. package/src/geometries/SphereGeometry.js +8 -3
  139. package/src/helpers/DirectionalLightHelper.js +2 -0
  140. package/src/helpers/HemisphereLightHelper.js +2 -0
  141. package/src/helpers/PointLightHelper.js +2 -0
  142. package/src/helpers/SpotLightHelper.js +1 -1
  143. package/src/loaders/DataTextureLoader.js +69 -38
  144. package/src/loaders/LoadingManager.js +5 -0
  145. package/src/loaders/MaterialLoader.js +36 -266
  146. package/src/loaders/ObjectLoader.js +3 -1
  147. package/src/materials/LineBasicMaterial.js +4 -0
  148. package/src/materials/Material.js +196 -1
  149. package/src/materials/MeshBasicMaterial.js +24 -0
  150. package/src/materials/MeshDepthMaterial.js +10 -0
  151. package/src/materials/MeshDistanceMaterial.js +10 -0
  152. package/src/materials/MeshLambertMaterial.js +40 -1
  153. package/src/materials/MeshMatcapMaterial.js +25 -1
  154. package/src/materials/MeshNormalMaterial.js +9 -1
  155. package/src/materials/MeshPhongMaterial.js +40 -1
  156. package/src/materials/MeshPhysicalMaterial.js +38 -0
  157. package/src/materials/MeshStandardMaterial.js +42 -1
  158. package/src/materials/MeshToonMaterial.js +34 -1
  159. package/src/materials/PointsMaterial.js +7 -0
  160. package/src/materials/ShaderMaterial.js +86 -0
  161. package/src/materials/SpriteMaterial.js +7 -0
  162. package/src/materials/nodes/Line2NodeMaterial.js +378 -322
  163. package/src/materials/nodes/MeshBasicNodeMaterial.js +2 -2
  164. package/src/materials/nodes/MeshNormalNodeMaterial.js +2 -2
  165. package/src/materials/nodes/MeshPhongNodeMaterial.js +0 -9
  166. package/src/materials/nodes/MeshPhysicalNodeMaterial.js +0 -30
  167. package/src/materials/nodes/MeshSSSNodeMaterial.js +0 -13
  168. package/src/materials/nodes/MeshStandardNodeMaterial.js +0 -11
  169. package/src/materials/nodes/NodeMaterial.js +115 -71
  170. package/src/materials/nodes/SpriteNodeMaterial.js +0 -10
  171. package/src/materials/nodes/manager/NodeMaterialObserver.js +49 -20
  172. package/src/math/Box3.js +5 -0
  173. package/src/math/FrustumArray.js +103 -133
  174. package/src/math/Interpolant.js +1 -1
  175. package/src/math/MathUtils.js +2 -2
  176. package/src/math/Matrix3.js +11 -0
  177. package/src/math/Matrix4.js +28 -3
  178. package/src/math/Vector2.js +2 -2
  179. package/src/math/Vector3.js +2 -2
  180. package/src/math/Vector4.js +2 -2
  181. package/src/math/interpolants/BezierInterpolant.js +4 -6
  182. package/src/nodes/Nodes.js +2 -5
  183. package/src/nodes/TSL.js +8 -6
  184. package/src/nodes/accessors/Arrays.js +4 -4
  185. package/src/nodes/accessors/Batch.js +108 -0
  186. package/src/nodes/accessors/Bitangent.js +2 -2
  187. package/src/nodes/accessors/BufferAttributeNode.js +13 -2
  188. package/src/nodes/accessors/Camera.js +7 -7
  189. package/src/nodes/accessors/ClippingNode.js +1 -1
  190. package/src/nodes/accessors/Instance.js +264 -0
  191. package/src/nodes/accessors/MaterialNode.js +18 -2
  192. package/src/nodes/accessors/MaterialProperties.js +4 -3
  193. package/src/nodes/accessors/{MorphNode.js → Morph.js} +99 -112
  194. package/src/nodes/accessors/Normal.js +13 -13
  195. package/src/nodes/accessors/Position.js +5 -1
  196. package/src/nodes/accessors/ReferenceNode.js +1 -0
  197. package/src/nodes/accessors/ReflectVector.js +3 -3
  198. package/src/nodes/accessors/SceneProperties.js +1 -1
  199. package/src/nodes/accessors/Skinning.js +263 -0
  200. package/src/nodes/accessors/StorageBufferNode.js +2 -2
  201. package/src/nodes/accessors/StorageTexture3DNode.js +100 -0
  202. package/src/nodes/accessors/StorageTextureNode.js +39 -7
  203. package/src/nodes/accessors/Tangent.js +4 -4
  204. package/src/nodes/accessors/TextureNode.js +60 -5
  205. package/src/nodes/code/FunctionNode.js +2 -16
  206. package/src/nodes/core/MRTNode.js +7 -2
  207. package/src/nodes/core/Node.js +39 -2
  208. package/src/nodes/core/NodeBuilder.js +201 -41
  209. package/src/nodes/core/NodeUtils.js +13 -13
  210. package/src/nodes/core/OutputStructNode.js +1 -1
  211. package/src/nodes/core/OverrideContextNode.js +153 -0
  212. package/src/nodes/core/PropertyNode.js +51 -5
  213. package/src/nodes/core/StackNode.js +56 -34
  214. package/src/nodes/core/StructNode.js +4 -6
  215. package/src/nodes/core/StructTypeNode.js +6 -6
  216. package/src/nodes/core/VarNode.js +8 -0
  217. package/src/nodes/core/VaryingNode.js +12 -2
  218. package/src/nodes/display/BlendModes.js +1 -41
  219. package/src/nodes/display/BumpMapNode.js +6 -1
  220. package/src/nodes/display/ColorAdjustment.js +10 -9
  221. package/src/nodes/display/FrontFacingNode.js +38 -9
  222. package/src/nodes/display/NormalMapNode.js +2 -2
  223. package/src/nodes/display/PassNode.js +35 -43
  224. package/src/nodes/display/PremultiplyAlphaFunctions.js +39 -0
  225. package/src/nodes/display/RenderOutputNode.js +12 -3
  226. package/src/nodes/functions/VolumetricLightingModel.js +40 -7
  227. package/src/nodes/gpgpu/WorkgroupInfoNode.js +1 -1
  228. package/src/nodes/lighting/EnvironmentNode.js +2 -2
  229. package/src/nodes/lighting/IESSpotLightNode.js +40 -2
  230. package/src/nodes/lighting/LightingContextNode.js +10 -2
  231. package/src/nodes/lighting/LightsNode.js +90 -37
  232. package/src/nodes/lighting/PointShadowNode.js +6 -1
  233. package/src/nodes/lighting/ShadowFilterNode.js +21 -52
  234. package/src/nodes/lighting/ShadowNode.js +34 -14
  235. package/src/nodes/materialx/lib/mx_noise.js +2 -2
  236. package/src/nodes/math/ConditionalNode.js +3 -3
  237. package/src/nodes/math/MathNode.js +39 -11
  238. package/src/nodes/math/OperatorNode.js +23 -23
  239. package/src/nodes/parsers/GLSLNodeFunction.js +1 -1
  240. package/src/nodes/pmrem/PMREMNode.js +33 -2
  241. package/src/nodes/tsl/TSLCore.js +63 -18
  242. package/src/nodes/utils/EquirectUV.js +30 -5
  243. package/src/nodes/utils/FunctionOverloadingNode.js +1 -1
  244. package/src/nodes/utils/Packing.js +35 -4
  245. package/src/nodes/utils/RTTNode.js +40 -24
  246. package/src/nodes/utils/ReflectorNode.js +1 -0
  247. package/src/nodes/utils/StorageArrayElementNode.js +1 -1
  248. package/src/objects/BatchedMesh.js +22 -14
  249. package/src/objects/InstancedMesh.js +0 -11
  250. package/src/objects/Skeleton.js +0 -9
  251. package/src/renderers/WebGLRenderer.js +19 -15
  252. package/src/renderers/common/Backend.js +49 -5
  253. package/src/renderers/common/Bindings.js +114 -45
  254. package/src/renderers/common/Buffer.js +9 -0
  255. package/src/renderers/common/ClippingContext.js +10 -2
  256. package/src/renderers/common/Info.js +63 -22
  257. package/src/renderers/common/Lighting.js +53 -5
  258. package/src/renderers/common/RenderList.js +41 -4
  259. package/src/renderers/common/RenderObject.js +73 -13
  260. package/src/renderers/common/Renderer.js +281 -108
  261. package/src/renderers/common/Sampler.js +16 -48
  262. package/src/renderers/common/Textures.js +32 -5
  263. package/src/renderers/common/TimestampQueryPool.js +1 -1
  264. package/src/renderers/common/UniformsGroup.js +31 -9
  265. package/src/renderers/common/XRManager.js +340 -22
  266. package/src/renderers/common/extras/PMREMGenerator.js +15 -38
  267. package/src/renderers/common/nodes/NodeBuilderState.js +9 -1
  268. package/src/renderers/common/nodes/NodeLibrary.js +4 -4
  269. package/src/renderers/common/nodes/NodeManager.js +63 -14
  270. package/src/renderers/common/nodes/NodeUniformBuffer.js +13 -0
  271. package/src/renderers/shaders/ShaderChunk/common.glsl.js +13 -4
  272. package/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js +0 -6
  273. package/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js +1 -1
  274. package/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js +2 -2
  275. package/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js +1 -1
  276. package/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js +1 -1
  277. package/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js +1 -1
  278. package/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js +2 -2
  279. package/src/renderers/shaders/ShaderChunk/normal_vertex.glsl.js +6 -0
  280. package/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js +1 -1
  281. package/src/renderers/shaders/ShaderChunk/transmission_fragment.glsl.js +1 -1
  282. package/src/renderers/shaders/ShaderLib/distance.glsl.js +1 -1
  283. package/src/renderers/webgl/WebGLOutput.js +2 -1
  284. package/src/renderers/webgl/WebGLProgram.js +5 -4
  285. package/src/renderers/webgl/WebGLPrograms.js +12 -5
  286. package/src/renderers/webgl/WebGLRenderLists.js +9 -1
  287. package/src/renderers/webgl/WebGLShaderCache.js +5 -11
  288. package/src/renderers/webgl/WebGLTextures.js +20 -7
  289. package/src/renderers/webgl/WebGLUniformsGroups.js +66 -38
  290. package/src/renderers/webgl-fallback/WebGLBackend.js +84 -25
  291. package/src/renderers/webgl-fallback/nodes/GLSLNodeBuilder.js +138 -8
  292. package/src/renderers/webgl-fallback/utils/WebGLAttributeUtils.js +1 -1
  293. package/src/renderers/webgl-fallback/utils/WebGLTextureUtils.js +52 -22
  294. package/src/renderers/webgl-fallback/utils/WebGLUtils.js +4 -2
  295. package/src/renderers/webgpu/WebGPUBackend.js +480 -169
  296. package/src/renderers/webgpu/descriptors/GPUBindGroupDescriptor.js +48 -0
  297. package/src/renderers/webgpu/descriptors/GPUBufferDescriptor.js +57 -0
  298. package/src/renderers/webgpu/descriptors/GPUCommandEncoderDescriptor.js +30 -0
  299. package/src/renderers/webgpu/descriptors/GPUComputePassDescriptor.js +38 -0
  300. package/src/renderers/webgpu/descriptors/GPUComputePipelineDescriptor.js +48 -0
  301. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageDestInfo.js +47 -0
  302. package/src/renderers/webgpu/descriptors/GPUCopyExternalImageSourceInfo.js +50 -0
  303. package/src/renderers/webgpu/descriptors/GPUExtent3D.js +51 -0
  304. package/src/renderers/webgpu/descriptors/GPUPipelineLayoutDescriptor.js +39 -0
  305. package/src/renderers/webgpu/descriptors/GPUQuerySetDescriptor.js +47 -0
  306. package/src/renderers/webgpu/descriptors/GPURenderBundleEncoderDescriptor.js +74 -0
  307. package/src/renderers/webgpu/descriptors/GPURenderPassColorAttachment.js +72 -0
  308. package/src/renderers/webgpu/descriptors/GPURenderPassDepthStencilAttachment.js +99 -0
  309. package/src/renderers/webgpu/descriptors/GPURenderPassDescriptor.js +72 -0
  310. package/src/renderers/webgpu/descriptors/GPURenderPassTimestampWrites.js +49 -0
  311. package/src/renderers/webgpu/descriptors/GPURenderPipelineDescriptor.js +130 -0
  312. package/src/renderers/webgpu/descriptors/GPUSamplerDescriptor.js +119 -0
  313. package/src/renderers/webgpu/descriptors/GPUShaderModuleDescriptor.js +46 -0
  314. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferInfo.js +57 -0
  315. package/src/renderers/webgpu/descriptors/GPUTexelCopyBufferLayout.js +48 -0
  316. package/src/renderers/webgpu/descriptors/GPUTexelCopyTextureInfo.js +61 -0
  317. package/src/renderers/webgpu/descriptors/GPUTextureDescriptor.js +99 -0
  318. package/src/renderers/webgpu/descriptors/GPUTextureViewDescriptor.js +108 -0
  319. package/src/renderers/webgpu/nodes/StandardNodeLibrary.js +0 -1
  320. package/src/renderers/webgpu/nodes/WGSLNodeBuilder.js +164 -7
  321. package/src/renderers/webgpu/nodes/WGSLNodeFunction.js +1 -1
  322. package/src/renderers/webgpu/utils/WebGPUAttributeUtils.js +98 -38
  323. package/src/renderers/webgpu/utils/WebGPUBindingUtils.js +72 -68
  324. package/src/renderers/webgpu/utils/WebGPUPipelineUtils.js +164 -69
  325. package/src/renderers/webgpu/utils/WebGPUTexturePassUtils.js +158 -95
  326. package/src/renderers/webgpu/utils/WebGPUTextureUtils.js +297 -141
  327. package/src/renderers/webgpu/utils/WebGPUTimestampQueryPool.js +33 -18
  328. package/src/renderers/webgpu/utils/WebGPUUtils.js +38 -3
  329. package/src/textures/DepthTexture.js +1 -1
  330. package/src/textures/ExternalTexture.js +0 -3
  331. package/examples/fonts/LICENSE +0 -13
  332. package/examples/fonts/MPLUSRounded1c/MPLUSRounded1c-Regular.typeface.json.zip +0 -0
  333. package/examples/fonts/MPLUSRounded1c/OFL.txt +0 -91
  334. package/examples/fonts/README.md +0 -11
  335. package/examples/fonts/droid/NOTICE +0 -190
  336. package/examples/fonts/droid/README.txt +0 -18
  337. package/examples/fonts/droid/droid_sans_bold.typeface.json +0 -1
  338. package/examples/fonts/droid/droid_sans_mono_regular.typeface.json +0 -1
  339. package/examples/fonts/droid/droid_sans_regular.typeface.json +0 -1
  340. package/examples/fonts/droid/droid_serif_bold.typeface.json +0 -1
  341. package/examples/fonts/droid/droid_serif_regular.typeface.json +0 -1
  342. package/examples/fonts/gentilis_bold.typeface.json +0 -1
  343. package/examples/fonts/gentilis_regular.typeface.json +0 -1
  344. package/examples/fonts/helvetiker_bold.typeface.json +0 -1
  345. package/examples/fonts/helvetiker_regular.typeface.json +0 -1
  346. package/examples/fonts/optimer_bold.typeface.json +0 -1
  347. package/examples/fonts/optimer_regular.typeface.json +0 -1
  348. package/examples/fonts/ttf/README.md +0 -9
  349. package/examples/fonts/ttf/kenpixel.ttf +0 -0
  350. package/examples/jsm/inspector/extensions/extensions.json +0 -6
  351. package/examples/jsm/libs/ammo.wasm.js +0 -822
  352. package/examples/jsm/libs/ammo.wasm.wasm +0 -0
  353. package/examples/jsm/libs/draco/draco_encoder.js +0 -33
  354. package/examples/jsm/libs/draco/gltf/draco_encoder.js +0 -33
  355. package/examples/jsm/libs/lottie_canvas.module.js +0 -14849
  356. package/examples/jsm/libs/opentype.module.js +0 -14506
  357. package/examples/jsm/libs/rhino3dm/rhino3dm.js +0 -21
  358. package/examples/jsm/libs/rhino3dm/rhino3dm.module.js +0 -16
  359. package/examples/jsm/libs/rhino3dm/rhino3dm.wasm +0 -0
  360. package/examples/jsm/lighting/TiledLighting.js +0 -42
  361. package/examples/jsm/tsl/display/AnamorphicNode.js +0 -293
  362. package/examples/jsm/tsl/lighting/TiledLightsNode.js +0 -442
  363. package/src/nodes/accessors/BatchNode.js +0 -163
  364. package/src/nodes/accessors/InstanceNode.js +0 -349
  365. package/src/nodes/accessors/InstancedMeshNode.js +0 -50
  366. package/src/nodes/accessors/SkinningNode.js +0 -328
@@ -26,7 +26,8 @@ class Performance extends Tab {
26
26
 
27
27
  const graph = new Graph();
28
28
  graph.addLine( 'fps', 'var( --color-fps )' );
29
- //graph.addLine( 'gpu', 'var( --color-yellow )' );
29
+ graph.addLine( 'cpu', 'var( --color-yellow )' );
30
+ graph.addLine( 'gpu', 'var( --color-green )' );
30
31
  graphContainer.append( graph.domElement );
31
32
 
32
33
  //
@@ -45,7 +46,8 @@ class Performance extends Tab {
45
46
  label.appendChild( checkmark );
46
47
  */
47
48
 
48
- const graphStats = new Item( 'Graph Stats', createValueSpan(), createValueSpan(), createValueSpan( 'graph-fps-counter' ) );
49
+ this.graphFpsCounter = createValueSpan();
50
+ const graphStats = new Item( 'Graph Stats', createValueSpan(), createValueSpan(), this.graphFpsCounter );
49
51
  perfList.add( graphStats );
50
52
 
51
53
  const graphItem = new Item( graphContainer );
@@ -160,9 +162,22 @@ class Performance extends Tab {
160
162
 
161
163
  }
162
164
 
163
- updateGraph( inspector/*, frame*/ ) {
165
+ updateGraph( inspector, frame ) {
166
+
167
+ const fps = inspector.fps;
168
+
169
+ this.graph.addPoint( 'fps', fps );
170
+
171
+ if ( frame ) {
172
+
173
+ const cpuValue = Math.min( ( ( frame.cpu || 0 ) * fps ) / 1000, 1.0 ) * fps;
174
+ const gpuValue = Math.min( ( ( frame.gpu || 0 ) * fps ) / 1000, 1.0 ) * fps;
175
+
176
+ this.graph.addPoint( 'cpu', cpuValue );
177
+ this.graph.addPoint( 'gpu', gpuValue );
178
+
179
+ }
164
180
 
165
- this.graph.addPoint( 'fps', inspector.fps );
166
181
  this.graph.update();
167
182
 
168
183
  }
@@ -243,12 +258,12 @@ class Performance extends Tab {
243
258
 
244
259
  //
245
260
 
246
- setText( 'graph-fps-counter', inspector.fps.toFixed() + ' FPS' );
261
+ setText( this.graphFpsCounter, inspector.fps.toFixed() + ' FPS' );
247
262
 
248
263
  //
249
264
 
250
265
  setText( this.frameStats.data[ 1 ], frame.cpu.toFixed( 2 ) );
251
- setText( this.frameStats.data[ 2 ], frame.gpu.toFixed( 2 ) );
266
+ setText( this.frameStats.data[ 2 ], inspector.getRenderer().backend.hasTimestamp ? frame.gpu.toFixed( 2 ) : '-' );
252
267
  setText( this.frameStats.data[ 3 ], frame.total.toFixed( 2 ) );
253
268
 
254
269
  //
@@ -2,7 +2,12 @@ import { Parameters } from './Parameters.js';
2
2
  import { WebGPURenderer, WebGLBackend, Node } from 'three/webgpu';
3
3
  import { getItem, setItem } from '../Inspector.js';
4
4
 
5
- const _EXTENSIONS_PATH = '../extensions/extensions.json';
5
+ const _extensions = [
6
+ {
7
+ name: 'TSL Graph',
8
+ url: '../extensions/tsl-graph/TSLGraphEditor.js'
9
+ }
10
+ ];
6
11
 
7
12
  const _init = WebGPURenderer.prototype.init;
8
13
 
@@ -43,7 +48,8 @@ function _loadState() {
43
48
  _state = {
44
49
  forceWebGL: settings.forceWebGL !== undefined ? settings.forceWebGL : false,
45
50
  captureStackTrace: settings.captureStackTrace !== undefined ? settings.captureStackTrace : false,
46
- activeExtensions: settings.activeExtensions !== undefined ? settings.activeExtensions : {}
51
+ activeExtensions: settings.activeExtensions !== undefined ? settings.activeExtensions : {},
52
+ storage: settings.storage !== undefined ? settings.storage : 'url'
47
53
  };
48
54
 
49
55
  if ( _state.forceWebGL ) {
@@ -67,7 +73,8 @@ function _saveState() {
67
73
  setItem( 'settings', {
68
74
  forceWebGL: _state.forceWebGL,
69
75
  captureStackTrace: _state.captureStackTrace,
70
- activeExtensions: _state.activeExtensions
76
+ activeExtensions: _state.activeExtensions,
77
+ storage: _state.storage
71
78
  } );
72
79
 
73
80
  }
@@ -108,12 +115,51 @@ class Settings extends Parameters {
108
115
 
109
116
  } );
110
117
 
118
+ // Render Modes
119
+
120
+ const modesGroup = this.createGroup( 'Render Modes' );
121
+
122
+ modesGroup.add( { overdraw: false }, 'overdraw' ).name( 'Overdraw' ).onChange( ( enable ) => {
123
+
124
+ this.inspector.overdraw = enable;
125
+
126
+ } ).info( 'Shows how many times each pixel is shaded.' );
127
+
111
128
  }
112
129
 
113
130
  init() {
114
131
 
115
132
  const extensionsGroup = this.createGroup( 'Extensions' );
116
133
 
134
+ const storageGroup = this.createGroup( 'Storage' );
135
+
136
+ const currentState = _loadState();
137
+
138
+ storageGroup.add( currentState, 'storage', { 'URL Session': 'url', 'Keep across Origin': 'origin' } )
139
+ .name( 'Save Settings' )
140
+ .onChange( () => {
141
+
142
+ _saveState();
143
+
144
+ } ).info( `
145
+ Defines how the **Inspector** preferences and states are stored in the browser.
146
+
147
+ **URL Session**
148
+ Saves state based on the exact URL. It will reset the settings whenever the URL changes.
149
+
150
+ **Keep across Origin**
151
+ Shares the same state across any page within the current origin.` );
152
+
153
+ storageGroup.add( {
154
+ clear: () => {
155
+
156
+ localStorage.removeItem( 'threejs-inspector' );
157
+
158
+ location.reload();
159
+
160
+ }
161
+ }, 'clear' ).name( 'Clear Settings' );
162
+
117
163
  this._getExtensions().then( extensions => {
118
164
 
119
165
  for ( const extension of extensions ) {
@@ -230,7 +276,7 @@ class Settings extends Parameters {
230
276
 
231
277
  extension.active = true;
232
278
 
233
- const extUrl = new URL( extension.url, new URL( _EXTENSIONS_PATH, import.meta.url ) ).href;
279
+ const extUrl = new URL( extension.url, import.meta.url ).href;
234
280
 
235
281
  const module = await import( extUrl );
236
282
 
@@ -251,11 +297,7 @@ class Settings extends Parameters {
251
297
 
252
298
  async _getExtensions() {
253
299
 
254
- const url = new URL( _EXTENSIONS_PATH, import.meta.url );
255
-
256
- const extensions = await fetch( url ).then( res => res.json() );
257
-
258
- return extensions;
300
+ return _extensions;
259
301
 
260
302
  }
261
303
 
@@ -1,6 +1,7 @@
1
1
  import { Tab } from '../ui/Tab.js';
2
2
  import { Graph } from '../ui/Graph.js';
3
3
  import { getItem, setItem } from '../Inspector.js';
4
+ import { info } from '../ui/utils.js';
4
5
  import {
5
6
  ByteType,
6
7
  FloatType,
@@ -37,6 +38,7 @@ class Timeline extends Tab {
37
38
 
38
39
  super( 'Timeline', options );
39
40
 
41
+ this.content.style.overflow = 'hidden';
40
42
  this.isRecording = false;
41
43
  this.frames = []; // Array of { id: number, calls: [] }
42
44
 
@@ -55,18 +57,29 @@ class Timeline extends Tab {
55
57
  this.graph.addLine( 'calls', 'var( --color-call )' );
56
58
  this.graph.addLine( 'triangles', 'var( --color-red )' );
57
59
 
58
- const scrollWrapper = document.createElement( 'div' );
59
- scrollWrapper.className = 'list-scroll-wrapper';
60
- this.scrollWrapper = scrollWrapper;
61
- this.content.appendChild( scrollWrapper );
62
-
63
60
  this.buildHeader();
64
61
  this.buildUI();
65
62
 
66
63
  // Bind window resize to update graph bounds
67
64
  window.addEventListener( 'resize', () => {
68
65
 
69
- if ( ! this.isRecording && this.frames.length > 0 ) {
66
+ if ( this.isActive && ! this.isRecording && this.frames.length > 0 ) {
67
+
68
+ this.renderSlider();
69
+
70
+ }
71
+
72
+ } );
73
+
74
+ }
75
+
76
+ init( inspector ) {
77
+
78
+ super.init( inspector );
79
+
80
+ this.profiler.addEventListener( 'resize', () => {
81
+
82
+ if ( this.isActive && ! this.isRecording && this.frames.length > 0 ) {
70
83
 
71
84
  this.renderSlider();
72
85
 
@@ -76,10 +89,22 @@ class Timeline extends Tab {
76
89
 
77
90
  }
78
91
 
92
+ setActive( isActive ) {
93
+
94
+ super.setActive( isActive );
95
+
96
+ if ( isActive && ! this.isRecording && this.frames.length > 0 ) {
97
+
98
+ this.renderSlider();
99
+
100
+ }
101
+
102
+ }
103
+
79
104
  buildHeader() {
80
105
 
81
106
  const header = document.createElement( 'div' );
82
- header.className = 'console-header';
107
+ header.className = 'toolbar';
83
108
 
84
109
  this.recordButton = document.createElement( 'button' );
85
110
  this.recordButton.className = 'console-copy-button'; // Reusing style
@@ -101,16 +126,26 @@ class Timeline extends Tab {
101
126
  clearButton.style.alignItems = 'center';
102
127
  clearButton.addEventListener( 'click', () => this.clear() );
103
128
 
104
- this.viewModeButton = document.createElement( 'button' );
105
- this.viewModeButton.className = 'console-copy-button';
106
- this.viewModeButton.title = 'Toggle View Mode';
107
- this.viewModeButton.textContent = 'Mode: Hierarchy';
108
- this.viewModeButton.style.padding = '0 10px';
109
- this.viewModeButton.style.lineHeight = '24px';
110
- this.viewModeButton.addEventListener( 'click', () => {
129
+ this.viewModeSelect = document.createElement( 'select' );
130
+ this.viewModeSelect.className = 'select';
131
+ this.viewModeSelect.style.width = '120px';
132
+ this.viewModeSelect.style.marginRight = '10px';
133
+
134
+ const hierarchyOption = document.createElement( 'option' );
135
+ hierarchyOption.value = 'hierarchy';
136
+ hierarchyOption.textContent = 'Hierarchy';
137
+ this.viewModeSelect.appendChild( hierarchyOption );
138
+
139
+ const countsOption = document.createElement( 'option' );
140
+ countsOption.value = 'counts';
141
+ countsOption.textContent = 'Count';
142
+ this.viewModeSelect.appendChild( countsOption );
143
+
144
+ this.viewModeSelect.value = this.isHierarchicalView ? 'hierarchy' : 'counts';
145
+
146
+ this.viewModeSelect.addEventListener( 'change', () => {
111
147
 
112
- this.isHierarchicalView = ! this.isHierarchicalView;
113
- this.viewModeButton.textContent = this.isHierarchicalView ? 'Mode: Hierarchy' : 'Mode: Counts';
148
+ this.isHierarchicalView = this.viewModeSelect.value === 'hierarchy';
114
149
 
115
150
  if ( this.selectedFrameIndex !== undefined && this.selectedFrameIndex !== - 1 ) {
116
151
 
@@ -150,37 +185,31 @@ class Timeline extends Tab {
150
185
 
151
186
  const buttonsGroup = document.createElement( 'div' );
152
187
  buttonsGroup.className = 'console-buttons-group';
153
- buttonsGroup.appendChild( this.viewModeButton );
154
188
  buttonsGroup.appendChild( this.recordButton );
155
189
  buttonsGroup.appendChild( this.recordRefreshButton );
156
190
  buttonsGroup.appendChild( this.exportButton );
157
191
  buttonsGroup.appendChild( clearButton );
158
192
 
159
- header.style.display = 'flex';
160
- header.style.justifyContent = 'space-between';
161
- header.style.padding = '6px';
162
- header.style.borderBottom = '1px solid var(--border-color)';
163
-
164
193
  const titleElement = document.createElement( 'div' );
165
- titleElement.textContent = 'Backend Calls';
166
194
  titleElement.style.display = 'flex';
167
195
  titleElement.style.alignItems = 'center';
168
196
  titleElement.style.color = 'var(--text-primary)';
169
197
  titleElement.style.alignSelf = 'center';
170
- titleElement.style.paddingLeft = '5px';
171
198
 
172
199
  this.frameInfo = document.createElement( 'span' );
173
200
  this.frameInfo.style.display = 'inline-flex';
174
201
  this.frameInfo.style.alignItems = 'center';
175
- this.frameInfo.style.marginLeft = '15px';
202
+ this.frameInfo.style.marginLeft = '5px';
176
203
  this.frameInfo.style.fontFamily = 'monospace';
177
204
  this.frameInfo.style.color = 'var(--text-secondary)';
178
205
  this.frameInfo.style.fontSize = '12px';
206
+
207
+ titleElement.appendChild( this.viewModeSelect );
179
208
  titleElement.appendChild( this.frameInfo );
180
209
 
181
210
  header.appendChild( titleElement );
182
211
  header.appendChild( buttonsGroup );
183
- this.scrollWrapper.appendChild( header );
212
+ this.content.appendChild( header );
184
213
 
185
214
  }
186
215
 
@@ -189,7 +218,9 @@ class Timeline extends Tab {
189
218
  const container = document.createElement( 'div' );
190
219
  container.style.display = 'flex';
191
220
  container.style.flexDirection = 'column';
192
- container.style.height = 'calc(100% - 37px)'; // Subtract header height
221
+ container.style.flex = '1';
222
+ container.style.minHeight = '0';
223
+ container.style.marginTop = '10px';
193
224
  container.style.width = '100%';
194
225
 
195
226
  // Top Player/Graph Slider using Graph.js SVG
@@ -204,11 +235,13 @@ class Timeline extends Tab {
204
235
  this.graphSlider.style.margin = '0 10px';
205
236
  this.graphSlider.style.position = 'relative';
206
237
  this.graphSlider.style.cursor = 'crosshair';
238
+ this.graphSlider.style.touchAction = 'none';
207
239
 
208
240
  graphContainer.appendChild( this.graphSlider );
209
241
 
210
242
  // Setup SVG from Graph
211
- this.graph.domElement.style.width = '100%';
243
+ this.graph.domElement.style.width = '0';
244
+ this.graph.domElement.style.minWidth = '100%';
212
245
  this.graph.domElement.style.height = '100%';
213
246
  this.graphSlider.appendChild( this.graph.domElement );
214
247
 
@@ -256,12 +289,12 @@ class Timeline extends Tab {
256
289
  this.graphSlider.tabIndex = 0;
257
290
  this.graphSlider.style.outline = 'none';
258
291
 
259
- // Mouse interactivity on the graph
292
+ // Pointer interactivity on the graph
260
293
  let isDragging = false;
261
294
 
262
295
  const updatePlayheadFromEvent = ( e ) => {
263
296
 
264
- if ( this.frames.length === 0 ) return;
297
+ if ( this.isRecording || this.frames.length === 0 ) return;
265
298
 
266
299
  const rect = this.graphSlider.getBoundingClientRect();
267
300
  let x = e.clientX - rect.left;
@@ -305,7 +338,9 @@ class Timeline extends Tab {
305
338
 
306
339
  };
307
340
 
308
- this.graphSlider.addEventListener( 'mousedown', ( e ) => {
341
+ this.graphSlider.addEventListener( 'pointerdown', ( e ) => {
342
+
343
+ if ( this.isRecording ) return;
309
344
 
310
345
  isDragging = true;
311
346
  this.isManualScrubbing = true;
@@ -314,7 +349,7 @@ class Timeline extends Tab {
314
349
 
315
350
  } );
316
351
 
317
- this.graphSlider.addEventListener( 'mouseenter', () => {
352
+ this.graphSlider.addEventListener( 'pointerenter', () => {
318
353
 
319
354
  if ( this.frames.length > 0 && ! this.isRecording ) {
320
355
 
@@ -324,13 +359,13 @@ class Timeline extends Tab {
324
359
 
325
360
  } );
326
361
 
327
- this.graphSlider.addEventListener( 'mouseleave', () => {
362
+ this.graphSlider.addEventListener( 'pointerleave', () => {
328
363
 
329
364
  this.hoverIndicator.style.display = 'none';
330
365
 
331
366
  } );
332
367
 
333
- this.graphSlider.addEventListener( 'mousemove', ( e ) => {
368
+ this.graphSlider.addEventListener( 'pointermove', ( e ) => {
334
369
 
335
370
  if ( this.frames.length === 0 || this.isRecording ) return;
336
371
 
@@ -414,7 +449,7 @@ class Timeline extends Tab {
414
449
 
415
450
  } );
416
451
 
417
- window.addEventListener( 'mousemove', ( e ) => {
452
+ window.addEventListener( 'pointermove', ( e ) => {
418
453
 
419
454
  if ( isDragging ) {
420
455
 
@@ -449,7 +484,7 @@ class Timeline extends Tab {
449
484
 
450
485
  } );
451
486
 
452
- window.addEventListener( 'mouseup', () => {
487
+ window.addEventListener( 'pointerup', () => {
453
488
 
454
489
  isDragging = false;
455
490
  this.isManualScrubbing = false;
@@ -470,11 +505,12 @@ class Timeline extends Tab {
470
505
  this.timelineTrack.style.flex = '1';
471
506
  this.timelineTrack.style.overflowY = 'auto';
472
507
  this.timelineTrack.style.margin = '10px';
508
+ this.timelineTrack.style.marginTop = '8px';
473
509
  this.timelineTrack.style.backgroundColor = 'var(--background-color)';
474
510
  mainArea.appendChild( this.timelineTrack );
475
511
 
476
512
  container.appendChild( mainArea );
477
- this.scrollWrapper.appendChild( container );
513
+ this.content.appendChild( container );
478
514
 
479
515
  }
480
516
 
@@ -614,42 +650,7 @@ class Timeline extends Tab {
614
650
 
615
651
  }
616
652
 
617
- // Sync playhead when new frames are added if user is actively watching a frame
618
- if ( ! this.isManualScrubbing ) {
619
-
620
- if ( this.isTrackingLatest ) {
621
-
622
- const targetIndex = this.frames.length > 1 ? this.frames.length - 2 : 0;
623
- this.selectFrame( targetIndex );
624
-
625
- } else if ( this.selectedFrameIndex !== - 1 ) {
626
-
627
- const pointCount = this.graph.lines[ 'calls' ].points.length;
628
653
 
629
- if ( pointCount > 0 ) {
630
-
631
- const rect = this.graphSlider.getBoundingClientRect();
632
- const pointStep = rect.width / ( this.graph.maxPoints - 1 );
633
- const offset = rect.width - ( ( pointCount - 1 ) * pointStep );
634
-
635
- let localFrameIndex = Math.round( ( this.fixedScreenX - offset ) / pointStep );
636
- localFrameIndex = Math.max( 0, Math.min( localFrameIndex, pointCount - 1 ) );
637
-
638
- let newFrameIndex = localFrameIndex;
639
-
640
- if ( this.frames.length > pointCount ) {
641
-
642
- newFrameIndex += this.frames.length - pointCount;
643
-
644
- }
645
-
646
- this.selectFrame( newFrameIndex );
647
-
648
- }
649
-
650
- }
651
-
652
- }
653
654
 
654
655
  }
655
656
 
@@ -817,7 +818,7 @@ class Timeline extends Tab {
817
818
 
818
819
  const details = {
819
820
  target: renderTarget.name || 'RenderTarget',
820
- [ `attachments(${ textures.length })` ]: attachments.join( ', ' )
821
+ [ `attachments(${ textures.length })` ]: '\n' + attachments.join( '\n' )
821
822
  };
822
823
 
823
824
  if ( renderTarget.depthTexture ) {
@@ -1044,11 +1045,29 @@ class Timeline extends Tab {
1044
1045
  case 'updateBindings': {
1045
1046
 
1046
1047
  const bindGroup = args[ 0 ];
1047
- const details = { group: bindGroup.name || 'unknown' };
1048
1048
 
1049
- if ( bindGroup.bindings ) {
1049
+ const details = {
1050
+ group: bindGroup.name || 'unknown',
1051
+ count: bindGroup.bindings.length
1052
+ };
1050
1053
 
1051
- details.count = bindGroup.bindings.length;
1054
+ return details;
1055
+
1056
+ }
1057
+
1058
+ case 'createUniformBuffer':
1059
+ case 'destroyUniformBuffer': {
1060
+
1061
+ const binding = args[ 0 ];
1062
+
1063
+ const details = {
1064
+ group: binding.groupNode.name || 'unknown',
1065
+ size: binding.byteLength + ' bytes'
1066
+ };
1067
+
1068
+ if ( binding.name !== details.group ) {
1069
+
1070
+ details.name = binding.name;
1052
1071
 
1053
1072
  }
1054
1073
 
@@ -1302,6 +1321,8 @@ class Timeline extends Tab {
1302
1321
 
1303
1322
  selectFrame( index ) {
1304
1323
 
1324
+ if ( this.isRecording ) return;
1325
+
1305
1326
  if ( index < 0 || index >= this.frames.length ) return;
1306
1327
 
1307
1328
  this.selectedFrameIndex = index;
@@ -1310,9 +1331,16 @@ class Timeline extends Tab {
1310
1331
  this.renderTimelineTrack( frame );
1311
1332
 
1312
1333
  // Update UI texts
1313
- const group = ( c, text ) => `<span style="display:inline-flex;align-items:center;margin-left:12px;"><span style="width:6px;height:6px;border-radius:50%;background-color:${c};margin-right:6px;"></span>${text}</span>`;
1334
+ const isCompact = this.profiler.panel.offsetWidth < 800;
1335
+ const frameLabel = isCompact ? '' : 'Frame: ';
1336
+ const fpsSuffix = isCompact ? '' : ' FPS';
1337
+ const callsSuffix = isCompact ? '' : ' calls';
1338
+ const trianglesSuffix = isCompact ? '' : ' triangles';
1339
+
1340
+ const group = ( c, text ) => `<span style="display:inline-flex;align-items:center;margin-left:12px;flex-shrink:0;"><span style="width:6px;height:6px;border-radius:50%;background-color:${c};margin-right:6px;flex-shrink:0;"></span>${text}</span>`;
1314
1341
  const maxTriangles = Math.max( this.baseTriangles, frame.triangles || 0 );
1315
- this.frameInfo.innerHTML = 'Frame: ' + frame.id + group( 'var(--color-fps)', ( frame.fps || 0 ).toFixed( 1 ) + ' FPS' ) + group( 'var(--color-call)', frame.calls.length + ' calls' ) + group( 'var(--color-red)', ( frame.triangles || 0 ) + ' / ' + maxTriangles + ' triangles' );
1342
+ const trianglesText = isCompact ? ( frame.triangles || 0 ) : ( frame.triangles || 0 ) + ' / ' + maxTriangles + trianglesSuffix;
1343
+ this.frameInfo.innerHTML = frameLabel + frame.id + group( 'var(--color-fps)', ( frame.fps || 0 ).toFixed( 1 ) + fpsSuffix ) + group( 'var(--color-call)', frame.calls.length + callsSuffix ) + group( 'var(--color-red)', trianglesText );
1316
1344
 
1317
1345
  // Update playhead position
1318
1346
  const rect = this.graphSlider.getBoundingClientRect();
@@ -1372,27 +1400,32 @@ class Timeline extends Tab {
1372
1400
  if ( ! block ) {
1373
1401
 
1374
1402
  block = document.createElement( 'div' );
1403
+ block.style.display = 'flex';
1404
+ block.style.alignItems = 'center';
1375
1405
  block.style.padding = '4px 8px';
1376
1406
  block.style.margin = '2px 0';
1377
1407
  block.style.backgroundColor = 'rgba(255, 255, 255, 0.03)';
1378
1408
  block.style.fontFamily = 'monospace';
1379
1409
  block.style.fontSize = '12px';
1380
1410
  block.style.color = 'var(--text-primary)';
1381
- block.style.whiteSpace = 'nowrap';
1382
1411
  block.style.overflow = 'hidden';
1383
- block.style.textOverflow = 'ellipsis';
1384
- block.style.display = 'flex';
1385
- block.style.alignItems = 'center';
1386
1412
 
1387
1413
  block.arrow = document.createElement( 'span' );
1388
1414
  block.arrow.style.fontSize = '10px';
1389
- block.arrow.style.marginRight = '10px';
1415
+ block.arrow.style.marginRight = '8px';
1390
1416
  block.arrow.style.cursor = 'pointer';
1391
- block.arrow.style.width = '26px';
1417
+ block.arrow.style.width = '35px';
1392
1418
  block.arrow.style.textAlign = 'center';
1419
+ block.arrow.style.flexShrink = '0';
1420
+ block.arrow.style.whiteSpace = 'nowrap';
1393
1421
  block.appendChild( block.arrow );
1394
1422
 
1395
1423
  block.titleSpan = document.createElement( 'span' );
1424
+ block.titleSpan.style.flex = '1';
1425
+ block.titleSpan.style.minWidth = '0';
1426
+ block.titleSpan.style.overflow = 'hidden';
1427
+ block.titleSpan.style.textOverflow = 'ellipsis';
1428
+ block.titleSpan.style.whiteSpace = 'nowrap';
1396
1429
  block.appendChild( block.titleSpan );
1397
1430
 
1398
1431
  block.addEventListener( 'click', ( e ) => {
@@ -1437,6 +1470,8 @@ class Timeline extends Tab {
1437
1470
 
1438
1471
  renderTimelineTrack( frame ) {
1439
1472
 
1473
+ if ( this.isRecording ) return;
1474
+
1440
1475
  if ( ! frame || frame.calls.length === 0 ) {
1441
1476
 
1442
1477
  this.timelineTrack.innerHTML = '';
@@ -1473,7 +1508,7 @@ class Timeline extends Tab {
1473
1508
 
1474
1509
  } else {
1475
1510
 
1476
- currentGroup = { method: call.method, count: 1, formatedDetails, target: call.target };
1511
+ currentGroup = { method: call.method, count: 1, formatedDetails, target: call.target, details: call.details };
1477
1512
  groupedCalls.push( currentGroup );
1478
1513
 
1479
1514
  }
@@ -1503,6 +1538,57 @@ class Timeline extends Tab {
1503
1538
  block.style.marginLeft = ( currentIndent * indentSize ) + 'px';
1504
1539
  block.style.borderLeft = '4px solid ' + this.getColorForMethod( call.method );
1505
1540
 
1541
+ // Clean up any old info-icon directly under block
1542
+ const directInfoIcon = block.querySelector( ':scope > .info-icon' );
1543
+ if ( directInfoIcon ) {
1544
+
1545
+ directInfoIcon.remove();
1546
+
1547
+ }
1548
+
1549
+ // Build titleSpan content
1550
+ block.titleSpan.textContent = '';
1551
+
1552
+ const methodSpan = document.createElement( 'span' );
1553
+ methodSpan.textContent = call.method;
1554
+ block.titleSpan.appendChild( methodSpan );
1555
+
1556
+ if ( call.details ) {
1557
+
1558
+ let tooltipText = `### ${call.method}\n`;
1559
+ for ( const key in call.details ) {
1560
+
1561
+ if ( call.details[ key ] !== undefined ) {
1562
+
1563
+ tooltipText += `**${key}**: ${call.details[ key ]}\n`;
1564
+
1565
+ }
1566
+
1567
+ }
1568
+
1569
+ const infoIcon = info( block.titleSpan, tooltipText );
1570
+ infoIcon.style.flexShrink = '0';
1571
+ infoIcon.style.marginLeft = '6px';
1572
+ infoIcon.style.display = 'inline-flex';
1573
+ infoIcon.style.verticalAlign = 'middle';
1574
+
1575
+ }
1576
+
1577
+ const detailsAndCountSpan = document.createElement( 'span' );
1578
+ let detailsAndCountHTML = ( call.formatedDetails ? call.formatedDetails : '' );
1579
+ if ( call.count > 1 ) {
1580
+
1581
+ detailsAndCountHTML += ` <span style="opacity: 0.5">( ${call.count} )</span>`;
1582
+
1583
+ }
1584
+
1585
+ if ( detailsAndCountHTML ) {
1586
+
1587
+ detailsAndCountSpan.innerHTML = detailsAndCountHTML;
1588
+ block.titleSpan.appendChild( detailsAndCountSpan );
1589
+
1590
+ }
1591
+
1506
1592
  const currentParent = elementStack[ elementStack.length - 1 ];
1507
1593
 
1508
1594
  // Only add to DOM if parent is not collapsed
@@ -1530,22 +1616,14 @@ class Timeline extends Tab {
1530
1616
  block.arrow.style.display = 'inline-block';
1531
1617
  block.arrow.textContent = isCollapsed ? '[ + ]' : '[ - ]';
1532
1618
 
1533
- block.titleSpan.innerHTML = call.method + ( call.formatedDetails ? call.formatedDetails : '' ) + ( call.count > 1 ? ` <span style="opacity: 0.5">( ${call.count} )</span>` : '' );
1534
-
1535
1619
  currentIndent ++;
1536
1620
  elementStack.push( { element: block, isCollapsed: currentParent.isCollapsed || isCollapsed, id: groupId, beginCount: 0 } );
1537
1621
 
1538
1622
  } else if ( call.method.startsWith( 'finish' ) ) {
1539
1623
 
1540
- block.titleSpan.innerHTML = call.method + ( call.formatedDetails ? call.formatedDetails : '' ) + ( call.count > 1 ? ` <span style="opacity: 0.5">( ${call.count} )</span>` : '' );
1541
-
1542
1624
  currentIndent = Math.max( 0, currentIndent - 1 );
1543
1625
  elementStack.pop();
1544
1626
 
1545
- } else {
1546
-
1547
- block.titleSpan.innerHTML = call.method + ( call.formatedDetails ? call.formatedDetails : '' ) + ( call.count > 1 ? ` <span style="opacity: 0.5">( ${call.count} )</span>` : '' );
1548
-
1549
1627
  }
1550
1628
 
1551
1629
  }
@@ -1575,6 +1653,13 @@ class Timeline extends Tab {
1575
1653
  block.style.marginLeft = '0px';
1576
1654
  block.style.borderLeft = '4px solid ' + this.getColorForMethod( call.method );
1577
1655
 
1656
+ const infoIcon = block.querySelector( '.info-icon' );
1657
+ if ( infoIcon ) {
1658
+
1659
+ infoIcon.remove();
1660
+
1661
+ }
1662
+
1578
1663
  block.titleSpan.innerHTML = call.method + ( call.count > 1 ? ` <span style="opacity: 0.5">( ${call.count} )</span>` : '' );
1579
1664
 
1580
1665
  if ( trackChildren[ childIndex ] !== block ) {