瀏覽代碼

Changes for r157 update - Updated event type system

master
Palash Bansal 1 年之前
父節點
當前提交
b0349db000
沒有連結到貢獻者的電子郵件帳戶。
共有 100 個檔案被更改,包括 814 行新增434 行删除
  1. 19
    26
      package-lock.json
  2. 8
    8
      package.json
  3. 1
    1
      plugins/configurator/package.json
  4. 1
    1
      plugins/configurator/src/GridItemListPlugin.ts
  5. 1
    1
      plugins/geometry-generator/package.json
  6. 1
    1
      plugins/geometry-generator/src/GeometryGeneratorPlugin.ts
  7. 1
    1
      plugins/gltf-transform/package.json
  8. 1
    1
      plugins/gltf-transform/src/GLTFDracoExportPlugin.ts
  9. 1
    1
      plugins/network/package.json
  10. 11
    1
      plugins/network/src/AWSClientPlugin.ts
  11. 1
    1
      plugins/network/src/TransfrSharePlugin.ts
  12. 1
    1
      plugins/svg-renderer/package.json
  13. 1
    1
      plugins/svg-renderer/src/BasicSVGRendererPlugin.ts
  14. 4
    4
      plugins/svg-renderer/src/ThreeSVGRendererPlugin.ts
  15. 2
    2
      plugins/tweakpane-editor/package.json
  16. 4
    4
      plugins/tweakpane-editor/src/HierarchyUiPlugin.ts
  17. 15
    5
      src/assetmanager/AssetExporter.ts
  18. 37
    11
      src/assetmanager/AssetImporter.ts
  19. 14
    7
      src/assetmanager/AssetManager.ts
  20. 29
    3
      src/assetmanager/IAssetImporter.ts
  21. 6
    7
      src/assetmanager/MaterialManager.ts
  22. 1
    1
      src/assetmanager/export/EXRExporter2.ts
  23. 2
    2
      src/assetmanager/import/MTLLoader2.ts
  24. 1
    2
      src/assetmanager/index.ts
  25. 18
    11
      src/core/ICamera.ts
  26. 24
    9
      src/core/IGeometry.ts
  27. 71
    12
      src/core/IMaterial.ts
  28. 133
    22
      src/core/IObject.ts
  29. 16
    20
      src/core/IRenderer.ts
  30. 85
    15
      src/core/IScene.ts
  31. 11
    9
      src/core/ITexture.ts
  32. 9
    2
      src/core/camera/CameraView.ts
  33. 6
    2
      src/core/camera/ICameraControls.ts
  34. 11
    7
      src/core/camera/OrthographicCamera2.ts
  35. 11
    7
      src/core/camera/PerspectiveCamera2.ts
  36. 2
    2
      src/core/geometry/BufferGeometry2.ts
  37. 16
    16
      src/core/index.ts
  38. 2
    2
      src/core/light/AmbientLight2.ts
  39. 3
    6
      src/core/light/DirectionalLight2.ts
  40. 2
    2
      src/core/light/HemisphereLight2.ts
  41. 9
    10
      src/core/light/ILight.ts
  42. 2
    2
      src/core/light/PointLight2.ts
  43. 2
    2
      src/core/light/RectAreaLight2.ts
  44. 2
    2
      src/core/light/SpotLight2.ts
  45. 5
    8
      src/core/material/LegacyPhongMaterial.ts
  46. 5
    14
      src/core/material/LineMaterial2.ts
  47. 4
    7
      src/core/material/ObjectShaderMaterial.ts
  48. 4
    6
      src/core/material/PhysicalMaterial.ts
  49. 4
    3
      src/core/material/ShaderMaterial2.ts
  50. 14
    8
      src/core/material/UnlitLineMaterial.ts
  51. 4
    6
      src/core/material/UnlitMaterial.ts
  52. 5
    5
      src/core/material/iMaterialCommons.ts
  53. 4
    5
      src/core/object/Mesh2.ts
  54. 22
    24
      src/core/object/RootScene.ts
  55. 4
    4
      src/core/object/iCameraCommons.ts
  56. 1
    1
      src/core/object/iLightCommons.ts
  57. 12
    11
      src/core/object/iObjectCommons.ts
  58. 9
    2
      src/plugins/animation/CameraViewPlugin.ts
  59. 8
    2
      src/plugins/animation/GLTFAnimationPlugin.ts
  60. 1
    1
      src/plugins/animation/PopmotionPlugin.ts
  61. 1
    1
      src/plugins/animation/TransformAnimationPlugin.ts
  62. 2
    2
      src/plugins/base/AAssetManagerProcessStatePlugin.ts
  63. 1
    1
      src/plugins/base/ACameraControlsPlugin.ts
  64. 11
    5
      src/plugins/base/BaseGroundPlugin.ts
  65. 2
    2
      src/plugins/base/PipelinePassPlugin.ts
  66. 1
    1
      src/plugins/configurator/MaterialConfiguratorBasePlugin.ts
  67. 1
    1
      src/plugins/configurator/SwitchNodeBasePlugin.ts
  68. 1
    1
      src/plugins/export/AssetExporterPlugin.ts
  69. 1
    1
      src/plugins/export/CanvasSnapshotPlugin.ts
  70. 12
    3
      src/plugins/export/FileTransferPlugin.ts
  71. 1
    1
      src/plugins/extras/GLTFKHRMaterialVariantsPlugin.ts
  72. 1
    1
      src/plugins/extras/HDRiGroundPlugin.ts
  73. 1
    1
      src/plugins/extras/Object3DGeneratorPlugin.ts
  74. 1
    1
      src/plugins/extras/Object3DWidgetsPlugin.ts
  75. 1
    1
      src/plugins/extras/SimplifyModifierPlugin.ts
  76. 8
    8
      src/plugins/index.ts
  77. 11
    2
      src/plugins/interaction/DropzonePlugin.ts
  78. 1
    1
      src/plugins/interaction/EditorViewWidgetPlugin.ts
  79. 7
    2
      src/plugins/interaction/FullScreenPlugin.ts
  80. 2
    2
      src/plugins/interaction/InteractionPromptPlugin.ts
  81. 14
    7
      src/plugins/interaction/PickingPlugin.ts
  82. 1
    2
      src/plugins/interaction/TransformControlsPlugin.ts
  83. 1
    1
      src/plugins/interaction/UndoManagerPlugin.ts
  84. 1
    1
      src/plugins/material/ClearcoatTintPlugin.ts
  85. 1
    1
      src/plugins/material/CustomBumpMapPlugin.ts
  86. 1
    1
      src/plugins/material/FragmentClippingExtensionPlugin.ts
  87. 1
    1
      src/plugins/material/NoiseBumpMaterialPlugin.ts
  88. 1
    1
      src/plugins/material/ParallaxMappingPlugin.ts
  89. 1
    2
      src/plugins/pipeline/DepthBufferPlugin.ts
  90. 7
    3
      src/plugins/pipeline/FrameFadePlugin.ts
  91. 5
    3
      src/plugins/pipeline/GBufferPlugin.ts
  92. 1
    2
      src/plugins/pipeline/NormalBufferPlugin.ts
  93. 1
    2
      src/plugins/pipeline/ProgressivePlugin.ts
  94. 1
    2
      src/plugins/pipeline/SSAAPlugin.ts
  95. 1
    2
      src/plugins/pipeline/SSAOPlugin.ts
  96. 2
    2
      src/plugins/postprocessing/AScreenPassExtensionPlugin.ts
  97. 1
    1
      src/plugins/postprocessing/ChromaticAberrationPlugin.ts
  98. 1
    1
      src/plugins/postprocessing/FilmicGrainPlugin.ts
  99. 1
    1
      src/plugins/postprocessing/TonemapPlugin.ts
  100. 0
    0
      src/plugins/postprocessing/VignettePlugin.ts

+ 19
- 26
package-lock.json 查看文件

{ {
"name": "threepipe", "name": "threepipe",
"version": "0.0.37",
"version": "0.0.38",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "threepipe", "name": "threepipe",
"version": "0.0.37",
"version": "0.0.38",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1002/package.tgz",
"@types/webxr": "^0.5.1", "@types/webxr": "^0.5.1",
"@types/wicg-file-system-access": "^2020.9.5", "@types/wicg-file-system-access": "^2020.9.5",
"popmotion": "^11.0.5", "popmotion": "^11.0.5",
"rimraf": "^5.0.1", "rimraf": "^5.0.1",
"rollup-plugin-glsl": "^1.3.0", "rollup-plugin-glsl": "^1.3.0",
"rollup-plugin-license": "^3.0.1", "rollup-plugin-license": "^3.0.1",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz",
"tslib": "^2.5.0", "tslib": "^2.5.0",
"typedoc": "^0.27.5", "typedoc": "^0.27.5",
"typescript": "5.7.2", "typescript": "5.7.2",
"win-node-env": "^0.6.1" "win-node-env": "^0.6.1"
}, },
"peerDependencies": { "peerDependencies": {
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz"
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"three": { "three": {
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/@tweenjs/tween.js": {
"version": "18.6.4",
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-18.6.4.tgz",
"integrity": "sha512-lB9lMjuqjtuJrx7/kOkqQBtllspPIN+96OvTCeJ2j5FEzinoAXTdAMFnDAQT1KVPRlnYfBrqxtqP66vDM40xxQ==",
"license": "MIT"
},
"node_modules/@types/argparse": { "node_modules/@types/argparse": {
"version": "1.0.38", "version": "1.0.38",
"resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/three": { "node_modules/@types/three": {
"version": "0.153.1002",
"resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz",
"integrity": "sha512-C0gfzxmzvVR0dwzBtHlgA7HoTUoLeDalMksQCgq+suzqhAfbgLVBjE641NtNiEyp1TQmEOCVfgBBzpq3AboRpg==",
"version": "0.157.1002",
"resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1002/package.tgz",
"integrity": "sha512-Awi3M95BysLnWcQYceEwwU/9IUOd0NeXCo+ldvRWbnHjbyCAwQKb2pSsEuhYcdA6Nk6sbJQMY814Svqy0fYuJg==",
"dependencies": { "dependencies": {
"@tweenjs/tween.js": "~18.6.4",
"fflate": "~0.6.9",
"lil-gui": "~0.17.0"
"fflate": "~0.6.10",
"meshoptimizer": "~0.18.1"
} }
}, },
"node_modules/@types/unist": { "node_modules/@types/unist": {
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/lil-gui": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/lil-gui/-/lil-gui-0.17.0.tgz",
"integrity": "sha512-MVBHmgY+uEbmJNApAaPbtvNh1RCAeMnKym82SBjtp5rODTYKWtM+MXHCifLe2H2Ti1HuBGBtK/5SyG4ShQ3pUQ==",
"license": "MIT"
},
"node_modules/lilconfig": { "node_modules/lilconfig": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/meshoptimizer": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz",
"integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==",
"license": "MIT"
},
"node_modules/methods": { "node_modules/methods": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"license": "MIT" "license": "MIT"
}, },
"node_modules/three": { "node_modules/three": {
"version": "0.153.1006",
"resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz",
"integrity": "sha512-vUj+kY9FDleRTLn+T8lbn5m8KQLOCR1nuQx2MyUtBrmYm3I+ttnfRlgjU5p/y2vrzjqnP6bCH5bfwp43YKl6LA==",
"version": "0.157.1002",
"resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz",
"integrity": "sha512-xnfOnDX1UmcKc992mYitqY0EOcBNDqI7hxPoQJRdFmTCbjpTe6LYhjN0LbTozVM1RmmpUZa3Tw2Ji8h1hh7QuQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },

+ 8
- 8
package.json 查看文件

{ {
"name": "threepipe", "name": "threepipe",
"version": "0.0.38",
"version": "0.0.39",
"description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.", "description": "A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.",
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.mjs", "module": "dist/index.mjs",
"rimraf": "^5.0.1", "rimraf": "^5.0.1",
"rollup-plugin-glsl": "^1.3.0", "rollup-plugin-glsl": "^1.3.0",
"rollup-plugin-license": "^3.0.1", "rollup-plugin-license": "^3.0.1",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.155.1001/package.tgz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz",
"tslib": "^2.5.0", "tslib": "^2.5.0",
"typedoc": "^0.27.5", "typedoc": "^0.27.5",
"typescript": "5.7.2", "typescript": "5.7.2",
"vitepress-plugin-nprogress": "^0.0.4" "vitepress-plugin-nprogress": "^0.0.4"
}, },
"dependencies": { "dependencies": {
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1002/package.tgz",
"@types/webxr": "^0.5.1", "@types/webxr": "^0.5.1",
"@types/wicg-file-system-access": "^2020.9.5", "@types/wicg-file-system-access": "^2020.9.5",
"stats.js": "^0.17.0", "stats.js": "^0.17.0",
"popmotion": "^11.0.5" "popmotion": "^11.0.5"
}, },
"peerDependencies": { "peerDependencies": {
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.153.1006/package.tgz"
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"three": { "three": {
"dependencies": { "dependencies": {
"uiconfig.js": "^0.1.3", "uiconfig.js": "^0.1.3",
"ts-browser-helpers": "^0.16.2", "ts-browser-helpers": "^0.16.2",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.155.1007/package.tgz",
"three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.155.1007.tar.gz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.153.1002/package.tgz",
"@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.153.1002.tar.gz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.157.1002/package.tgz",
"three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.157.1002.tar.gz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.157.1002/package.tgz",
"@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.157.1002.tar.gz",
"@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three" "@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three"
}, },
"local_dependencies": { "local_dependencies": {

+ 1
- 1
plugins/configurator/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.30"
"threepipe": "^0.0.39"
} }
} }
}, },

+ 1
- 1
plugins/configurator/src/GridItemListPlugin.ts 查看文件

/** /**
* A helper plugin to create a a simple list of small grids like for material or object configurator * A helper plugin to create a a simple list of small grids like for material or object configurator
*/ */
export class GridItemListPlugin extends AViewerPluginSync<''> {
export class GridItemListPlugin extends AViewerPluginSync {
enabled = true enabled = true
toJSON: any = undefined toJSON: any = undefined
create = GridItemList.Create create = GridItemList.Create

+ 1
- 1
plugins/geometry-generator/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.20"
"threepipe": "^0.0.39"
} }
} }
}, },

+ 1
- 1
plugins/geometry-generator/src/GeometryGeneratorPlugin.ts 查看文件

* Geometry generator plugin to create updatable parametric objects/geometries. * Geometry generator plugin to create updatable parametric objects/geometries.
* Includes support for several primitive types from three.js * Includes support for several primitive types from three.js
*/ */
export class GeometryGeneratorPlugin extends AViewerPluginSync<''> {
export class GeometryGeneratorPlugin extends AViewerPluginSync {
public static readonly PluginType = 'GeometryGeneratorPlugin' public static readonly PluginType = 'GeometryGeneratorPlugin'
enabled = true enabled = true
toJSON: any = undefined toJSON: any = undefined

+ 1
- 1
plugins/gltf-transform/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.35"
"threepipe": "^0.0.39"
} }
} }
}, },

+ 1
- 1
plugins/gltf-transform/src/GLTFDracoExportPlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class GLTFDracoExportPlugin extends AViewerPluginSync<''> {
export class GLTFDracoExportPlugin extends AViewerPluginSync {
public static readonly PluginType = 'GLTFDracoExportPlugin' public static readonly PluginType = 'GLTFDracoExportPlugin'
enabled = true enabled = true



+ 1
- 1
plugins/network/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.30"
"threepipe": "^0.0.39"
} }
} }
}, },

+ 11
- 1
plugins/network/src/AWSClientPlugin.ts 查看文件

import { import {
AViewerPluginEventMap,
AViewerPluginSync, AViewerPluginSync,
FileTransferPlugin, FileTransferPlugin,
pathJoin, pathJoin,
} from 'threepipe' } from 'threepipe'
import {AwsClient, AwsV4Signer} from 'aws4fetch' import {AwsClient, AwsV4Signer} from 'aws4fetch'


export interface AWSClientPluginEventMap extends AViewerPluginEventMap {
fileUpload: {
name: string
blob: Blob
response: Response
path: string
}
}

/** /**
* AWSClientPlugin * AWSClientPlugin
* Provides `fetch` function that performs a fetch request with AWS v4 signing. * Provides `fetch` function that performs a fetch request with AWS v4 signing.
* {@todo Make an example for AWSClient Plugin} * {@todo Make an example for AWSClient Plugin}
*/ */
@uiFolderContainer('AWS/S3 Client') @uiFolderContainer('AWS/S3 Client')
export class AWSClientPlugin extends AViewerPluginSync<'fileUpload'> {
export class AWSClientPlugin extends AViewerPluginSync<AWSClientPluginEventMap> {
static readonly PluginType = 'AWSClientPlugin1' static readonly PluginType = 'AWSClientPlugin1'
declare uiConfig: UiObjectConfig declare uiConfig: UiObjectConfig



+ 1
- 1
plugins/network/src/TransfrSharePlugin.ts 查看文件

* Note: since the uploaded files are publicly accessible by anyone by default, it is recommended to encrypt the file using the exporter options or use a secure backend. * Note: since the uploaded files are publicly accessible by anyone by default, it is recommended to encrypt the file using the exporter options or use a secure backend.
*/ */
@uiFolderContainer('Share Link') @uiFolderContainer('Share Link')
export class TransfrSharePlugin extends AViewerPluginSync<''> {
export class TransfrSharePlugin extends AViewerPluginSync {
public static readonly PluginType = 'TransfrSharePlugin' public static readonly PluginType = 'TransfrSharePlugin'


toJSON: any = null toJSON: any = null

+ 1
- 1
plugins/svg-renderer/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.30"
"threepipe": "^0.0.39"
} }
} }
}, },

+ 1
- 1
plugins/svg-renderer/src/BasicSVGRendererPlugin.ts 查看文件

* SVG rendering of 3d objects using SVGRenderer from three/addons * SVG rendering of 3d objects using SVGRenderer from three/addons
*/ */
@uiFolderContainer('SVG Renderer') @uiFolderContainer('SVG Renderer')
export class BasicSVGRendererPlugin extends AViewerPluginSync<''> {
export class BasicSVGRendererPlugin extends AViewerPluginSync {
static readonly PluginType = 'BasicSVGRendererPlugin' static readonly PluginType = 'BasicSVGRendererPlugin'


@uiToggle() @uiToggle()

+ 4
- 4
plugins/svg-renderer/src/ThreeSVGRendererPlugin.ts 查看文件

* SVG Rendering from 3d scenes helper plugin using [three-svg-renderer](https://www.npmjs.com/package/three-svg-renderer) (GPLV3 Licenced) * SVG Rendering from 3d scenes helper plugin using [three-svg-renderer](https://www.npmjs.com/package/three-svg-renderer) (GPLV3 Licenced)
*/ */
@uiFolderContainer('SVG Renderer') @uiFolderContainer('SVG Renderer')
export class ThreeSVGRendererPlugin extends AViewerPluginSync<''> {
export class ThreeSVGRendererPlugin extends AViewerPluginSync {
static readonly PluginType = 'ThreeSVGRendererPlugin' static readonly PluginType = 'ThreeSVGRendererPlugin'


@uiToggle() @uiToggle()
this.renderer.viewmap.options.creaseAngle.max = this.creaseAngle.y this.renderer.viewmap.options.creaseAngle.max = this.creaseAngle.y


const passes = this.renderer.drawHandler.passes const passes = this.renderer.drawHandler.passes
const fillPass = passes.find(p=>p instanceof FillPass) as FillPass
const visibleContourPass = passes.find(p=>p instanceof VisibleChainPass) as VisibleChainPass
const hiddenContourPass = passes.find(p=>p instanceof HiddenChainPass) as HiddenChainPass
const fillPass = passes.find(p=>p instanceof FillPass)!
const visibleContourPass = passes.find(p=>p instanceof VisibleChainPass)!
const hiddenContourPass = passes.find(p=>p instanceof HiddenChainPass)!
if (fillPass) { if (fillPass) {
fillPass.enabled = this.drawPolygons && (this.drawPolygonFills || this.drawPolygonStrokes || this.drawImageFills) fillPass.enabled = this.drawPolygons && (this.drawPolygonFills || this.drawPolygonStrokes || this.drawImageFills)
fillPass.drawFills = this.drawPolygonFills fillPass.drawFills = this.drawPolygonFills

+ 2
- 2
plugins/tweakpane-editor/package.json 查看文件

"replace": { "replace": {
"dependencies": {}, "dependencies": {},
"peerDependencies": { "peerDependencies": {
"threepipe": "^0.0.18",
"@threepipe/plugin-tweakpane": "^0.2.0"
"threepipe": "^0.0.39",
"@threepipe/plugin-tweakpane": "^0.5.3"
} }
} }
}, },

+ 4
- 4
plugins/tweakpane-editor/src/HierarchyUiPlugin.ts 查看文件

import {AViewerPluginSync, IObject3D, Object3D, ThreeViewer} from 'threepipe' import {AViewerPluginSync, IObject3D, Object3D, ThreeViewer} from 'threepipe'
import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'


export class HierarchyUiPlugin extends AViewerPluginSync<''> {
export class HierarchyUiPlugin extends AViewerPluginSync {
enabled = true enabled = true
public static readonly PluginType = 'HierarchyUiPlugin' public static readonly PluginType = 'HierarchyUiPlugin'


} }


reset(e?: any) { reset(e?: any) {
if (e?.fromHierarchyPlugin) return // for infinite loop
if (e?.source !== HierarchyUiPlugin.PluginType) return // for infinite loop
if (!e?.hierarchyChanged) return if (!e?.hierarchyChanged) return
this._needsReset = true this._needsReset = true
} }
onItemLabelClick: (item: any) => { onItemLabelClick: (item: any) => {
const obj1 = this._viewer?.scene.modelRoot.getObjectByProperty('uuid', item) const obj1 = this._viewer?.scene.modelRoot.getObjectByProperty('uuid', item)
if (!obj1 || !obj.visible) return if (!obj1 || !obj.visible) return
obj1.dispatchEvent({type: 'select', value: obj1, ui: true})
obj1.dispatchEvent({type: 'select', value: obj1, object: obj1, ui: true})
}, },
}) })
}) })
if (o.visible) o.traverseAncestors(p=>ancestorSet.add(p)) if (o.visible) o.traverseAncestors(p=>ancestorSet.add(p))
}) })
ancestorSet.forEach(o=> o.visible = true) ancestorSet.forEach(o=> o.visible = true)
this._viewer?.scene?.setDirty({refreshScene: true, fromHierarchyPlugin: true, updateGround: false})
this._viewer?.scene?.setDirty({refreshScene: true, source: HierarchyUiPlugin.PluginType, updateGround: false})
}) })
} }
} }

+ 15
- 5
src/assetmanager/AssetExporter.ts 查看文件

import {BaseEvent, EventDispatcher, WebGLRenderTarget} from 'three'
import {EventDispatcher, WebGLRenderTarget} from 'three'
import {IMaterial, IObject3D, ITexture} from '../core' import {IMaterial, IObject3D, ITexture} from '../core'
import {BlobExt, ExportFileOptions, IAssetExporter, IExporter, IExportParser} from './IExporter' import {BlobExt, ExportFileOptions, IAssetExporter, IExporter, IExportParser} from './IExporter'
import {EXRExporter2, SimpleJSONExporter, SimpleTextExporter} from './export' import {EXRExporter2, SimpleJSONExporter, SimpleTextExporter} from './export'
import {IRenderTarget} from '../rendering' import {IRenderTarget} from '../rendering'


export interface AssetExporterEventMap {
exporterCreate: {exporter: IExporter, parser: IExportParser}
exportFile: {
obj: IObject3D|IMaterial|ITexture|IRenderTarget,
state: 'processing'|'exporting'|'done'|'error',
error?: any,
exportOptions: ExportFileOptions
}
}

/** /**
* Asset Exporter * Asset Exporter
* *
* Used in {@link AssetManager} to export assets. * Used in {@link AssetManager} to export assets.
* @category Asset Manager * @category Asset Manager
*/ */
export class AssetExporter extends EventDispatcher<BaseEvent, 'exporterCreate' | 'exportFile'> implements IAssetExporter {
export class AssetExporter extends EventDispatcher<AssetExporterEventMap> implements IAssetExporter {
readonly exporters: IExporter[] = [ readonly exporters: IExporter[] = [
{ctor: ()=>new SimpleJSONExporter(), ext: ['json']}, {ctor: ()=>new SimpleJSONExporter(), ext: ['json']},
{ctor: ()=>new SimpleTextExporter(), ext: ['txt', 'text']}, {ctor: ()=>new SimpleTextExporter(), ext: ['txt', 'text']},
else { else {
const parser = this._getParser(ext) const parser = this._getParser(ext)


this.dispatchEvent({type: 'exportFile', obj, state:'exporting'})
this.dispatchEvent({type: 'exportFile', obj, state:'exporting', exportOptions: options})
res = await parser.parseAsync(processed.obj, {exportExt: processed.ext ?? ext, ...options}) as BlobExt res = await parser.parseAsync(processed.obj, {exportExt: processed.ext ?? ext, ...options}) as BlobExt
res.ext = processed.ext res.ext = processed.ext
} }


this.dispatchEvent({type: 'exportFile', obj, state: 'done'})
this.dispatchEvent({type: 'exportFile', obj, state: 'done', exportOptions: options})


} catch (e) { } catch (e) {
console.error('AssetExporter: Unable to Export file', obj) console.error('AssetExporter: Unable to Export file', obj)
// console.error(e) // console.error(e)
this.dispatchEvent({type: 'exportFile', obj, state: 'error', error: e})
this.dispatchEvent({type: 'exportFile', obj, state: 'error', error: e, exportOptions: options})
throw e throw e
return undefined return undefined
} }

+ 37
- 11
src/assetmanager/AssetImporter.ts 查看文件

import {Event, EventDispatcher, EventListener, FileLoader, LoaderUtils, LoadingManager} from 'three'
import {EventDispatcher, EventListener, FileLoader, LoaderUtils, LoadingManager} from 'three'
import { import {
IAssetImporter, IAssetImporter,
IAssetImporterEventTypes,
IImportResultUserData, IImportResultUserData,
ImportAssetOptions, ImportAssetOptions,
ImportFilesOptions, ImportFilesOptions,
import {parseFileExtension} from 'ts-browser-helpers' import {parseFileExtension} from 'ts-browser-helpers'
import {IObject3D} from '../core' import {IObject3D} from '../core'


export type IAssetImporterEvent = Event&{
type: IAssetImporterEventTypes,
data?: ImportResult, options?: ProcessRawOptions,
path?: string, progress?: number, state?: string, error?: any
files?: Map<string, IFile>
url?: string, loaded?: number, total?: number
loader?: ILoader,
// export type IAssetImporterEvent = Event&{
// type: IAssetImporterEventTypes,
// data?: ImportResult, options?: ProcessRawOptions,
// path?: string, progress?: number, state?: string, error?: any
// files?: Map<string, IFile>
// url?: string, loaded?: number, total?: number
// loader?: ILoader,
// }

// export type IAssetImporterEventTypes = 'onLoad' | 'onProgress' | 'onStop' | 'onError' | 'onStart' | 'loaderCreate' | 'importFile' | 'importFiles' | 'processRaw' | 'processRawStart'
export interface IAssetImporterEventMap {
loaderCreate: {type: 'loaderCreate', loader: ILoader}
importFile: {type: 'importFile', path: string, state: 'downloading'|'done'|'error'|'adding', progress?: number, loadedBytes?: number, totalBytes?: number, error?: any}
importFiles: {type: 'importFiles', files: Map<string, IFile>, state: 'start'|'end'}
processRaw: {type: 'processRaw', data: any, options: ProcessRawOptions, path?: string}
processRawStart: {type: 'processRawStart', data: any, options: ProcessRawOptions, path?: string}

/**
* @deprecated use the {@link importFile} event instead
*/
onLoad: {type: 'onLoad'}
/**
* @deprecated use the {@link importFile} event instead
*/
onProgress: {type: 'onProgress', url: string, loaded: number, total: number}
/**
* @deprecated use the {@link importFile} event instead
*/
onError: {type: 'onError', url: string}
/**
* @deprecated use the {@link importFile} event instead
*/
onStart: {type: 'onStart', url: string, loaded: number, total: number}
} }

/** /**
* Asset Importer * Asset Importer
* *
* Acts as a wrapper over three.js LoadingManager and adds support for dynamically loading loaders, caching assets, better event dispatching and file tracking. * Acts as a wrapper over three.js LoadingManager and adds support for dynamically loading loaders, caching assets, better event dispatching and file tracking.
* @category Asset Manager * @category Asset Manager
*/ */
export class AssetImporter extends EventDispatcher<IAssetImporterEvent, IAssetImporterEventTypes> implements IAssetImporter {
export class AssetImporter extends EventDispatcher<IAssetImporterEventMap> implements IAssetImporter {
private _loadingManager: LoadingManager private _loadingManager: LoadingManager


private _logger = console.log private _logger = console.log
return loader return loader
} }


addEventListener<T extends IAssetImporterEvent['type'] & IAssetImporterEventTypes>(type: T, listener: EventListener<IAssetImporterEvent, T, this>) {
addEventListener<T extends keyof IAssetImporterEventMap>(type: T, listener: EventListener<IAssetImporterEventMap[T], T, this>): void {
super.addEventListener(type, listener) super.addEventListener(type, listener)
if (type === 'loaderCreate') { if (type === 'loaderCreate') {
for (const loaderCacheElement of this._loaderCache) { for (const loaderCacheElement of this._loaderCache) {

+ 14
- 7
src/assetmanager/AssetManager.ts 查看文件

iMaterialCommons, iMaterialCommons,
IObject3D, IObject3D,
iObjectCommons, iObjectCommons,
ISceneEvent,
ISceneEventMap,
ITexture, ITexture,
PerspectiveCamera2, PerspectiveCamera2,
PointLight2, PointLight2,
export type ImportAddOptions = ImportAssetOptions & AddAssetOptions export type ImportAddOptions = ImportAssetOptions & AddAssetOptions
export type AddRawOptions = ProcessRawOptions & AddAssetOptions export type AddRawOptions = ProcessRawOptions & AddAssetOptions


export interface AssetManagerEventMap{
loadAsset: {data: ImportResult}
processStateUpdate: object
}


/** /**
* Asset Manager * Asset Manager
* Utility class to manage import, export, and material management. * Utility class to manage import, export, and material management.
* @category Asset Manager * @category Asset Manager
*/ */
export class AssetManager extends EventDispatcher<BaseEvent&{data?: ImportResult}, 'loadAsset'|'processStateUpdate'> {
export class AssetManager extends EventDispatcher<AssetManagerEventMap> {
readonly viewer: ThreeViewer readonly viewer: ThreeViewer
readonly importer: AssetImporter readonly importer: AssetImporter
readonly exporter: AssetExporter readonly exporter: AssetExporter
return (await this.addRaw<T>(res, options))?.[0] return (await this.addRaw<T>(res, options))?.[0]
} }


private _sceneUpdated(event: ISceneEvent) { // todo: check if objects are added some other way.
if (event.type === 'addSceneObject') {
private _sceneUpdated<T extends keyof ISceneEventMap>(ev: BaseEvent<T> & ISceneEventMap[T]) { // todo: check if objects are added some other way.
if (ev.type === 'addSceneObject') {
const event = ev as ISceneEventMap['addSceneObject']
const target = event.object as ImportResult const target = event.object as ImportResult
switch (target.assetType) { switch (target.assetType) {
case 'material': case 'material':
default: default:
break break
} }
} else if (event.type === 'materialChanged') {
} else if (ev.type === 'materialChanged') {
const event = ev as ISceneEventMap['materialChanged']
const target = event.material as IMaterial | IMaterial[] | undefined const target = event.material as IMaterial | IMaterial[] | undefined
const targets = Array.isArray(target) ? target : target ? [target] : [] const targets = Array.isArray(target) ? target : target ? [target] : []
for (const t of targets) { for (const t of targets) {
this.materials.registerMaterial(t) this.materials.registerMaterial(t)
} }
} else if (event.type === 'beforeDeserialize') {
} else if (ev.type === 'beforeDeserialize') {
const event = ev as ISceneEventMap['beforeDeserialize']
// object/material/texture to be deserialized // object/material/texture to be deserialized
const data = event.data
const data = event.data as any
const meta = event.meta const meta = event.meta
if (!data.metadata) { if (!data.metadata) {
console.warn('Invalid data(no metadata)', data) console.warn('Invalid data(no metadata)', data)

+ 29
- 3
src/assetmanager/IAssetImporter.ts 查看文件

import {BaseEvent, EventDispatcher, LoadingManager, Object3D} from 'three'
import {EventDispatcher, LoadingManager, Object3D} from 'three'
import {IDisposable} from 'ts-browser-helpers' import {IDisposable} from 'ts-browser-helpers'
import {IAsset, IFile} from './IAsset' import {IAsset, IFile} from './IAsset'
import {ILoader} from './IImporter' import {ILoader} from './IImporter'
importedFile?: IFile, importedFile?: IFile,
} }


export type IAssetImporterEventTypes = 'onLoad' | 'onProgress' | 'onStop' | 'onError' | 'onStart' | 'loaderCreate' | 'importFile' | 'importFiles' | 'processRaw' | 'processRawStart'
export interface IAssetImporter extends EventDispatcher<BaseEvent, IAssetImporterEventTypes>, IDisposable {
// export type IAssetImporterEventTypes = 'onLoad' | 'onProgress' | 'onStop' | 'onError' | 'onStart' | 'loaderCreate' | 'importFile' | 'importFiles' | 'processRaw' | 'processRawStart'

export interface IAssetImporterEventMap {
loaderCreate: {type: 'loaderCreate', loader: ILoader}
importFile: {type: 'importFile', path: string, state: 'downloading'|'done'|'error'|'adding', progress?: number, loadedBytes?: number, totalBytes?: number, error?: any}
importFiles: {type: 'importFiles', files: Map<string, IFile>, state: 'start'|'end'}
processRaw: {type: 'processRaw', data: any, options: ProcessRawOptions, path?: string}
processRawStart: {type: 'processRawStart', data: any, options: ProcessRawOptions, path?: string}

/**
* @deprecated use the {@link importFile} event instead
*/
onLoad: {type: 'onLoad'}
/**
* @deprecated use the {@link importFile} event instead
*/
onProgress: {type: 'onProgress', url: string, loaded: number, total: number}
/**
* @deprecated use the {@link importFile} event instead
*/
onError: {type: 'onError', url: string}
/**
* @deprecated use the {@link importFile} event instead
*/
onStart: {type: 'onStart', url: string, loaded: number, total: number}
}

export interface IAssetImporter<TE extends IAssetImporterEventMap = IAssetImporterEventMap> extends EventDispatcher<TE>, IDisposable {
readonly loadingManager: LoadingManager readonly loadingManager: LoadingManager
readonly cachedAssets: IAsset[] readonly cachedAssets: IAsset[]



+ 6
- 7
src/assetmanager/MaterialManager.ts 查看文件

import {BaseEvent, ColorManagement, EventDispatcher, Material} from 'three'
import {ColorManagement, Event, EventDispatcher, EventListener, Material, Texture} from 'three'
import { import {
IMaterial, IMaterial,
iMaterialCommons, iMaterialCommons,
IMaterialEvent,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
ITexture, ITexture,
ITextureEvent,
LegacyPhongMaterial, LegacyPhongMaterial,
LineMaterial2, LineMaterial2,
ObjectShaderMaterial,
PhysicalMaterial, PhysicalMaterial,
UnlitLineMaterial, UnlitLineMaterial,
UnlitMaterial, UnlitMaterial,
ObjectShaderMaterial,
} from '../core' } from '../core'
import {downloadFile} from 'ts-browser-helpers' import {downloadFile} from 'ts-browser-helpers'
import {MaterialExtension} from '../materials' import {MaterialExtension} from '../materials'
import {generateUUID, isInScene} from '../three' import {generateUUID, isInScene} from '../three'
import {IMaterialEventMap} from '../core/IMaterial'


/** /**
* Material Manager * Material Manager
* Used in {@link AssetManager} to manage materials. * Used in {@link AssetManager} to manage materials.
* @category Asset Manager * @category Asset Manager
*/ */
export class MaterialManager<T = ''> extends EventDispatcher<BaseEvent, T> {
export class MaterialManager<TEventMap extends object = object> extends EventDispatcher<TEventMap> {
readonly templates: IMaterialTemplate[] = [ readonly templates: IMaterialTemplate[] = [
PhysicalMaterial.MaterialTemplate, PhysicalMaterial.MaterialTemplate,
UnlitMaterial.MaterialTemplate, UnlitMaterial.MaterialTemplate,


private _materialMaps = new Map<string, Set<ITexture>>() private _materialMaps = new Map<string, Set<ITexture>>()


protected _materialUpdate = (e: IMaterialEvent<'materialUpdate'>)=>{
protected _materialUpdate: EventListener<IMaterialEventMap['materialUpdate'], 'materialUpdate', IMaterial> = (e)=>{
const mat = e.material || e.target const mat = e.material || e.target
if (!mat || mat.assetType !== 'material') return if (!mat || mat.assetType !== 'material') return
this._refreshTextureRefs(mat) this._refreshTextureRefs(mat)
} }


protected _textureUpdate = function(this: IMaterial, e: ITextureEvent<'update'>) {
protected _textureUpdate = function(this: IMaterial, e: Event<'update', Texture>) {
if (!this || this.assetType !== 'material') return if (!this || this.assetType !== 'material') return
this.dispatchEvent({texture: e.target, bubbleToParent: true, bubbleToObject: true, ...e, type: 'textureUpdate'}) this.dispatchEvent({texture: e.target, bubbleToParent: true, bubbleToObject: true, ...e, type: 'textureUpdate'})
} }

+ 1
- 1
src/assetmanager/export/EXRExporter2.ts 查看文件

console.warn('No textureIndex specified for WebGLMultipleRenderTargets') console.warn('No textureIndex specified for WebGLMultipleRenderTargets')
const res = target.isWebGLRenderTarget ? const res = target.isWebGLRenderTarget ?
this.parse(target.renderManager!.webglRenderer, <WebGLRenderTarget>target, options) : this.parse(target.renderManager!.webglRenderer, <WebGLRenderTarget>target, options) :
this.parse(undefined, <DataTexture>obj, options)
this.parse(<DataTexture>obj, options)
return new Blob([res], {type: 'image/x-exr'}) return new Blob([res], {type: 'image/x-exr'})
} }
} }

+ 2
- 2
src/assetmanager/import/MTLLoader2.ts 查看文件

* @param {Function} [onProgress] - Callback for download progress. * @param {Function} [onProgress] - Callback for download progress.
* @param {Function} [onError] - Callback for download errors. * @param {Function} [onError] - Callback for download errors.
* *
* @link setPath setResourcePath
* {@link setPath} {@link setResourcePath}
* *
* @note In order for relative texture references to resolve correctly * @note In order for relative texture references to resolve correctly
* you must call setResourcePath() explicitly prior to load. * you must call setResourcePath() explicitly prior to load.
* @param {String} text - Content of MTL file * @param {String} text - Content of MTL file
* @return {MaterialCreator} * @return {MaterialCreator}
* *
* @link setPath setResourcePath
* {@link setPath} {@link setResourcePath}
* *
* @note In order for relative texture references to resolve correctly * @note In order for relative texture references to resolve correctly
* you must call setResourcePath() explicitly prior to parse. * you must call setResourcePath() explicitly prior to parse.

+ 1
- 2
src/assetmanager/index.ts 查看文件

export {AssetManager} from './AssetManager' export {AssetManager} from './AssetManager'
export {Importer} from './Importer' export {Importer} from './Importer'
export {MaterialManager} from './MaterialManager' export {MaterialManager} from './MaterialManager'
export type {IAssetImporterEvent} from './AssetImporter'
export type {AssetManagerOptions, AddRawOptions, ImportAddOptions, AddAssetOptions} from './AssetManager' export type {AssetManagerOptions, AddRawOptions, ImportAddOptions, AddAssetOptions} from './AssetManager'
export type {IAsset, IFile, IAssetID, IAssetList} from './IAsset' export type {IAsset, IFile, IAssetID, IAssetList} from './IAsset'
export type {ImportResult, IImportResultUserData, ImportResultObject, IAssetImporter, IAssetImporterEventTypes, ImportAssetOptions, ImportFilesOptions, LoadFileOptions, ProcessRawOptions, RootSceneImportResult, ImportResultExtras} from './IAssetImporter'
export type {ImportResult, IImportResultUserData, ImportResultObject, IAssetImporter, IAssetImporterEventMap, ImportAssetOptions, ImportFilesOptions, LoadFileOptions, ProcessRawOptions, RootSceneImportResult, ImportResultExtras} from './IAssetImporter'
export type {IAssetExporter, IExporter, IExportParser, ExportFileOptions, BlobExt} from './IExporter' export type {IAssetExporter, IExporter, IExportParser, ExportFileOptions, BlobExt} from './IExporter'
export type {IImporter, ILoader} from './IImporter' export type {IImporter, ILoader} from './IImporter'



+ 18
- 11
src/core/ICamera.ts 查看文件

import {Camera, Vector3} from 'three' import {Camera, Vector3} from 'three'
import {IObject3D, IObject3DEvent, IObject3DEventTypes, IObject3DUserData, IObjectSetDirtyOptions} from './IObject'
import {IObject3D, IObject3DEventMap, IObject3DUserData, IObjectSetDirtyOptions} from './IObject'
import {IShaderPropertiesUpdater} from '../materials' import {IShaderPropertiesUpdater} from '../materials'
import {ICameraControls, TControlsCtor} from './camera/ICameraControls' import {ICameraControls, TControlsCtor} from './camera/ICameraControls'
import {CameraView, ICameraView} from './camera/CameraView' import {CameraView, ICameraView} from './camera/CameraView'
// [key: string]: any // commented for noe // [key: string]: any // commented for noe
} }


export interface ICamera<E extends ICameraEvent = ICameraEvent, ET extends ICameraEventTypes = ICameraEventTypes> extends Camera<E, ET>, IObject3D<E, ET>, IShaderPropertiesUpdater {
export interface ICamera<TE extends ICameraEventMap = ICameraEventMap> extends Camera<TE>, IObject3D<TE>, IShaderPropertiesUpdater {
assetType: 'camera' assetType: 'camera'
readonly isCamera: true readonly isCamera: true
setDirty(options?: ICameraSetDirtyOptions): void; setDirty(options?: ICameraSetDirtyOptions): void;
readonly isPerspectiveCamera?: boolean; readonly isPerspectiveCamera?: boolean;
readonly isOrthographicCamera?: boolean; readonly isOrthographicCamera?: boolean;


activateMain(options?: Partial<ICameraEvent>, _internal?: boolean, _refresh?: boolean): void;
deactivateMain(options?: Partial<ICameraEvent>, _internal?: boolean, _refresh?: boolean): void;
activateMain(options?: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'>, _internal?: boolean, _refresh?: boolean): void;
deactivateMain(options?: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'>, _internal?: boolean, _refresh?: boolean): void;


/** /**
* @deprecated use `this` instead * @deprecated use `this` instead
* Dispatches the `setView` event which triggers the main camera to set its view to this camera's view. * Dispatches the `setView` event which triggers the main camera to set its view to this camera's view.
* @param eventOptions * @param eventOptions
*/ */
setViewToMain(eventOptions: Partial<ICameraEvent>): void
setViewToMain(eventOptions: Pick<ICameraEventMap['setView'], 'ui'>): void
// region inherited type fixes // region inherited type fixes
// re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936 // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936


} }




export type ICameraEventTypes = IObject3DEventTypes | 'update'// | string
export type ICameraEvent = Omit<IObject3DEvent, 'type'> & {
type: ICameraEventTypes
camera?: ICamera | null
// change?: string
}
// export type ICameraEventTypes = IObject3DEventTypes | 'update'// | string
// export type ICameraEvent = Omit<IObject3DEvent, 'type'> & {
// type: ICameraEventTypes
// camera?: ICamera | null
// // change?: string
// }
export type ICameraSetDirtyOptions = IObjectSetDirtyOptions export type ICameraSetDirtyOptions = IObjectSetDirtyOptions


export interface ICameraEventMap extends IObject3DEventMap {
update: {
camera: ICamera
bubbleToParent: false
// todo
} & ICameraSetDirtyOptions
}

+ 24
- 9
src/core/IGeometry.ts 查看文件

import {BufferGeometry, Event, NormalBufferAttributes, NormalOrGLBufferAttributes, Vector3} from 'three'
import {
BufferGeometry,
BufferGeometryEventMap,
NormalBufferAttributes,
NormalOrGLBufferAttributes,
Vector3,
} from 'three'
import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js'
import {AnyOptions} from 'ts-browser-helpers' import {AnyOptions} from 'ts-browser-helpers'
import {IObject3D} from './IObject' import {IObject3D} from './IObject'
disposeOnIdle?: boolean disposeOnIdle?: boolean
// [key: string]: any // commented for noe // [key: string]: any // commented for noe
} }
export interface IGeometry<Attributes extends NormalOrGLBufferAttributes = NormalBufferAttributes> extends BufferGeometry<Attributes, IGeometryEvent, IGeometryEventTypes>, IUiConfigContainer {
export interface IGeometry<Attributes extends NormalOrGLBufferAttributes = NormalBufferAttributes, TE extends IGeometryEventMap = IGeometryEventMap> extends BufferGeometry<Attributes, TE>, IUiConfigContainer {
assetType: 'geometry' assetType: 'geometry'
setDirty(options?: IGeometrySetDirtyOptions): void; setDirty(options?: IGeometrySetDirtyOptions): void;
refreshUi(): void; refreshUi(): void;
_uiConfig?: UiObjectConfig _uiConfig?: UiObjectConfig


} }
export type IGeometryEventTypes = 'dispose' | 'geometryUpdate' // | string
export type IGeometryEvent<T extends string = IGeometryEventTypes> = Event & {
type: T
bubbleToObject?: boolean // bubble event to parent root
geometry?: IGeometry
// change?: string
}
// export type IGeometryEventTypes = 'dispose' | 'geometryUpdate' // | string
// export type IGeometryEvent<T extends string = IGeometryEventTypes> = Event & {
// type: T
// bubbleToObject?: boolean // bubble event to parent root
// geometry?: IGeometry
// // change?: string
// }
export type IGeometrySetDirtyOptions = AnyOptions & {bubbleToObject?: boolean} export type IGeometrySetDirtyOptions = AnyOptions & {bubbleToObject?: boolean}


export type IGeometryEventMap = BufferGeometryEventMap


declare module 'three'{
export interface BufferGeometryEventMap{
geometryUpdate: {
geometry: IGeometry
bubbleToObject?: boolean
}
}
}

+ 71
- 12
src/core/IMaterial.ts 查看文件

import type {Color, Event, IUniform, Material, MaterialParameters, Shader} from 'three'
import {
BufferGeometry,
Camera,
Color,
IUniform,
Material,
MaterialEventMap,
MaterialParameters,
Object3D,
Scene,
Shader,
WebGLRenderer,
} from 'three'
import type {IDisposable, IJSONSerializable} from 'ts-browser-helpers' import type {IDisposable, IJSONSerializable} from 'ts-browser-helpers'
import type {MaterialExtension} from '../materials' import type {MaterialExtension} from '../materials'
import type {ChangeEvent, IUiConfigContainer} from 'uiconfig.js' import type {ChangeEvent, IUiConfigContainer} from 'uiconfig.js'
import type {IImportResultUserData} from '../assetmanager' import type {IImportResultUserData} from '../assetmanager'


export type IMaterialParameters = MaterialParameters & {customMaterialExtensions?: MaterialExtension[]} export type IMaterialParameters = MaterialParameters & {customMaterialExtensions?: MaterialExtension[]}
export type IMaterialEventTypes = 'dispose' | 'materialUpdate' | 'beforeRender' | 'beforeCompile' | 'afterRender' | 'textureUpdate' | 'beforeDeserialize'
export type IMaterialEvent<T extends string = IMaterialEventTypes> = Event & {
type: T
bubbleToObject?: boolean
bubbleToParent?: boolean
material?: IMaterial

texture?: ITexture
oldTexture?: ITexture
// export type IMaterialEventTypes = 'dispose' | 'materialUpdate' | 'beforeRender' | 'beforeCompile' | 'afterRender' | 'textureUpdate' | 'beforeDeserialize'
// export type IMaterialEvent<T extends string = IMaterialEventTypes> = Event & {
// type: T
// bubbleToObject?: boolean
// bubbleToParent?: boolean
// material?: IMaterial
//
// texture?: ITexture
// oldTexture?: ITexture
//
// uiChangeEvent?: ChangeEvent
// }

export interface IMaterialEventMap extends MaterialEventMap{
beforeCompile: {
shader: Shader
renderer: WebGLRenderer
}
beforeRender: {
renderer: WebGLRenderer
scene: Scene
camera: Camera
geometry: BufferGeometry
object: Object3D
}
afterRender: {
renderer: WebGLRenderer
scene: Scene
camera: Camera
geometry: BufferGeometry
object: Object3D
}
/**
* For internal use
*/
beforeDeserialize: {
data: unknown
meta?: SerializationMetaType
bubbleToObject: boolean
bubbleToParent: boolean
}
}


uiChangeEvent?: ChangeEvent
declare module 'three'{
export interface MaterialEventMap{
materialUpdate: {
bubbleToObject?: boolean
bubbleToParent?: boolean
uiChangeEvent?: ChangeEvent
} & IMaterialSetDirtyOptions
textureUpdate: {
texture: ITexture
bubbleToObject?: boolean
bubbleToParent?: boolean
uiChangeEvent?: ChangeEvent
}
}
} }

export interface IMaterialSetDirtyOptions extends ISetDirtyCommonOptions{ export interface IMaterialSetDirtyOptions extends ISetDirtyCommonOptions{
/** /**
* @default true * @default true
postTonemap?: boolean postTonemap?: boolean
} }


export interface IMaterial<E extends IMaterialEvent = IMaterialEvent, ET = IMaterialEventTypes> extends Material<E, ET>, IJSONSerializable, IDisposable, IUiConfigContainer {
export interface IMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends Material<TE>, IJSONSerializable, IDisposable, IUiConfigContainer {
constructor: { constructor: {
TYPE: string TYPE: string
TypeSlug: string TypeSlug: string

+ 133
- 22
src/core/IObject.ts 查看文件

import {IDisposable} from 'ts-browser-helpers'
import {IMaterial} from './IMaterial'
import {Event, Object3D, Vector3} from 'three'
import {IMaterial, IMaterialEventMap} from './IMaterial'
import {EventListener, Object3D, Object3DEventMap, Vector3} from 'three'
import {ChangeEvent, IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' import {ChangeEvent, IUiConfigContainer, UiObjectConfig} from 'uiconfig.js'
import {IGeometry, IGeometryEvent} from './IGeometry'
import {IGeometry, IGeometryEventMap} from './IGeometry'
import {IImportResultUserData} from '../assetmanager' import {IImportResultUserData} from '../assetmanager'
import {GLTF} from 'three/examples/jsm/loaders/GLTFLoader.js' import {GLTF} from 'three/examples/jsm/loaders/GLTFLoader.js'

export type IObject3DEventTypes = 'dispose' | 'materialUpdate' | 'objectUpdate' | 'textureUpdate' | 'geometryChanged' |
'materialChanged' | 'geometryUpdate' | 'added' | 'removed' | 'select' | 'beforeDeserialize' |
'setView' | 'activateMain' | 'cameraUpdate' // from camera
// | string
export interface IObject3DEvent<T extends string = IObject3DEventTypes> extends Event {
type: T
object?: IObject3D // object that triggered the event, target might be parent in case of bubbleToParent
bubbleToParent?: boolean // bubble event to parent root
change?: string
material?: IMaterial|undefined|IMaterial[] // from materialUpdate and materialChanged
oldMaterial?: IMaterial|undefined|IMaterial[] // from materialChanged
geometry?: IGeometry|undefined // from geometryUpdate, geometryChanged
oldGeometry?: IGeometry|undefined // from geometryChanged
source?: any
import {ICamera, type ICameraSetDirtyOptions} from './ICamera'

// export type IObject3DEventTypes = 'dispose' | 'materialUpdate' | 'objectUpdate' | 'textureUpdate' | 'geometryChanged' |
// 'materialChanged' | 'geometryUpdate' | 'added' | 'removed' | 'select' | 'beforeDeserialize' |
// 'setView' | 'activateMain' | 'cameraUpdate' // from camera
// | string
// export interface IObject3DEvent<T extends string = IObject3DEventTypes> extends Event {
// type: T
// object?: IObject3D // object that triggered the event, target might be parent in case of bubbleToParent
// bubbleToParent?: boolean // bubble event to parent root
// change?: string // todo - add to new type...
// material?: IMaterial|undefined|IMaterial[] // from materialUpdate and materialChanged
// oldMaterial?: IMaterial|undefined|IMaterial[] // from materialChanged
// geometry?: IGeometry|undefined // from geometryUpdate, geometryChanged
// oldGeometry?: IGeometry|undefined // from geometryChanged
// source?: any // todo - add to new type...
// }

declare module 'three'{
export interface Object3DEventMap{
select: { // todo
ui?: boolean
focusCamera?: boolean
bubbleToParent?: boolean
object: IObject3D
value?: IObject3D /* | Material*/ // todo is this required?

source?: string // who is triggering the event. so that recursive events can be prevented
}
}
}
// [key: keyof Object3DEventMap]: Object3DEventMap[key] & {
// bubbleToParent?: boolean
// }
export interface IObject3DEventMap extends Object3DEventMap{
dispose: {
// object: IObject3D
// todo
bubbleToParent: false
}
materialUpdate: {
// object: IObject3D
material: IMaterial|IMaterial[]
}
objectUpdate: {
object: IObject3D
change?: string
args?: any[]
bubbleToParent: boolean
}
textureUpdate: {
// object: IObject3D
// todo
}
geometryChanged: {
object: IObject3D
geometry: IGeometry|null
oldGeometry: IGeometry|null
bubbleToParent: boolean
}
materialChanged: {
object: IObject3D
material: IMaterial|IMaterial[]|null
oldMaterial: IMaterial|IMaterial[]|null
bubbleToParent: boolean
}
geometryUpdate: {
object: IObject3D
geometry: IGeometry
// oldGeometry: IGeometry
bubbleToParent: boolean
}
added: {
// object: IObject3D
// todo
}
removed: {
// object: IObject3D
// todo
}
beforeDeserialize: { // from material
material: IMaterial
// todo
} & IMaterialEventMap['beforeDeserialize']
setView: {
ui?: boolean
camera: ICamera
bubbleToParent: boolean
// object: IObject3D
// todo
}
activateMain: {
ui?: boolean
camera?: ICamera | null
bubbleToParent: boolean
// object: IObject3D
// todo
}
cameraUpdate: {
ui?: boolean
camera?: ICamera
// object: IObject3D
bubbleToParent: boolean
// todo
} & ICameraSetDirtyOptions
} }
// Record<keyof IObject3DEventMap0, IObject3DEventMap0[keyof IObject3DEventMap0] & {
// // bubbleToParent?: boolean
// }>


export interface ISetDirtyCommonOptions { export interface ISetDirtyCommonOptions {
/** /**
*/ */
sceneUpdate?: boolean // update scene after setting dirty sceneUpdate?: boolean // update scene after setting dirty


[key: string]: any
source?: string // who is triggering the event. so that recursive events can be prevented

// from onChange3 etc.
key?: string

/**
* Set to true if this is the last value in a user input chain. (like when mouse up on slider)
*/
last?: boolean
/**
* Indicates that this change in from an `undo` operation.
*/
undo?: boolean

// value: any;
// oldValue: any;

// [key: string]: any
} }


export interface IObjectProcessor { // todo, should be viewer export interface IObjectProcessor { // todo, should be viewer
[key: string]: any [key: string]: any
} }


export interface IObject3D<E extends Event = IObject3DEvent, ET = IObject3DEventTypes> extends Object3D<E, ET>, IUiConfigContainer, IDisposable {
export interface IObject3D<TE extends IObject3DEventMap = IObject3DEventMap> extends Object3D<TE>, IUiConfigContainer {
assetType: 'model' | 'light' | 'camera' | 'widget' assetType: 'model' | 'light' | 'camera' | 'widget'
isLight?: boolean isLight?: boolean
isCamera?: boolean isCamera?: boolean




// eslint-disable-next-line @typescript-eslint/naming-convention // eslint-disable-next-line @typescript-eslint/naming-convention
_onGeometryUpdate?: (e: IGeometryEvent<'geometryUpdate'>) => void
_onGeometryUpdate?: EventListener<IGeometryEventMap['geometryUpdate'], 'geometryUpdate', IGeometry>



objectProcessor?: IObjectProcessor objectProcessor?: IObjectProcessor


// endregion // endregion


} }


+ 16
- 20
src/core/IRenderer.ts 查看文件

import {PartialRecord} from 'ts-browser-helpers' import {PartialRecord} from 'ts-browser-helpers'
import {
Blending,
Clock,
Event,
ShaderMaterial,
Texture,
Vector2,
Vector4,
WebGLRenderer,
WebGLRenderTarget,
} from 'three'
import {Blending, Clock, ShaderMaterial, Texture, Vector2, Vector4, WebGLRenderer, WebGLRenderTarget} from 'three'
import {CreateRenderTargetOptions, IRenderTarget, RenderTargetManager} from '../rendering' import {CreateRenderTargetOptions, IRenderTarget, RenderTargetManager} from '../rendering'
import {IShaderPropertiesUpdater} from '../materials' import {IShaderPropertiesUpdater} from '../materials'
import {EffectComposer2, IPassID, IPipelinePass} from '../postprocessing' import {EffectComposer2, IPassID, IPipelinePass} from '../postprocessing'
export type TThreeRendererMode = 'shadowMapRender' | 'backgroundRender' | 'sceneRender' | 'opaqueRender' | 'transparentRender' | 'transmissionRender' | 'mainRenderPass' | 'screenSpaceRendering' export type TThreeRendererMode = 'shadowMapRender' | 'backgroundRender' | 'sceneRender' | 'opaqueRender' | 'transparentRender' | 'transmissionRender' | 'mainRenderPass' | 'screenSpaceRendering'
export type TThreeRendererModeUserData = PartialRecord<TThreeRendererMode, boolean> export type TThreeRendererModeUserData = PartialRecord<TThreeRendererMode, boolean>


export interface IAnimationLoopEvent extends Event{
export interface IAnimationLoopEvent {
renderer: IWebGLRenderer renderer: IWebGLRenderer
deltaTime: number deltaTime: number
time: number time: number
xrFrame?: XRFrame xrFrame?: XRFrame
} }
export interface IRenderManagerUpdateEvent extends Event{
change: 'registerPass' | 'unregisterPass' | 'useLegacyLights' | 'passRefresh' | 'size' | 'rebuild' | string
data: any
pass: IPipelinePass
export interface IRenderManagerUpdateEvent {
change?: 'registerPass' | 'unregisterPass' | 'useLegacyLights' | 'passRefresh' | 'size' | 'rebuild' | string
data?: any
pass?: IPipelinePass
} }
export type IRenderManagerEvent = Partial<IAnimationLoopEvent>&Partial<IRenderManagerUpdateEvent>&Event & {


[key: string]: any
export interface IRenderManagerEventMap {
animationLoop: IAnimationLoopEvent
update: IRenderManagerUpdateEvent
resize: object
contextRestored: object
contextLost: {
event: WebGLContextEvent
}
} }
export type IRenderManagerEventTypes = 'animationLoop'|'update'|'resize'|'contextLost'|'contextRestored'
export interface RendererBlitOptions {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean, respectColorSpace?: boolean, blending?: Blending, transparent?: boolean} export interface RendererBlitOptions {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean, respectColorSpace?: boolean, blending?: Blending, transparent?: boolean}
export interface IRenderManager<E extends IRenderManagerEvent = IRenderManagerEvent, ET extends string = IRenderManagerEventTypes> extends RenderTargetManager<E, ET>, IShaderPropertiesUpdater{
export interface IRenderManager<TE extends IRenderManagerEventMap = IRenderManagerEventMap> extends RenderTargetManager<TE>, IShaderPropertiesUpdater{
readonly renderer: IWebGLRenderer readonly renderer: IWebGLRenderer
readonly needsRender: boolean readonly needsRender: boolean
rebuildPipeline(setDirty?: boolean): void rebuildPipeline(setDirty?: boolean): void

+ 85
- 15
src/core/IScene.ts 查看文件

import {IObject3D, IObject3DEvent, IObject3DEventTypes, IObject3DUserData, IObjectSetDirtyOptions} from './IObject'
import {Color, Scene} from 'three'
import {IObject3D, IObject3DEventMap, IObject3DUserData, IObjectSetDirtyOptions} from './IObject'
import {Color, Scene, Texture} from 'three'
import {IShaderPropertiesUpdater} from '../materials' import {IShaderPropertiesUpdater} from '../materials'
import {ICamera} from './ICamera' import {ICamera} from './ICamera'
import {Box3B} from '../three' import {Box3B} from '../three'
import {ITexture} from './ITexture' import {ITexture} from './ITexture'
import {IGeometry} from './IGeometry'


export interface AddObjectOptions { export interface AddObjectOptions {
/** /**
} }


// | string // | string
export type ISceneEventTypes = IObject3DEventTypes | 'sceneUpdate' | 'addSceneObject' |
'mainCameraChange' | 'mainCameraUpdate' | 'environmentChanged' | 'backgroundChanged' | 'renderCameraChange' |
'update' | // todo: deprecate, use 'sceneUpdate' instead
'textureAdded' | // todo remove
'activeCameraChange' | 'activeCameraUpdate' | // todo: deprecate
'sceneMaterialUpdate' // todo deprecate: use 'materialUpdate' instead
// export type ISceneEventTypes =
// 'update' // todo: deprecate, use 'sceneUpdate' instead
// | string // | string


export interface ISceneEvent<T extends string = ISceneEventTypes> extends IObject3DEvent<T> {
scene?: IScene | null
// export interface ISceneEvent<T extends string = ISceneEventTypes> extends IObject3DEvent<T> {
// scene?: IScene | null
//
// hierarchyChanged?: boolean // for 'sceneUpdate' event
// // change?: string
// }

export interface ISceneEventMap extends IObject3DEventMap {
sceneUpdate: {
hierarchyChanged?: boolean
refreshScene?: boolean
object?: IObject3D
change?: ISceneEventMap['objectUpdate']['change']

// args?: any[]
bubbleToParent?: boolean // objectUpdate, geometryUpdate, geometryChanged
geometry?: IGeometry|null // geometryUpdate and geometryChanged
oldGeometry?: IGeometry|null // geometryChanged

/**
* @deprecated use {@link refreshScene} instead
*/
sceneUpdate?: boolean
} & ISceneSetDirtyOptions
addSceneObject: {
object: IObject3D
options?: AddObjectOptions

geometryChanged?: boolean
updateGround?: boolean
}
mainCameraChange: {
lastCamera: ICamera
camera: ICamera
}
mainCameraUpdate: IObject3DEventMap['cameraUpdate']

renderCameraChange: {
lastCamera: ICamera | undefined
camera: ICamera
},
// sceneUpdate: {
// change?: string
// sceneUpdate?: boolean
// refreshScene?: boolean
// hierarchyChanged: boolean
// geometryChanged: boolean
// }
environmentChanged: {
environment: ITexture|null
}
backgroundChanged: {
background: Texture | Color | 'environment' | null
backgroundColor: Color | null
}
// textureAdded: {
// texture: ITexture
// }


hierarchyChanged?: boolean // for 'sceneUpdate' event
// change?: string
/**
* @deprecated use {@link mainCameraChange} instead
*/
activeCameraChange: ISceneEventMap['mainCameraChange']
/**
* @deprecated use {@link mainCameraUpdate} instead
*/
activeCameraUpdate: ISceneEventMap['mainCameraUpdate']
/**
* @deprecated use {@link materialUpdate} instead
*/
sceneMaterialUpdate: IObject3DEventMap['materialUpdate']
/**
* @deprecated use {@link objectUpdate} or {@link sceneUpdate} instead
*/
update: IObject3DEventMap['objectUpdate']
}

export interface ISceneSetDirtyOptions extends IObjectSetDirtyOptions{
refreshScene?: boolean // duplicated declaration from parent intentionally
} }
export type ISceneSetDirtyOptions = IObjectSetDirtyOptions




export type ISceneUserData = IObject3DUserData export type ISceneUserData = IObject3DUserData
dispose?(): void dispose?(): void
} }


export interface IScene<E extends ISceneEvent = ISceneEvent, ET extends ISceneEventTypes = ISceneEventTypes>
extends Scene<E, ET>, IObject3D<E, ET>, IShaderPropertiesUpdater {
export interface IScene<TE extends ISceneEventMap = ISceneEventMap>
extends Scene<TE>, IObject3D<TE>, IShaderPropertiesUpdater {
readonly visible: boolean; readonly visible: boolean;
readonly isScene: true; readonly isScene: true;
/** /**

+ 11
- 9
src/core/ITexture.ts 查看文件

import {IMaterial} from './IMaterial' import {IMaterial} from './IMaterial'
import {Event, Source, Texture} from 'three'
import {ChangeEvent} from 'uiconfig.js'
import {Source, Texture, TextureEventMap} from 'three'
import {IRenderTarget} from '../rendering' import {IRenderTarget} from '../rendering'


export interface ITextureUserData{ export interface ITextureUserData{
*/ */
disposeOnIdle?: boolean disposeOnIdle?: boolean
} }
export type ITextureEventTypes = 'dispose' | 'update'
export type ITextureEvent<T extends string = ITextureEventTypes> = Event & {
type: T
texture?: ITexture
uiChangeEvent?: ChangeEvent
}


export interface ITexture extends Texture {
// export type ITextureEventTypes = 'dispose' | 'update'
// export type ITextureEvent<T extends string = ITextureEventTypes> = Event & {
// type: T
// texture?: ITexture
// uiChangeEvent?: ChangeEvent
// }

export type ITextureEventMap = TextureEventMap

export interface ITexture<TE extends ITextureEventMap = ITextureEventMap> extends Texture<TE> {
assetType?: 'texture' assetType?: 'texture'
userData: ITextureUserData userData: ITextureUserData
readonly isTexture: true readonly isTexture: true

+ 9
- 2
src/core/camera/CameraView.ts 查看文件

import {Event, EventDispatcher, Quaternion, Vector3} from 'three'
import {EventDispatcher, Quaternion, Vector3} from 'three'
import {onChange, serializable, serialize} from 'ts-browser-helpers' import {onChange, serializable, serialize} from 'ts-browser-helpers'
import {IUiConfigContainer, uiButton, uiInput, uiNumber, UiObjectConfig, uiPanelContainer, uiVector} from 'uiconfig.js' import {IUiConfigContainer, uiButton, uiInput, uiNumber, UiObjectConfig, uiPanelContainer, uiVector} from 'uiconfig.js'
import {ICamera} from '../ICamera' import {ICamera} from '../ICamera'
delete(camera?: ICamera): void delete(camera?: ICamera): void
} }


export interface CameraViewEventMap {
setView: {camera?: ICamera, view: ICameraView}
animateView: {camera?: ICamera, duration?: number, view: ICameraView}
updateView: {camera?: ICamera, view: ICameraView}
deleteView: {camera?: ICamera, view: ICameraView}
}

@serializable('CameraView') @serializable('CameraView')
@uiPanelContainer('Camera View') @uiPanelContainer('Camera View')
export class CameraView extends EventDispatcher<Event, 'setView'|'animateView'|'updateView'|'deleteView'> implements ICameraView, IUiConfigContainer {
export class CameraView extends EventDispatcher<CameraViewEventMap> implements ICameraView, IUiConfigContainer {
uuid = generateUUID() uuid = generateUUID()
@onChange(CameraView.prototype._nameChanged) @onChange(CameraView.prototype._nameChanged)
@serialize() @uiInput() name = 'Camera View' @serialize() @uiInput() name = 'Camera View'

+ 6
- 2
src/core/camera/ICameraControls.ts 查看文件

import {IUiConfigContainer} from 'uiconfig.js' import {IUiConfigContainer} from 'uiconfig.js'
import {Camera, Event, EventDispatcher, Object3D, Vector3} from 'three'
import {Camera, EventDispatcher, Object3D, Vector3} from 'three'


export interface ICameraControls<TEvents = 'change'|string> extends IUiConfigContainer<void, 'panel'>, EventDispatcher<Event, TEvents> {
export interface ICameraControlsEventMap {
change: object
}

export interface ICameraControls<TE extends ICameraControlsEventMap = ICameraControlsEventMap> extends IUiConfigContainer<void, 'panel'>, EventDispatcher<TE> {
object: Object3D object: Object3D
enabled: boolean enabled: boolean



+ 11
- 7
src/core/camera/OrthographicCamera2.ts 查看文件

import {Camera, Event, IUniform, Object3D, OrthographicCamera, Vector3} from 'three'
import {Camera, IUniform, Object3D, OrthographicCamera, Vector3} from 'three'
import {generateUiConfig, uiInput, uiNumber, UiObjectConfig, uiToggle, uiVector} from 'uiconfig.js' import {generateUiConfig, uiInput, uiNumber, UiObjectConfig, uiToggle, uiVector} from 'uiconfig.js'
import {onChange, onChange2, onChange3, serialize} from 'ts-browser-helpers' import {onChange, onChange2, onChange3, serialize} from 'ts-browser-helpers'
import type {ICamera, ICameraEvent, ICameraUserData, TCameraControlsMode} from '../ICamera'
import type {ICamera, ICameraEventMap, ICameraUserData, TCameraControlsMode} from '../ICamera'
import {ICameraSetDirtyOptions} from '../ICamera' import {ICameraSetDirtyOptions} from '../ICamera'
import type {ICameraControls, TControlsCtor} from './ICameraControls' import type {ICameraControls, TControlsCtor} from './ICameraControls'
import {OrbitControls3} from '../../three/controls/OrbitControls3' import {OrbitControls3} from '../../three/controls/OrbitControls3'


// todo: extract out common functions with perspective camera into iCameraCommons // todo: extract out common functions with perspective camera into iCameraCommons
// todo: maybe change domElement to some wrapper/base class of viewer // todo: maybe change domElement to some wrapper/base class of viewer
export class OrthographicCamera2 extends OrthographicCamera implements ICamera {
export class OrthographicCamera2<TE extends ICameraEventMap = ICameraEventMap> extends OrthographicCamera<TE&ICameraEventMap> implements ICamera<TE&ICameraEventMap> {
assetType = 'camera' as const assetType = 'camera' as const
get controls(): ICameraControls | undefined { get controls(): ICameraControls | undefined {
return this._controls return this._controls


// region refreshing // region refreshing


setDirty(options?: ICameraSetDirtyOptions|Event): void {
setDirty(options?: ICameraSetDirtyOptions): void {
if (!this._positionWorld) return // class not initialized if (!this._positionWorld) return // class not initialized


if (!options?.key || ['zoom', 'left', 'right', 'top', 'bottom', 'aspect', 'frustumSize'].includes(options.key)) {
// noinspection SuspiciousTypeOfGuard it can be string when called from bindToValue
const changeKey = typeof options === 'string' ? options : options?.key
if (!changeKey || ['zoom', 'left', 'right', 'top', 'bottom', 'aspect', 'frustumSize'].includes(changeKey)) {
this.updateProjectionMatrix() this.updateProjectionMatrix()
} }


if (typeof options === 'string') options = undefined

this.getWorldPosition(this._positionWorld) this.getWorldPosition(this._positionWorld)


iCameraCommons.setDirty.call(this, options) iCameraCommons.setDirty.call(this, options)
this.copy(camera, undefined, distanceFromTarget, worldSpace) this.copy(camera, undefined, distanceFromTarget, worldSpace)
} }


setViewToMain(eventOptions: Partial<ICameraEvent>) {
setViewToMain(eventOptions: Omit<ICameraEventMap['setView'], 'camera'|'bubbleToParent'>) {
this.dispatchEvent({type: 'setView', ...eventOptions, camera: this, bubbleToParent: true}) this.dispatchEvent({type: 'setView', ...eventOptions, camera: this, bubbleToParent: true})
} }


clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
add: (...object: IObject3D[]) => this add: (...object: IObject3D[]) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ICameraEvent) => void
// dispatchEvent: (event: ICameraEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 11
- 7
src/core/camera/PerspectiveCamera2.ts 查看文件

import {Camera, Event, IUniform, Object3D, PerspectiveCamera, Vector3} from 'three'
import {Camera, IUniform, Object3D, PerspectiveCamera, Vector3} from 'three'
import {generateUiConfig, uiInput, UiObjectConfig, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {generateUiConfig, uiInput, UiObjectConfig, uiSlider, uiToggle, uiVector} from 'uiconfig.js'
import {onChange, onChange2, onChange3, serialize} from 'ts-browser-helpers' import {onChange, onChange2, onChange3, serialize} from 'ts-browser-helpers'
import type {ICamera, ICameraEvent, ICameraUserData, TCameraControlsMode} from '../ICamera'
import type {ICamera, ICameraEventMap, ICameraUserData, TCameraControlsMode} from '../ICamera'
import {ICameraSetDirtyOptions} from '../ICamera' import {ICameraSetDirtyOptions} from '../ICamera'
import type {ICameraControls, TControlsCtor} from './ICameraControls' import type {ICameraControls, TControlsCtor} from './ICameraControls'
import {OrbitControls3} from '../../three/controls/OrbitControls3' import {OrbitControls3} from '../../three/controls/OrbitControls3'
import {CameraView, ICameraView} from './CameraView' import {CameraView, ICameraView} from './CameraView'


// todo: maybe change domElement to some wrapper/base class of viewer // todo: maybe change domElement to some wrapper/base class of viewer
export class PerspectiveCamera2 extends PerspectiveCamera implements ICamera {
export class PerspectiveCamera2<TE extends ICameraEventMap = ICameraEventMap> extends PerspectiveCamera<TE&ICameraEventMap> implements ICamera<TE&ICameraEventMap> {
assetType = 'camera' as const assetType = 'camera' as const
get controls(): ICameraControls | undefined { get controls(): ICameraControls | undefined {
return this._controls return this._controls


// region refreshing // region refreshing


setDirty(options?: ICameraSetDirtyOptions|Event): void {
setDirty(options?: ICameraSetDirtyOptions): void {
if (!this._positionWorld) return // class not initialized if (!this._positionWorld) return // class not initialized


if (!options?.key || options?.key === 'fov' || options?.key === 'zoom') this.updateProjectionMatrix()
// noinspection SuspiciousTypeOfGuard it can be string when called from bindToValue
const changeKey = typeof options === 'string' ? options : options?.key
if (!changeKey || changeKey === 'fov' || changeKey === 'zoom') this.updateProjectionMatrix()

if (typeof options === 'string') options = undefined


this.getWorldPosition(this._positionWorld) this.getWorldPosition(this._positionWorld)


this.copy(camera, undefined, distanceFromTarget, worldSpace) this.copy(camera, undefined, distanceFromTarget, worldSpace)
} }


setViewToMain(eventOptions: Partial<ICameraEvent>) {
setViewToMain(eventOptions: Omit<ICameraEventMap['setView'], 'camera'|'bubbleToParent'>): void {
this.dispatchEvent({type: 'setView', ...eventOptions, camera: this, bubbleToParent: true}) this.dispatchEvent({type: 'setView', ...eventOptions, camera: this, bubbleToParent: true})
} }


clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
add: (...object: IObject3D[]) => this add: (...object: IObject3D[]) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ICameraEvent) => void
// dispatchEvent: (event: ICameraEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 2
- 2
src/core/geometry/BufferGeometry2.ts 查看文件

import {BufferGeometry, NormalBufferAttributes, NormalOrGLBufferAttributes} from 'three' import {BufferGeometry, NormalBufferAttributes, NormalOrGLBufferAttributes} from 'three'
import type {IGeometry, IGeometryEvent, IGeometryEventTypes} from '../IGeometry'
import type {IGeometry, IGeometryEventMap} from '../IGeometry'
import {iGeometryCommons} from './iGeometryCommons' import {iGeometryCommons} from './iGeometryCommons'
import type {IObject3D} from '../IObject' import type {IObject3D} from '../IObject'


export class BufferGeometry2<Attributes extends NormalOrGLBufferAttributes = NormalBufferAttributes> extends BufferGeometry<Attributes, IGeometryEvent, IGeometryEventTypes> implements IGeometry<Attributes> {
export class BufferGeometry2<Attributes extends NormalOrGLBufferAttributes = NormalBufferAttributes, TE extends IGeometryEventMap = IGeometryEventMap> extends BufferGeometry<Attributes, TE> implements IGeometry<Attributes, TE> {
assetType: 'geometry' // dont set the value here since its checked in upgradeGeometry assetType: 'geometry' // dont set the value here since its checked in upgradeGeometry
center2 = iGeometryCommons.center2 center2 = iGeometryCommons.center2
setDirty = iGeometryCommons.setDirty setDirty = iGeometryCommons.setDirty

+ 16
- 16
src/core/index.ts 查看文件

export {PerspectiveCamera2, PerspectiveCamera0} from './camera/PerspectiveCamera2' export {PerspectiveCamera2, PerspectiveCamera0} from './camera/PerspectiveCamera2'
export {OrthographicCamera2, OrthographicCamera0} from './camera/OrthographicCamera2' export {OrthographicCamera2, OrthographicCamera0} from './camera/OrthographicCamera2'
export {CameraView, type ICameraView} from './camera/CameraView'
export {CameraView, type ICameraView, type CameraViewEventMap} from './camera/CameraView'
export {ExtendedShaderMaterial} from './material/ExtendedShaderMaterial' export {ExtendedShaderMaterial} from './material/ExtendedShaderMaterial'
export {PhysicalMaterial, type PhysicalMaterialEventTypes, MeshStandardMaterial2} from './material/PhysicalMaterial'
export {PhysicalMaterial, MeshStandardMaterial2} from './material/PhysicalMaterial'
export {ShaderMaterial2} from './material/ShaderMaterial2' export {ShaderMaterial2} from './material/ShaderMaterial2'
export {ObjectShaderMaterial, type ObjectShaderMaterialEventTypes} from './material/ObjectShaderMaterial'
export {UnlitMaterial, type UnlitMaterialEventTypes, MeshBasicMaterial2} from './material/UnlitMaterial'
export {UnlitLineMaterial, type UnlitLineMaterialEventTypes, LineBasicMaterial2} from './material/UnlitLineMaterial'
export {LineMaterial2, type LineMaterial2EventTypes} from './material/LineMaterial2'
export {LegacyPhongMaterial, type PhongMaterialEventTypes} from './material/LegacyPhongMaterial'
export {ObjectShaderMaterial} from './material/ObjectShaderMaterial'
export {UnlitMaterial, MeshBasicMaterial2} from './material/UnlitMaterial'
export {UnlitLineMaterial, LineBasicMaterial2} from './material/UnlitLineMaterial'
export {LineMaterial2} from './material/LineMaterial2'
export {LegacyPhongMaterial} from './material/LegacyPhongMaterial'
export {Mesh2} from './object/Mesh2' export {Mesh2} from './object/Mesh2'
export {BufferGeometry2} from './geometry/BufferGeometry2' export {BufferGeometry2} from './geometry/BufferGeometry2'
export {AmbientLight2} from './light/AmbientLight2' export {AmbientLight2} from './light/AmbientLight2'
export {upgradeTexture} from './ITexture' export {upgradeTexture} from './ITexture'
export {upgradeWebGLRenderer, setThreeRendererMode} from './IRenderer' export {upgradeWebGLRenderer, setThreeRendererMode} from './IRenderer'
export {RootScene} from './object/RootScene' export {RootScene} from './object/RootScene'
export type {ICameraControls, TControlsCtor} from './camera/ICameraControls'
export type {ICamera, ICameraEvent, ICameraEventTypes, ICameraUserData, TCameraControlsMode, ICameraSetDirtyOptions} from './ICamera'
export type {IGeometry, IGeometryUserData, IGeometryEvent, IGeometryEventTypes, IGeometrySetDirtyOptions} from './IGeometry'
export type {IMaterial, IMaterialEvent, IMaterialEventTypes, IMaterialParameters, IMaterialUserData, IMaterialSetDirtyOptions, IMaterialTemplate, IMaterialGenerator} from './IMaterial'
export type {IObject3D, IObject3DEvent, IObjectSetDirtyOptions, IObjectProcessor, IObject3DEventTypes, IObject3DUserData} from './IObject'
export type {IRenderManager, IRenderManagerOptions, IWebGLRenderer, IRenderManagerEventTypes, IAnimationLoopEvent, TThreeRendererMode, TThreeRendererModeUserData, IRenderManagerUpdateEvent, IRenderManagerEvent, RendererBlitOptions} from './IRenderer'
export type {IScene, ISceneEvent, ISceneEventTypes, ISceneSetDirtyOptions, AddObjectOptions, ISceneUserData, IWidget} from './IScene'
export type {ITexture, ITextureUserData, ITextureEvent, ITextureEventTypes} from './ITexture'
export type {ILight, ILightEvent, ILightEventTypes} from './light/ILight'
export type {ICameraControls, TControlsCtor, ICameraControlsEventMap} from './camera/ICameraControls'
export type {ICamera, ICameraEventMap, ICameraUserData, TCameraControlsMode, ICameraSetDirtyOptions} from './ICamera'
export type {IGeometry, IGeometryUserData, IGeometryEventMap, IGeometrySetDirtyOptions} from './IGeometry'
export type {IMaterial, IMaterialEventMap, IMaterialParameters, IMaterialUserData, IMaterialSetDirtyOptions, IMaterialTemplate, IMaterialGenerator} from './IMaterial'
export type {IObject3D, IObject3DEventMap, ISetDirtyCommonOptions, IObjectSetDirtyOptions, IObjectProcessor, IObject3DUserData} from './IObject'
export type {IRenderManager, IRenderManagerOptions, IWebGLRenderer, IRenderManagerEventMap, IAnimationLoopEvent, TThreeRendererMode, TThreeRendererModeUserData, IRenderManagerUpdateEvent, RendererBlitOptions} from './IRenderer'
export type {IScene, ISceneEventMap, ISceneSetDirtyOptions, AddObjectOptions, ISceneUserData, IWidget} from './IScene'
export type {ITexture, ITextureUserData, ITextureEventMap} from './ITexture'
export type {ILight} from './light/ILight'

+ 2
- 2
src/core/light/AmbientLight2.ts 查看文件

import {AmbientLight, Color, ColorRepresentation} from 'three' import {AmbientLight, Color, ColorRepresentation} from 'three'
import {ILight, ILightEvent} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js' import {uiColor, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js'
copy: (source: AmbientLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: AmbientLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 3
- 6
src/core/light/DirectionalLight2.ts 查看文件

import {Color, ColorRepresentation, DirectionalLight, DirectionalLightShadow, Euler, Vector2, Vector3} from 'three' import {Color, ColorRepresentation, DirectionalLight, DirectionalLightShadow, Euler, Vector2, Vector3} from 'three'
import {ILight, ILightEvent, ILightEventTypes} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js'
*/ */
// todo: add Light section in the readme detailing these ...2 lights // todo: add Light section in the readme detailing these ...2 lights
@uiPanelContainer('Directional Light') @uiPanelContainer('Directional Light')
export class DirectionalLight2<
E extends ILightEvent = ILightEvent,
ET extends ILightEventTypes = ILightEventTypes
> extends DirectionalLight<E, ET> implements ILight<DirectionalLightShadow> {
export class DirectionalLight2 extends DirectionalLight implements ILight<DirectionalLightShadow> {
assetType = 'light' as const assetType = 'light' as const
setDirty = iLightCommons.setDirty setDirty = iLightCommons.setDirty
refreshUi = iLightCommons.refreshUi refreshUi = iLightCommons.refreshUi
copy: (source: DirectionalLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: DirectionalLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 2
- 2
src/core/light/HemisphereLight2.ts 查看文件

import {Color, ColorRepresentation, HemisphereLight, Vector3} from 'three' import {Color, ColorRepresentation, HemisphereLight, Vector3} from 'three'
import {ILight, ILightEvent} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {uiColor, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js'
copy: (source: HemisphereLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: HemisphereLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 9
- 10
src/core/light/ILight.ts 查看文件

import {Light, LightShadow, Object3D} from 'three' import {Light, LightShadow, Object3D} from 'three'
import {IObject3D, IObject3DEvent, IObject3DEventTypes, IObject3DUserData} from '../IObject'
import {IObject3D, IObject3DEventMap, IObject3DUserData} from '../IObject'


export interface ILight< export interface ILight<
TShadowSupport extends LightShadow | undefined = LightShadow | undefined, TShadowSupport extends LightShadow | undefined = LightShadow | undefined,
E extends ILightEvent = ILightEvent,
ET extends ILightEventTypes = ILightEventTypes
> extends Light<TShadowSupport, E, ET>, IObject3D<E, ET> {
TE extends IObject3DEventMap = IObject3DEventMap
> extends Light<TShadowSupport, TE>, IObject3D<TE> {
assetType: 'light' assetType: 'light'
readonly isLight: true readonly isLight: true


// endregion // endregion
} }


export type ILightEventTypes = IObject3DEventTypes | 'lightUpdate'// | string
export type ILightEvent = Omit<IObject3DEvent, 'type'> & {
type: ILightEventTypes
light?: ILight | null
// change?: string
}
// export type ILightEventTypes = IObject3DEventTypes | 'lightUpdate'// | string
// export type ILightEvent = Omit<IObject3DEvent, 'type'> & {
// type: ILightEventTypes
// light?: ILight | null
// // change?: string
// }

+ 2
- 2
src/core/light/PointLight2.ts 查看文件

import {Color, ColorRepresentation, PointLight, PointLightShadow, Vector2, Vector3} from 'three' import {Color, ColorRepresentation, PointLight, PointLightShadow, Vector2, Vector3} from 'three'
import {ILight, ILightEvent} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js'
copy: (source: PointLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: PointLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 2
- 2
src/core/light/RectAreaLight2.ts 查看文件

import {Color, ColorRepresentation, RectAreaLight} from 'three' import {Color, ColorRepresentation, RectAreaLight} from 'three'
import {ILight, ILightEvent} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js' import {uiColor, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle} from 'uiconfig.js'
copy: (source: RectAreaLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: RectAreaLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 2
- 2
src/core/light/SpotLight2.ts 查看文件

import {Color, ColorRepresentation, Euler, SpotLight, SpotLightShadow, Vector2, Vector3} from 'three' import {Color, ColorRepresentation, Euler, SpotLight, SpotLightShadow, Vector2, Vector3} from 'three'
import {ILight, ILightEvent} from './ILight'
import {ILight} from './ILight'
import {iLightCommons} from '../object/iLightCommons' import {iLightCommons} from '../object/iLightCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {uiColor, uiInput, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {uiColor, uiInput, uiNumber, UiObjectConfig, uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js'
copy: (source: SpotLight|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: SpotLight|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
// dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]



+ 5
- 8
src/core/material/LegacyPhongMaterial.ts 查看文件

import { import {
BaseEvent,
Color, Color,
IUniform, IUniform,
Material, Material,
import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import { import {
IMaterial, IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialEventMap,
IMaterialGenerator, IMaterialGenerator,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'
import {makeSamplerUi} from '../../ui/image-ui' import {makeSamplerUi} from '../../ui/image-ui'


export type PhongMaterialEventTypes = IMaterialEventTypes | ''

export class LegacyPhongMaterial extends MeshPhongMaterial<IMaterialEvent, PhongMaterialEventTypes> implements IMaterial<IMaterialEvent, PhongMaterialEventTypes> {
export class LegacyPhongMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends MeshPhongMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof LegacyPhongMaterial declare ['constructor']: typeof LegacyPhongMaterial


public static readonly TypeSlug = 'phongmat' public static readonly TypeSlug = 'phongmat'
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}

dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
generator?: IMaterialGenerator generator?: IMaterialGenerator


envMap: ITexture | null = null envMap: ITexture | null = null
/** /**
* Serializes this material to JSON. * Serializes this material to JSON.
* @param meta - metadata for serialization * @param meta - metadata for serialization
* @param _internal - Calls only super.toJSON, does internal three.js serialization and @serialize tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
* @param _internal - Calls only super.toJSON, does internal three.js serialization and `@serialize` tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
*/ */
toJSON(meta?: SerializationMetaType, _internal = false): any { toJSON(meta?: SerializationMetaType, _internal = false): any {
if (_internal) return { if (_internal) return {

+ 5
- 14
src/core/material/LineMaterial2.ts 查看文件

import {generateUiConfig, uiColor, uiInput, uiNumber, UiObjectConfig, uiToggle, uiVector} from 'uiconfig.js' import {generateUiConfig, uiColor, uiInput, uiNumber, UiObjectConfig, uiToggle, uiVector} from 'uiconfig.js'
import {Color, IUniform, Material, Shader, Vector2, WebGLRenderer} from 'three'
import {BaseEvent, Color, IUniform, Material, Shader, Vector2, WebGLRenderer} from 'three'
import {SerializationMetaType, shaderReplaceString, ThreeSerialization} from '../../utils' import {SerializationMetaType, shaderReplaceString, ThreeSerialization} from '../../utils'
import {
IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialGenerator,
IMaterialParameters,
IMaterialTemplate,
} from '../IMaterial'
import {IMaterial, IMaterialEventMap, IMaterialGenerator, IMaterialParameters, IMaterialTemplate} from '../IMaterial'
import {MaterialExtension} from '../../materials' import {MaterialExtension} from '../../materials'
import {iMaterialCommons, threeMaterialPropList} from './iMaterialCommons' import {iMaterialCommons, threeMaterialPropList} from './iMaterialCommons'
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'
import {LineMaterial, type LineMaterialParameters} from 'three/examples/jsm/lines/LineMaterial.js' import {LineMaterial, type LineMaterialParameters} from 'three/examples/jsm/lines/LineMaterial.js'


export type LineMaterial2EventTypes = IMaterialEventTypes | ''

/** /**
* And extension of three.js LineMaterial that can be assigned to lines, and support threepipe features, uiconfig, and serialization. * And extension of three.js LineMaterial that can be assigned to lines, and support threepipe features, uiconfig, and serialization.
* *
* @category Materials * @category Materials
*/ */
export class LineMaterial2 extends LineMaterial<IMaterialEvent, LineMaterial2EventTypes> implements IMaterial<IMaterialEvent, LineMaterial2EventTypes> {
export class LineMaterial2<TE extends IMaterialEventMap = IMaterialEventMap> extends LineMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof LineMaterial2 declare ['constructor']: typeof LineMaterial2
public static readonly TypeSlug = 'lmat' public static readonly TypeSlug = 'lmat'
public static readonly TYPE = 'LineMaterial2' // not using .type because it is used by three.js public static readonly TYPE = 'LineMaterial2' // not using .type because it is used by three.js
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator


/** /**
* Serializes this material to JSON. * Serializes this material to JSON.
* @param meta - metadata for serialization * @param meta - metadata for serialization
* @param _internal - Calls only super.toJSON, does internal three.js serialization and @serialize tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
* @param _internal - Calls only super.toJSON, does internal three.js serialization and `@serialize` tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
*/ */
toJSON(meta?: SerializationMetaType, _internal = false): any { toJSON(meta?: SerializationMetaType, _internal = false): any {
if (_internal) return { if (_internal) return {

+ 4
- 7
src/core/material/ObjectShaderMaterial.ts 查看文件

import {IUniform, Material, Shader, ShaderMaterial, ShaderMaterialParameters, WebGLRenderer} from 'three'
import {BaseEvent, IUniform, Material, Shader, ShaderMaterial, ShaderMaterialParameters, WebGLRenderer} from 'three'
import {generateUiConfig, UiObjectConfig} from 'uiconfig.js' import {generateUiConfig, UiObjectConfig} from 'uiconfig.js'
import { import {
IMaterial, IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialEventMap,
IMaterialGenerator, IMaterialGenerator,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'


export type ObjectShaderMaterialEventTypes = IMaterialEventTypes | ''

/** /**
* And extension of three.js ShaderMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization. * And extension of three.js ShaderMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization.
* *
* @category Materials * @category Materials
*/ */
export class ObjectShaderMaterial extends ShaderMaterial<IMaterialEvent, ObjectShaderMaterialEventTypes> implements IMaterial<IMaterialEvent, ObjectShaderMaterialEventTypes> {
export class ObjectShaderMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends ShaderMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof ObjectShaderMaterial declare ['constructor']: typeof ObjectShaderMaterial


public static readonly TypeSlug = 'shmat' public static readonly TypeSlug = 'shmat'
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator



+ 4
- 6
src/core/material/PhysicalMaterial.ts 查看文件

import {generateUiConfig, UiObjectConfig} from 'uiconfig.js' import {generateUiConfig, UiObjectConfig} from 'uiconfig.js'
import { import {
BaseEvent,
BufferGeometry, BufferGeometry,
Camera, Camera,
Color, Color,
import {SerializationMetaType, shaderReplaceString, ThreeSerialization} from '../../utils' import {SerializationMetaType, shaderReplaceString, ThreeSerialization} from '../../utils'
import { import {
IMaterial, IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialEventMap,
IMaterialGenerator, IMaterialGenerator,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
import {ITexture} from '../ITexture' import {ITexture} from '../ITexture'
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'


export type PhysicalMaterialEventTypes = IMaterialEventTypes | ''

/** /**
* And extension of three.js MeshPhysicalMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization. * And extension of three.js MeshPhysicalMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization.
* *
* @category Materials * @category Materials
*/ */
export class PhysicalMaterial extends MeshPhysicalMaterial<IMaterialEvent, PhysicalMaterialEventTypes> implements IMaterial<IMaterialEvent, PhysicalMaterialEventTypes> {
export class PhysicalMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends MeshPhysicalMaterial<TE & IMaterialEventMap> implements IMaterial<TE> {
declare ['constructor']: typeof PhysicalMaterial declare ['constructor']: typeof PhysicalMaterial
public static readonly TypeSlug = 'pmat' public static readonly TypeSlug = 'pmat'
public static readonly TYPE = 'PhysicalMaterial' // not using .type because it is used by three.js public static readonly TYPE = 'PhysicalMaterial' // not using .type because it is used by three.js
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator



+ 4
- 3
src/core/material/ShaderMaterial2.ts 查看文件

import { import {
BaseEvent,
BufferGeometry, BufferGeometry,
Camera, Camera,
IUniform, IUniform,
ShaderMaterialParameters, ShaderMaterialParameters,
WebGLRenderer, WebGLRenderer,
} from 'three' } from 'three'
import {IMaterial, IMaterialEvent, IMaterialEventTypes, IMaterialParameters, IMaterialUserData} from '../IMaterial'
import {IMaterial, IMaterialEventMap, IMaterialParameters, IMaterialUserData} from '../IMaterial'
import {MaterialExtension} from '../../materials' import {MaterialExtension} from '../../materials'
import {iMaterialCommons, threeMaterialPropList} from './iMaterialCommons' import {iMaterialCommons, threeMaterialPropList} from './iMaterialCommons'


export class ShaderMaterial2<E extends IMaterialEvent = IMaterialEvent, ET = IMaterialEventTypes> extends ShaderMaterial<E, ET> implements IMaterial<E, ET> {
export class ShaderMaterial2<TE extends IMaterialEventMap = IMaterialEventMap> extends ShaderMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof ShaderMaterial2 declare ['constructor']: typeof ShaderMaterial2


static readonly TypeSlug = 'shaderMat' static readonly TypeSlug = 'shaderMat'
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


readonly isRawShaderMaterial: boolean readonly isRawShaderMaterial: boolean



+ 14
- 8
src/core/material/UnlitLineMaterial.ts 查看文件

import {Color, IUniform, LineBasicMaterial, LineBasicMaterialParameters, Material, Shader, WebGLRenderer} from 'three'
import {
BaseEvent,
Color,
IUniform,
LineBasicMaterial,
LineBasicMaterialParameters,
Material,
Shader,
WebGLRenderer,
} from 'three'
import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import { import {
IMaterial, IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialEventMap,
IMaterialGenerator, IMaterialGenerator,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
import {makeSamplerUi} from '../../ui/image-ui' import {makeSamplerUi} from '../../ui/image-ui'
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'


export type UnlitLineMaterialEventTypes = IMaterialEventTypes | ''

/** /**
* And extension of three.js LineBasicMaterial that can be assigned to lines, and support threepipe features, uiconfig, and serialization. * And extension of three.js LineBasicMaterial that can be assigned to lines, and support threepipe features, uiconfig, and serialization.
* *
* @category Materials * @category Materials
*/ */
export class UnlitLineMaterial extends LineBasicMaterial<IMaterialEvent, UnlitLineMaterialEventTypes> implements IMaterial<IMaterialEvent, UnlitLineMaterialEventTypes> {
export class UnlitLineMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends LineBasicMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof UnlitLineMaterial declare ['constructor']: typeof UnlitLineMaterial


public static readonly TypeSlug = 'blmat' public static readonly TypeSlug = 'blmat'
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator


/** /**
* Serializes this material to JSON. * Serializes this material to JSON.
* @param meta - metadata for serialization * @param meta - metadata for serialization
* @param _internal - Calls only super.toJSON, does internal three.js serialization and @serialize tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
* @param _internal - Calls only super.toJSON, does internal three.js serialization and `@serialize` tags. Set it to true only if you know what you are doing. This is used in Serialization->serializer->material
*/ */
toJSON(meta?: SerializationMetaType, _internal = false): any { toJSON(meta?: SerializationMetaType, _internal = false): any {
if (_internal) return { if (_internal) return {

+ 4
- 6
src/core/material/UnlitMaterial.ts 查看文件

import { import {
BaseEvent,
Color, Color,
IUniform, IUniform,
Material, Material,
import {generateUiConfig, UiObjectConfig} from 'uiconfig.js' import {generateUiConfig, UiObjectConfig} from 'uiconfig.js'
import { import {
IMaterial, IMaterial,
IMaterialEvent,
IMaterialEventTypes,
IMaterialEventMap,
IMaterialGenerator, IMaterialGenerator,
IMaterialParameters, IMaterialParameters,
IMaterialTemplate, IMaterialTemplate,
import {IObject3D} from '../IObject' import {IObject3D} from '../IObject'
import {iMaterialUI} from './IMaterialUi' import {iMaterialUI} from './IMaterialUi'


export type UnlitMaterialEventTypes = IMaterialEventTypes | ''

/** /**
* And extension of three.js MeshBasicMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization. * And extension of three.js MeshBasicMaterial that can be assigned to objects, and support threepipe features, uiconfig, and serialization.
* *
* @category Materials * @category Materials
*/ */
export class UnlitMaterial extends MeshBasicMaterial<IMaterialEvent, UnlitMaterialEventTypes> implements IMaterial<IMaterialEvent, UnlitMaterialEventTypes> {
export class UnlitMaterial<TE extends IMaterialEventMap = IMaterialEventMap> extends MeshBasicMaterial<TE> implements IMaterial<TE> {
declare ['constructor']: typeof UnlitMaterial declare ['constructor']: typeof UnlitMaterial


public static readonly TypeSlug = 'bmat' public static readonly TypeSlug = 'bmat'
readonly setDirty = iMaterialCommons.setDirty readonly setDirty = iMaterialCommons.setDirty
dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)} dispose(): this {return iMaterialCommons.dispose(super.dispose).call(this)}
clone(): this {return iMaterialCommons.clone(super.clone).call(this)} clone(): this {return iMaterialCommons.clone(super.clone).call(this)}
dispatchEvent(event: IMaterialEvent): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}
dispatchEvent<T extends Extract<keyof (TE&IMaterialEventMap), string>>(event: BaseEvent<T> & (TE&IMaterialEventMap)[T]): void {iMaterialCommons.dispatchEvent(super.dispatchEvent).call(this, event)}


generator?: IMaterialGenerator generator?: IMaterialGenerator



+ 5
- 5
src/core/material/iMaterialCommons.ts 查看文件

import {copyMaterialUserData} from '../../utils/serialization' import {copyMaterialUserData} from '../../utils/serialization'
import {MaterialExtender, MaterialExtension} from '../../materials' import {MaterialExtender, MaterialExtension} from '../../materials'
import {IScene} from '../IScene' import {IScene} from '../IScene'
import {IMaterial, IMaterialEvent, IMaterialSetDirtyOptions} from '../IMaterial'
import {IMaterial, IMaterialEventMap, IMaterialSetDirtyOptions} from '../IMaterial'
import {isInScene} from '../../three/utils' import {isInScene} from '../../three/utils'


/** /**
this.setDirty?.() this.setDirty?.()
return this return this
}, },
dispose: (superDispose: Material<any, any>['dispose']): IMaterial['dispose'] =>
dispose: (superDispose: Material['dispose']): IMaterial['dispose'] =>
function(this: IMaterial, force = true): void { function(this: IMaterial, force = true): void {
if (!force && (this.userData.disposeOnIdle === false || isInScene(this))) return if (!force && (this.userData.disposeOnIdle === false || isInScene(this))) return
superDispose.call(this) superDispose.call(this)
}, },
clone: (superClone: Material<any, any>['clone']): IMaterial['clone'] =>
clone: (superClone: Material['clone']): IMaterial['clone'] =>
function(this: IMaterial): IMaterial { function(this: IMaterial): IMaterial {
if (!this.userData.cloneId) { if (!this.userData.cloneId) {
this.userData.cloneId = '0' this.userData.cloneId = '0'
return material return material
}, },
dispatchEvent: (superDispatchEvent: Material['dispatchEvent']): IMaterial['dispatchEvent'] => dispatchEvent: (superDispatchEvent: Material['dispatchEvent']): IMaterial['dispatchEvent'] =>
function(this: IMaterial, event: IMaterialEvent): void {
function(this: IMaterial, event): void {
superDispatchEvent.call(this, event) superDispatchEvent.call(this, event)
const type = event.type const type = event.type
if (event.bubbleToObject && (
if ((event as IMaterialEventMap['materialUpdate']).bubbleToObject && (
type === 'beforeDeserialize' || type === 'materialUpdate' || type === 'textureUpdate' // todo - add more events type === 'beforeDeserialize' || type === 'materialUpdate' || type === 'textureUpdate' // todo - add more events
)) { )) {
this.appliedMeshes.forEach(m => m.dispatchEvent({...event, material: this, type})) this.appliedMeshes.forEach(m => m.dispatchEvent({...event, material: this, type}))

+ 4
- 5
src/core/object/Mesh2.ts 查看文件

import {Mesh} from 'three' import {Mesh} from 'three'
import {IObject3D, IObject3DUserData} from '../IObject'
import {IObject3D, IObject3DEventMap, IObject3DUserData} from '../IObject'
import {iObjectCommons} from './iObjectCommons' import {iObjectCommons} from './iObjectCommons'
import {IMaterial} from '../IMaterial' import {IMaterial} from '../IMaterial'
import {IGeometry} from '../IGeometry' import {IGeometry} from '../IGeometry'
import {ILightEvent} from '../light/ILight'


export class Mesh2< export class Mesh2<
TGeometry extends IGeometry = IGeometry, TGeometry extends IGeometry = IGeometry,
TMaterial extends IMaterial | IMaterial[] = IMaterial | IMaterial[]
> extends Mesh<TGeometry, TMaterial> implements IObject3D {
TMaterial extends IMaterial | IMaterial[] = IMaterial | IMaterial[],
TE extends IObject3DEventMap = IObject3DEventMap
> extends Mesh<TGeometry, TMaterial, TE> implements IObject3D<TE> {
assetType = 'model' as const assetType = 'model' as const
setDirty = iObjectCommons.setDirty setDirty = iObjectCommons.setDirty
refreshUi = iObjectCommons.refreshUi refreshUi = iObjectCommons.refreshUi
copy: (source: Mesh2|IObject3D, recursive?: boolean, ...args: any[]) => this copy: (source: Mesh2|IObject3D, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ILightEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]
dispose: (removeFromParent?: boolean) => void dispose: (removeFromParent?: boolean) => void

+ 22
- 24
src/core/object/RootScene.ts 查看文件

UVMapping, UVMapping,
Vector3, Vector3,
} from 'three' } from 'three'
import type {IObject3D, IObjectProcessor} from '../IObject'
import type {IObject3D, IObject3DEventMap, IObjectProcessor} from '../IObject'
import {type ICamera} from '../ICamera' import {type ICamera} from '../ICamera'
import {autoGPUInstanceMeshes, bindToValue, Box3B} from '../../three' import {autoGPUInstanceMeshes, bindToValue, Box3B} from '../../three'
import {AnyOptions, onChange2, onChange3, serialize} from 'ts-browser-helpers' import {AnyOptions, onChange2, onChange3, serialize} from 'ts-browser-helpers'
import {PerspectiveCamera2} from '../camera/PerspectiveCamera2' import {PerspectiveCamera2} from '../camera/PerspectiveCamera2'
import {ThreeSerialization} from '../../utils' import {ThreeSerialization} from '../../utils'
import {ITexture} from '../ITexture' import {ITexture} from '../ITexture'
import {AddObjectOptions, IScene, ISceneEvent, ISceneEventTypes, ISceneSetDirtyOptions, IWidget} from '../IScene'
import {AddObjectOptions, IScene, ISceneEventMap, ISceneSetDirtyOptions, IWidget} from '../IScene'
import {iObjectCommons} from './iObjectCommons' import {iObjectCommons} from './iObjectCommons'
import {RootSceneImportResult} from '../../assetmanager' import {RootSceneImportResult} from '../../assetmanager'
import {uiButton, uiColor, uiConfig, uiFolderContainer, uiImage, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js' import {uiButton, uiColor, uiConfig, uiFolderContainer, uiImage, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js'
import {IGeometry} from '../IGeometry' import {IGeometry} from '../IGeometry'
import {getFittingDistance} from '../../three/utils/camera' import {getFittingDistance} from '../../three/utils/camera'


export type TCamera = ICamera

@uiFolderContainer('Root Scene') @uiFolderContainer('Root Scene')
export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements IScene<ISceneEvent, ISceneEventTypes> {
export class RootScene<TE extends ISceneEventMap = ISceneEventMap> extends Scene<TE&ISceneEventMap> implements IScene<TE> {
readonly isRootScene = true readonly isRootScene = true


assetType = 'model' as const assetType = 'model' as const


// private _processors = new ObjectProcessorMap<'environment' | 'background'>() // private _processors = new ObjectProcessorMap<'environment' | 'background'>()
// private _sceneObjects: ISceneObject[] = [] // private _sceneObjects: ISceneObject[] = []
private _mainCamera: TCamera | null = null
private _mainCamera: ICamera | null = null
/** /**
* The root object where all imported objects are added. * The root object where all imported objects are added.
*/ */
/** /**
* The default camera in the scene * The default camera in the scene
*/ */
@uiConfig() @serialize() readonly defaultCamera: TCamera
@uiConfig() @serialize() readonly defaultCamera: ICamera


// private _environmentLight?: IEnvironmentLight // private _environmentLight?: IEnvironmentLight


// required just because we don't want activeCamera to be null. // required just because we don't want activeCamera to be null.
private _dummyCam = new PerspectiveCamera2('') as TCamera
private _dummyCam = new PerspectiveCamera2('') as ICamera


get mainCamera(): TCamera {
get mainCamera(): ICamera {
return this._mainCamera || this._dummyCam return this._mainCamera || this._dummyCam
} }
set mainCamera(camera: TCamera | undefined) {
set mainCamera(camera: ICamera | undefined) {
const cam = this.mainCamera const cam = this.mainCamera
if (!camera) camera = this.defaultCamera if (!camera) camera = this.defaultCamera
if (cam === camera) return if (cam === camera) return
this.setDirty() this.setDirty()
} }


private _renderCamera: TCamera | undefined
private _renderCamera: ICamera | undefined
get renderCamera() { get renderCamera() {
return this._renderCamera ?? this.mainCamera return this._renderCamera ?? this.mainCamera
} }
set renderCamera(camera: TCamera) {
set renderCamera(camera: ICamera) {
const cam = this._renderCamera const cam = this._renderCamera
this._renderCamera = camera this._renderCamera = camera
this.dispatchEvent({type: 'renderCameraChange', lastCamera: cam, camera}) this.dispatchEvent({type: 'renderCameraChange', lastCamera: cam, camera})
* @param camera * @param camera
* @param objectProcessor * @param objectProcessor
*/ */
constructor(camera: TCamera, objectProcessor?: IObjectProcessor) {
constructor(camera: ICamera, objectProcessor?: IObjectProcessor) {
super() super()
this.setDirty = this.setDirty.bind(this) this.setDirty = this.setDirty.bind(this)


if (options?.refreshScene) { if (options?.refreshScene) {
this.refreshScene(options) this.refreshScene(options)
} else { } else {
this.dispatchEvent({type: 'update'}) // todo remove
this.dispatchEvent({type: 'update', bubbleToParent: false, object: this}) // todo remove
iObjectCommons.setDirty.call(this, {...options, scene: this}) iObjectCommons.setDirty.call(this, {...options, scene: this})
} // this sets dirty in the viewer } // this sets dirty in the viewer
return this return this
} }




private _mainCameraUpdate = (e: any) => {
private _mainCameraUpdate: EventListener<IObject3DEventMap['cameraUpdate'], 'cameraUpdate', ICamera> = (e) => {
this.setDirty({refreshScene: false}) this.setDirty({refreshScene: false})
this.refreshActiveCameraNearFar() this.refreshActiveCameraNearFar()
if (e.key === 'fov') this.dollyActiveCameraFov() if (e.key === 'fov') this.dollyActiveCameraFov()
*/ */
// readonly boxHelper: Box3Helper // readonly boxHelper: Box3Helper


refreshScene(event?: Partial<ISceneEvent> & ISceneSetDirtyOptions): this {
refreshScene(event?: Partial<(ISceneEventMap['objectUpdate']|ISceneEventMap['geometryUpdate']|ISceneEventMap['geometryChanged'])> & ISceneSetDirtyOptions & {type?: keyof ISceneEventMap}): this {
if (event && event.type === 'objectUpdate' && event.object === this) return this // ignore self if (event && event.type === 'objectUpdate' && event.object === this) return this // ignore self
// todo test the isCamera here. this is for animation object plugin // todo test the isCamera here. this is for animation object plugin
if (event?.sceneUpdate === false || event?.refreshScene === false || event?.object?.isCamera) return this.setDirty(event) // so that it doesn't trigger frame fade, shadow refresh etc if (event?.sceneUpdate === false || event?.refreshScene === false || event?.object?.isCamera) return this.setDirty(event) // so that it doesn't trigger frame fade, shadow refresh etc


/** /**
* Dispose the scene and clear all resources. * Dispose the scene and clear all resources.
* @warn Not fully implemented yet, just clears the scene.
* WARNING - Not fully implemented yet, just clears the scene.
*/ */
dispose(clear = true): void { dispose(clear = true): void {
this.disposeSceneModels(false, clear) this.disposeSceneModels(false, clear)
* This is called automatically every time the camera is updated. * This is called automatically every time the camera is updated.
*/ */
refreshActiveCameraNearFar(): void { refreshActiveCameraNearFar(): void {
const camera = this.mainCamera as TCamera
const camera = this.mainCamera as ICamera
if (!camera) return if (!camera) return
if (!this.autoNearFarEnabled || camera.userData.autoNearFar === false) { if (!this.autoNearFarEnabled || camera.userData.autoNearFar === false) {
camera.near = camera.userData.minNearPlane ?? 0.5 camera.near = camera.userData.minNearPlane ?? 0.5
* This is called automatically every time the camera fov is updated. * This is called automatically every time the camera fov is updated.
*/ */
dollyActiveCameraFov(): void { dollyActiveCameraFov(): void {
const camera = this.mainCamera as TCamera
const camera = this.mainCamera as ICamera
if (!camera) return if (!camera) return
if (!camera.userData.dollyFov) { if (!camera.userData.dollyFov) {
return return
* Deserialize the scene properties * Deserialize the scene properties
* @param json - object from {@link toJSON} * @param json - object from {@link toJSON}
* @param meta * @param meta
* @returns {this<TCamera>}
* @returns {this<ICamera>}
*/ */
fromJSON(json: any, meta?: any): this { fromJSON(json: any, meta?: any): this {
const env = json.environment const env = json.environment
return this return this
} }


addEventListener<T extends ISceneEventTypes>(type: T, listener: EventListener<ISceneEvent, T, this>): void {
addEventListener<T extends keyof ISceneEventMap>(type: T, listener: EventListener<ISceneEventMap[T], T, this>): void {
if (type === 'activeCameraChange') console.error('activeCameraChange is deprecated. Use mainCameraChange instead.') if (type === 'activeCameraChange') console.error('activeCameraChange is deprecated. Use mainCameraChange instead.')
if (type === 'activeCameraUpdate') console.error('activeCameraUpdate is deprecated. Use mainCameraUpdate instead.') if (type === 'activeCameraUpdate') console.error('activeCameraUpdate is deprecated. Use mainCameraUpdate instead.')
if (type === 'sceneMaterialUpdate') console.error('sceneMaterialUpdate is deprecated. Use materialUpdate instead.') if (type === 'sceneMaterialUpdate') console.error('sceneMaterialUpdate is deprecated. Use materialUpdate instead.')
copy: (source: this, recursive?: boolean, ...args: any[]) => this copy: (source: this, recursive?: boolean, ...args: any[]) => this
clone: (recursive?: boolean) => this clone: (recursive?: boolean) => this
remove: (...object: IObject3D[]) => this remove: (...object: IObject3D[]) => this
dispatchEvent: (event: ISceneEvent) => void
// dispatchEvent: (event: ISceneEvent) => void
declare parent: IObject3D | null declare parent: IObject3D | null
declare children: IObject3D[] declare children: IObject3D[]


/** /**
* @deprecated * @deprecated
*/ */
get activeCamera(): TCamera {
get activeCamera(): ICamera {
console.error('activeCamera is deprecated. Use mainCamera instead.') console.error('activeCamera is deprecated. Use mainCamera instead.')
return this.mainCamera return this.mainCamera
} }
/** /**
* @deprecated * @deprecated
*/ */
set activeCamera(camera: TCamera | undefined) {
set activeCamera(camera: ICamera | undefined) {
console.error('activeCamera is deprecated. Use mainCamera instead.') console.error('activeCamera is deprecated. Use mainCamera instead.')
this.mainCamera = camera this.mainCamera = camera
} }

+ 4
- 4
src/core/object/iCameraCommons.ts 查看文件

import {iObjectCommons} from './iObjectCommons' import {iObjectCommons} from './iObjectCommons'
import {Camera, Vector3} from 'three' import {Camera, Vector3} from 'three'
import type {ICamera, ICameraEvent, ICameraSetDirtyOptions} from '../ICamera'
import type {ICamera, ICameraEventMap, ICameraSetDirtyOptions} from '../ICamera'


export const iCameraCommons = { export const iCameraCommons = {
setDirty: function(this: ICamera, options?: ICameraSetDirtyOptions): void { setDirty: function(this: ICamera, options?: ICameraSetDirtyOptions): void {
this.lookAt(this.target) this.lookAt(this.target)
} }
// } // }
this.dispatchEvent({...options, type: 'update'}) // does not bubble
this.dispatchEvent({...options, type: 'update', bubbleToParent: false, camera: this}) // does not bubble
this.dispatchEvent({...options, type: 'cameraUpdate', bubbleToParent: true}) // this sets dirty in the viewer this.dispatchEvent({...options, type: 'cameraUpdate', bubbleToParent: true}) // this sets dirty in the viewer
iObjectCommons.setDirty.call(this, {refreshScene: false, ...options}) iObjectCommons.setDirty.call(this, {refreshScene: false, ...options})
}, },
activateMain: function(this: ICamera, options: Partial<ICameraEvent> = {}, _internal = false, _refresh = true): void {
activateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true): void {
if (!_internal) { if (!_internal) {
if (options.camera === null) return this.deactivateMain(options, _internal, _refresh) if (options.camera === null) return this.deactivateMain(options, _internal, _refresh)
return this.dispatchEvent({ return this.dispatchEvent({
this.setDirty({change: 'activateMain', ...options}) this.setDirty({change: 'activateMain', ...options})
// console.log({...this._camera.modelObject.position}) // console.log({...this._camera.modelObject.position})
}, },
deactivateMain: function(this: ICamera, options: Partial<ICameraEvent> = {}, _internal = false, _refresh = true): void {
deactivateMain: function(this: ICamera, options: Omit<ICameraEventMap['activateMain'], 'bubbleToParent'> = {}, _internal = false, _refresh = true): void {
if (!_internal) return this.dispatchEvent({ if (!_internal) return this.dispatchEvent({
type: 'activateMain', ...options, type: 'activateMain', ...options,
camera: null, camera: null,

+ 1
- 1
src/core/object/iLightCommons.ts 查看文件

if (typeof options === 'string') { // just incase called by decorators if (typeof options === 'string') { // just incase called by decorators
options = {change: options} options = {change: options}
} }
this.dispatchEvent({bubbleToParent: true, ...options, type: 'lightUpdate', light: this, object: this, args}) // this sets sceneUpdate in root scene
// this.dispatchEvent({bubbleToParent: true, ...options, type: 'lightUpdate', light: this, object: this, args}) // this sets sceneUpdate in root scene
iObjectCommons.setDirty.call(this, options, ...args) iObjectCommons.setDirty.call(this, options, ...args)
}, },
upgradeLight: upgradeLight, upgradeLight: upgradeLight,

+ 12
- 11
src/core/object/iObjectCommons.ts 查看文件

import {Event, Matrix4, Mesh, Vector3} from 'three' import {Event, Matrix4, Mesh, Vector3} from 'three'
import {IMaterial} from '../IMaterial' import {IMaterial} from '../IMaterial'
import {objectHasOwn} from 'ts-browser-helpers' import {objectHasOwn} from 'ts-browser-helpers'
import {IObject3D, IObject3DEvent, IObjectProcessor, IObjectSetDirtyOptions} from '../IObject'
import {IObject3D, IObject3DEventMap, IObjectProcessor, IObjectSetDirtyOptions} from '../IObject'
import {copyObject3DUserData} from '../../utils' import {copyObject3DUserData} from '../../utils'
import {IGeometry, IGeometryEvent} from '../IGeometry'
import {IGeometry, IGeometryEventMap} from '../IGeometry'
import {Box3B} from '../../three' import {Box3B} from '../../three'
import {makeIObject3DUiConfig} from './IObjectUi' import {makeIObject3DUiConfig} from './IObjectUi'
import {iGeometryCommons} from '../geometry/iGeometryCommons' import {iGeometryCommons} from '../geometry/iGeometryCommons'
}) })
} }
}, },
onGeometryUpdate: function(this: IObject3D, e: IGeometryEvent<'geometryUpdate'>): void {
onGeometryUpdate: function(this: IObject3D, e: IGeometryEventMap['geometryUpdate']&Event<'geometryUpdate'>): void {
if (!e.bubbleToObject) return if (!e.bubbleToObject) return
this.dispatchEvent({bubbleToParent: true, ...e, object: this, geometry: e.geometry}) this.dispatchEvent({bubbleToParent: true, ...e, object: this, geometry: e.geometry})
}, },
// todo: check by uuid? // todo: check by uuid?


// Remove old material listeners // Remove old material listeners
const mats = Array.isArray(this.material) ? [...(this.material as IMaterial[])] : [this.material!]
const oldMats = this.material
const mats = Array.isArray(oldMats) ? [...oldMats] : [oldMats!]
for (const mat of mats) { for (const mat of mats) {
if (!mat) continue if (!mat) continue
if (mat.appliedMeshes) { if (mat.appliedMeshes) {
} }
this._currentMaterial = !materials.length ? null : materials.length !== 1 ? materials : materials[0] || null this._currentMaterial = !materials.length ? null : materials.length !== 1 ? materials : materials[0] || null


this.dispatchEvent({type: 'materialChanged', material, oldMaterial: mats, object: this, bubbleToParent: true})
this.dispatchEvent({type: 'materialChanged', material: this._currentMaterial ?? null, oldMaterial: oldMats ?? null, object: this, bubbleToParent: true})
this.refreshUi() this.refreshUi()
}, },
setMaterials: function(this: IObject3D, materials: IMaterial[]) { setMaterials: function(this: IObject3D, materials: IMaterial[]) {
this._onGeometryUpdate && geometry.addEventListener('geometryUpdate', this._onGeometryUpdate) this._onGeometryUpdate && geometry.addEventListener('geometryUpdate', this._onGeometryUpdate)
geometry.appliedMeshes.add(this) geometry.appliedMeshes.add(this)
} }
this.dispatchEvent({type: 'geometryChanged', geometry, oldGeometry: geom, bubbleToParent: true})
this.dispatchEvent({type: 'geometryChanged', geometry: geometry ?? null, oldGeometry: geom, bubbleToParent: true, object: this})
this.refreshUi() this.refreshUi()


}, },
this.uiConfig?.uiRefresh?.(true, 'postFrame', 1) this.uiConfig?.uiRefresh?.(true, 'postFrame', 1)
}, },


dispatchEvent: (superDispatch: IObject3D['dispatchEvent']) =>
function(this: IObject3D, event: IObject3DEvent): void {
if (event.bubbleToParent || this.userData?.__autoBubbleToParentEvents?.includes(event.type)) {
dispatchEvent: (superDispatch: IObject3D['dispatchEvent']): IObject3D['dispatchEvent'] =>
function(this: IObject3D, event): void {
if ((event as IObject3DEventMap['objectUpdate']).bubbleToParent || this.userData?.__autoBubbleToParentEvents?.includes(event.type)) {
// console.log('parent dispatch', e, this.parentRoot, this.parent) // console.log('parent dispatch', e, this.parentRoot, this.parent)
const pRoot = this.parentRoot || this.parent const pRoot = this.parentRoot || this.parent
if (this.parentRoot !== this) pRoot?.dispatchEvent(event) if (this.parentRoot !== this) pRoot?.dispatchEvent(event)
return clone return clone
}, },
copy: (superCopy: IObject3D['copy']): IObject3D['copy'] => copy: (superCopy: IObject3D['copy']): IObject3D['copy'] =>
function(this: IObject3D|ILight, source: IObject3D, ...args): IObject3D {
function(this: IObject3D, source: IObject3D, ...args): IObject3D {
const lightTarget = this.isLight ? (this as ILight).target : null const lightTarget = this.isLight ? (this as ILight).target : null


const userData = source.userData const userData = source.userData
if ((this.isMesh || this.isLine) && !this.userData.__meshSetup) { if ((this.isMesh || this.isLine) && !this.userData.__meshSetup) {
this.userData.__meshSetup = true this.userData.__meshSetup = true


this._onGeometryUpdate = (e: IGeometryEvent) => iObjectCommons.eventCallbacks.onGeometryUpdate.call(this, e)
this._onGeometryUpdate = (e) => iObjectCommons.eventCallbacks.onGeometryUpdate.call(this, e)


// Material, Geometry prop init // Material, Geometry prop init
iObjectCommons.initMaterial.call(this) iObjectCommons.initMaterial.call(this)

+ 9
- 2
src/plugins/animation/CameraViewPlugin.ts 查看文件

import {Object3D, Vector3} from 'three' import {Object3D, Vector3} from 'three'
import {Easing} from 'popmotion' import {Easing} from 'popmotion'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {Box3B} from '../../three' import {Box3B} from '../../three'
import {onChange, serialize, timeout} from 'ts-browser-helpers' import {onChange, serialize, timeout} from 'ts-browser-helpers'
import {generateUiConfig, uiButton, uiDropdown, uiInput, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js' import {generateUiConfig, uiButton, uiDropdown, uiInput, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js'


export interface CameraViewPluginOptions{duration?: number, ease?: EasingFunctionType, interpolateMode?: 'spherical'|'linear'} export interface CameraViewPluginOptions{duration?: number, ease?: EasingFunctionType, interpolateMode?: 'spherical'|'linear'}


export interface CameraViewPluginEventMap extends AViewerPluginEventMap{
viewChange: {view: CameraView}
startViewChange: {view: CameraView}
viewAdd: {view: CameraView}
viewDelete: {view: CameraView}
}

/** /**
* Camera View Plugin * Camera View Plugin
* *
* Provides API to save, interact and animate and loop between with multiple camera states/views using the {@link PopmotionPlugin}. * Provides API to save, interact and animate and loop between with multiple camera states/views using the {@link PopmotionPlugin}.
* *
*/ */
export class CameraViewPlugin extends AViewerPluginSync<'viewChange'|'startViewChange'|'viewAdd'|'viewDelete'> {
export class CameraViewPlugin extends AViewerPluginSync<CameraViewPluginEventMap> {
static readonly PluginType = 'CameraViews' static readonly PluginType = 'CameraViews'


enabled = true enabled = true

+ 8
- 2
src/plugins/animation/GLTFAnimationPlugin.ts 查看文件

import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {absMax, now, onChange, onChange2, PointerDragHelper, serialize} from 'ts-browser-helpers' import {absMax, now, onChange, onChange2, PointerDragHelper, serialize} from 'ts-browser-helpers'
import {uiButton, uiDropdown, uiFolderContainer, uiMonitor, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js' import {uiButton, uiDropdown, uiFolderContainer, uiMonitor, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js'
import {AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat} from 'three' import {AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat} from 'three'
import {generateUUID} from '../../three' import {generateUUID} from '../../three'
import type {FrameFadePlugin} from '../pipeline/FrameFadePlugin' import type {FrameFadePlugin} from '../pipeline/FrameFadePlugin'


export interface GLTFAnimationPluginEventMap extends AViewerPluginEventMap{
checkpointBegin: object
checkpointEnd: object
animationStep: {delta: number, time: number}
}

/** /**
* Manages playback of GLTF animations. * Manages playback of GLTF animations.
* *
* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('GLTF Animations') @uiFolderContainer('GLTF Animations')
export class GLTFAnimationPlugin extends AViewerPluginSync<'checkpointEnd'|'checkpointBegin'|'animationStep'> {
export class GLTFAnimationPlugin extends AViewerPluginSync<GLTFAnimationPluginEventMap> {
enabled = true enabled = true
declare uiConfig: UiObjectConfig declare uiConfig: UiObjectConfig



+ 1
- 1
src/plugins/animation/PopmotionPlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class PopmotionPlugin extends AViewerPluginSync<''> {
export class PopmotionPlugin extends AViewerPluginSync {
public static readonly PluginType = 'PopmotionPlugin' public static readonly PluginType = 'PopmotionPlugin'
enabled = true enabled = true



+ 1
- 1
src/plugins/animation/TransformAnimationPlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class TransformAnimationPlugin extends AViewerPluginSync<''> {
export class TransformAnimationPlugin extends AViewerPluginSync {
public static readonly PluginType = 'TransformAnimationPlugin' public static readonly PluginType = 'TransformAnimationPlugin'
toJSON: any = undefined toJSON: any = undefined



+ 2
- 2
src/plugins/base/AAssetManagerProcessStatePlugin.ts 查看文件

import {createDiv, onChange, serialize} from 'ts-browser-helpers' import {createDiv, onChange, serialize} from 'ts-browser-helpers'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {uiToggle} from 'uiconfig.js' import {uiToggle} from 'uiconfig.js'


export abstract class AAssetManagerProcessStatePlugin<T extends string = ''> extends AViewerPluginSync<T> {
export abstract class AAssetManagerProcessStatePlugin<TE extends AViewerPluginEventMap = AViewerPluginEventMap> extends AViewerPluginSync<TE> {
@uiToggle('Enabled') @uiToggle('Enabled')
@onChange(AAssetManagerProcessStatePlugin.prototype._onEnabledChange) @onChange(AAssetManagerProcessStatePlugin.prototype._onEnabledChange)
@serialize() enabled = true @serialize() enabled = true

+ 1
- 1
src/plugins/base/ACameraControlsPlugin.ts 查看文件

import {AViewerPluginSync, ThreeViewer} from '../../viewer' import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {TControlsCtor} from '../../core' import {TControlsCtor} from '../../core'


export abstract class ACameraControlsPlugin extends AViewerPluginSync<''> {
export abstract class ACameraControlsPlugin extends AViewerPluginSync {
readonly enabled = true readonly enabled = true
toJSON: any = undefined toJSON: any = undefined
protected abstract _controlsCtor: TControlsCtor protected abstract _controlsCtor: TControlsCtor

+ 11
- 5
src/plugins/base/BaseGroundPlugin.ts 查看文件

import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {IGeometry, iGeometryCommons, IMaterial, ISceneEvent, Mesh2, PhysicalMaterial} from '../../core'
import {BufferAttribute, BufferGeometry, Euler, InterleavedBufferAttribute, PlaneGeometry, Vector3} from 'three'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {IGeometry, iGeometryCommons, IMaterial, IScene, ISceneEventMap, Mesh2, PhysicalMaterial} from '../../core'
import {BufferAttribute, BufferGeometry, Euler, InterleavedBufferAttribute, PlaneGeometry, Vector3, Event} from 'three'
import {onChange, onChange2, serialize} from 'ts-browser-helpers' import {onChange, onChange2, serialize} from 'ts-browser-helpers'
import {bindToValue, OrbitControls3} from '../../three' import {bindToValue, OrbitControls3} from '../../three'
import {uiConfig, uiFolderContainer, uiNumber, uiToggle} from 'uiconfig.js' import {uiConfig, uiFolderContainer, uiNumber, uiToggle} from 'uiconfig.js'


@uiFolderContainer('Ground') @uiFolderContainer('Ground')
export class BaseGroundPlugin<TEvent extends string = ''> extends AViewerPluginSync<TEvent> {
export class BaseGroundPlugin<TE extends AViewerPluginEventMap = AViewerPluginEventMap> extends AViewerPluginSync<TE> {
public static readonly PluginType: string = 'BaseGroundPlugin' public static readonly PluginType: string = 'BaseGroundPlugin'
public static readonly OldPluginType: string = 'Ground' public static readonly OldPluginType: string = 'Ground'


this._material = undefined this._material = undefined
} }


protected _onSceneUpdate(event?: ISceneEvent) {
protected _onSceneUpdate(event?: ISceneEventMap['addSceneObject' | 'sceneUpdate'] & Event<'addSceneObject' | 'sceneUpdate', IScene>) {
if (event?.geometryChanged === false) return if (event?.geometryChanged === false) return
if (event?.updateGround !== false) if (event?.updateGround !== false)
this.refreshTransform() this.refreshTransform()
} }


} }

declare module '../../core/IScene' {
interface ISceneSetDirtyOptions {
updateGround?: boolean
}
}

+ 2
- 2
src/plugins/base/PipelinePassPlugin.ts 查看文件

import {IPassID, IPipelinePass} from '../../postprocessing' import {IPassID, IPipelinePass} from '../../postprocessing'
import {AViewerPluginSync, ISerializedConfig, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ISerializedConfig, ThreeViewer} from '../../viewer'
import {onChange, serialize} from 'ts-browser-helpers' import {onChange, serialize} from 'ts-browser-helpers'
import {SerializationMetaType, wrapThisFunction2} from '../../utils' import {SerializationMetaType, wrapThisFunction2} from '../../utils'
import {uiToggle} from 'uiconfig.js' import {uiToggle} from 'uiconfig.js'
* *
* @category Plugins * @category Plugins
*/ */
export abstract class PipelinePassPlugin<T extends IPipelinePass, TPassId extends IPassID, TEvent extends string, TViewer extends ThreeViewer=ThreeViewer> extends AViewerPluginSync<TEvent, TViewer> {
export abstract class PipelinePassPlugin<T extends IPipelinePass, TPassId extends IPassID, TEvent extends AViewerPluginEventMap = AViewerPluginEventMap, TViewer extends ThreeViewer=ThreeViewer> extends AViewerPluginSync<TEvent, TViewer> {
abstract passId: TPassId abstract passId: TPassId


@serialize() @serialize()

+ 1
- 1
src/plugins/configurator/MaterialConfiguratorBasePlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class MaterialConfiguratorBasePlugin extends AViewerPluginSync<''> {
export class MaterialConfiguratorBasePlugin extends AViewerPluginSync {
enabled = true enabled = true
public static PluginType = 'MaterialConfiguratorPlugin' public static PluginType = 'MaterialConfiguratorPlugin'
private _picking: PickingPlugin | undefined private _picking: PickingPlugin | undefined

+ 1
- 1
src/plugins/configurator/SwitchNodeBasePlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class SwitchNodeBasePlugin extends AViewerPluginSync<''> {
export class SwitchNodeBasePlugin extends AViewerPluginSync {
public static readonly PluginType = 'SwitchNodePlugin' public static readonly PluginType = 'SwitchNodePlugin'


enabled = true enabled = true

+ 1
- 1
src/plugins/export/AssetExporterPlugin.ts 查看文件

* Provides options and methods to export the scene, object GLB or Viewer Config. * Provides options and methods to export the scene, object GLB or Viewer Config.
* All the functionality is available in the viewer directly, this provides only a ui-config and maintains state of the options. * All the functionality is available in the viewer directly, this provides only a ui-config and maintains state of the options.
*/ */
export class AssetExporterPlugin extends AViewerPluginSync<''> {
export class AssetExporterPlugin extends AViewerPluginSync {
public static readonly PluginType = 'AssetExporterPlugin' public static readonly PluginType = 'AssetExporterPlugin'
enabled = true enabled = true



+ 1
- 1
src/plugins/export/CanvasSnapshotPlugin.ts 查看文件

import {ProgressivePlugin} from '../pipeline/ProgressivePlugin' import {ProgressivePlugin} from '../pipeline/ProgressivePlugin'


@uiFolderContainer('Canvas Snapshot (Image Export)') @uiFolderContainer('Canvas Snapshot (Image Export)')
export class CanvasSnapshotPlugin extends AViewerPluginSync<''> {
export class CanvasSnapshotPlugin extends AViewerPluginSync {
static readonly PluginType = 'CanvasSnapshotPlugin' static readonly PluginType = 'CanvasSnapshotPlugin'
enabled = true enabled = true



+ 12
- 3
src/plugins/export/FileTransferPlugin.ts 查看文件

import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {downloadBlob} from 'ts-browser-helpers' import {downloadBlob} from 'ts-browser-helpers'


export interface FileTransferPluginEventMap extends AViewerPluginEventMap{
transferFile: {
path: string
state: 'exporting'|'done'|'error'
progress?: number
name?: string
}
}

/** /**
* File Transfer Plugin * File Transfer Plugin
* *
* *
* @category Plugins * @category Plugins
*/ */
export class FileTransferPlugin extends AViewerPluginSync<'transferFile'> {
export class FileTransferPlugin extends AViewerPluginSync<FileTransferPluginEventMap> {
enabled = true enabled = true


static readonly PluginType = 'FileTransferPlugin' static readonly PluginType = 'FileTransferPlugin'
} }


readonly defaultActions = { readonly defaultActions = {
exportFile: async(blob: Blob, name: string, _onProgress?: (d: {state?: string, progress?: number})=>void)=>{
exportFile: async(blob: Blob, name: string, _onProgress?: (d: {state?: 'exporting'|'done'|'error', progress?: number})=>void)=>{
downloadBlob(blob, name) downloadBlob(blob, name)
}, },
} }

+ 1
- 1
src/plugins/extras/GLTFKHRMaterialVariantsPlugin.ts 查看文件

* *
* @category Plugins * @category Plugins
*/ */
export class GLTFKHRMaterialVariantsPlugin extends AViewerPluginSync<''> {
export class GLTFKHRMaterialVariantsPlugin extends AViewerPluginSync {
public static readonly PluginType = 'GLTFKHRMaterialVariantsPlugin' public static readonly PluginType = 'GLTFKHRMaterialVariantsPlugin'
enabled = true enabled = true



+ 1
- 1
src/plugins/extras/HDRiGroundPlugin.ts 查看文件

import {uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js' import {uiPanelContainer, uiSlider, uiToggle, uiVector} from 'uiconfig.js'


@uiPanelContainer('HDRi Ground') @uiPanelContainer('HDRi Ground')
export class HDRiGroundPlugin extends AViewerPluginSync<'', ThreeViewer> {
export class HDRiGroundPlugin extends AViewerPluginSync {
static readonly PluginType = 'HDRiGroundPlugin' static readonly PluginType = 'HDRiGroundPlugin'


@serialize() @serialize()

+ 1
- 1
src/plugins/extras/Object3DGeneratorPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiPanelContainer('Generate Scene Objects') @uiPanelContainer('Generate Scene Objects')
export class Object3DGeneratorPlugin extends AViewerPluginSync<''> {
export class Object3DGeneratorPlugin extends AViewerPluginSync {
public static readonly PluginType = 'Object3DGeneratorPlugin' public static readonly PluginType = 'Object3DGeneratorPlugin'
enabled = true enabled = true
toJSON: any = undefined toJSON: any = undefined

+ 1
- 1
src/plugins/extras/Object3DWidgetsPlugin.ts 查看文件

* A helper is automatically created when any supported light or camera is added to the scene. * A helper is automatically created when any supported light or camera is added to the scene.
* @category Plugins * @category Plugins
*/ */
export class Object3DWidgetsPlugin extends AViewerPluginSync<''> {
export class Object3DWidgetsPlugin extends AViewerPluginSync {
@onChange(Object3DWidgetsPlugin.prototype.setDirty) @onChange(Object3DWidgetsPlugin.prototype.setDirty)
enabled = true enabled = true
public static readonly PluginType = 'Object3DWidgetsPlugin' public static readonly PluginType = 'Object3DWidgetsPlugin'

+ 1
- 1
src/plugins/extras/SimplifyModifierPlugin.ts 查看文件

* This is a base class and cannot be used directly. * This is a base class and cannot be used directly.
* See {@link MeshOptSimplifyModifierPlugin} the [simplify-modifier-plugin](https://threepipe.org/examples/#simplify-modifier-plugin) example for a sample implementation. * See {@link MeshOptSimplifyModifierPlugin} the [simplify-modifier-plugin](https://threepipe.org/examples/#simplify-modifier-plugin) example for a sample implementation.
*/ */
export abstract class SimplifyModifierPlugin extends AViewerPluginSync<''> {
export abstract class SimplifyModifierPlugin extends AViewerPluginSync {
public static readonly PluginType: string = 'SimplifyModifierPlugin' public static readonly PluginType: string = 'SimplifyModifierPlugin'
enabled = true enabled = true
toJSON: any = undefined toJSON: any = undefined

+ 8
- 8
src/plugins/index.ts 查看文件

export {GBufferPlugin, GBufferMaterial, DepthNormalMaterial} from './pipeline/GBufferPlugin' export {GBufferPlugin, GBufferMaterial, DepthNormalMaterial} from './pipeline/GBufferPlugin'
export {DepthBufferPlugin} from './pipeline/DepthBufferPlugin' export {DepthBufferPlugin} from './pipeline/DepthBufferPlugin'
export {NormalBufferPlugin} from './pipeline/NormalBufferPlugin' export {NormalBufferPlugin} from './pipeline/NormalBufferPlugin'
export {FrameFadePlugin, FrameFadeBlendPass, type FrameFadePluginEventTypes} from './pipeline/FrameFadePlugin'
export type {ProgressivePluginEventTypes, ProgressivePluginTarget} from './pipeline/ProgressivePlugin'
export type {GBufferPluginEventTypes, GBufferPluginPass, GBufferUpdater, GBufferUpdaterContext, GBufferPluginTarget} from './pipeline/GBufferPlugin'
export type {DepthBufferPluginEventTypes, DepthBufferPluginPass, DepthBufferPluginTarget} from './pipeline/DepthBufferPlugin'
export type {NormalBufferPluginEventTypes, NormalBufferPluginPass, NormalBufferPluginTarget} from './pipeline/NormalBufferPlugin'
export {SSAAPlugin, type SSAAPluginEventTypes} from './pipeline/SSAAPlugin'
export {SSAOPlugin, SSAOPluginPass, type SSAOPluginEventTypes, type SSAOPluginTarget} from './pipeline/SSAOPlugin'
export {FrameFadePlugin, FrameFadeBlendPass} from './pipeline/FrameFadePlugin'
export type {ProgressivePluginTarget} from './pipeline/ProgressivePlugin'
export type {GBufferPluginPass, GBufferUpdater, GBufferUpdaterContext, GBufferPluginTarget} from './pipeline/GBufferPlugin'
export type {DepthBufferPluginPass, DepthBufferPluginTarget} from './pipeline/DepthBufferPlugin'
export type {NormalBufferPluginPass, NormalBufferPluginTarget} from './pipeline/NormalBufferPlugin'
export {SSAAPlugin} from './pipeline/SSAAPlugin'
export {SSAOPlugin, SSAOPluginPass, type SSAOPluginTarget} from './pipeline/SSAOPlugin'


// ui // ui
export {RenderTargetPreviewPlugin, type RenderTargetBlock} from './ui/RenderTargetPreviewPlugin' export {RenderTargetPreviewPlugin, type RenderTargetBlock} from './ui/RenderTargetPreviewPlugin'
export {FragmentClippingExtensionPlugin, FragmentClippingMode, fragmentClippingGLTFExtension} from './material/FragmentClippingExtensionPlugin' export {FragmentClippingExtensionPlugin, FragmentClippingMode, fragmentClippingGLTFExtension} from './material/FragmentClippingExtensionPlugin'


// rendering // rendering
export {VirtualCamerasPlugin, type VirtualCamera} from './rendering/VirtualCamerasPlugin'
export {VirtualCamerasPlugin, type VirtualCamera, type VirtualCamerasPluginEventMap} from './rendering/VirtualCamerasPlugin'


// configurator // configurator
export {MaterialConfiguratorBasePlugin, type MaterialVariations} from './configurator/MaterialConfiguratorBasePlugin' export {MaterialConfiguratorBasePlugin, type MaterialVariations} from './configurator/MaterialConfiguratorBasePlugin'

+ 11
- 2
src/plugins/interaction/DropzonePlugin.ts 查看文件

import {type ThreeViewer} from '../../viewer/'
import {AViewerPluginEventMap, type ThreeViewer} from '../../viewer/'
// noinspection ES6PreferShortImport // noinspection ES6PreferShortImport
import {AViewerPluginSync} from '../../viewer/AViewerPlugin' import {AViewerPluginSync} from '../../viewer/AViewerPlugin'
import {Dropzone} from '../../utils' import {Dropzone} from '../../utils'
addOptions?: AddAssetOptions addOptions?: AddAssetOptions
} }


export interface DropzonePluginEventMap extends AViewerPluginEventMap{
drop: {
files: Map<string, File>
imported?: Map<string, (ImportResult | undefined)[]>
assets?: (ImportResult | undefined)[]
nativeEvent: DragEvent
}
}

/** /**
* Dropzone Plugin * Dropzone Plugin
* *
* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Dropzone') @uiFolderContainer('Dropzone')
export class DropzonePlugin extends AViewerPluginSync<'drop'> {
export class DropzonePlugin extends AViewerPluginSync<DropzonePluginEventMap> {
static readonly PluginType = 'Dropzone' static readonly PluginType = 'Dropzone'
declare uiConfig: UiObjectConfig declare uiConfig: UiObjectConfig
@uiToggle() @serialize() enabled = true @uiToggle() @serialize() enabled = true

+ 1
- 1
src/plugins/interaction/EditorViewWidgetPlugin.ts 查看文件

import {onChange} from 'ts-browser-helpers' import {onChange} from 'ts-browser-helpers'


@uiFolderContainer('Editor View Widget') @uiFolderContainer('Editor View Widget')
export class EditorViewWidgetPlugin extends AViewerPluginSync<''> {
export class EditorViewWidgetPlugin extends AViewerPluginSync {
public static readonly PluginType = 'EditorViewWidgetPlugin' public static readonly PluginType = 'EditorViewWidgetPlugin'


@uiToggle() @uiToggle()

+ 7
- 2
src/plugins/interaction/FullScreenPlugin.ts 查看文件

import {uiButton, uiFolderContainer} from 'uiconfig.js' import {uiButton, uiFolderContainer} from 'uiconfig.js'
import {AViewerPluginSync} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync} from '../../viewer'

export interface FullScreenPluginEventMap extends AViewerPluginEventMap{
enter: object
exit: object
}


/** /**
* Full Screen Plugin * Full Screen Plugin
* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Full Screen') @uiFolderContainer('Full Screen')
export class FullScreenPlugin extends AViewerPluginSync<'enter'|'exit'> {
export class FullScreenPlugin extends AViewerPluginSync<FullScreenPluginEventMap> {
public static readonly PluginType = 'FullScreenPlugin' public static readonly PluginType = 'FullScreenPlugin'


toJSON: any = undefined toJSON: any = undefined

+ 2
- 2
src/plugins/interaction/InteractionPromptPlugin.ts 查看文件

* The animation starts after a delay and stops on user interaction. It then restarts after a delay after the user stops interacting * The animation starts after a delay and stops on user interaction. It then restarts after a delay after the user stops interacting
* *
* The plugin provides several options and functions to configure the automatic behaviour or trigger the animation manually. * The plugin provides several options and functions to configure the automatic behaviour or trigger the animation manually.
* @todo - create example
* TODO - create example
* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Interaction Prompt') @uiFolderContainer('Interaction Prompt')
export class InteractionPromptPlugin extends AViewerPluginSync<''> {
export class InteractionPromptPlugin extends AViewerPluginSync {
static readonly PluginType = 'InteractionPromptPlugin' static readonly PluginType = 'InteractionPromptPlugin'
@serialize() @serialize()
@uiToggle() enabled @uiToggle() enabled

+ 14
- 7
src/plugins/interaction/PickingPlugin.ts 查看文件

import {Object3D} from 'three'
import {EventListener, Object3D} from 'three'
import {Class, onChange, serialize} from 'ts-browser-helpers' import {Class, onChange, serialize} from 'ts-browser-helpers'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {AViewerPluginEventMap, AViewerPluginSync, ThreeViewer} from '../../viewer'
import {BoxSelectionWidget, ObjectPicker, SelectionWidget} from '../../three' import {BoxSelectionWidget, ObjectPicker, SelectionWidget} from '../../three'
import {IObject3D, IObject3DEvent, ISceneEvent} from '../../core'
import {IObject3D, IScene, ISceneEventMap} from '../../core'
import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js'
import {FrameFadePlugin} from '../pipeline/FrameFadePlugin' import {FrameFadePlugin} from '../pipeline/FrameFadePlugin'
import {type UndoManagerPlugin} from './UndoManagerPlugin' import {type UndoManagerPlugin} from './UndoManagerPlugin'
import {ObjectPickerEventMap} from '../../three/utils/ObjectPicker'


export class PickingPlugin extends AViewerPluginSync<'selectedObjectChanged'|'hoverObjectChanged'|'hitObject'> {
export interface PickingPluginEventMap extends AViewerPluginEventMap{
selectedObjectChanged: {object: IObject3D|null}
hoverObjectChanged: {object: IObject3D|null}
hitObject: {intersects: {selectedObject: IObject3D|null}}
}

export class PickingPlugin extends AViewerPluginSync<PickingPluginEventMap> {
@serialize() @serialize()
@onChange(PickingPlugin.prototype.setDirty) @onChange(PickingPlugin.prototype.setDirty)
enabled = true enabled = true
if (!this._picker || !this._viewer) return if (!this._picker || !this._viewer) return
this._picker.camera = this._viewer.scene.mainCamera this._picker.camera = this._viewer.scene.mainCamera
} }
private _onSceneUpdate = (e: ISceneEvent)=>{
private _onSceneUpdate: EventListener<ISceneEventMap['sceneUpdate'], 'sceneUpdate', IScene> = (e)=>{
if (!e.hierarchyChanged) return if (!e.hierarchyChanged) return
const s = this.getSelectedObject() const s = this.getSelectedObject()
let inScene = false let inScene = false
if (!inScene) this.setSelectedObject(undefined) if (!inScene) this.setSelectedObject(undefined)
} }


private _onObjectSelectEvent = (e: IObject3DEvent)=>{
private _onObjectSelectEvent: EventListener<ISceneEventMap['select'], 'select', IScene> = (e)=>{
if (e.source === PickingPlugin.PluginType) return if (e.source === PickingPlugin.PluginType) return
if (e.object === undefined && e.value === undefined) console.error('e.object or e.value must be set for picking, can be null to unselect') if (e.object === undefined && e.value === undefined) console.error('e.object or e.value must be set for picking, can be null to unselect')
else this.setSelectedObject(e.object || e.value, this.autoFocus || e.focusCamera) else this.setSelectedObject(e.object || e.value, this.autoFocus || e.focusCamera)
} }


private _selectedObjectChanged = (e: any) => {
private _selectedObjectChanged: EventListener<ObjectPickerEventMap['selectedObjectChanged'], 'selectedObjectChanged', ObjectPicker> = (e: any) => {
if (!this._viewer) return if (!this._viewer) return
this.dispatchEvent(e) this.dispatchEvent(e)



+ 1
- 2
src/plugins/interaction/TransformControlsPlugin.ts 查看文件

import type {UndoManagerPlugin} from './UndoManagerPlugin' import type {UndoManagerPlugin} from './UndoManagerPlugin'


@uiPanelContainer('Transform Controls') @uiPanelContainer('Transform Controls')
export class TransformControlsPlugin extends AViewerPluginSync<''> {
export class TransformControlsPlugin extends AViewerPluginSync {
public static readonly PluginType = 'TransformControlsPlugin' public static readonly PluginType = 'TransformControlsPlugin'


@uiToggle() @uiToggle()
}, },
} }



private _transformState = { private _transformState = {
obj: null as Object3D|null, obj: null as Object3D|null,
position: new Vector3(), position: new Vector3(),

+ 1
- 1
src/plugins/interaction/UndoManagerPlugin.ts 查看文件

import {getUrlQueryParam, JSUndoManager, onChange} from 'ts-browser-helpers' import {getUrlQueryParam, JSUndoManager, onChange} from 'ts-browser-helpers'


// @uiPanelContainer('Undo Manager') // @uiPanelContainer('Undo Manager')
export class UndoManagerPlugin extends AViewerPluginSync<''> {
export class UndoManagerPlugin extends AViewerPluginSync {
public static readonly PluginType = 'UndoManagerPlugin' public static readonly PluginType = 'UndoManagerPlugin'


// @uiToggle() // @uiToggle()

+ 1
- 1
src/plugins/material/ClearcoatTintPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Clearcoat Tint (MatExt)') @uiFolderContainer('Clearcoat Tint (MatExt)')
export class ClearcoatTintPlugin extends AViewerPluginSync<''> {
export class ClearcoatTintPlugin extends AViewerPluginSync {
static readonly PluginType = 'ClearcoatTintPlugin' static readonly PluginType = 'ClearcoatTintPlugin'


@uiToggle('Enabled', (that: ClearcoatTintPlugin)=>({onChange: that.setDirty})) @uiToggle('Enabled', (that: ClearcoatTintPlugin)=>({onChange: that.setDirty}))

+ 1
- 1
src/plugins/material/CustomBumpMapPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Custom BumpMap (MatExt)') @uiFolderContainer('Custom BumpMap (MatExt)')
export class CustomBumpMapPlugin extends AViewerPluginSync<''> {
export class CustomBumpMapPlugin extends AViewerPluginSync {
static readonly PluginType = 'CustomBumpMapPlugin' static readonly PluginType = 'CustomBumpMapPlugin'


@uiToggle('Enabled', (that: CustomBumpMapPlugin)=>({onChange: that.setDirty})) @uiToggle('Enabled', (that: CustomBumpMapPlugin)=>({onChange: that.setDirty}))

+ 1
- 1
src/plugins/material/FragmentClippingExtensionPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Fragment Clipping (MatExt)') @uiFolderContainer('Fragment Clipping (MatExt)')
export class FragmentClippingExtensionPlugin extends AViewerPluginSync<''> {
export class FragmentClippingExtensionPlugin extends AViewerPluginSync {
static readonly PluginType = 'FragmentClippingExtensionPlugin1' static readonly PluginType = 'FragmentClippingExtensionPlugin1'


@uiToggle('Enabled', (that: FragmentClippingExtensionPlugin)=>({onChange: that.setDirty})) @uiToggle('Enabled', (that: FragmentClippingExtensionPlugin)=>({onChange: that.setDirty}))

+ 1
- 1
src/plugins/material/NoiseBumpMaterialPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Noise/Sparkle Bump (MatExt)') @uiFolderContainer('Noise/Sparkle Bump (MatExt)')
export class NoiseBumpMaterialPlugin extends AViewerPluginSync<''> {
export class NoiseBumpMaterialPlugin extends AViewerPluginSync {
static readonly PluginType = 'NoiseBumpMaterialPlugin' static readonly PluginType = 'NoiseBumpMaterialPlugin'


@uiToggle('Enabled', (that: NoiseBumpMaterialPlugin)=>({onChange: that.setDirty})) @uiToggle('Enabled', (that: NoiseBumpMaterialPlugin)=>({onChange: that.setDirty}))

+ 1
- 1
src/plugins/material/ParallaxMappingPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Parallax Bump Mapping (MatExt)') @uiFolderContainer('Parallax Bump Mapping (MatExt)')
export class ParallaxMappingPlugin extends AViewerPluginSync<''> {
export class ParallaxMappingPlugin extends AViewerPluginSync {
public static PluginType = 'ReliefParallaxMapping' public static PluginType = 'ReliefParallaxMapping'


@onChange(ParallaxMappingPlugin.prototype._updateExtension) @onChange(ParallaxMappingPlugin.prototype._updateExtension)

+ 1
- 2
src/plugins/pipeline/DepthBufferPlugin.ts 查看文件

import {threeConstMappings} from '../../three' import {threeConstMappings} from '../../three'
import {IMaterial, PhysicalMaterial} from '../../core' import {IMaterial, PhysicalMaterial} from '../../core'


export type DepthBufferPluginEventTypes = ''
// type DepthBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget // type DepthBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget
export type DepthBufferPluginTarget = WebGLRenderTarget export type DepthBufferPluginTarget = WebGLRenderTarget
export type DepthBufferPluginPass = GBufferRenderPass<'depth', DepthBufferPluginTarget|undefined> export type DepthBufferPluginPass = GBufferRenderPass<'depth', DepthBufferPluginTarget|undefined>
*/ */
@uiFolderContainer('Depth Buffer Plugin') @uiFolderContainer('Depth Buffer Plugin')
export class DepthBufferPlugin export class DepthBufferPlugin
extends PipelinePassPlugin<DepthBufferPluginPass, 'depth', DepthBufferPluginEventTypes> {
extends PipelinePassPlugin<DepthBufferPluginPass, 'depth'> {


readonly passId = 'depth' readonly passId = 'depth'
public static readonly PluginType = 'DepthBufferPlugin' public static readonly PluginType = 'DepthBufferPlugin'

+ 7
- 3
src/plugins/pipeline/FrameFadePlugin.ts 查看文件

import {ProgressivePlugin} from './ProgressivePlugin' import {ProgressivePlugin} from './ProgressivePlugin'
import {IRenderTarget} from '../../rendering' import {IRenderTarget} from '../../rendering'


export type FrameFadePluginEventTypes = ''

/** /**
* FrameFade Plugin * FrameFade Plugin
* *
*/ */
@uiFolderContainer('FrameFade Plugin') @uiFolderContainer('FrameFade Plugin')
export class FrameFadePlugin export class FrameFadePlugin
extends PipelinePassPlugin<FrameFadeBlendPass, 'frameFade', FrameFadePluginEventTypes> {
extends PipelinePassPlugin<FrameFadeBlendPass, 'frameFade'> {


readonly passId = 'frameFade' readonly passId = 'frameFade'
public static readonly PluginType = 'FrameFadePlugin' public static readonly PluginType = 'FrameFadePlugin'
} }


} }

declare module '../../core/IObject'{
export interface IObjectSetDirtyOptions{
frameFade?: boolean
}
}

+ 5
- 3
src/plugins/pipeline/GBufferPlugin.ts 查看文件

ShaderMaterial2, ShaderMaterial2,
} from '../../core' } from '../../core'


export type GBufferPluginEventTypes = ''
export type GBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget export type GBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget
// export type GBufferPluginTarget = WebGLRenderTarget // export type GBufferPluginTarget = WebGLRenderTarget
export type GBufferPluginPass = GBufferRenderPass<'gbuffer', GBufferPluginTarget|undefined> export type GBufferPluginPass = GBufferRenderPass<'gbuffer', GBufferPluginTarget|undefined>
*/ */
@uiFolderContainer('G-Buffer Plugin') @uiFolderContainer('G-Buffer Plugin')
export class GBufferPlugin export class GBufferPlugin
extends PipelinePassPlugin<GBufferPluginPass, 'gbuffer', GBufferPluginEventTypes> {
extends PipelinePassPlugin<GBufferPluginPass, 'gbuffer'> {


readonly passId = 'gbuffer' readonly passId = 'gbuffer'
public static readonly PluginType = 'GBuffer' public static readonly PluginType = 'GBuffer'
if (!map) return if (!map) return
this.uniforms[key].value = map this.uniforms[key].value = map
if (!this.uniforms[key + 'Transform']) console.error('GBufferMaterial: ' + key + 'Transform is not defined in uniform') if (!this.uniforms[key + 'Transform']) console.error('GBufferMaterial: ' + key + 'Transform is not defined in uniform')
else renderer.materials.refreshTransformUniform(map, this.uniforms[key + 'Transform'])
else {
if ((map as Texture).isTexture)
renderer.materials.refreshTransformUniform((map as Texture), this.uniforms[key + 'Transform'])
}
} }


setMap('map') setMap('map')

+ 1
- 2
src/plugins/pipeline/NormalBufferPlugin.ts 查看文件

import type {IMaterial, PhysicalMaterial} from '../../core' import type {IMaterial, PhysicalMaterial} from '../../core'
import {uiFolderContainer, uiImage} from 'uiconfig.js' import {uiFolderContainer, uiImage} from 'uiconfig.js'


export type NormalBufferPluginEventTypes = ''
// type NormalBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget // type NormalBufferPluginTarget = WebGLMultipleRenderTargets | WebGLRenderTarget
export type NormalBufferPluginTarget = WebGLRenderTarget export type NormalBufferPluginTarget = WebGLRenderTarget
export type NormalBufferPluginPass = GBufferRenderPass<'normal', NormalBufferPluginTarget|undefined> export type NormalBufferPluginPass = GBufferRenderPass<'normal', NormalBufferPluginTarget|undefined>
*/ */
@uiFolderContainer('Normal Buffer Plugin') @uiFolderContainer('Normal Buffer Plugin')
export class NormalBufferPlugin export class NormalBufferPlugin
extends PipelinePassPlugin<NormalBufferPluginPass, 'normal', NormalBufferPluginEventTypes> {
extends PipelinePassPlugin<NormalBufferPluginPass, 'normal'> {


readonly passId = 'normal' readonly passId = 'normal'
public static readonly PluginType = 'NormalBufferPlugin' public static readonly PluginType = 'NormalBufferPlugin'

+ 1
- 2
src/plugins/pipeline/ProgressivePlugin.ts 查看文件

import {SerializationMetaType} from '../../utils' import {SerializationMetaType} from '../../utils'
import {SSAAPlugin} from './SSAAPlugin' import {SSAAPlugin} from './SSAAPlugin'


export type ProgressivePluginEventTypes = ''
export type ProgressivePluginTarget = WebGLRenderTarget export type ProgressivePluginTarget = WebGLRenderTarget


/** /**
*/ */
@uiFolderContainer('Progressive Plugin') @uiFolderContainer('Progressive Plugin')
export class ProgressivePlugin export class ProgressivePlugin
extends PipelinePassPlugin<ProgressiveBlendPass, 'progressive', ProgressivePluginEventTypes> implements IShaderPropertiesUpdater {
extends PipelinePassPlugin<ProgressiveBlendPass, 'progressive'> implements IShaderPropertiesUpdater {


readonly passId = 'progressive' readonly passId = 'progressive'
public static readonly PluginType = 'ProgressivePlugin' public static readonly PluginType = 'ProgressivePlugin'

+ 1
- 2
src/plugins/pipeline/SSAAPlugin.ts 查看文件

import {ICamera, ILight} from '../../core' import {ICamera, ILight} from '../../core'
import {ProgressivePlugin} from './ProgressivePlugin' import {ProgressivePlugin} from './ProgressivePlugin'


export type SSAAPluginEventTypes = ''
export type TCamera = ICamera & (PerspectiveCamera|OrthographicCamera) export type TCamera = ICamera & (PerspectiveCamera|OrthographicCamera)


/** /**
* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('SSAA Plugin') @uiFolderContainer('SSAA Plugin')
export class SSAAPlugin extends AViewerPluginSync<SSAAPluginEventTypes> {
export class SSAAPlugin extends AViewerPluginSync {
public static readonly PluginType = 'SSAAPlugin' public static readonly PluginType = 'SSAAPlugin'


@serialize() @uiToggle('Enabled') @serialize() @uiToggle('Enabled')

+ 1
- 2
src/plugins/pipeline/SSAOPlugin.ts 查看文件

import {uiConfigMaterialExtension} from '../../materials/MaterialExtender' import {uiConfigMaterialExtension} from '../../materials/MaterialExtender'
import {GBufferPlugin, GBufferUpdaterContext} from './GBufferPlugin' import {GBufferPlugin, GBufferUpdaterContext} from './GBufferPlugin'


export type SSAOPluginEventTypes = ''
export type SSAOPluginTarget = WebGLRenderTarget export type SSAOPluginTarget = WebGLRenderTarget


/** /**
*/ */
@uiFolderContainer('SSAO Plugin') @uiFolderContainer('SSAO Plugin')
export class SSAOPlugin export class SSAOPlugin
extends PipelinePassPlugin<SSAOPluginPass, 'ssao', SSAOPluginEventTypes> {
extends PipelinePassPlugin<SSAOPluginPass, 'ssao'> {


readonly passId = 'ssao' readonly passId = 'ssao'
public static readonly PluginType = 'SSAOPlugin' public static readonly PluginType = 'SSAOPlugin'

+ 2
- 2
src/plugins/postprocessing/AScreenPassExtensionPlugin.ts 查看文件

import {type AViewerPlugin, AViewerPluginSync} from '../../viewer/AViewerPlugin'
import {type AViewerPlugin, AViewerPluginEventMap, AViewerPluginSync} from '../../viewer/AViewerPlugin'
import type {ThreeViewer} from '../../viewer' import type {ThreeViewer} from '../../viewer'
import {MaterialExtension} from '../../materials' import {MaterialExtension} from '../../materials'
import {Shader, Vector4, WebGLRenderer} from 'three' import {Shader, Vector4, WebGLRenderer} from 'three'
* *
* @category Plugins * @category Plugins
*/ */
export abstract class AScreenPassExtensionPlugin<T extends string> extends AViewerPluginSync<T> implements MaterialExtension, GBufferUpdater {
export abstract class AScreenPassExtensionPlugin<TE extends AViewerPluginEventMap = AViewerPluginEventMap> extends AViewerPluginSync<TE> implements MaterialExtension, GBufferUpdater {
declare ['constructor']: (typeof AScreenPassExtensionPlugin) & (typeof AViewerPluginSync) & (typeof AViewerPlugin) declare ['constructor']: (typeof AScreenPassExtensionPlugin) & (typeof AViewerPluginSync) & (typeof AViewerPlugin)


abstract enabled: boolean abstract enabled: boolean

+ 1
- 1
src/plugins/postprocessing/ChromaticAberrationPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('ChromaticAberration') @uiFolderContainer('ChromaticAberration')
export class ChromaticAberrationPlugin extends AScreenPassExtensionPlugin<''> {
export class ChromaticAberrationPlugin extends AScreenPassExtensionPlugin {
static readonly PluginType = 'ChromaticAberration' static readonly PluginType = 'ChromaticAberration'


readonly extraUniforms = { readonly extraUniforms = {

+ 1
- 1
src/plugins/postprocessing/FilmicGrainPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('FilmicGrain') @uiFolderContainer('FilmicGrain')
export class FilmicGrainPlugin extends AScreenPassExtensionPlugin<''> {
export class FilmicGrainPlugin extends AScreenPassExtensionPlugin {
static readonly PluginType = 'FilmicGrain' static readonly PluginType = 'FilmicGrain'


readonly extraUniforms = { readonly extraUniforms = {

+ 1
- 1
src/plugins/postprocessing/TonemapPlugin.ts 查看文件

* @category Plugins * @category Plugins
*/ */
@uiFolderContainer('Tonemapping') @uiFolderContainer('Tonemapping')
export class TonemapPlugin extends AScreenPassExtensionPlugin<''> {
export class TonemapPlugin extends AScreenPassExtensionPlugin {
static readonly PluginType = 'Tonemap' static readonly PluginType = 'Tonemap'


readonly extraUniforms = { readonly extraUniforms = {

+ 0
- 0
src/plugins/postprocessing/VignettePlugin.ts 查看文件


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存