diff --git a/editor/i18n/en/assets.js b/editor/i18n/en/assets.js
index d1a1784633a..e439e3879b6 100644
--- a/editor/i18n/en/assets.js
+++ b/editor/i18n/en/assets.js
@@ -10,6 +10,7 @@ module.exports = {
cloneToDirectoryIllegal: 'Please limit the saved path to the current project assets path',
preview: {
header: 'Preview',
+ resetCameraView: 'Reset camera view',
},
spine: {
skin: 'Skin',
diff --git a/editor/i18n/zh/assets.js b/editor/i18n/zh/assets.js
index b496908c557..b070b4dce6d 100644
--- a/editor/i18n/zh/assets.js
+++ b/editor/i18n/zh/assets.js
@@ -10,6 +10,7 @@ module.exports = {
cloneToDirectoryIllegal: '保存路径请限制在当前项目 /assets 路径内',
preview: {
header: '预览',
+ resetCameraView: '复位摄像机视图',
},
spine: {
skin: '皮肤',
diff --git a/editor/inspector/assets/prefab-preview.js b/editor/inspector/assets/prefab-preview.js
index 369ba92aff2..6e0ab7e8f23 100644
--- a/editor/inspector/assets/prefab-preview.js
+++ b/editor/inspector/assets/prefab-preview.js
@@ -1,12 +1,10 @@
'use strict';
+const { PreviewControl, hideElement } = require("../utils/preview");
+
exports.template = /* html */`
-
+
`;
@@ -15,164 +13,30 @@ exports.style = /* css */`
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();
+ ready(panel) {
+ panel.preview.init();
},
- 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);
+ async update(panel) {
+ await panel.preview.callPreviewFunction('setPrefab', panel.asset.uuid);
},
+ close(panel) {},
},
};
-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.methods = {};
exports.ready = function() {
- for (const prop in Elements) {
- const element = Elements[prop];
- if (element.ready) {
- element.ready.call(this);
- }
- }
+ this.preview = new PreviewControl('scene:prefab-preview', 'query-prefab-preview-data', this.$.container);
+
+ Object.values(Elements).forEach((element) => element.ready && element.ready(this));
};
exports.update = function(assetList, metaList) {
@@ -182,25 +46,13 @@ exports.update = function(assetList, metaList) {
this.meta = metaList[0];
// 如何多选就隐藏预览
- if (assetList.length > 1) {
- this.$.container.style.display = 'none';
- } else {
- this.$.container.style.display = 'block';
- }
+ hideElement(this.$.container, assetList.length > 1);
- for (const prop in Elements) {
- const element = Elements[prop];
- if (element.update) {
- element.update.call(this);
- }
- }
+ Object.values(Elements).forEach((element) => element.update && element.update(this));
};
exports.close = function() {
- for (const prop in Elements) {
- const element = Elements[prop];
- if (element.close) {
- element.close.call(this);
- }
- }
+ this.preview.close();
+
+ Object.values(Elements).forEach((element) => element.close && element.close(this));
};
diff --git a/editor/inspector/assets/spine-preview.js b/editor/inspector/assets/spine-preview.js
index bee8da6a8b8..ba6887696ee 100644
--- a/editor/inspector/assets/spine-preview.js
+++ b/editor/inspector/assets/spine-preview.js
@@ -77,9 +77,6 @@ exports.template = /* html */`
-
-
-
`;
@@ -126,18 +123,6 @@ exports.style = /* css */`
}
}
}
- & > .image {
- height: var(--inspector-footer-preview-height, 200px);
- overflow: hidden;
- display: flex;
- flex: 1;
- position: relative;
-
- & > .canvas {
- position: absolute;
- inset: 0;
- }
- }
}
}
`;
@@ -153,8 +138,6 @@ const Properties = [...Config.CHECKBOX, ...Config.SLIDER, ...Config.OTHER, ...Co
exports.$ = {
container: '.preview',
- canvas: '.canvas',
- image: '.image',
...Object.fromEntries(Properties.map((key) => [key, `.${key}`])),
@@ -167,11 +150,8 @@ const Elements = {
panel.preview.init();
},
async update(panel) {
- if (!panel.$.canvas) { return; }
-
const spineData = await panel.preview.callPreviewFunction('setSpine', panel.asset.uuid);
panel.spinUpdate(panel, spineData);
- panel.preview.doRefreshDirty();
},
close(panel) {
panel.preview.callPreviewFunction('stop');
@@ -228,7 +208,6 @@ const Elements = {
Elements.spine.updateDuration(panel, 0, Elements.spine.getDurations(panel, info));
Elements.control.update(panel, false);
Elements.control.updateInfo(panel, info);
- panel.preview.doRefreshDirty();
},
updateDuration(panel, time, duration) {
panel.$.duration.setConfig({
@@ -249,9 +228,7 @@ const Elements = {
Config.CHECKBOX.forEach((key) => {
panel.$[key].addEventListener('confirm', (event) => {
- panel.preview.callPreviewFunction('setProperties', key, Boolean(event.target.value)).then((() => {
- panel.preview.doRefreshDirty();
- }));
+ panel.preview.callPreviewFunction('setProperties', key, Boolean(event.target.value));
});
});
@@ -299,7 +276,7 @@ exports.ready = function() {
Editor.Message.__protected__.addBroadcastListener('scene:spine-preview-animation-time-change', this.onAnimationUpdateBind);
- this.preview = new PreviewControl('scene:spine-preview', 'query-spine-preview-data', this.$.canvas, this.$.image);
+ this.preview = new PreviewControl('scene:spine-preview', 'query-spine-preview-data', this.$.container);
Object.values(Elements).forEach((element) => element.ready && element.ready(this));
};
diff --git a/editor/inspector/utils/preview.js b/editor/inspector/utils/preview.js
index bd117c23771..82ffa6bc19a 100644
--- a/editor/inspector/utils/preview.js
+++ b/editor/inspector/utils/preview.js
@@ -24,8 +24,13 @@ class PreviewControl {
_glPreview = null;
// html element
- _canvasElement = null;
- _imageElement = null;
+ _container = null;
+
+ _image = null;
+ _canvas = null;
+
+ _toolbar = null;
+ _resetCamera = null;
_resizeObserver = null;
@@ -33,28 +38,89 @@ class PreviewControl {
_onMouseDownBind = this._onMouseDown.bind(this);
_onMouseWheelBind = this._onMouseWheel.bind(this);
- constructor(name, method, canvas, image) {
- this._canvasElement = canvas;
- this._imageElement = image;
+ _onResetCameraBind = this._onResetCamera.bind(this);
+
+ enabledResetCamera = true;
+
+ /**
+ * create
+ * image
+ * - toolbar
+ * - button:reset-camera
+ * - canvas
+ * @param container - preview root
+ * @private
+ */
+ _createElements(container) {
+ this._container = container;
+
+ this._image = document.createElement('div');
+ this._image.classList.add('image');
+ this._image.style = `
+ height: var(--inspector-footer-preview-height, 200px);
+ overflow: hidden;
+ display: flex;
+ flex: 1;
+ `;
+ this._container.appendChild(this._image);
+
+ this._toolbar = document.createElement('div');
+ this._toolbar.classList.add('toolbar');
+ this._toolbar.style = `
+ display: flex;
+ `;
+ this._image.appendChild(this._toolbar);
+
+ if (this.enabledResetCamera) {
+ this._resetCamera = document.createElement('ui-button');
+ this._resetCamera.classList.add('reset-camera');
+ this._resetCamera.setAttribute('type', 'icon');
+ this._resetCamera.setAttribute('tooltip', 'i18n:ENGINE.inspector.preview.resetCameraView');
+ this._resetCamera.style = `
+ position: absolute;
+ right: 10px;
+ bottom: 10px;
+ `;
+ this._resetCamera.innerHTML = ``;
+ this._toolbar.appendChild(this._resetCamera);
+ }
+
+ this._canvas = document.createElement('canvas');
+ this._canvas.style = `
+ flex: 1;
+ `;
+ this._canvas.classList.add('canvas');
+ this._image.appendChild(this._canvas);
+ }
+
+ constructor(name, method, container) {
this._gLPreviewConfig = {
name: name,
method: method,
};
+ this._createElements(container);
}
async callPreviewFunction(funcName, ...args) {
- return await Editor.Message.request('scene', 'call-preview-function', this._gLPreviewConfig.name, funcName, ...args);
+ try {
+ const result = await Editor.Message.request('scene', 'call-preview-function', this._gLPreviewConfig.name, funcName, ...args);
+ this.doRefreshDirty();
+ return result;
+ } catch (e) {
+ console.error(e);
+ return null;
+ }
}
async init() {
const GLPreview = Editor._Module.require('PreviewExtends').default;
this._glPreview = new GLPreview(this._gLPreviewConfig.name, this._gLPreviewConfig.method);
await this._glPreview.init({
- width: this._canvasElement.clientWidth,
- height: this._canvasElement.clientHeight,
+ width: this._canvas.clientWidth,
+ height: this._canvas.clientHeight,
});
this._resizeObserver = new window.ResizeObserver(this._observerBind);
- this._resizeObserver.observe(this._imageElement);
+ this._resizeObserver.observe(this._image);
this._registerEventListener();
await this._refresh();
@@ -66,19 +132,21 @@ class PreviewControl {
}
close() {
- this._resizeObserver && this._resizeObserver.unobserve(this._imageElement);
+ this._resizeObserver && this._resizeObserver.unobserve(this._image);
cancelAnimationFrame(this._animationId);
this._unregisterEventListener();
}
_registerEventListener() {
- this._canvasElement.addEventListener('mousedown', this._onMouseDownBind);
- this._canvasElement.addEventListener('wheel', this._onMouseWheelBind);
+ this._resetCamera.addEventListener('click', this._onResetCameraBind);
+ this._canvas.addEventListener('mousedown', this._onMouseDownBind);
+ this._canvas.addEventListener('wheel', this._onMouseWheelBind);
}
_unregisterEventListener() {
- this._canvasElement.removeEventListener('mousedown', this._onMouseDownBind);
- this._canvasElement.removeEventListener('wheel', this._onMouseWheelBind);
+ this._resetCamera.removeEventListener('click', this._onResetCameraBind);
+ this._canvas.removeEventListener('mousedown', this._onMouseDownBind);
+ this._canvas.removeEventListener('wheel', this._onMouseWheelBind);
}
_observer() {
@@ -89,8 +157,8 @@ class PreviewControl {
if (this._isDirty) {
try {
this._isDirty = false;
- const canvas = this._canvasElement;
- const image = this._imageElement;
+ const canvas = this._canvas;
+ const image = this._image;
const width = image.clientWidth;
const height = image.clientHeight;
@@ -163,6 +231,13 @@ class PreviewControl {
this._isDirty = true;
}
+
+ _onResetCamera() {
+ this.callPreviewFunction('resetCameraView')
+ .then(() => {
+ this.doRefreshDirty();
+ });
+ }
}
module.exports = {