Files
ComfyUI_frontend/src/components/load3d/controls/RecordingControls.vue
Terry Jia afa10f7a1e [refactor] refactor load3d (#5765)
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)
2025-10-31 16:19:35 -04:00

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>