-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
`;
exports.style = /* css */`
+.preview-section {
+ margin-top: 0px;
+}
.preview {
-
border-top: 1px solid var(--color-normal-border);
}
.preview > .info {
@@ -292,6 +296,13 @@ exports.update = function(assetList, metaList) {
this.asset = assetList[0];
this.meta = metaList[0];
+ // 如何多选就隐藏预览
+ if (assetList.length > 1) {
+ this.$.container.style.display = 'none';
+ } else {
+ this.$.container.style.display = 'block';
+ }
+
for (const prop in Elements) {
const element = Elements[prop];
if (element.update) {
diff --git a/editor/inspector/assets/prefab-preview.js b/editor/inspector/assets/prefab-preview.js
new file mode 100644
index 00000000000..369ba92aff2
--- /dev/null
+++ b/editor/inspector/assets/prefab-preview.js
@@ -0,0 +1,206 @@
+'use strict';
+
+exports.template = /* html */`
+
+
+
+`;
+
+exports.style = /* css */`
+ .preview-section {
+ margin-top: 0px;
+ }
+ .preview { }
+ .preview > .image {
+ height: var(--inspector-footer-preview-height, 200px);
+ overflow: hidden;
+ display: flex;
+ flex: 1;
+ }
+ .preview >.image > .canvas {
+ flex: 1;
+ }
+`;
+
+
+exports.$ = {
+ container: '.preview',
+ canvas: '.canvas',
+ image: '.image',
+};
+
+async function callFunction(funcName, ...args) {
+ return await Editor.Message.request('scene', 'call-preview-function', 'scene:prefab-preview', funcName, ...args);
+}
+
+const Elements = {
+ preview: {
+ ready() {
+ const panel = this;
+
+ let _isPreviewDataDirty = false;
+ Object.defineProperty(panel, 'isPreviewDataDirty', {
+ get() {
+ return _isPreviewDataDirty;
+ },
+ set(value) {
+ if (value !== _isPreviewDataDirty) {
+ _isPreviewDataDirty = value;
+ value && panel.refreshPreview();
+ }
+ },
+ });
+ panel.$.canvas.addEventListener('mousedown', async (event) => {
+ await callFunction('onMouseDown', { x: event.x, y: event.y, button: event.button });
+
+ async function mousemove(event) {
+ await callFunction('onMouseMove', {
+ movementX: event.movementX,
+ movementY: event.movementY,
+ });
+
+ panel.isPreviewDataDirty = true;
+ }
+
+ async function mouseup(event) {
+ await callFunction('onMouseUp', {
+ x: event.x,
+ y: event.y,
+ });
+
+ document.removeEventListener('mousemove', mousemove);
+ document.removeEventListener('mouseup', mouseup);
+
+ panel.isPreviewDataDirty = false;
+ }
+
+ document.addEventListener('mousemove', mousemove);
+ document.addEventListener('mouseup', mouseup);
+
+
+ panel.isPreviewDataDirty = true;
+ });
+
+ panel.$.canvas.addEventListener('wheel', async (event) => {
+ await callFunction('onMouseWheel', {
+ wheelDeltaY: event.wheelDeltaY,
+ wheelDeltaX: event.wheelDeltaX,
+ });
+ panel.isPreviewDataDirty = true;
+ });
+
+
+ const GlPreview = Editor._Module.require('PreviewExtends').default;
+ panel.glPreview = new GlPreview('scene:prefab-preview', 'query-prefab-preview-data');
+
+ function observer() {
+ panel.isPreviewDataDirty = true;
+ }
+
+ panel.resizeObserver = new window.ResizeObserver(observer);
+ panel.resizeObserver.observe(panel.$.image);
+ observer();
+ },
+ async update() {
+ const panel = this;
+
+ if (!panel.$.canvas) {
+ return;
+ }
+
+ await panel.glPreview.init({ width: panel.$.canvas.clientWidth, height: panel.$.canvas.clientHeight });
+ await callFunction('setPrefab', panel.asset.uuid);
+ this.isPreviewDataDirty = true;
+ },
+ close() {
+ const panel = this;
+
+ panel.resizeObserver.unobserve(panel.$.image);
+ },
+ },
+};
+
+exports.methods = {
+ async refreshPreview() {
+ const panel = this;
+
+ // After await, the panel no longer exists
+ if (!panel.$.canvas) {
+ return;
+ }
+
+ const doDraw = async () => {
+ try {
+ const canvas = panel.$.canvas;
+ const image = panel.$.image;
+
+ const width = image.clientWidth;
+ const height = image.clientHeight;
+ if (canvas.width !== width || canvas.height !== height) {
+ canvas.width = width;
+ canvas.height = height;
+
+ await panel.glPreview.initGL(canvas, { width, height });
+ await panel.glPreview.resizeGL(width, height);
+ }
+
+ const info = await panel.glPreview.queryPreviewData({
+ width: canvas.width,
+ height: canvas.height,
+ });
+
+ panel.glPreview.drawGL(info);
+ } catch (e) {
+ console.warn(e);
+ }
+ };
+
+ requestAnimationFrame(async () => {
+ await doDraw();
+ panel.isPreviewDataDirty = false;
+ });
+ },
+};
+
+exports.ready = function() {
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.ready) {
+ element.ready.call(this);
+ }
+ }
+};
+
+exports.update = function(assetList, metaList) {
+ this.assetList = assetList;
+ this.metaList = metaList;
+ this.asset = assetList[0];
+ this.meta = metaList[0];
+
+ // 如何多选就隐藏预览
+ if (assetList.length > 1) {
+ this.$.container.style.display = 'none';
+ } else {
+ this.$.container.style.display = 'block';
+ }
+
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.update) {
+ element.update.call(this);
+ }
+ }
+};
+
+exports.close = function() {
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.close) {
+ element.close.call(this);
+ }
+ }
+};
diff --git a/editor/inspector/assets/skeleton-preview.js b/editor/inspector/assets/skeleton-preview.js
index 3d68bbf01cf..4bd780f4ec6 100644
--- a/editor/inspector/assets/skeleton-preview.js
+++ b/editor/inspector/assets/skeleton-preview.js
@@ -1,17 +1,22 @@
'use strict';
exports.template = /* html */`
-
-
+
`;
exports.style = /* css */`
+.preview-section {
+ margin-top: 0px;
+}
.preview {
border-top: 1px solid var(--color-normal-border);
}
@@ -209,6 +214,13 @@ exports.update = function(assetList, metaList) {
this.asset = assetList[0];
this.meta = metaList[0];
+ // 如何多选就隐藏预览
+ if (assetList.length > 1) {
+ this.$.container.style.display = 'none';
+ } else {
+ this.$.container.style.display = 'block';
+ }
+
for (const prop in Elements) {
const element = Elements[prop];
if (element.update) {
diff --git a/editor/inspector/assets/spine-preview.js b/editor/inspector/assets/spine-preview.js
new file mode 100644
index 00000000000..5a79b52ece4
--- /dev/null
+++ b/editor/inspector/assets/spine-preview.js
@@ -0,0 +1,385 @@
+'use strict';
+
+exports.template = /* html */`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports.style = /* css */`
+.preview-section {
+ margin-top: 0px;
+}
+.preview {
+ border-top: 1px solid var(--color-normal-border);
+}
+.preview > .control {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ display: flex;
+ width: 100%;
+ flex-direction: column;
+ align-items: flex-start;
+}
+.preview > .control[hidden] {
+ display: none;
+}
+.preview > .control > ui-prop {
+ min-width: 250px;
+}
+.preview > .image {
+ height: var(--inspector-footer-preview-height, 200px);
+ overflow: hidden;
+ display: flex;
+ flex: 1;
+}
+.preview > .image > .anim-control {
+ position: absolute;
+ right: 15px;
+ bottom: 15px;
+ height: 25px;
+}
+.preview > .image > .anim-control[hidden] {
+ display: none;
+}
+.preview > .image .play[hidden] {
+ display: none;
+}
+.preview > .image .pause[hidden] {
+ display: none;
+}
+.preview > .image .duration {
+ position: absolute;
+ left: 50%;
+ bottom: 4px;
+ transform: translate(-50%);
+}
+.preview >.image > .canvas {
+ flex: 1;
+}
+`;
+
+exports.$ = {
+ container: '.preview',
+ canvas: '.canvas',
+ image: '.image',
+ skinSelectPro: '.skin-select-pro',
+ animationSelectPro: '.animation-select-pro',
+ control: '.control',
+ playState: '.play-state',
+ play: '.play',
+ pause: '.pause',
+ stop: '.stop',
+ duration: '.duration',
+ loop: '.loop-check-box',
+ animationCtrl: '.anim-control',
+};
+
+async function callFunction(funcName, ...args) {
+ return await Editor.Message.request('scene', 'call-preview-function', 'scene:spine-preview', funcName, ...args);
+}
+
+const Elements = {
+ preview: {
+ ready() {
+ const panel = this;
+
+ let _isPreviewDataDirty = false;
+ Object.defineProperty(panel, 'isPreviewDataDirty', {
+ get() {
+ return _isPreviewDataDirty;
+ },
+ set(value) {
+ if (value !== _isPreviewDataDirty) {
+ _isPreviewDataDirty = value;
+ value && panel.refreshPreview();
+ }
+ },
+ });
+ panel.$.canvas.addEventListener('mousedown', async (event) => {
+ await callFunction('onMouseDown', { x: event.x, y: event.y, button: event.button });
+
+ async function mousemove(event) {
+ await callFunction('onMouseMove', {
+ movementX: event.movementX,
+ movementY: event.movementY,
+ });
+
+ panel.isPreviewDataDirty = true;
+ }
+
+ async function mouseup(event) {
+ await callFunction('onMouseUp', {
+ x: event.x,
+ y: event.y,
+ });
+
+ document.removeEventListener('mousemove', mousemove);
+ document.removeEventListener('mouseup', mouseup);
+
+ panel.isPreviewDataDirty = false;
+ }
+
+ document.addEventListener('mousemove', mousemove);
+ document.addEventListener('mouseup', mouseup);
+
+ panel.isPreviewDataDirty = true;
+ });
+
+ panel.$.canvas.addEventListener('wheel', async (event) => {
+ await callFunction('onMouseWheel', {
+ wheelDeltaY: event.wheelDeltaY,
+ wheelDeltaX: event.wheelDeltaX,
+ });
+ panel.isPreviewDataDirty = true;
+ });
+
+
+ const GlPreview = Editor._Module.require('PreviewExtends').default;
+ panel.glPreview = new GlPreview('scene:spine-preview', 'query-spine-preview-data');
+
+ function observer() {
+ panel.isPreviewDataDirty = true;
+ }
+
+ panel.resizeObserver = new window.ResizeObserver(observer);
+ panel.resizeObserver.observe(panel.$.image);
+ observer();
+ },
+ async update() {
+ const panel = this;
+
+ if (!panel.$.canvas) {
+ return;
+ }
+
+ await panel.glPreview.init({ width: panel.$.canvas.clientWidth, height: panel.$.canvas.clientHeight });
+ const spineData = await callFunction('setSpine', panel.asset.uuid);
+ panel.spinUpdate(spineData);
+ this.isPreviewDataDirty = true;
+ },
+ close() {
+ const panel = this;
+
+ panel.resizeObserver.unobserve(panel.$.image);
+ },
+ },
+ spine: {
+ updateEnum($selectPro, info) {
+ const panel = this;
+
+ $selectPro.innerHTML = '';
+ for (const key in info.list) {
+ const value = info.list[key];
+ const option = document.createElement('ui-select-option-pro');
+ option.setAttribute('label', key);
+ option.setAttribute('value', value);
+ if (info.index === value) {
+ panel.animationIndex = Number(value);
+ option.setAttribute('selected', '');
+ }
+ $selectPro.appendChild(option);
+ }
+ },
+ ready() {
+ const panel = this;
+
+ panel.animationIndex = 0;
+ panel.$.skinSelectPro.addEventListener('confirm', (event) => {
+ callFunction('setSkinIndex', Number(event.detail)).then(() => {});
+ });
+ panel.$.animationSelectPro.addEventListener('confirm', (event) => {
+ panel.animationIndex = Number(event.detail);
+ callFunction('play', panel.animationIndex).then(() => {});
+ });
+ panel.spinUpdate = Elements.spine.update.bind(panel);
+ },
+ update(info) {
+ const panel = this;
+
+ if (!info) {
+ panel.$.loop.setAttribute('disabled', '');
+ panel.$.play.setAttribute('disabled', '');
+ panel.$.stop.setAttribute('disabled', '');
+ panel.$.skinSelectPro.setAttribute('disabled', '');
+ panel.$.animationSelectPro.setAttribute('disabled', '');
+ return;
+ }
+
+ panel.$.loop.removeAttribute('disabled');
+ panel.$.play.removeAttribute('disabled');
+ panel.$.stop.removeAttribute('disabled');
+ panel.$.skinSelectPro.removeAttribute('disabled');
+ panel.$.animationSelectPro.removeAttribute('disabled');
+
+ Elements.spine.updateEnum.call(panel, panel.$.skinSelectPro, info.skin);
+ Elements.spine.updateEnum.call(panel, panel.$.animationSelectPro, info.animation);
+ Elements.spine.updateDuration.call(panel, 0, info.animation.durations[panel.animationIndex]);
+ Elements.control.update.call(panel, false);
+ Elements.control.updateLoop.call(panel, info.loop);
+ panel.isPreviewDataDirty = true;
+ },
+ updateDuration(delay, duration) {
+ const panel = this;
+
+ panel.$.duration.setAttribute('value', `${Number(delay).toFixed(3)} / ${duration.toFixed(3)}`);
+ },
+ },
+ control: {
+ ready() {
+ const panel = this;
+
+ panel.$.loop.addEventListener('confirm', (event) => {
+ callFunction('setLoop', Boolean(event.target.value)).then(() => {});
+ });
+ panel.$.play.addEventListener('click', () => {
+ callFunction('play', panel.animationIndex).then(() => {});
+ });
+ panel.$.pause.addEventListener('confirm', (event) => {
+ callFunction('pause').then(() => {});
+ });
+ panel.$.stop.addEventListener('confirm', (event) => {
+ callFunction('stop').then(() => {});
+ });
+ },
+ updateLoop(loop) {
+ const panel = this;
+
+ panel.$.loop.setAttribute('value', Boolean(loop));
+ },
+ update(playing) {
+ const panel = this;
+
+ if (playing) {
+ panel.$.play.setAttribute('hidden', '');
+ panel.$.pause.removeAttribute('hidden');
+ } else {
+ panel.$.pause.setAttribute('hidden', '');
+ panel.$.play.removeAttribute('hidden');
+ }
+ },
+ },
+};
+
+exports.methods = {
+ async refreshPreview() {
+ const panel = this;
+
+ // After await, the panel no longer exists
+ if (!panel.$.canvas) {
+ return;
+ }
+
+ const doDraw = async () => {
+ try {
+ const canvas = panel.$.canvas;
+ const image = panel.$.image;
+
+ const width = image.clientWidth;
+ const height = image.clientHeight;
+ if (canvas.width !== width || canvas.height !== height) {
+ canvas.width = width;
+ canvas.height = height;
+
+ await panel.glPreview.initGL(canvas, { width, height });
+ await panel.glPreview.resizeGL(width, height);
+ }
+
+ const info = await panel.glPreview.queryPreviewData({
+ width: canvas.width,
+ height: canvas.height,
+ });
+
+ panel.glPreview.drawGL(info);
+ } catch (e) {
+ console.warn(e);
+ }
+ };
+
+ requestAnimationFrame(async () => {
+ await doDraw();
+ panel.isPreviewDataDirty = false;
+ });
+ },
+
+ onAnimationUpdate(playing, delay, duration) {
+ const panel = this;
+ // this.$.playState.setAttribute('');
+ Elements.spine.updateDuration.call(panel, delay, duration);
+ Elements.control.update.call(panel, playing);
+ panel.isPreviewDataDirty = true;
+ },
+};
+
+exports.ready = function() {
+ this.onAnimationUpdateBind = this.onAnimationUpdate.bind(this);
+
+ Editor.Message.addBroadcastListener('scene:spine-preview-animation-time-change', this.onAnimationUpdateBind);
+
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.ready) {
+ element.ready.call(this);
+ }
+ }
+};
+
+exports.update = function(assetList, metaList) {
+ this.assetList = assetList;
+ this.metaList = metaList;
+ this.asset = assetList[0];
+ this.meta = metaList[0];
+
+ // 如何多选就隐藏预览
+ if (assetList.length > 1) {
+ this.$.container.style.display = 'none';
+ } else {
+ this.$.container.style.display = 'block';
+ }
+
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.update) {
+ element.update.call(this);
+ }
+ }
+};
+
+exports.close = function() {
+ for (const prop in Elements) {
+ const element = Elements[prop];
+ if (element.close) {
+ element.close.call(this);
+ }
+ }
+};