'use strict'; const { updateElementReadonly } = require('../utils/assets'); exports.template = /* html */`
`; exports.style = /* css */` .asset-animation-mask { display: flex; height: 100%; flex-direction: column; } .asset-animation-mask[multiple-invalid] > *:not(.multiple-warn-tip) { display: none!important; } .asset-animation-mask[multiple-invalid] > .multiple-warn-tip { display: block; } .asset-animation-mask .multiple-warn-tip { display: none; text-align: center; color: var(--color-focus-contrast-weakest); margin-top: 8px; } .asset-animation-mask > .header { margin-top: 4px; margin-right: 4px; display: flex; } .asset-animation-mask > .header ui-button { text-align: center; } .asset-animation-mask > .header .import { flex: 1; margin-left: 10px; } .asset-animation-mask > .header .clear { margin-left: 10px; } .asset-animation-mask > .content { flex: 1; margin-top: 10px; } .asset-animation-mask > .content .tree { height: 100%; } `; exports.$ = { container: '.asset-animation-mask', import: '.import', clear: '.clear', tree: '.tree', }; exports.methods = { record() { return JSON.stringify(this.queryData); }, async restore(record) { record = JSON.parse(record); if (!record || typeof record !== 'object') { return false; } await this.change(record); return true; }, async query(uuid) { return await Editor.Message.request('scene', 'query-animation-mask', uuid); }, async apply() { this.reset(); await Editor.Message.request('scene', 'apply-animation-mask', this.asset.uuid); }, abort() { this.reset(); }, reset() { this.dirtyData.uuid = ''; }, async clear() { this.queryData = await Editor.Message.request('scene', 'change-animation-mask', { method: 'clear-nodes', uuid: this.asset.uuid, }); this.changed(); }, async import(uuid) { this.queryData = await Editor.Message.request('scene', 'change-animation-mask', { method: 'import-skeleton', uuid: uuid, }); this.changed(); }, async change(dump) { this.queryData = await Editor.Message.request('scene', 'change-animation-mask', { method: 'change-dump', dump, }); this.changed(); }, changed() { this.updateInterface(); this.setDirtyData(); this.dispatch('change'); /** * 由于编辑项中不需要区分 change 和 confirm 的情况, * 所以可以在 change 后 snapshot */ this.dispatch('snapshot'); }, updateInterface() { const convertData = this.convertData(this.queryData.joints.value); this.flatData = convertData.flatData; this.$.tree.tree = convertData.treeData; updateElementReadonly.call(this, this.$.import); updateElementReadonly.call(this, this.$.clear); updateElementReadonly.call(this, this.$.tree); }, setDirtyData() { this.dirtyData.realtime = JSON.stringify(this.queryData); if (!this.dirtyData.origin) { this.dirtyData.origin = this.dirtyData.realtime; } }, isDirty() { const isDirty = this.dirtyData.origin !== this.dirtyData.realtime; return isDirty; }, convertData(jointArr) { const collator = new Intl.Collator('en', { numeric: true, sensitivity: 'base', }); jointArr.sort((a, b) => { return collator.compare(a.value.path.value, b.value.path.value); }); const flatData = {}; for (const joint of jointArr) { const key = joint.value.path.value; if (!key) { continue; } let childKey = key; let parentKey = childKey.substr(0, childKey.lastIndexOf('/')); while (parentKey) { if (!flatData[parentKey]) { flatData[parentKey] = { children: [childKey] }; } else { if (!flatData[parentKey].children.includes(childKey)) { flatData[parentKey].children.push(childKey); } } childKey = parentKey; parentKey = childKey.substr(0, childKey.lastIndexOf('/')); } if (!flatData[key]) { flatData[key] = { origin: joint, children: [] }; } else { flatData[key].origin = joint; } } const treeData = []; const keys = Object.keys(flatData); keys.sort((a, b) => { return collator.compare(a, b); }); const roots = []; for (const key of keys) { // 一级根路径 if (key.indexOf('/') === -1) { roots.push(key); } } treeDataFromFlatData(treeData, roots); function treeDataFromFlatData(treeArr, keys) { if (!Array.isArray(keys)) { return; } keys.forEach((key) => { const { origin, children } = flatData[key]; const treeNode = { detail: { key, name: key.substr(key.lastIndexOf('/') + 1), disabled: true, }, children: [], }; if (origin) { treeNode.detail.disabled = false; } treeArr.push(treeNode); treeDataFromFlatData(treeNode.children, children); }); } return { flatData, treeData }; }, jointEnableChange(key, checked, loop) { const { children, origin } = this.flatData[key]; origin.value.enabled.value = checked; if (loop) { children.forEach((childKey) => { this.jointEnableChange(childKey, checked, loop); }); } }, }; exports.ready = function() { const panel = this; panel.$.import.addEventListener('change', (event) => { Editor.Panel.__protected__.openKit('ui-kit.searcher', { elem: event.target, params: [ { type: 'asset', assetFilter: { importer: ['gltf-scene'], }, }, ], listeners: { async confirm(detail) { if (!detail) { return; } await panel.import(detail.value); }, }, }); }); panel.$.clear.addEventListener('change', async () => { const result = await Editor.Dialog.warn(Editor.I18n.t('ENGINE.assets.animationMask.clearAllNodesWarn'), { title: Editor.I18n.t('ENGINE.assets.animationMask.clearAllNodes'), buttons: [Editor.I18n.t('ENGINE.dialog.confirm'), Editor.I18n.t('ENGINE.dialog.cancel')], default: 0, cancel: 1, }); if (result.response === 0) { await this.clear(); } }); // Used to determine whether the material has been modified in isDirty() panel.dirtyData = { uuid: '', origin: '', realtime: '', }; panel.$.tree.setTemplate('left', ''); panel.$.tree.setTemplateInit('left', ($left) => { $left.$checkbox = $left.querySelector('ui-checkbox'); $left.$checkbox.addEventListener('click', async (event) => { const key = $left.data.detail.key; const origin = panel.flatData[key].origin; panel.jointEnableChange(key, !origin.value.enabled.value, !event.altKey); await panel.change(this.queryData); }); }); panel.$.tree.setRender('left', ($left) => { const { key, disabled } = $left.data.detail; if (disabled) { $left.$checkbox.setAttribute('disabled', true); $left.$checkbox.value = true; } else { $left.$checkbox.removeAttribute('disabled'); } const origin = panel.flatData[key].origin; if (origin) { $left.$checkbox.value = origin.value.enabled.value; } }); panel.$.tree.setTemplate('text', ``); panel.$.tree.setTemplateInit('text', ($text) => { $text.$name = $text.querySelector('.name'); }); panel.$.tree.setRender('text', ($text, data) => { $text.$name.innerHTML = data.detail.name || data.detail.root; }); }; exports.update = async function(assetList, metaList) { this.assetList = assetList; this.metaList = metaList; this.asset = assetList[0]; this.meta = metaList[0]; if (assetList.length > 1) { this.$.container.setAttribute('multiple-invalid', ''); return; } else { this.$.container.removeAttribute('multiple-invalid'); } if (this.dirtyData.uuid !== this.asset.uuid) { this.dirtyData.uuid = this.asset.uuid; this.dirtyData.origin = ''; } this.queryData = await this.query(this.asset.uuid); this.updateInterface(); this.setDirtyData(); }; exports.close = function() { // Used to determine whether the material has been modified in isDirty() this.dirtyData = { uuid: '', origin: '', realtime: '', }; };