mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-05 07:30:11 +00:00
- Updated all imports from '@comfyorg/litegraph' to '@/lib/litegraph/src/' - Replaced deep dist imports with direct source paths - Updated CSS import in main.ts - All imports now use the @ alias consistently
236 lines
6.1 KiB
Vue
236 lines
6.1 KiB
Vue
<template>
|
|
<div ref="container" class="w-full h-full relative comfy-load-3d">
|
|
<LoadingOverlay ref="loadingOverlayRef" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { onMounted, onUnmounted, ref, toRaw, watch } from 'vue'
|
|
|
|
import LoadingOverlay from '@/components/load3d/LoadingOverlay.vue'
|
|
import Load3d from '@/extensions/core/load3d/Load3d'
|
|
import Load3dAnimation from '@/extensions/core/load3d/Load3dAnimation'
|
|
import {
|
|
CameraType,
|
|
MaterialMode,
|
|
UpDirection
|
|
} from '@/extensions/core/load3d/interfaces'
|
|
import { t } from '@/i18n'
|
|
import { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
|
import type { CustomInputSpec } from '@/schemas/nodeDef/nodeDefSchemaV2'
|
|
import { useLoad3dService } from '@/services/load3dService'
|
|
|
|
const props = defineProps<{
|
|
node: LGraphNode
|
|
inputSpec: CustomInputSpec
|
|
backgroundColor: string
|
|
showGrid: boolean
|
|
lightIntensity: number
|
|
fov: number
|
|
cameraType: CameraType
|
|
showPreview: boolean
|
|
backgroundImage: string
|
|
upDirection: UpDirection
|
|
materialMode: MaterialMode
|
|
edgeThreshold?: number
|
|
extraListeners?: Record<string, (value: any) => void>
|
|
}>()
|
|
|
|
const container = ref<HTMLElement | null>(null)
|
|
const node = ref(props.node)
|
|
const load3d = ref<Load3d | Load3dAnimation | null>(null)
|
|
const loadingOverlayRef = ref<InstanceType<typeof LoadingOverlay> | null>(null)
|
|
|
|
const eventConfig = {
|
|
materialModeChange: (value: string) => emit('materialModeChange', value),
|
|
backgroundColorChange: (value: string) =>
|
|
emit('backgroundColorChange', value),
|
|
lightIntensityChange: (value: number) => emit('lightIntensityChange', value),
|
|
fovChange: (value: number) => emit('fovChange', value),
|
|
cameraTypeChange: (value: string) => emit('cameraTypeChange', value),
|
|
showGridChange: (value: boolean) => emit('showGridChange', value),
|
|
showPreviewChange: (value: boolean) => emit('showPreviewChange', value),
|
|
backgroundImageChange: (value: string) =>
|
|
emit('backgroundImageChange', value),
|
|
backgroundImageLoadingStart: () =>
|
|
loadingOverlayRef.value?.startLoading(t('load3d.loadingBackgroundImage')),
|
|
backgroundImageLoadingEnd: () => loadingOverlayRef.value?.endLoading(),
|
|
upDirectionChange: (value: string) => emit('upDirectionChange', value),
|
|
edgeThresholdChange: (value: number) => emit('edgeThresholdChange', value),
|
|
modelLoadingStart: () =>
|
|
loadingOverlayRef.value?.startLoading(t('load3d.loadingModel')),
|
|
modelLoadingEnd: () => loadingOverlayRef.value?.endLoading(),
|
|
materialLoadingStart: () =>
|
|
loadingOverlayRef.value?.startLoading(t('load3d.switchingMaterialMode')),
|
|
materialLoadingEnd: () => loadingOverlayRef.value?.endLoading(),
|
|
exportLoadingStart: (message: string) => {
|
|
loadingOverlayRef.value?.startLoading(message || t('load3d.exportingModel'))
|
|
},
|
|
exportLoadingEnd: () => {
|
|
loadingOverlayRef.value?.endLoading()
|
|
},
|
|
recordingStatusChange: (value: boolean) =>
|
|
emit('recordingStatusChange', value)
|
|
} as const
|
|
|
|
watch(
|
|
() => props.showPreview,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.togglePreview(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.cameraType,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.toggleCamera(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.fov,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setFOV(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.lightIntensity,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setLightIntensity(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.showGrid,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.toggleGrid(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.backgroundColor,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setBackgroundColor(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.backgroundImage,
|
|
async (newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
await rawLoad3d.setBackgroundImage(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.upDirection,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setUpDirection(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.materialMode,
|
|
(newValue) => {
|
|
if (load3d.value) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setMaterialMode(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => props.edgeThreshold,
|
|
(newValue) => {
|
|
if (load3d.value && newValue) {
|
|
const rawLoad3d = toRaw(load3d.value) as Load3d
|
|
|
|
rawLoad3d.setEdgeThreshold(newValue)
|
|
}
|
|
}
|
|
)
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'materialModeChange', materialMode: string): void
|
|
(e: 'backgroundColorChange', color: string): void
|
|
(e: 'lightIntensityChange', lightIntensity: number): void
|
|
(e: 'fovChange', fov: number): void
|
|
(e: 'cameraTypeChange', cameraType: string): void
|
|
(e: 'showGridChange', showGrid: boolean): void
|
|
(e: 'showPreviewChange', showPreview: boolean): void
|
|
(e: 'backgroundImageChange', backgroundImage: string): void
|
|
(e: 'upDirectionChange', upDirection: string): void
|
|
(e: 'edgeThresholdChange', threshold: number): void
|
|
(e: 'recordingStatusChange', status: boolean): void
|
|
}>()
|
|
|
|
const handleEvents = (action: 'add' | 'remove') => {
|
|
if (!load3d.value) return
|
|
|
|
Object.entries(eventConfig).forEach(([event, handler]) => {
|
|
const method = `${action}EventListener` as const
|
|
load3d.value?.[method](event, handler)
|
|
})
|
|
|
|
if (props.extraListeners) {
|
|
Object.entries(props.extraListeners).forEach(([event, handler]) => {
|
|
const method = `${action}EventListener` as const
|
|
load3d.value?.[method](event, handler)
|
|
})
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
if (container.value) {
|
|
load3d.value = useLoad3dService().registerLoad3d(
|
|
node.value as LGraphNode,
|
|
container.value,
|
|
props.inputSpec
|
|
)
|
|
}
|
|
handleEvents('add')
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
handleEvents('remove')
|
|
useLoad3dService().removeLoad3d(node.value as LGraphNode)
|
|
})
|
|
|
|
defineExpose({
|
|
load3d
|
|
})
|
|
</script>
|