'use strict'; const { PreviewControl, hideElement } = require('../utils/preview'); exports.template = /* html */`
`; exports.style = /* css */` .preview-section { margin-top: 0px; .preview { border-top: 1px solid var(--color-normal-border); & > .content { display: flex; padding-top: 4px; padding-bottom: 8px; padding-right: 8px; padding-left: 8px; flex-direction: column; & > .content[hidden] { display: none; } & > .attribute { padding-bottom: 4px; & > .time-scale-prop [slot="content"] { display: flex; & > .timeScale { flex: 1; } } } & > .duration[disabled] { pointer-events: none; } & > .buttons-group { padding: 6px; display: flex; align-items: center; justify-content: space-between; & > .play-buttons { & > ui-button[disabled] { pointer-events: none; } & > ui-button[hidden] { display: none; } } } } } } `; const Config = { CHECKBOX: ['loop', 'useTint', 'debugSlots', 'debugBones', 'debugMesh', 'premultipliedAlpha'], SLIDER: ['timeScale'], PLAY_CONTROL: ['rewind', 'prevPlay', 'play', 'nextPlay', 'pause', 'stop', 'forward'], OTHER: ['skin', 'animation', 'duration'], }; const Properties = [...Config.CHECKBOX, ...Config.SLIDER, ...Config.OTHER, ...Config.PLAY_CONTROL]; exports.$ = { container: '.preview', ...Object.fromEntries(Properties.map((key) => [key, `.${key}`])), resetTimeScale: '.reset-timeScale', buttonsGroup: '.buttons-group', trackGroup: '.track-group', }; const Elements = { preview: { ready(panel) { panel.preview.init(); }, async update(panel) { const spineData = await panel.preview.callPreviewFunction('setSpine', panel.asset.uuid); panel.spinUpdate(panel, spineData); }, close(panel) { panel.preview.callPreviewFunction('stop'); panel.preview.callPreviewFunction('close'); panel.preview.close(); }, }, spine: { updateTrackGroup(trackGroupElement, index, total) { trackGroupElement.innerHTML = ''; trackGroupElement.setAttribute('value', index); for (let i = 0; i < total; i++) { const item = document.createElement('ui-radio-button'); item.setAttribute('value', i.toString()); trackGroupElement.appendChild(item); const label = document.createElement('ui-label'); label.setAttribute('value', i.toString()); item.appendChild(label); } }, updateEnum($selectPro, info, cb) { $selectPro.innerHTML = ''; for (const key in info.list) { const value = info.list[key]; const option = document.createElement('ui-select-option-pro'); option.setAttribute('label', key); option.setAttribute('value', value); if (info.index === value) { cb && cb(Number(value)); option.setAttribute('selected', ''); } $selectPro.appendChild(option); } }, ready(panel) { panel.animationIndex = 0; panel.$.skin.addEventListener('confirm', (event) => { panel.preview.callPreviewFunction('setSkinIndex', Number(event.detail)); }); panel.$.animation.addEventListener('confirm', async (event) => { panel.animationIndex = Number(event.detail); Elements.spine.resetConfig(panel); await panel.preview.callPreviewFunction('setAnimationIndex', panel.animationIndex); Elements.control.updateState(panel); }); panel.$.duration.addEventListener('confirm', (event) => { panel.preview.callPreviewFunction('stop'); panel.preview.callPreviewFunction('setCurrentTime', Number(event.target.value)); }); panel.$.resetTimeScale.addEventListener('click', (event) => { panel.$.timeScale.setAttribute('value', 1 + ''); panel.preview.callPreviewFunction('setProperties', 'timeScale', 1); }); panel.$.trackGroup.addEventListener('change', (event) => { panel.preview.callPreviewFunction('setTrackIndex', Number(event.target.value)); }); panel.spinUpdate = Elements.spine.update.bind(panel); }, getDurations(panel, info) { return info.animation.durations[panel.animationIndex]; }, update(panel, info) { Properties.forEach(property => { panel.$[property].toggleAttribute('disabled', !info); }); if (!info) { return; } Elements.control.updateState(panel); Elements.spine.updateTrackGroup(panel.$.trackGroup, info.trackIndex, info.trackTotals); Elements.spine.updateEnum(panel.$.skin, info.skin); Elements.spine.updateEnum(panel.$.animation, info.animation, (value) => { panel.animationIndex = value; }); Elements.spine.updateDuration(panel, 0, Elements.spine.getDurations(panel, info)); Elements.control.update(panel, false); Elements.control.updateInfo(panel, info); }, resetConfig(panel) { panel.$.duration.setConfig({ min: 0, max: -1, minStep: 0.1, }); }, updateConfig(panel, duration) { const config = panel.$.duration.config; if (config.max === -1) { panel.$.duration.setConfig({ min: 0, max: duration, minStep: 0.1, }); } }, updateDuration(panel, time, duration) { this.updateConfig(panel, duration); panel.$.duration.setAttribute('value', time); }, }, control: { ready(panel) { Config.SLIDER.forEach((key) => { panel.$[key].addEventListener('change', (event) => { panel.preview.callPreviewFunction('setProperties', key, Number(event.target.value)); }); }); Config.CHECKBOX.forEach((key) => { panel.$[key].addEventListener('confirm', (event) => { panel.preview.callPreviewFunction('setProperties', key, Boolean(event.target.value)); }); }); Config.PLAY_CONTROL.forEach((key) => { panel.$[key].addEventListener('click', () => { panel.preview.callPreviewFunction(key); }); }); }, updateState(panel) { const disabled = 0 === panel.animationIndex; Config.PLAY_CONTROL.forEach(property => panel.$[property].toggleAttribute('disabled', disabled)); panel.$.timeScale.toggleAttribute('disabled', disabled); panel.$.duration.toggleAttribute('disabled', disabled); }, updateInfo(panel, info) { Config.CHECKBOX.forEach((key) => panel.$[key].setAttribute('value', Boolean(info[key]))); Config.SLIDER.forEach((key) => panel.$[key].setAttribute('value', Number(info[key]))); }, update(panel, playing) { panel.$.play.toggleAttribute('hidden', playing); panel.$.pause.toggleAttribute('hidden', !playing); }, }, }; exports.methods = { /** * * @param info * isPlaying * duration * currentTime */ onAnimationUpdate(info) { const panel = this; Elements.spine.updateDuration(panel, info.currentTime, info.duration); Elements.control.update(panel, info.isPlaying); panel.preview.doRefreshDirty(); }, }; exports.ready = function() { this.onAnimationUpdateBind = this.onAnimationUpdate.bind(this); Editor.Message.__protected__.addBroadcastListener('scene:spine-preview-animation-time-change', this.onAnimationUpdateBind); this.preview = new PreviewControl('scene:spine-preview', 'query-spine-preview-data', this.$.container); Object.values(Elements).forEach((element) => element.ready && element.ready(this)); }; exports.update = function(assetList, metaList) { this.assetList = assetList; this.metaList = metaList; this.asset = assetList[0]; this.meta = metaList[0]; // 如何多选就隐藏预览 hideElement(this.$.container, assetList.length > 1); Object.values(Elements).forEach((element) => element.update && element.update(this)); }; exports.close = function() { Editor.Message.__protected__.removeBroadcastListener('scene:spine-preview-animation-time-change', this.onAnimationUpdateBind); this.preview.close(); Object.values(Elements).forEach((element) => element.close && element.close(this)); };