diff --git a/src/extensions/core/load3d.ts b/src/extensions/core/load3d.ts
index 4110ae3579..24aa9ef8b1 100644
--- a/src/extensions/core/load3d.ts
+++ b/src/extensions/core/load3d.ts
@@ -25,7 +25,7 @@ app.registerExtension({
container.id = `comfy-load-3d-${load3dNode.length}`
container.classList.add('comfy-load-3d')
- const load3d = new Load3d(container)
+ const load3d = new Load3d(container, true)
containerToLoad3D.set(container.id, load3d)
@@ -129,40 +129,34 @@ app.registerExtension({
const material = node.widgets.find((w: IWidget) => w.name === 'material')
- const lightIntensity = node.widgets.find(
- (w: IWidget) => w.name === 'light_intensity'
- )
-
const upDirection = node.widgets.find(
(w: IWidget) => w.name === 'up_direction'
)
- const fov = node.widgets.find((w: IWidget) => w.name === 'fov')
-
let cameraState = node.properties['Camera Info']
+ const width = node.widgets.find((w: IWidget) => w.name === 'width')
+ const height = node.widgets.find((w: IWidget) => w.name === 'height')
+
const config = new Load3DConfiguration(load3d)
config.configure(
'input',
modelWidget,
material,
- lightIntensity,
upDirection,
- fov,
- cameraState
+ cameraState,
+ width,
+ height
)
- const w = node.widgets.find((w: IWidget) => w.name === 'width')
- const h = node.widgets.find((w: IWidget) => w.name === 'height')
-
// @ts-expect-error hacky override
sceneWidget.serializeValue = async () => {
node.properties['Camera Info'] = load3d.getCameraState()
const { scene: imageData, mask: maskData } = await load3d.captureScene(
- w.value,
- h.value
+ width.value,
+ height.value
)
const [data, dataMask] = await Promise.all([
@@ -194,7 +188,7 @@ app.registerExtension({
container.id = `comfy-load-3d-animation-${load3dNode.length}`
container.classList.add('comfy-load-3d-animation')
- const load3d = new Load3dAnimation(container)
+ const load3d = new Load3dAnimation(container, true)
containerToLoad3D.set(container.id, load3d)
@@ -298,33 +292,27 @@ app.registerExtension({
const material = node.widgets.find((w: IWidget) => w.name === 'material')
- const lightIntensity = node.widgets.find(
- (w: IWidget) => w.name === 'light_intensity'
- )
-
const upDirection = node.widgets.find(
(w: IWidget) => w.name === 'up_direction'
)
- const fov = node.widgets.find((w: IWidget) => w.name === 'fov')
-
let cameraState = node.properties['Camera Info']
+ const width = node.widgets.find((w: IWidget) => w.name === 'width')
+ const height = node.widgets.find((w: IWidget) => w.name === 'height')
+
const config = new Load3DConfiguration(load3d)
config.configure(
'input',
modelWidget,
material,
- lightIntensity,
upDirection,
- fov,
- cameraState
+ cameraState,
+ width,
+ height
)
- const w = node.widgets.find((w: IWidget) => w.name === 'width')
- const h = node.widgets.find((w: IWidget) => w.name === 'height')
-
// @ts-expect-error hacky override
sceneWidget.serializeValue = async () => {
node.properties['Camera Info'] = load3d.getCameraState()
@@ -332,8 +320,8 @@ app.registerExtension({
load3d.toggleAnimation(false)
const { scene: imageData, mask: maskData } = await load3d.captureScene(
- w.value,
- h.value
+ width.value,
+ height.value
)
const [data, dataMask] = await Promise.all([
@@ -432,16 +420,10 @@ app.registerExtension({
const material = node.widgets.find((w: IWidget) => w.name === 'material')
- const lightIntensity = node.widgets.find(
- (w: IWidget) => w.name === 'light_intensity'
- )
-
const upDirection = node.widgets.find(
(w: IWidget) => w.name === 'up_direction'
)
- const fov = node.widgets.find((w: IWidget) => w.name === 'fov')
-
const onExecuted = node.onExecuted
node.onExecuted = function (message: any) {
@@ -461,14 +443,7 @@ app.registerExtension({
const config = new Load3DConfiguration(load3d)
- config.configure(
- 'output',
- modelWidget,
- material,
- lightIntensity,
- upDirection,
- fov
- )
+ config.configure('output', modelWidget, material, upDirection)
}
}
})
@@ -562,16 +537,10 @@ app.registerExtension({
const material = node.widgets.find((w: IWidget) => w.name === 'material')
- const lightIntensity = node.widgets.find(
- (w: IWidget) => w.name === 'light_intensity'
- )
-
const upDirection = node.widgets.find(
(w: IWidget) => w.name === 'up_direction'
)
- const fov = node.widgets.find((w: IWidget) => w.name === 'fov')
-
const onExecuted = node.onExecuted
node.onExecuted = function (message: any) {
@@ -591,14 +560,7 @@ app.registerExtension({
const config = new Load3DConfiguration(load3d)
- config.configure(
- 'output',
- modelWidget,
- material,
- lightIntensity,
- upDirection,
- fov
- )
+ config.configure('output', modelWidget, material, upDirection)
}
}
})
diff --git a/src/extensions/core/load3d/Load3DConfiguration.ts b/src/extensions/core/load3d/Load3DConfiguration.ts
index 089123baf7..4bf370fc06 100644
--- a/src/extensions/core/load3d/Load3DConfiguration.ts
+++ b/src/extensions/core/load3d/Load3DConfiguration.ts
@@ -11,10 +11,10 @@ class Load3DConfiguration {
loadFolder: 'input' | 'output',
modelWidget: IWidget,
material: IWidget,
- lightIntensity: IWidget,
upDirection: IWidget,
- fov: IWidget,
cameraState?: any,
+ width: IWidget | null = null,
+ height: IWidget | null = null,
postModelUpdateFunc?: (load3d: Load3d) => void
) {
this.setupModelHandling(
@@ -24,9 +24,8 @@ class Load3DConfiguration {
postModelUpdateFunc
)
this.setupMaterial(material)
- this.setupLighting(lightIntensity)
this.setupDirection(upDirection)
- this.setupCamera(fov)
+ this.setupTargetSize(width, height)
this.setupDefaultProperties()
}
@@ -56,13 +55,6 @@ class Load3DConfiguration {
)
}
- private setupLighting(lightIntensity: IWidget) {
- lightIntensity.callback = (value: number) => {
- this.load3d.setLightIntensity(value)
- }
- this.load3d.setLightIntensity(lightIntensity.value as number)
- }
-
private setupDirection(upDirection: IWidget) {
upDirection.callback = (
value: 'original' | '-x' | '+x' | '-y' | '+y' | '-z' | '+z'
@@ -74,11 +66,18 @@ class Load3DConfiguration {
)
}
- private setupCamera(fov: IWidget) {
- fov.callback = (value: number) => {
- this.load3d.setFOV(value)
+ private setupTargetSize(width: IWidget | null, height: IWidget | null) {
+ if (width && height) {
+ this.load3d.setTargetSize(width.value as number, height.value as number)
+
+ width.callback = (value: number) => {
+ this.load3d.setTargetSize(value, height.value as number)
+ }
+
+ height.callback = (value: number) => {
+ this.load3d.setTargetSize(width.value as number, value)
+ }
}
- this.load3d.setFOV(fov.value as number)
}
private setupDefaultProperties() {
@@ -94,6 +93,21 @@ class Load3DConfiguration {
const bgColor = this.load3d.loadNodeProperty('Background Color', '#282828')
this.load3d.setBackgroundColor(bgColor)
+
+ const fov = this.load3d.loadNodeProperty('FOV', '75')
+
+ this.load3d.setFOV(fov)
+
+ const lightIntensity = this.load3d.loadNodeProperty('Light Intensity', '5')
+
+ this.load3d.setLightIntensity(lightIntensity)
+
+ const previewVisible = this.load3d.loadNodeProperty(
+ 'Preview Visible',
+ false
+ )
+
+ this.load3d.setPreviewVisible(previewVisible)
}
private createModelUpdateHandler(
diff --git a/src/extensions/core/load3d/Load3d.ts b/src/extensions/core/load3d/Load3d.ts
index 53fb6fd429..78f7a4b60a 100644
--- a/src/extensions/core/load3d/Load3d.ts
+++ b/src/extensions/core/load3d/Load3d.ts
@@ -45,8 +45,20 @@ class Load3d {
gridSwitcherContainer: HTMLDivElement = {} as HTMLDivElement
node: LGraphNode = {} as LGraphNode
bgColorInput: HTMLInputElement = {} as HTMLInputElement
-
- constructor(container: Element | HTMLElement) {
+ fovSliderContainer: HTMLDivElement = {} as HTMLDivElement
+ lightSliderContainer: HTMLDivElement = {} as HTMLDivElement
+ previewRenderer: THREE.WebGLRenderer | null = null
+ previewCamera: THREE.Camera | null = null
+ previewContainer: HTMLDivElement = {} as HTMLDivElement
+ targetWidth: number = 1024
+ targetHeight: number = 1024
+ previewToggleContainer: HTMLDivElement = {} as HTMLDivElement
+ isPreviewVisible: boolean = true
+
+ constructor(
+ container: Element | HTMLElement,
+ createPreview: boolean = false
+ ) {
this.scene = new THREE.Scene()
this.perspectiveCamera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000)
@@ -123,12 +135,16 @@ class Load3d {
this.standardMaterial = this.createSTLMaterial()
this.createViewHelper(container)
-
this.createGridSwitcher(container)
-
this.createCameraSwitcher(container)
-
this.createColorPicker(container)
+ this.createFOVSlider(container)
+ this.createLightIntensitySlider(container)
+
+ if (createPreview) {
+ this.createPreviewToggle(container)
+ this.createCapturePreview(container)
+ }
this.handleResize()
@@ -156,6 +172,161 @@ class Load3d {
return this.node.properties[name]
}
+ createCapturePreview(container: Element | HTMLElement) {
+ this.previewRenderer = new THREE.WebGLRenderer({
+ alpha: true,
+ antialias: true
+ })
+ this.previewRenderer.setSize(this.targetWidth, this.targetHeight)
+ this.previewRenderer.setClearColor(0x282828)
+
+ this.previewContainer = document.createElement('div')
+ this.previewContainer.style.cssText = `
+ position: absolute;
+ right: 0px;
+ bottom: 0px;
+ background: rgba(0, 0, 0, 0.2);
+ display: block;
+ `
+ this.previewContainer.appendChild(this.previewRenderer.domElement)
+
+ this.previewContainer.style.display = this.isPreviewVisible
+ ? 'block'
+ : 'none'
+
+ container.appendChild(this.previewContainer)
+ }
+
+ updatePreviewRender() {
+ if (!this.previewRenderer || !this.previewContainer) return
+
+ if (
+ !this.previewCamera ||
+ (this.activeCamera instanceof THREE.PerspectiveCamera &&
+ !(this.previewCamera instanceof THREE.PerspectiveCamera)) ||
+ (this.activeCamera instanceof THREE.OrthographicCamera &&
+ !(this.previewCamera instanceof THREE.OrthographicCamera))
+ ) {
+ this.previewCamera = this.activeCamera.clone()
+ }
+
+ this.previewCamera.position.copy(this.activeCamera.position)
+ this.previewCamera.rotation.copy(this.activeCamera.rotation)
+
+ const aspect = this.targetWidth / this.targetHeight
+
+ if (this.activeCamera instanceof THREE.OrthographicCamera) {
+ const activeOrtho = this.activeCamera as THREE.OrthographicCamera
+ const previewOrtho = this.previewCamera as THREE.OrthographicCamera
+
+ const frustumHeight =
+ (activeOrtho.top - activeOrtho.bottom) / activeOrtho.zoom
+
+ const frustumWidth = frustumHeight * aspect
+
+ previewOrtho.top = frustumHeight / 2
+ previewOrtho.left = -frustumWidth / 2
+ previewOrtho.right = frustumWidth / 2
+ previewOrtho.bottom = -frustumHeight / 2
+ previewOrtho.zoom = 1
+
+ previewOrtho.updateProjectionMatrix()
+ } else {
+ ;(this.previewCamera as THREE.PerspectiveCamera).aspect = aspect
+ ;(this.previewCamera as THREE.PerspectiveCamera).fov = (
+ this.activeCamera as THREE.PerspectiveCamera
+ ).fov
+ }
+
+ this.previewCamera.lookAt(this.controls.target)
+
+ const previewWidth = 120
+ const previewHeight = (previewWidth * this.targetHeight) / this.targetWidth
+ this.previewRenderer.setSize(previewWidth, previewHeight, false)
+ this.previewRenderer.render(this.scene, this.previewCamera)
+ }
+
+ createPreviewToggle(container: Element | HTMLElement) {
+ this.previewToggleContainer = document.createElement('div')
+ this.previewToggleContainer.style.position = 'absolute'
+ this.previewToggleContainer.style.top = '128px'
+ this.previewToggleContainer.style.left = '3px'
+ this.previewToggleContainer.style.width = '20px'
+ this.previewToggleContainer.style.height = '20px'
+ this.previewToggleContainer.style.cursor = 'pointer'
+ this.previewToggleContainer.style.display = 'flex'
+ this.previewToggleContainer.style.alignItems = 'center'
+ this.previewToggleContainer.style.justifyContent = 'center'
+ this.previewToggleContainer.style.borderRadius = '2px'
+ this.previewToggleContainer.title = 'Toggle Preview'
+
+ const eyeIcon = document.createElement('div')
+ eyeIcon.innerHTML = `
+
+ `
+
+ const updateButtonState = () => {
+ if (this.isPreviewVisible) {
+ this.previewToggleContainer.style.backgroundColor =
+ 'rgba(255, 255, 255, 0.2)'
+ } else {
+ this.previewToggleContainer.style.backgroundColor = 'transparent'
+ }
+ }
+
+ this.previewToggleContainer.addEventListener('mouseenter', () => {
+ if (!this.isPreviewVisible) {
+ this.previewToggleContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
+ }
+ })
+
+ this.previewToggleContainer.addEventListener('mouseleave', () => {
+ if (!this.isPreviewVisible) {
+ this.previewToggleContainer.style.backgroundColor = 'transparent'
+ }
+ })
+
+ this.previewToggleContainer.addEventListener('click', (event) => {
+ event.stopPropagation()
+
+ this.setPreviewVisible(!this.isPreviewVisible)
+
+ updateButtonState()
+ })
+
+ this.previewToggleContainer.appendChild(eyeIcon)
+
+ container.appendChild(this.previewToggleContainer)
+
+ this.isPreviewVisible = this.loadNodeProperty('Preview Visible', true)
+
+ updateButtonState()
+ }
+
+ setPreviewVisible(visible: boolean) {
+ if (!this.previewContainer) return
+
+ this.isPreviewVisible = visible
+
+ this.previewContainer.style.display = this.isPreviewVisible
+ ? 'block'
+ : 'none'
+
+ this.storeNodeProperty('Preview Visible', this.isPreviewVisible)
+ }
+
+ updatePreviewSize() {
+ if (!this.previewContainer) return
+
+ const previewWidth = 120
+ const previewHeight = (previewWidth * this.targetHeight) / this.targetWidth
+
+ this.previewRenderer?.setSize(previewWidth, previewHeight, false)
+ }
+
createViewHelper(container: Element | HTMLElement) {
this.viewHelperContainer = document.createElement('div')
@@ -187,8 +358,8 @@ class Load3d {
createGridSwitcher(container: Element | HTMLElement) {
this.gridSwitcherContainer = document.createElement('div')
this.gridSwitcherContainer.style.position = 'absolute'
- this.gridSwitcherContainer.style.top = '28px' // 修改这里,让按钮在相机按钮下方
- this.gridSwitcherContainer.style.left = '3px' // 与相机按钮左对齐
+ this.gridSwitcherContainer.style.top = '28px'
+ this.gridSwitcherContainer.style.left = '3px'
this.gridSwitcherContainer.style.width = '20px'
this.gridSwitcherContainer.style.height = '20px'
this.gridSwitcherContainer.style.cursor = 'pointer'
@@ -323,12 +494,257 @@ class Load3d {
container.appendChild(colorPickerContainer)
}
+ createFOVSlider(container: Element | HTMLElement) {
+ this.fovSliderContainer = document.createElement('div')
+ this.fovSliderContainer.style.position = 'absolute'
+ this.fovSliderContainer.style.top = '78px'
+ this.fovSliderContainer.style.left = '3px'
+ this.fovSliderContainer.style.display = 'flex'
+ this.fovSliderContainer.style.alignItems = 'center'
+ this.fovSliderContainer.title = 'FOV (Perspective Camera Only)'
+
+ const wrapper = document.createElement('div')
+ wrapper.style.position = 'relative'
+ wrapper.style.display = 'flex'
+ wrapper.style.alignItems = 'center'
+
+ const iconContainer = document.createElement('div')
+ iconContainer.style.width = '20px'
+ iconContainer.style.height = '20px'
+ iconContainer.style.cursor = 'pointer'
+ iconContainer.style.display = 'flex'
+ iconContainer.style.alignItems = 'center'
+ iconContainer.style.justifyContent = 'center'
+ iconContainer.style.borderRadius = '2px'
+
+ const fovIcon = document.createElement('div')
+ fovIcon.innerHTML = `
+
+ `
+ fovIcon.style.display = 'flex'
+ fovIcon.style.alignItems = 'center'
+ fovIcon.style.justifyContent = 'center'
+ iconContainer.appendChild(fovIcon)
+
+ const sliderContainer = document.createElement('div')
+ sliderContainer.style.position = 'absolute'
+ sliderContainer.style.left = '25px'
+ sliderContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'
+ sliderContainer.style.padding = '5px'
+ sliderContainer.style.borderRadius = '4px'
+ sliderContainer.style.display = 'none'
+ sliderContainer.style.width = '150px'
+ sliderContainer.style.zIndex = '1000'
+
+ const slider = document.createElement('input')
+ slider.type = 'range'
+ slider.min = '10'
+ slider.max = '150'
+ slider.value = '75'
+ slider.style.width = '100%'
+ slider.style.height = '10px'
+
+ slider.addEventListener('input', (event) => {
+ const value = parseInt((event.target as HTMLInputElement).value)
+ this.setFOV(value)
+ this.storeNodeProperty('FOV', value)
+ })
+
+ let isHovered = false
+
+ const showSlider = () => {
+ if (this.activeCamera === this.perspectiveCamera) {
+ sliderContainer.style.display = 'block'
+ iconContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
+ isHovered = true
+ }
+ }
+
+ const hideSlider = () => {
+ isHovered = false
+ setTimeout(() => {
+ if (!isHovered) {
+ sliderContainer.style.display = 'none'
+ iconContainer.style.backgroundColor = 'transparent'
+ }
+ }, 100)
+ }
+
+ iconContainer.addEventListener('mouseenter', showSlider)
+ iconContainer.addEventListener('mouseleave', hideSlider)
+ sliderContainer.addEventListener('mouseenter', () => {
+ isHovered = true
+ })
+ sliderContainer.addEventListener('mouseleave', hideSlider)
+
+ sliderContainer.appendChild(slider)
+ wrapper.appendChild(iconContainer)
+ wrapper.appendChild(sliderContainer)
+ this.fovSliderContainer.appendChild(wrapper)
+ container.appendChild(this.fovSliderContainer)
+
+ this.updateFOVSliderVisibility()
+ }
+
+ updateFOVSliderVisibility() {
+ if (this.activeCamera === this.perspectiveCamera) {
+ this.fovSliderContainer.style.display = 'block'
+ } else {
+ this.fovSliderContainer.style.display = 'none'
+ }
+ }
+
+ setTargetSize(width: number, height: number) {
+ this.targetWidth = width
+ this.targetHeight = height
+ this.updatePreviewSize()
+ if (this.previewRenderer && this.previewCamera) {
+ if (this.previewCamera instanceof THREE.PerspectiveCamera) {
+ this.previewCamera.aspect = width / height
+ this.previewCamera.updateProjectionMatrix()
+ } else if (this.previewCamera instanceof THREE.OrthographicCamera) {
+ const frustumSize = 10
+ const aspect = width / height
+ this.previewCamera.left = (-frustumSize * aspect) / 2
+ this.previewCamera.right = (frustumSize * aspect) / 2
+ this.previewCamera.updateProjectionMatrix()
+ }
+ }
+ }
+
setFOV(fov: number) {
if (this.activeCamera === this.perspectiveCamera) {
this.perspectiveCamera.fov = fov
this.perspectiveCamera.updateProjectionMatrix()
this.renderer.render(this.scene, this.activeCamera)
}
+
+ if (
+ this.previewRenderer &&
+ this.previewCamera instanceof THREE.PerspectiveCamera
+ ) {
+ this.previewCamera.fov = fov
+ this.previewCamera.updateProjectionMatrix()
+ this.previewRenderer.render(this.scene, this.previewCamera)
+ }
+ }
+
+ createLightIntensitySlider(container: Element | HTMLElement) {
+ this.lightSliderContainer = document.createElement('div')
+ this.lightSliderContainer.style.position = 'absolute'
+ this.lightSliderContainer.style.top = '103px'
+ this.lightSliderContainer.style.left = '3px'
+ this.lightSliderContainer.style.display = 'flex'
+ this.lightSliderContainer.style.alignItems = 'center'
+ this.lightSliderContainer.title = 'Light Intensity'
+
+ const wrapper = document.createElement('div')
+ wrapper.style.position = 'relative'
+ wrapper.style.display = 'flex'
+ wrapper.style.alignItems = 'center'
+
+ const iconContainer = document.createElement('div')
+ iconContainer.style.width = '20px'
+ iconContainer.style.height = '20px'
+ iconContainer.style.cursor = 'pointer'
+ iconContainer.style.display = 'flex'
+ iconContainer.style.alignItems = 'center'
+ iconContainer.style.justifyContent = 'center'
+ iconContainer.style.borderRadius = '2px'
+
+ const lightIcon = document.createElement('div')
+ lightIcon.innerHTML = `
+
+ `
+ lightIcon.style.display = 'flex'
+ lightIcon.style.alignItems = 'center'
+ lightIcon.style.justifyContent = 'center'
+ iconContainer.appendChild(lightIcon)
+
+ const sliderContainer = document.createElement('div')
+ sliderContainer.style.position = 'absolute'
+ sliderContainer.style.left = '25px'
+ sliderContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'
+ sliderContainer.style.padding = '5px'
+ sliderContainer.style.borderRadius = '4px'
+ sliderContainer.style.display = 'none'
+ sliderContainer.style.width = '150px'
+ sliderContainer.style.zIndex = '1000'
+
+ const slider = document.createElement('input')
+ slider.type = 'range'
+ slider.min = '1'
+ slider.max = '20'
+ slider.step = '1'
+ slider.value = '5'
+ slider.style.width = '100%'
+ slider.style.height = '10px'
+
+ slider.addEventListener('input', (event) => {
+ const value = parseFloat((event.target as HTMLInputElement).value)
+ this.setLightIntensity(value)
+ this.storeNodeProperty('Light Intensity', value)
+ })
+
+ let isHovered = false
+
+ const showSlider = () => {
+ sliderContainer.style.display = 'block'
+ iconContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.5)'
+ isHovered = true
+ }
+
+ const hideSlider = () => {
+ isHovered = false
+ setTimeout(() => {
+ if (!isHovered) {
+ sliderContainer.style.display = 'none'
+ iconContainer.style.backgroundColor = 'transparent'
+ }
+ }, 100)
+ }
+
+ iconContainer.addEventListener('mouseenter', showSlider)
+ iconContainer.addEventListener('mouseleave', hideSlider)
+ sliderContainer.addEventListener('mouseenter', () => {
+ isHovered = true
+ })
+ sliderContainer.addEventListener('mouseleave', hideSlider)
+
+ sliderContainer.appendChild(slider)
+ wrapper.appendChild(iconContainer)
+ wrapper.appendChild(sliderContainer)
+ this.lightSliderContainer.appendChild(wrapper)
+ container.appendChild(this.lightSliderContainer)
+
+ const savedIntensity = this.loadNodeProperty('Light Intensity', 5)
+ slider.value = savedIntensity.toString()
+ this.setLightIntensity(savedIntensity)
+ this.updateLightIntensitySliderVisibility()
+ }
+
+ updateLightIntensitySliderVisibility() {
+ if (this.materialMode === 'original') {
+ this.lightSliderContainer.style.display = 'block'
+ } else {
+ this.lightSliderContainer.style.display = 'none'
+ }
}
getCameraState() {
@@ -417,6 +833,8 @@ class Load3d {
setMaterialMode(mode: 'original' | 'normal' | 'wireframe' | 'depth') {
this.materialMode = mode
+ this.updateLightIntensitySliderVisibility()
+
if (this.currentModel) {
if (mode === 'depth') {
this.renderer.outputColorSpace = THREE.LinearSRGBColorSpace
@@ -567,6 +985,11 @@ class Load3d {
}
}
+ if (this.previewCamera) {
+ this.previewCamera = null
+ }
+ this.previewCamera = this.activeCamera.clone()
+
this.activeCamera.position.copy(position)
this.activeCamera.rotation.copy(rotation)
@@ -585,8 +1008,11 @@ class Load3d {
)
this.viewHelper.center = this.controls.target
+ this.updateFOVSliderVisibility()
+
this.storeNodeProperty('Camera Type', this.getCurrentCameraType())
this.handleResize()
+ this.updatePreviewRender()
}
getCurrentCameraType(): 'perspective' | 'orthographic' {
@@ -624,6 +1050,11 @@ class Load3d {
startAnimation() {
const animate = () => {
this.animationFrameId = requestAnimationFrame(animate)
+
+ if (this.isPreviewVisible) {
+ this.updatePreviewRender()
+ }
+
const delta = this.clock.getDelta()
if (this.viewHelper.animating) {
@@ -725,6 +1156,7 @@ class Load3d {
this.controls.dispose()
this.viewHelper.dispose()
this.renderer.dispose()
+ this.fovSliderContainer.remove()
this.renderer.domElement.remove()
this.scene.clear()
}
@@ -921,6 +1353,7 @@ class Load3d {
}
this.renderer.setSize(width, height)
+ this.setTargetSize(this.targetWidth, this.targetHeight)
}
animate = () => {
@@ -936,6 +1369,7 @@ class Load3d {
): Promise<{ scene: string; mask: string }> {
return new Promise(async (resolve, reject) => {
try {
+ this.updatePreviewSize()
const originalWidth = this.renderer.domElement.width
const originalHeight = this.renderer.domElement.height
const originalClearColor = this.renderer.getClearColor(
diff --git a/src/extensions/core/load3d/Load3dAnimation.ts b/src/extensions/core/load3d/Load3dAnimation.ts
index 91f5ee0cd3..af5dbc7742 100644
--- a/src/extensions/core/load3d/Load3dAnimation.ts
+++ b/src/extensions/core/load3d/Load3dAnimation.ts
@@ -14,8 +14,11 @@ class Load3dAnimation extends Load3d {
animationSelect: HTMLSelectElement = {} as HTMLSelectElement
speedSelect: HTMLSelectElement = {} as HTMLSelectElement
- constructor(container: Element | HTMLElement) {
- super(container)
+ constructor(
+ container: Element | HTMLElement,
+ createPreview: boolean = false
+ ) {
+ super(container, createPreview)
this.createPlayPauseButton(container)
this.createAnimationList(container)
this.createSpeedSelect(container)
@@ -200,12 +203,6 @@ class Load3dAnimation extends Load3d {
}
}
- if (this.animationClips.length > 0) {
- this.playPauseContainer.style.display = 'block'
- } else {
- this.playPauseContainer.style.display = 'none'
- }
-
if (this.animationClips.length > 0) {
this.playPauseContainer.style.display = 'block'
this.animationSelect.style.display = 'block'
@@ -330,6 +327,11 @@ class Load3dAnimation extends Load3d {
startAnimation() {
const animate = () => {
this.animationFrameId = requestAnimationFrame(animate)
+
+ if (this.isPreviewVisible) {
+ this.updatePreviewRender()
+ }
+
const delta = this.clock.getDelta()
if (this.currentAnimation && this.isAnimationPlaying) {