'use strict';
const { join } = require('path');
const { updateElementReadonly, updateElementInvalid } = require('../utils/assets');
const { injectionStyle } = require('../utils/prop');
const { ModeMap } = require('./texture/texture');
const imageTypeToImporter = {
raw: '',
texture: 'texture',
'normal map': 'texture',
'sprite-frame': 'sprite-frame',
'texture cube': 'erp-texture-cube',
};
const imageTypeToName = {
raw: '',
texture: 'texture',
'normal map': 'normalMap',
'sprite-frame': 'spriteFrame',
'texture cube': 'textureCube',
};
exports.template = /* html */`
`;
exports.style = /* css */`
:host .asset-image > ui-prop { margin-right: 4px; }
`;
exports.$ = {
container: '.asset-image',
typeSelect: '.type-select',
flipVerticalCheckbox: '.flipVertical-checkbox',
flipGreenChannel: '.flipGreenChannel-checkbox',
fixAlphaTransparencyArtifactsCheckbox: '.fixAlphaTransparencyArtifacts-checkbox',
fixATAProp: '.fixATA-prop',
isRGBEProp: '.isRGBE-prop',
isRGBECheckbox: '.isRGBE-checkbox',
panelSection: '.sub-panel-section',
texturePanelSection: '.sub-texture-panel-section',
};
const Elements = {
type: {
ready() {
const panel = this;
panel.$.typeSelect.addEventListener('change', async (event) => {
panel.metaList.forEach((meta) => {
meta.userData.type = event.target.value;
});
await panel.changeSubMetaWithType();
// There are other properties whose updates depend on its changes attribute corresponds to the edit element
Elements.isRGBE.update.call(panel);
Elements.fixAlphaTransparencyArtifacts.update.call(panel);
// imageAssets type change to spriteFrame, update mipmaps
panel.updatePanel();
// need to be dispatched after updatePanel
panel.dispatch('change');
});
panel.$.typeSelect.addEventListener('confirm', () => {
panel.dispatch('snapshot');
});
},
update() {
const panel = this;
let optionsHtml = '';
const types = ['raw', 'texture', 'normal map', 'sprite-frame', 'texture cube'];
types.forEach((type) => {
optionsHtml += ``;
});
panel.$.typeSelect.innerHTML = optionsHtml;
panel.$.typeSelect.value = panel.meta.userData.type;
updateElementInvalid.call(panel, panel.$.typeSelect, 'type');
updateElementReadonly.call(panel, panel.$.typeSelect);
},
},
flipVertical: {
ready() {
const panel = this;
panel.$.flipVerticalCheckbox.addEventListener('change', (event) => {
panel.metaList.forEach((meta) => {
meta.userData.flipVertical = event.target.value;
});
panel.dispatch('change');
});
panel.$.flipVerticalCheckbox.addEventListener('confirm', () => {
panel.dispatch('snapshot');
});
},
update() {
const panel = this;
panel.$.flipVerticalCheckbox.value = panel.meta.userData.flipVertical;
updateElementInvalid.call(panel, panel.$.flipVerticalCheckbox, 'flipVertical');
updateElementReadonly.call(panel, panel.$.flipVerticalCheckbox);
},
},
fixAlphaTransparencyArtifacts: {
ready() {
const panel = this;
panel.$.fixAlphaTransparencyArtifactsCheckbox.addEventListener('change', (event) => {
panel.metaList.forEach((meta) => {
meta.userData.fixAlphaTransparencyArtifacts = event.target.value;
});
panel.dispatch('change');
});
panel.$.fixAlphaTransparencyArtifactsCheckbox.addEventListener('confirm', () => {
panel.dispatch('snapshot');
});
},
update() {
const panel = this;
const fixAlphaTransparencyArtifactsCheckbox = panel.$.fixAlphaTransparencyArtifactsCheckbox;
const fixATAProp = panel.$.fixATAProp;
fixAlphaTransparencyArtifactsCheckbox.value = panel.meta.userData.fixAlphaTransparencyArtifacts;
const bannedTypes = ['normal map'];
const isCapableToFixAlphaTransparencyArtifacts = !bannedTypes.includes(panel.meta.userData.type);
if (isCapableToFixAlphaTransparencyArtifacts) {
fixATAProp.style.display = 'block';
updateElementInvalid.call(panel, panel.$.fixAlphaTransparencyArtifactsCheckbox, 'fixAlphaTransparencyArtifacts');
updateElementReadonly.call(panel, panel.$.fixAlphaTransparencyArtifactsCheckbox);
} else {
fixATAProp.style.display = 'none';
}
},
},
isRGBE: {
ready() {
const panel = this;
panel.$.isRGBECheckbox.addEventListener('change', (event) => {
panel.metaList.forEach((meta) => {
meta.userData.isRGBE = event.target.value;
});
panel.dispatch('change');
});
panel.$.isRGBECheckbox.addEventListener('confirm', () => {
panel.dispatch('snapshot');
});
},
update() {
const panel = this;
if (panel.meta.userData.type === 'texture cube') {
panel.$.isRGBEProp.style.display = 'block';
panel.$.isRGBECheckbox.value = panel.meta.userData.isRGBE;
updateElementInvalid.call(panel, panel.$.isRGBECheckbox, 'isRGBE');
updateElementReadonly.call(panel, panel.$.isRGBECheckbox);
} else {
panel.$.isRGBEProp.style.display = 'none';
}
},
},
flipGreenChannel: {
ready() {
const panel = this;
panel.$.flipGreenChannel.addEventListener('change', (event) => {
panel.metaList.forEach((meta) => {
meta.userData.flipGreenChannel = event.target.value;
});
panel.dispatch('change');
panel.dispatch('snapshot');
});
},
update() {
const panel = this;
panel.$.flipGreenChannel.value = panel.meta.userData.flipGreenChannel;
updateElementInvalid.call(panel, panel.$.flipGreenChannel, 'flipGreenChannel');
updateElementReadonly.call(panel, panel.$.flipGreenChannel);
},
},
};
exports.methods = {
updatePanel() {
this.setPanel(this.$.panelSection, this.meta.userData.type);
// sprite-frame 需要多显示 texture 面板
if (this.meta.userData.type === 'sprite-frame') {
this.setPanel(this.$.texturePanelSection, 'texture');
} else {
this.$.texturePanelSection.style.display = 'none';
}
},
setPanel($section, type) {
const assetList = [];
const metaList = [];
const imageImporter = imageTypeToImporter[type];
this.assetList.forEach((asset) => {
if (!asset) {
return;
}
for (const subUuid in asset.subAssets) {
const subAsset = asset.subAssets[subUuid];
if (!subAsset || subAsset.importer === '*') {
continue;
}
if (subAsset.importer === imageImporter) {
assetList.push(subAsset);
break;
}
}
});
this.metaList.forEach((meta) => {
if (!meta) {
return;
}
for (const subUuid in meta.subMetas) {
const subMeta = meta.subMetas[subUuid];
if (!subMeta || subMeta.importer === '*') {
continue;
}
if (subMeta.importer === imageImporter) {
metaList.push(subMeta);
break;
}
}
});
if (!assetList.length || !metaList.length) {
$section.style.display = 'none';
return;
} else {
$section.style.display = 'block';
}
const asset = assetList[0];
const $label = $section.querySelector('ui-label');
$label.setAttribute('value', asset.name);
const $panel = $section.querySelector('ui-panel');
$panel.setAttribute('src', join(__dirname, `./${asset.importer}.js`));
$panel.injectionStyle(injectionStyle);
$panel.update(assetList, metaList, this.assetList);
},
changeMipFilter(targetSubMetaKey) {
if (this.originImageType === 'sprite-frame') {
// spriteFrame -> any
this.metaList.forEach(async (meta) => {
if (!meta.subMetas[targetSubMetaKey]) {
meta.subMetas[targetSubMetaKey] = {
userData: {},
}
}
// hack only record the configuration of the type that has been updated, not the accurate configuration of the child resources after import.
// If targetSubMeta does not have mipfilter or miupfilter is none, set mipfilter to nearest
const preMipfilter = await Editor.Profile.getTemp('inspector', `${meta.uuid}@${targetSubMetaKey}.texture.mipfilter`, 'default');
if (!preMipfilter || preMipfilter === 'none') {
meta.subMetas[targetSubMetaKey].userData.mipfilter = 'nearest';
}
});
} else if (this.meta.userData.type === 'sprite-frame') {
// any -> sprite,disabled mipmaps
this.metaList.forEach((meta) => {
if (!meta.subMetas[targetSubMetaKey]) {
meta.subMetas[targetSubMetaKey] = {
userData: {},
}
}
meta.subMetas[targetSubMetaKey].userData.mipfilter = 'none';
});
}
},
async changeSubMetaWithType() {
// any -> texture : texture.wrapMode -> Repeat
// any -> sprite : texture.wrapMode -> Clamp
if (['sprite-frame', 'texture'].includes(this.meta.userData.type)) {
const textureKey = Editor.Utils.UUID.nameToSubId('texture');
let wrapModeCache;
if (this.meta.subMetas[textureKey]) {
const textureUUID = this.meta.subMetas[textureKey].uuid;
wrapModeCache = await Editor.Profile.getTemp('inspector', `${textureUUID}.texture.wrapMode`);
if (!wrapModeCache) {
// use default wrapMode if not changed
const wrapModeName = this.meta.userData.type === 'texture' ? 'Repeat' : 'Clamp';
this.metaList.forEach((meta) => {
const data = ModeMap.wrap[wrapModeName];
if (!meta.subMetas[textureKey]) {
meta.subMetas[textureKey] = {
userData: {}
}
}
for (const key of Object.keys(data)) {
meta.subMetas[textureKey].userData[key] = data[key];
}
});
}
}
if (this.originImageType === 'sprite-frame' || this.meta.userData.type === 'sprite-frame') {
const changeTypes = ['texture', 'normal map', 'texture cube', 'sprite-frame'];
if (!changeTypes.includes(this.meta.userData.type)) {
return;
}
let targetName = imageTypeToName[this.meta.userData.type];
if (targetName === 'spriteFrame') {
// change texture asset when import as sprite
targetName = 'texture';
}
const targetSubMetaKey = Editor.Utils.UUID.nameToSubId(targetName);
targetSubMetaKey && this.changeMipFilter(targetSubMetaKey);
}
}
},
};
exports.ready = function() {
for (const prop in Elements) {
const element = Elements[prop];
if (element.ready) {
element.ready.call(this);
}
}
this.$.panelSection.addEventListener('change', () => {
this.dispatch('change');
});
this.$.panelSection.addEventListener('snapshot', () => {
this.dispatch('snapshot');
});
this.$.texturePanelSection.addEventListener('change', () => {
this.dispatch('change');
});
this.$.texturePanelSection.addEventListener('snapshot', () => {
this.dispatch('snapshot');
});
};
exports.update = function(assetList, metaList) {
this.assetList = assetList;
this.metaList = metaList;
this.asset = assetList[0];
this.meta = metaList[0];
this.originImageType = this.meta.userData.type;
for (const prop in Elements) {
const element = Elements[prop];
if (element.update) {
element.update.call(this);
}
}
this.updatePanel();
};