| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- 'use strict';
- const { updateElementReadonly } = require('../utils/assets');
- exports.template = /* html */`
- <section class="asset-animation-mask">
- <div class="header">
- <ui-button class="import">
- <ui-icon value="import"></ui-icon>
- <ui-label value="i18n:ENGINE.assets.animationMask.importSkeleton"></ui-label>
- </ui-button>
- <ui-button class="clear">
- <ui-icon value="del" color="true"></ui-icon>
- <ui-label value="i18n:ENGINE.assets.animationMask.clearAllNodes"></ui-label>
- </ui-button>
- </div>
- <div class="content">
- <ui-tree class="tree"></ui-tree>
- </div>
- <ui-label class="multiple-warn-tip" value="i18n:ENGINE.assets.multipleWarning"></ui-label>
- </section>
- `;
- 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', '<ui-checkbox tooltip="i18n:ENGINE.assets.animationMask.nodeEnableTip"></ui-checkbox>');
- 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', `<span class="name"></span>`);
- 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: '',
- };
- };
|