Files
SpineParticlesWeb/src/views/particle-panel/ExportSettingsSection.vue
T
2026-10-28 14:32:52 +08:00

116 lines
6.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<!-- 7. 导出资源:导出参数与资源输出操作。 -->
<div class="group">
<div class="group-head" @click="toggle('export')">
<span class="caret">{{ collapsed.export ? '▸' : '▾' }}</span><span>{{ $t('export.title') }}</span>
<button class="group-reset" data-matomo-event="export.reset" :title="$t('export.reset')" @click.stop="resetModule('export')">{{ $t('common.reset') }}</button>
</div>
<div class="group-body export-settings" v-show="sectionOpen('export')">
<label class="export-field">
<span>{{ $t('export.imagesPath') }}</span>
<input v-model.trim="exportSettings.imagesPath" class="inp export-input" type="text" placeholder="./images/" />
</label>
<label class="export-field">
<span>{{ $t('export.spineVersion') }}</span>
<select v-model="exportSettings.spineVersion" class="inp export-input">
<option value="3.8">Spine 3.8</option>
<option value="4.0">Spine 4.0</option>
<option value="4.1">Spine 4.1</option>
<option value="4.2">Spine 4.2</option>
<option value="4.3">Spine 4.3</option>
</select>
</label>
<label class="export-field">
<span>{{ $t('export.keyframeCurve') }}</span>
<select v-model="exportSettings.keyframeCurve" class="inp export-input">
<option value="linear">{{ $t('export.linear') }}</option>
<option value="bezier">{{ $t('export.smoothBezier') }}</option>
</select>
</label>
<div class="export-help">{{ $t('export.bezierHelp') }}</div>
<div v-if="exportSettings.spineVersion === '3.8'" class="export-help">{{ $t('export.spine38Help') }}</div>
<div class="export-fps-row">
<label class="export-field export-fps-field">
<span>{{ $t('export.fps') }}</span>
<input v-model.number="exportSettings.fps" class="inp export-input" type="number" min="1" max="240" step="1" @change="normalizeExportFps" />
</label>
<label class="export-checkbox"><input v-model="exportSettings.omitFps" type="checkbox" />{{ $t('export.omitFps') }}</label>
</div>
<div class="export-help">{{ $t('export.fpsHelp') }}</div>
<div class="export-switches">
<label class="switch-row export-switch">
<input v-model="exportSettings.integerFrameAlignment" type="checkbox" />
<span class="switch-ui"></span><span>{{ $t('export.integerFrames') }}</span>
</label>
<label class="switch-row export-switch">
<input v-model="exportSettings.bonePool" type="checkbox" />
<span class="switch-ui"></span><span>{{ $t('export.bonePool') }}</span>
</label>
<label class="switch-row export-switch export-switch-last">
<input v-model="exportSettings.excludeEmptyAnimations" type="checkbox" />
<span class="switch-ui"></span><span>{{ $t('export.excludeEmpty') }}</span>
</label>
</div>
<div class="export-resource-actions">
<ParticleExportFooter />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import NumSlider from '../NumSlider.vue'
import CurveEditor from '../CurveEditor.vue'
import ParticleAttributeControl from '../ParticleAttributeControl.vue'
import ColorGradientEditor from '../ColorGradientEditor.vue'
import ImageResourceCard from '../ImageResourceCard.vue'
import SpineObjectPanel from '../../spine/SpineObjectPanel.vue'
import ParticleExportFooter from './ParticleExportFooter.vue'
import { useParticlePanelContext } from './particlePanelContext'
const { exportSettings, collapsed, toggle, sectionOpen, resetModule, normalizeExportFps, select } = useParticlePanelContext()
</script>
<style scoped>
.group { border: 1px solid #2a2a3c; border-radius: 8px; margin-bottom: 10px; overflow: hidden; }
.group-head {
display: flex; align-items: center; gap: 6px; padding: 7px 10px; cursor: pointer;
font-size: 12px; font-weight: 600; color: #ccd; background: #191924; user-select: none;
}
.group-head:hover { background: #20202e; }
.group-reset {
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid #3a465f; border-radius: 5px;
background: #252d3d; color: #9eabc3; font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: #7774ff; background: #45426f; color: #fff; }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: #667; font-size: 11px; }
.row { display: flex; align-items: center; gap: 8px; margin: 6px 0; font-size: 12px; color: #aab; }
.row > span:first-child { width: 60px; flex-shrink: 0; color: #8a93bb; }
.inp { flex: 1; min-width: 0; padding: 3px 5px; background: #1a1a28; border: 1px solid #2e2e44; border-radius: 5px; color: #dde; font-size: 12px; }
.placeholder { color: #667; font-size: 11px; padding: 6px 0; }
.export-settings { padding-top: 3px; }
.export-field { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 13px; color: #9ca8bf; font-size: 11px; font-weight: 600; }
.export-input { width: 100%; min-height: 34px; box-sizing: border-box; padding: 6px 9px; color: #e3e7f2; background: #141a29; border-color: #35445f; }
.export-fps-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: end; }
.export-fps-field { margin-bottom: 5px; }
.export-checkbox { display: flex; align-items: center; gap: 7px; min-height: 34px; margin-bottom: 5px; color: #aeb8cc; font-size: 11px; white-space: nowrap; }
.export-checkbox input { width: 17px; height: 17px; margin: 0; accent-color: #625ff1; }
.export-help { margin: -6px 0 14px; color: #66758e; font-size: 10px; line-height: 1.5; }
.export-switches { display: grid; gap: 13px; margin: 4px 0 7px; padding-top: 2px; }
.export-switch { font-weight: 600; }
.export-switch-last { margin-top: 13px; }
.export-resource-actions { margin-top: 14px; padding-top: 12px; border-top: 1px solid #2d3950; }
.inp.tiny { width: 46px; flex: 0 0 46px; text-align: center; }
.switch-row { display: flex; align-items: center; gap: 9px; color: #b8c1d5; font-size: 12px; cursor: pointer; }
.switch-row input { position: absolute; opacity: 0; pointer-events: none; }
.switch-ui { position: relative; width: 32px; height: 18px; border-radius: 10px; background: #354258; transition: background .16s ease; }
.switch-ui::after { content: ''; position: absolute; left: 2px; top: 2px; width: 14px; height: 14px; border-radius: 50%; background: #fff; transition: transform .16s ease; }
.switch-row input:checked + .switch-ui { background: #625ff1; }
.switch-row input:checked + .switch-ui::after { transform: translateX(14px); }
.switch-row input:disabled + .switch-ui { opacity: 0.45; cursor: not-allowed; }
</style>