mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
Summary Fully Refactored the Load3D module to improve architecture and maintainability by consolidating functionality into a centralized composable pattern and simplifying component structure. and support VueNodes system Changes - Architecture: Introduced new useLoad3d composable to centralize 3D loading logic and state management - Component Simplification: Removed redundant components (Load3DAnimation.vue, Load3DAnimationScene.vue, PreviewManager.ts) - Support VueNodes - improve config store - remove lineart output due Animation doesnot support it, may add it back later - remove Preview screen and keep scene in fixed ratio in load3d (not affect preview3d) - improve record video feature which will already record video by same ratio as scene Need BE change https://github.com/comfyanonymous/ComfyUI/pull/10025 https://github.com/user-attachments/assets/9e038729-84a0-45ad-b0f2-11c57d7e0c9a ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-5765-refactor-refactor-load3d-2796d73d365081728297cc486e2e9052) by [Unito](https://www.unito.io)
117 lines
2.7 KiB
Vue
117 lines
2.7 KiB
Vue
<template>
|
|
<div class="relative rounded-lg bg-smoke-700/30">
|
|
<div class="flex flex-col gap-2">
|
|
<Button
|
|
class="p-button-rounded p-button-text"
|
|
:class="{
|
|
'p-button-danger': isRecording,
|
|
'recording-button-blink': isRecording
|
|
}"
|
|
@click="toggleRecording"
|
|
>
|
|
<i
|
|
v-tooltip.right="{
|
|
value: isRecording
|
|
? $t('load3d.stopRecording')
|
|
: $t('load3d.startRecording'),
|
|
showDelay: 300
|
|
}"
|
|
:class="[
|
|
'pi',
|
|
isRecording ? 'pi-circle-fill' : 'pi-video',
|
|
'text-lg text-white'
|
|
]"
|
|
/>
|
|
</Button>
|
|
|
|
<Button
|
|
v-if="hasRecording && !isRecording"
|
|
class="p-button-rounded p-button-text"
|
|
@click="handleExportRecording"
|
|
>
|
|
<i
|
|
v-tooltip.right="{
|
|
value: $t('load3d.exportRecording'),
|
|
showDelay: 300
|
|
}"
|
|
class="pi pi-download text-lg text-white"
|
|
/>
|
|
</Button>
|
|
|
|
<Button
|
|
v-if="hasRecording && !isRecording"
|
|
class="p-button-rounded p-button-text"
|
|
@click="handleClearRecording"
|
|
>
|
|
<i
|
|
v-tooltip.right="{
|
|
value: $t('load3d.clearRecording'),
|
|
showDelay: 300
|
|
}"
|
|
class="pi pi-trash text-lg text-white"
|
|
/>
|
|
</Button>
|
|
|
|
<div
|
|
v-if="recordingDuration && recordingDuration > 0 && !isRecording"
|
|
class="mt-1 text-center text-xs text-white"
|
|
>
|
|
{{ formatDuration(recordingDuration) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import Button from 'primevue/button'
|
|
|
|
const hasRecording = defineModel<boolean>('hasRecording')
|
|
const isRecording = defineModel<boolean>('isRecording')
|
|
const recordingDuration = defineModel<number>('recordingDuration')
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'startRecording'): void
|
|
(e: 'stopRecording'): void
|
|
(e: 'exportRecording'): void
|
|
(e: 'clearRecording'): void
|
|
}>()
|
|
|
|
const toggleRecording = () => {
|
|
if (isRecording.value) {
|
|
emit('stopRecording')
|
|
} else {
|
|
emit('startRecording')
|
|
}
|
|
}
|
|
|
|
const handleExportRecording = () => {
|
|
emit('exportRecording')
|
|
}
|
|
|
|
const handleClearRecording = () => {
|
|
emit('clearRecording')
|
|
}
|
|
|
|
const formatDuration = (seconds: number): string => {
|
|
const minutes = Math.floor(seconds / 60)
|
|
const remainingSeconds = Math.floor(seconds % 60)
|
|
return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.recording-button-blink {
|
|
animation: blink 1s infinite;
|
|
}
|
|
|
|
@keyframes blink {
|
|
0%,
|
|
100% {
|
|
opacity: 1;
|
|
}
|
|
50% {
|
|
opacity: 0.5;
|
|
}
|
|
}
|
|
</style>
|