diff --git a/editor/i18n/en/assets.js b/editor/i18n/en/assets.js index f9747b95809..f7322f360de 100644 --- a/editor/i18n/en/assets.js +++ b/editor/i18n/en/assets.js @@ -508,6 +508,10 @@ module.exports = { save: 'Save', abort: 'Discard', }, + spine_data: { + atlas: 'Atlas', + atlas_warn: 'Failed to set up the atlas and requires a text file with the .atlas suffix', + }, }, menu: { diff --git a/editor/i18n/zh/assets.js b/editor/i18n/zh/assets.js index cffc333c5ed..d332c8634bb 100644 --- a/editor/i18n/zh/assets.js +++ b/editor/i18n/zh/assets.js @@ -493,6 +493,10 @@ module.exports = { save: '保存', abort: '丢弃', }, + spine_data: { + atlas: '图集', + atlas_warn: '设置图集失败,需要后缀为 .atlas 的文本文件', + }, }, menu: { diff --git a/editor/inspector/assets.js b/editor/inspector/assets.js index a52fb7b84d3..e1aa28e2875 100644 --- a/editor/inspector/assets.js +++ b/editor/inspector/assets.js @@ -16,6 +16,7 @@ module.exports = { 'render-pipeline': join(__dirname, './assets/render-pipeline.js'), 'render-texture': join(__dirname, './assets/render-texture.js'), 'sprite-frame': join(__dirname, './assets/sprite-frame.js'), + 'spine-data': join(__dirname, './assets/spine-data.js'), 'texture-cube': join(__dirname, './assets/texture-cube.js'), 'video-clip': join(__dirname, './assets/video-clip.js'), effect: join(__dirname, './assets/effect.js'), diff --git a/editor/inspector/assets/spine-data.js b/editor/inspector/assets/spine-data.js new file mode 100644 index 00000000000..cfe9595d9ba --- /dev/null +++ b/editor/inspector/assets/spine-data.js @@ -0,0 +1,137 @@ +'use strict'; + +const { readJSONSync } = require('fs-extra'); + +exports.template = /* html */` +
+ + + + + +
+
+
`; + +exports.$ = { + container: '.spine-data', + atlasSection: '.atlas-section', + atlas: '.atlas', + textures: '.textures', +}; + +exports.style = ` +.spine-data { + padding-right: 4px; +} + +.spine-data > .atlas-section [slot="header"] { + width: 100%; + display: block; +} + +.spine-data > .atlas-section[whole] { + padding-left: 20px; +} + +.spine-data > .atlas-section > .textures > {} +.spine-data > .atlas-section > .textures > .texture-item { + margin-left: 4px; +} +`; + +exports.ready = function() { + const panel = this; + + function setAtlas(value) { + panel.metaList.forEach((meta) => { + meta.userData.atlasUuid = value; + }); + panel.dispatch('change'); + panel.dispatch('snapshot'); + } + + panel.$.atlas.addEventListener('confirm', async (event) => { + const atlas = event.target.value; + if (!atlas) { + setAtlas(atlas); + return; + } + + const assetInfo = await Editor.Message.request('asset-db', 'query-asset-info', atlas); + if (!assetInfo) { + panel.$.atlas.setAttribute('value', ''); + return; + } + + if (!assetInfo.source.endsWith('.atlas')) { + await Editor.Dialog.warn(Editor.I18n.t('ENGINE.assets.spine_data.atlas_warn'), { + buttons: [ + Editor.I18n.t('ENGINE.dialog.confirm'), + ], + }); + panel.$.atlas.setAttribute('value', ''); + return; + } + + setAtlas(atlas); + }); +}; + +exports.update = function(assetList, metaList) { + const panel = this; + + panel.assetList = assetList; + panel.metaList = metaList; + panel.asset = assetList[0]; + panel.meta = metaList[0]; + + while (panel.$.textures.firstChild) { + panel.$.textures.removeChild(panel.$.textures.firstChild); + } + + // 先隐藏箭头,等有数值才显示 + panel.$.atlasSection.setAttribute('whole', ''); + + const libraryJSON = panel.asset.library['.json']; + if (libraryJSON) { + const spData = readJSONSync(libraryJSON); + if (spData && spData.textures && spData.textures.length > 0) { + createTextureSection(spData.textures, panel.$.textures); + } + } + // 只允许显示 .atlas 的资源 + panel.$.atlas.setAttribute('filter', JSON.stringify({ + pattern: 'db://**/*.atlas', + })); + panel.$.atlas.setAttribute('value', panel.meta.userData.atlasUuid); +}; + +function createTextureSection(textures, parentElement) { + for (let i = 0; i < textures.length; i++) { + const texture = textures[i]; + let item = parentElement.querySelector('.texture-item'); + let uiAsset = item && item.querySelector('.ui-asset'); + if (!uiAsset) { + item = document.createElement('ui-prop'); + item.classList.add('texture-item'); + item.setAttribute('readonly', ''); + parentElement.appendChild(item); + + let type = texture.__expectedType__.split('cc.'); + type = type.length > 0 ? type[1] : type[0]; + + const label = document.createElement('ui-label'); + label.setAttribute('slot', 'label'); + label.setAttribute('value', i); + item.appendChild(label); + + uiAsset = document.createElement('ui-asset'); + uiAsset.setAttribute('slot', 'content'); + item.appendChild(uiAsset); + } + uiAsset.setAttribute('readonly', ''); + uiAsset.setAttribute('value', texture.__uuid__); + uiAsset.setAttribute('droppable', texture.__expectedType__); + } +}