const { template, $, update, close } = require('./base'); const { getMessageProtocolScene } = require('../utils/prop'); // 排列时,相邻元素的间隔间距 const MARGIN = '4px'; exports.template = template; exports.$ = $; exports.update = update; exports.close = close; const { setHidden, setDisabled, isMultipleInvalid } = require('../utils/prop'); exports.ready = function() { // Handling in-line displayed attributes const needToInlines = [ 'life', 'startColor', 'endColor', 'angle', 'startSize', 'endSize', 'startSpin', 'endSpin', 'speed', 'tangentialAccel', 'radialAccel', 'startRadius', 'endRadius', 'rotatePerS', ]; this.elements = { file: { update(element, dump) { setDisabled(!dump.file.value.uuid, this.$.syncButton); }, }, custom: { ready(element) { const $checkbox = element.querySelector('ui-checkbox[slot="content"]'); const $sync = document.createElement('ui-button'); $sync.setAttribute('style', `margin-right: ${MARGIN}`); $sync.setAttribute('slot', 'content'); $sync.setAttribute('class', 'blue'); $sync.setAttribute('tooltip', 'i18n:ENGINE.components.particle_system_2d.sync_tips'); const $syncLabel = document.createElement('ui-label'); $syncLabel.setAttribute('value', 'i18n:ENGINE.components.particle_system_2d.sync'); $sync.appendChild($syncLabel); $checkbox.after($sync); // Hack: ui-button has extra events that are passed up to ui-prop ; $sync.addEventListener('change', (event) => { event.stopPropagation(); }); $sync.addEventListener('confirm', async (event) => { event.stopPropagation(); const fileUuid = this.dump.value.file.value.uuid; const fileInfo = await Editor.Message.request('asset-db', 'query-asset-meta', fileUuid); if (fileInfo) { let values = [this.$this.dump.value]; if (this.$this.dump.values) { values = this.$this.dump.values; } for (const item of values) { item.file.value.uuid = fileUuid; item.custom.value = true; /** * TODO Hack: a serious problem * The data with underscores is also involved in setting in the engine. * but it's visible = false, and it's impossible to assert the file and _file association from the name. * easily ignored when data changes * There is a place under the same */ item._file.value.uuid = fileUuid; item._custom.value = true; for (const key in fileInfo.userData) { const value = fileInfo.userData[key]; if (key === 'spriteFrameUuid') { item.spriteFrame.value.uuid = value; } else if (item[key] !== undefined) { item[key].value = value; } } } this.$this.dispatch('change-dump'); this.$this.dispatch('confirm-dump'); } }); const $export = document.createElement('ui-button'); $export.setAttribute('slot', 'content'); $export.setAttribute('class', 'blue'); $export.setAttribute('tooltip', 'i18n:ENGINE.components.particle_system_2d.export_tips'); const $exportLabel = document.createElement('ui-label'); $exportLabel.setAttribute('value', 'i18n:ENGINE.components.particle_system_2d.export'); $export.appendChild($exportLabel); $sync.after($export); $export.addEventListener('change', (event) => { event.stopPropagation(); }); $export.addEventListener('confirm', async (event) => { event.stopPropagation(); let assetInfo = await Editor.Message.request(getMessageProtocolScene(this.$this), 'export-particle-plist', this.dump.value.uuid.value); if (assetInfo) { let values = [this.$this.dump.value]; if (this.$this.dump.values) { values = this.$this.dump.values; } for (const item of values) { item.file.value.uuid = assetInfo.uuid; item.custom.value = false; // Same instructions as above item._file.value.uuid = assetInfo.uuid; item._custom.value = false; } this.$this.dispatch('change-dump'); this.$this.dispatch('confirm-dump'); } }); this.$.syncButton = $sync; this.$.exportButton = $export; }, update(element, dump) { const existKeys = ['customMaterial', 'color', 'preview', 'playOnLoad', 'autoRemoveOnFinish', 'file', 'custom']; const toggleProps = []; for (const name in this.dump.value) { if (this.dump.value[name].visible && !existKeys.includes(name)) { toggleProps.push(name); } } const toggleElements = ['syncButton', 'exportButton']; const toggleKeys = toggleProps.concat(toggleElements); const isMultiple = dump.custom && !!dump.custom.values; setDisabled(isMultiple, this.$.exportButton); const hidden = isMultipleInvalid(dump.custom) || !dump.custom.value; toggleKeys.forEach((key) => { setHidden(hidden, this.$[key]); }); needToInlines.forEach((key) => { const $left = this.$[key]; const $right = this.$[`${key}Var`]; if ($right && $right.parentNode === $left) { return; } $right.setAttribute('no-label', ''); $right.setAttribute('slot', 'content'); $right.setAttribute('style', `margin-left: ${MARGIN}`); $left.appendChild($right); }); }, }, emitterMode: { update(element, dump) { if (isMultipleInvalid(dump.custom) || !dump.custom.value) { return; } // when dump.emitterMode.value === 0 let shows = ['gravity', 'speed', 'tangentialAccel', 'radialAccel', 'rotationIsDir']; let hiddens = ['startRadius', 'endRadius', 'rotatePerS']; if (dump.emitterMode.value === 1) { const temp = hiddens; hiddens = shows; shows = temp; } shows.forEach((key) => setHidden(false, this.$[key])); hiddens.forEach((key) => setHidden(true, this.$[key])); }, }, }; needToInlines.forEach((key) => { const rightKey = `${key}Var`; this.elements[rightKey] = { isAppendToParent() { const $left = this.$[key]; const $right = this.$[`${key}Var`]; if ($left && $right && $right.parentNode === $left) { return false; } return true; }, }; }); };