import { Command, FunctionCommand } from "./Command"; import { getLiquifyReferenceManager } from "../managers/LiquifyReferenceManager"; import { optimizeCanvasRendering } from "../utils/helper"; import { fabric } from "fabric-with-all"; /** * 液化命令基类 * 所有液化相关命令的基类 */ export class LiquifyCommand extends Command { /** * 创建液化命令 * @param {Object} options 配置选项 * @param {Object} options.canvas Fabric.js画布实例 * @param {Object} options.layerManager 图层管理器实例 * @param {Object} options.liquifyManager 液化管理器实例 * @param {String} options.mode 液化模式 * @param {Object} options.params 液化参数 * @param {Object} options.targetObject 目标对象 * @param {ImageData} options.originalData 原始图像数据 * @param {ImageData} options.resultData 变形后图像数据 */ constructor(options) { super({ name: options.name || `液化操作: ${options.mode || "未知模式"}`, description: options.description || `使用${options.mode || "未知模式"}模式进行液化操作`, }); this.canvas = options.canvas; this.layerManager = options.layerManager; this.liquifyManager = options.liquifyManager; this.mode = options.mode; this.params = options.params || {}; this.targetObject = options.targetObject; this.targetLayerId = options.targetLayerId; this.originalData = options.originalData; // 操作前的图像数据 this.resultData = options.resultData; // 操作后的图像数据 this.savedState = null; } /** * 执行液化操作 * @returns {Promise} 执行结果 */ async execute() { if (!this.canvas || !this.targetObject) { throw new Error("液化命令缺少必要的画布或目标对象"); } if (!this.resultData) { // 如果没有预先计算的结果数据,现场执行变形 this.resultData = await this.liquifyManager.applyLiquify( this.targetObject, this.mode, this.params ); } // 保存执行前的状态 this.savedState = await this._saveObjectState(); // 更新画布上的对象 await this._updateObjectWithResult(); // 注意:_updateObjectWithResult 内部已使用 optimizeCanvasRendering,会自动渲染 return this.resultData; } /** * 撤销液化操作 * @returns {Promise} 撤销结果 */ async undo() { if (!this.canvas || !this.targetObject || !this.savedState) { throw new Error("无法撤销:缺少必要的状态信息"); } // 恢复对象到原始状态 await this._restoreObjectState(); // 刷新Canvas this.canvas.renderAll(); return true; } /** * 保存对象状态 * @private */ async _saveObjectState() { if (!this.targetObject) return null; // 对于图像对象,我们需要保存src和元数据 const state = { src: this.targetObject.getSrc ? this.targetObject.getSrc() : null, element: this.targetObject._element ? this.targetObject._element.cloneNode(true) : null, filters: this.targetObject.filters ? [...this.targetObject.filters] : [], originalData: this.originalData, targetLayerId: this.targetLayerId, }; return state; } /** * 恢复对象状态 * @private */ async _restoreObjectState() { if (!this.targetObject || !this.savedState) return false; // 获取当前图层对象 const layer = this.layerManager.getLayerById(this.savedState.targetLayerId); if (!layer) return false; // 恢复原始图像 if (this.savedState.element && this.targetObject.setElement) { this.targetObject.setElement(this.savedState.element); // 恢复滤镜 if (this.savedState.filters) { this.targetObject.filters = [...this.savedState.filters]; this.targetObject.applyFilters(); } } return true; } /** * 使用变形结果更新对象 * 优化:直接使用 setElement 更新现有对象,避免创建新对象和替换操作 * @private */ async _updateObjectWithResult() { if (!this.targetObject || !this.resultData) return false; // 创建临时canvas来渲染结果数据 const tempCanvas = document.createElement("canvas"); tempCanvas.width = this.resultData.width; tempCanvas.height = this.resultData.height; const tempCtx = tempCanvas.getContext("2d"); tempCtx.putImageData(this.resultData, 0, 0); console.log("临时Canvas创建成功 _updateObjectWithResult", this.resultData); // 使用优化渲染工具,避免图层闪烁 await optimizeCanvasRendering(this.canvas, async () => { // 预加载图像元素,确保完全加载后再更新 await this._updateObjectElementDirectly(tempCanvas.toDataURL()); }); return true; } /** * 直接更新对象的图像元素,避免对象替换造成的图层闪烁 * @param {String} imageDataURL 图像数据的 DataURL * @private */ async _updateObjectElementDirectly(imageDataURL) { return new Promise((resolve, reject) => { // 创建 HTMLImageElement 并预加载 const imgElement = new Image(); imgElement.onload = () => { try { // 保存当前对象状态(非图像属性) const currentState = { left: this.targetObject.left, top: this.targetObject.top, scaleX: this.targetObject.scaleX, scaleY: this.targetObject.scaleY, angle: this.targetObject.angle, flipX: this.targetObject.flipX, flipY: this.targetObject.flipY, opacity: this.targetObject.opacity, }; // 直接更新现有对象的图像元素,保持对象引用不变 if (this.targetObject.setElement) { this.targetObject.setElement(imgElement); } else if (this.targetObject._element) { this.targetObject._element = imgElement; this.targetObject._originalElement = imgElement; } // 恢复对象属性(setElement 可能会重置一些属性) this.targetObject.set(currentState); // 标记对象需要重新渲染 this.targetObject.dirty = true; this.targetObject.setCoords(); resolve(); } catch (error) { console.error("更新对象元素失败:", error); reject(error); } }; imgElement.onerror = () => { reject(new Error("图像加载失败")); }; // 开始加载图像 imgElement.src = imageDataURL; }); } /** * 安全地替换对象,避免图层闪烁(保留作为备用方法) * @param {Object} newImg 新的fabric图像对象 * @private */ _replaceObjectSafely(newImg) { // 保存旧对象引用,用于更新图层引用 const oldObject = this.targetObject; // 替换Canvas上的对象 const index = this.canvas.getObjects().indexOf(oldObject); if (index !== -1) { // 在禁用自动渲染的情况下,先插入新对象,再移除旧对象 // 这样可以避免中间出现空白(因为renderOnAddRemove已被禁用) this.canvas.insertAt(newImg, index); this.canvas.remove(oldObject); this.targetObject = newImg; } // 确保图层引用更新 const layer = this.layerManager.getLayerById(this.targetLayerId); if (layer) { if (layer.type === "background" && layer.fabricObject === oldObject) { layer.fabricObject = newImg; } else if (layer.fabricObjects) { const objIndex = layer.fabricObjects.indexOf(oldObject); if (objIndex !== -1) { layer.fabricObjects[objIndex] = newImg; } } } } } /** * 液化工具初始化命令 * 用于初始化液化工具的状态,不执行实际操作 */ export class InitLiquifyToolCommand extends Command { constructor(options) { super({ name: "初始化液化工具", description: "准备液化工具工作环境", undoable: false, // 这个命令不需要撤销 }); this.canvas = options.canvas; this.layerManager = options.layerManager; this.liquifyManager = options.liquifyManager; this.toolManager = options.toolManager; } /** * 执行初始化 */ execute() { if (this.liquifyManager) { this.liquifyManager.initialize({ canvas: this.canvas, layerManager: this.layerManager, }); } // 通知各管理器进入液化模式 this.toolManager?.notifyObservers("LIQUIFY"); return true; } undo() { // 不需要撤销初始化 return true; } } /** * 液化操作命令 - 针对单次变形操作 * 用于实现可撤销的单次液化变形 */ export class LiquifyDeformCommand extends LiquifyCommand { /** * 创建液化变形命令 * @param {Object} options 配置选项 * @param {Number} options.x 变形中心X坐标 * @param {Number} options.y 变形中心Y坐标 * @param {ImageData} options.beforeData 变形前的图像数据 * @param {ImageData} options.afterData 变形后的图像数据 */ constructor(options) { super({ ...options, name: `液化变形: ${options.mode || "未知模式"}`, description: `在(${options.x}, ${options.y})应用${options.mode || "未知模式"}变形`, }); this.x = options.x; this.y = options.y; this.beforeData = options.beforeData; this.afterData = options.afterData; } async execute() { if (!this.afterData) { // 如果没有预计算的结果,实时计算 await this.liquifyManager.prepareForLiquify(this.targetObject); this.afterData = await this.liquifyManager.applyLiquify( this.targetObject, this.mode, this.params, this.x, this.y ); } // 保存当前状态 this.savedState = await this._saveObjectState(); // 应用变形结果 await this._updateObjectWithImageData(this.afterData); // 注意:_updateObjectWithImageData 内部已使用 optimizeCanvasRendering,会自动渲染 return this.afterData; } async undo() { if (!this.beforeData) { throw new Error("无法撤销:缺少变形前的数据"); } // 恢复到变形前的状态 await this._updateObjectWithImageData(this.beforeData); // 注意:_updateObjectWithImageData 内部已使用 optimizeCanvasRendering,会自动渲染 return true; } /** * 使用图像数据更新对象 * 优化:直接使用 setElement 更新现有对象,避免创建新对象和替换操作 * @param {ImageData} imageData 图像数据 * @private */ async _updateObjectWithImageData(imageData) { // 创建临时canvas const tempCanvas = document.createElement("canvas"); tempCanvas.width = imageData.width; tempCanvas.height = imageData.height; const tempCtx = tempCanvas.getContext("2d"); tempCtx.putImageData(imageData, 0, 0); // 使用优化渲染工具,避免图层闪烁 await optimizeCanvasRendering(this.canvas, async () => { // 直接更新对象元素,避免对象替换 await this._updateObjectElementDirectly(tempCanvas.toDataURL()); }); } /** * 安全地替换变形对象,避免图层闪烁(保留作为备用方法) * @param {Object} newImg 新的fabric图像对象 * @private */ _replaceDeformObjectSafely(newImg) { // 保存旧对象引用,用于更新图层引用 const oldObject = this.targetObject; // 替换Canvas上的对象 const index = this.canvas.getObjects().indexOf(oldObject); if (index !== -1) { // 在禁用自动渲染的情况下,先插入新对象,再移除旧对象 // 这样可以避免中间出现空白 this.canvas.insertAt(newImg, index); this.canvas.remove(oldObject); this.targetObject = newImg; } // 更新图层引用 const layer = this.layerManager.getLayerById(this.targetLayerId); if (layer) { if ( layer.type === "background" && (layer.fabricObject === this.savedState?.originalObject || layer.fabricObject === oldObject) ) { layer.fabricObject = newImg; } else if (layer.fabricObjects) { const objIndex = layer.fabricObjects.findIndex( (obj) => obj === this.savedState?.originalObject || obj === oldObject ); if (objIndex !== -1) { layer.fabricObjects[objIndex] = newImg; } } } } } /** * 复合液化命令 - 用于组合多个液化操作 * 支持一次撤销多个相关的液化变形 */ export class CompositeLiquifyCommand extends Command { /** * 创建复合液化命令 * @param {Object} options 配置选项 * @param {Array} options.commands 子命令列表 * @param {String} options.name 命令名称 */ constructor(options) { super({ name: options.name || "液化操作组合", description: options.description || `包含${options.commands?.length || 0}个液化操作`, }); this.commands = options.commands || []; this.canvas = options.canvas; this.layerManager = options.layerManager; this.liquifyManager = options.liquifyManager; } /** * 添加子命令 * @param {Command} command 要添加的命令 */ addCommand(command) { this.commands.push(command); } async execute() { const results = []; for (const command of this.commands) { try { const result = await command.execute(); results.push(result); } catch (error) { // 如果有命令失败,尝试回滚已执行的命令 console.error("复合液化命令执行失败:", error); await this.undo(); throw error; } } return results; } async undo() { // 逆序撤销所有子命令 const errors = []; for (let i = this.commands.length - 1; i >= 0; i--) { try { await this.commands[i].undo(); } catch (error) { console.error(`撤销子命令${i}失败:`, error); errors.push(error); } } if (errors.length > 0) { throw new Error(`复合命令撤销部分失败: ${errors.length}个错误`); } return true; } /** * 检查命令是否可以执行 * @returns {Boolean} 是否可执行 */ canExecute() { return ( this.commands.length > 0 && this.commands.every((cmd) => (cmd.canExecute ? cmd.canExecute() : true)) ); } } /** * 液化重置命令 - 将图像恢复到原始状态 */ export class LiquifyResetCommand extends LiquifyCommand { constructor(options) { super({ ...options, name: "重置液化", description: "将图像恢复到液化前的原始状态", }); } async execute() { if (!this.liquifyManager || !this.targetObject) { throw new Error("无法重置:缺少必要的管理器或目标对象"); } // 保存当前状态 this.savedState = await this._saveObjectState(); // 重置液化管理器 const resetData = this.liquifyManager.reset(); if (!resetData) { throw new Error("重置失败:没有原始数据"); } // 应用重置结果 await this._updateObjectWithResult(); this.canvas.renderAll(); return resetData; } } /** * 液化状态命令 - 最优化版本 * 使用引用管理器避免对象引用丢失,支持高性能的状态管理 */ export class LiquifyStateCommand extends Command { /** * 创建液化状态命令 * @param {Object} options 配置选项 * @param {Object} options.canvas Fabric.js画布实例 * @param {Object} options.layerManager 图层管理器实例 * @param {Object} options.targetObject 目标对象(保持引用) * @param {String} options.targetLayerId 目标图层ID * @param {ImageData} options.initialImageData 初始图像数据 * @param {ImageData} options.finalImageData 最终图像数据 * @param {Object} options.liquifyManager 液化管理器实例 */ constructor(options) { super({ name: options.name || "液化操作", description: options.description || "液化变形操作的状态记录", }); this.canvas = options.canvas; this.layerManager = options.layerManager; this.targetObject = options.targetObject; this.targetLayerId = options.targetLayerId; this.targetObjectId = options.targetObjectId; this.liquifyManager = options.liquifyManager; // 添加液化管理器引用 // 获取引用管理器实例 this.refManager = getLiquifyReferenceManager(); // 实时更新实例 this.realtimeUpdater = options.realtimeUpdater || null; // 注册对象到引用管理器 this.objectRefId = this.refManager.registerObject( this.targetObject, this.targetObjectId || `liquify_${Date.now()}` ); // 保存状态快照ID this.initialSnapshotId = null; this.finalSnapshotId = null; // 设置图像数据 this.initialImageData = options.initialImageData; this.finalImageData = options.finalImageData; // 保存液化管理器的操作记录状态 this.initialLiquifyState = null; this.finalLiquifyState = null; this.currentState = "initial"; // 创建初始快照 if (this.initialImageData) { this._createInitialSnapshot(); } } /** * 执行命令 - 应用最终状态 */ async execute() { if (!this.finalImageData) { throw new Error("缺少最终状态数据"); } // 确保有最终状态快照 if (!this.finalSnapshotId) { await this._createFinalSnapshot(); } // 通过引用管理器更新图像数据 await this.refManager.updateObjectImageData(this.objectRefId, this.finalImageData); // 恢复液化管理器到最终状态 if (this.liquifyManager && this.finalLiquifyState) { this._restoreLiquifyManagerState(this.finalLiquifyState); } else if (this.liquifyManager) { // 如果没有保存的最终状态,重新准备液化环境 const currentTarget = this.refManager.getObjectRef(this.objectRefId); if (currentTarget) { await this.liquifyManager.prepareForLiquify(currentTarget); // 保存当前的液化管理器状态作为最终状态 this.finalLiquifyState = this._captureLiquifyManagerState(); } } this.currentState = "final"; this.canvas.renderAll(); console.log("✅ 液化命令执行完成,应用最终状态"); return true; } /** * 撤销命令 - 恢复初始状态 */ async undo() { if (!this.initialImageData || !this.initialSnapshotId) { throw new Error("缺少初始状态数据或快照"); } // 通过引用管理器恢复到初始快照 await this.refManager.restoreFromSnapshot(this.objectRefId, this.initialSnapshotId); // 恢复液化管理器到初始状态 - 关键修复 if (this.liquifyManager) { // if (this.initialLiquifyState) { // this._restoreLiquifyManagerState(this.initialLiquifyState); // } else { // 如果没有初始状态,重置液化管理器并重新初始化 this.liquifyManager.reset(); const currentTarget = this.refManager.getObjectRef(this.objectRefId); if (currentTarget) { // 重新准备液化环境,使用初始图像数据 await this.liquifyManager.prepareForLiquify(currentTarget); // 强制设置原始图像数据为初始状态 if (this.liquifyManager.enhancedManager) { this.liquifyManager.enhancedManager.originalImageData = this.initialImageData; this.liquifyManager.enhancedManager.currentImageData = this._cloneImageData( this.initialImageData ); // 重置激活渲染器的数据 if (this.liquifyManager.enhancedManager.activeRenderer) { const renderer = this.liquifyManager.enhancedManager.activeRenderer; renderer.originalImageData = this.initialImageData; renderer.currentImageData = this._cloneImageData(this.initialImageData); // 重置CPU渲染器的网格和变形历史 if (renderer.reset) { renderer.reset(); } // } } } } // 确保实时更新器使用正确的目标对象和初始数据 if (this.realtimeUpdater) { const currentTarget = this.refManager.getObjectRef(this.objectRefId); this.realtimeUpdater.targetObject = currentTarget; // 重置实时更新器的内部状态 if (this.realtimeUpdater.reset) { this.realtimeUpdater.reset(); } } } this.currentState = "initial"; this.canvas.renderAll(); console.log("🔄 液化命令撤销完成,恢复初始状态(已重置所有内部状态)"); return true; } /** * 重做命令 - 重新应用最终状态 */ async redo() { return this.execute(); } /** * 设置最终状态的图像数据 * @param {ImageData} finalImageData 最终状态的图像数据 */ setFinalImageData(finalImageData) { this.finalImageData = finalImageData; this.finalSnapshotId = null; // 重置快照ID,下次执行时重新创建 // 捕获当前液化管理器状态作为最终状态 if (this.liquifyManager) { this.finalLiquifyState = this._captureLiquifyManagerState(); } } /** * 获取当前状态标记 * @returns {String} 'initial' 或 'final' */ getCurrentState() { return this.currentState; } /** * 检查命令是否有效 * @returns {Boolean} 是否有效 */ isValid() { const targetObject = this.refManager.getObjectRef(this.objectRefId); return !!(targetObject && this.initialImageData && this.finalImageData); } /** * 获取目标对象的当前引用 * @returns {Object|null} Fabric对象 */ getTargetObject() { return this.refManager.getObjectRef(this.objectRefId); } /** * 清理资源 */ dispose() { if (this.objectRefId) { // 清理快照 if (this.initialSnapshotId) { this.refManager.stateSnapshots.delete(this.initialSnapshotId); } if (this.finalSnapshotId) { this.refManager.stateSnapshots.delete(this.finalSnapshotId); } // 注意:不要清理对象引用,因为可能有其他命令在使用 console.log(`🗑️ 液化状态命令资源已清理: ${this.objectRefId}`); } } /** * 获取内存使用统计 * @returns {Object} 统计信息 */ getMemoryStats() { const refManagerStats = this.refManager.getMemoryStats(); const commandMemory = this._calculateCommandMemory(); return { ...refManagerStats, commandMemory, totalCommandMemory: commandMemory, }; } // 私有方法 /** * 创建初始状态快照 * @private */ async _createInitialSnapshot() { if (!this.initialImageData) return; this.initialSnapshotId = `${this.objectRefId}_initial_${Date.now()}`; // 手动创建初始快照,包含图像数据 const fabricObject = this.refManager.getObjectRef(this.objectRefId); if (fabricObject) { const snapshot = { timestamp: Date.now(), properties: this.refManager._captureObjectState(fabricObject), imageData: this.initialImageData, eventListeners: this.refManager.eventListeners.get(this.objectRefId) || {}, }; this.refManager.stateSnapshots.set(this.initialSnapshotId, snapshot); // 捕获初始液化管理器状态 if (this.liquifyManager) { this.initialLiquifyState = this._captureLiquifyManagerState(); } console.log(`📸 初始状态快照已创建: ${this.initialSnapshotId}`); } } /** * 创建最终状态快照 * @private */ async _createFinalSnapshot() { if (!this.finalImageData) return; this.finalSnapshotId = `${this.objectRefId}_final_${Date.now()}`; // 手动创建最终快照,包含图像数据 const fabricObject = this.refManager.getObjectRef(this.objectRefId); if (fabricObject) { const snapshot = { timestamp: Date.now(), properties: this.refManager._captureObjectState(fabricObject), imageData: this.finalImageData, eventListeners: this.refManager.eventListeners.get(this.objectRefId) || {}, }; this.refManager.stateSnapshots.set(this.finalSnapshotId, snapshot); // 捕获最终液化管理器状态 if (this.liquifyManager) { this.finalLiquifyState = this._captureLiquifyManagerState(); } console.log(`📸 最终状态快照已创建: ${this.finalSnapshotId}`); } } /** * 捕获液化管理器的当前状态 * @returns {Object} 液化管理器状态 * @private */ _captureLiquifyManagerState() { if (!this.liquifyManager) return null; try { const enhancedManager = this.liquifyManager.enhancedManager; const state = { // 捕获增强管理器状态 enhancedManagerState: null, // 捕获当前渲染器状态 activeRendererState: null, // 捕获目标对象引用 targetObjectRef: this.liquifyManager.targetObject ?? enhancedManager.targetObject, // 捕获初始化状态 initialized: this.liquifyManager.initialized || false, }; // 如果有增强管理器,捕获其状态 if (this.liquifyManager.enhancedManager) { state.enhancedManagerState = { initialized: enhancedManager.initialized, renderMode: enhancedManager.renderMode, targetObject: enhancedManager.targetObject, originalImageData: enhancedManager.originalImageData, currentImageData: enhancedManager.currentImageData, params: { ...enhancedManager.params }, currentMode: enhancedManager.currentMode, }; // 如果有激活的渲染器,捕获其状态 if (enhancedManager.activeRenderer) { const renderer = enhancedManager.activeRenderer; state.activeRendererState = { initialized: renderer.initialized, originalImageData: renderer.originalImageData, currentImageData: renderer.currentImageData, params: { ...renderer.params }, currentMode: renderer.currentMode, // 对于CPU渲染器,还需要保存网格状态 meshState: renderer.mesh ? this._captureMeshState(renderer.mesh) : null, // 保存变形历史 deformHistory: renderer.deformHistory ? [...renderer.deformHistory] : [], }; } } console.log(`💾 液化管理器状态已捕获:`, state); return state; } catch (error) { console.error("捕获液化管理器状态失败:", error); return null; } } /** * 恢复液化管理器状态 * @param {Object} state 要恢复的状态 * @private */ _restoreLiquifyManagerState(state) { if (!this.liquifyManager || !state) return; try { // 恢复基本状态 this.liquifyManager.initialized = state.initialized; if (state.targetObjectRef) { this.liquifyManager.targetObject = state.targetObjectRef; } // 确保实时更新器使用正确的目标对象 if (this.realtimeUpdater) { this.realtimeUpdater.targetObject = this.liquifyManager.targetObject; // 如果有setTargetObject方法,调用它 if (typeof this.realtimeUpdater.setTargetObject === "function") { this.realtimeUpdater.setTargetObject(this.liquifyManager.targetObject); } } // 恢复增强管理器状态 if (state.enhancedManagerState && this.liquifyManager.enhancedManager) { const enhancedManager = this.liquifyManager.enhancedManager; const enhancedState = state.enhancedManagerState; enhancedManager.initialized = enhancedState.initialized; enhancedManager.renderMode = enhancedState.renderMode; enhancedManager.targetObject = enhancedState.targetObject; // 关键修复:确保图像数据被正确恢复 enhancedManager.originalImageData = enhancedState.originalImageData; enhancedManager.currentImageData = enhancedState.currentImageData; enhancedManager.params = { ...enhancedState.params }; enhancedManager.currentMode = enhancedState.currentMode; // 恢复激活渲染器状态 if (state.activeRendererState && enhancedManager.activeRenderer) { const renderer = enhancedManager.activeRenderer; const rendererState = state.activeRendererState; renderer.initialized = rendererState.initialized; // 关键修复:强制重置渲染器的图像数据 renderer.originalImageData = rendererState.originalImageData; renderer.currentImageData = rendererState.currentImageData; renderer.params = { ...rendererState.params }; renderer.currentMode = rendererState.currentMode; // 恢复网格状态(如果是CPU渲染器) if (rendererState.meshState && renderer.mesh) { this._restoreMeshState(renderer.mesh, rendererState.meshState); } else if (renderer.mesh && renderer._initMesh) { // 如果没有保存的网格状态,重新初始化网格 renderer._initMesh( rendererState.originalImageData?.width || renderer.originalImageData?.width, rendererState.originalImageData?.height || renderer.originalImageData?.height ); } // 重置变形历史 if (rendererState.deformHistory) { renderer.deformHistory = [...rendererState.deformHistory]; } else { // 如果没有保存的历史,清空变形历史 renderer.deformHistory = []; } // 重置持续按压相关状态(如果存在) if (renderer.isHolding !== undefined) { renderer.isHolding = false; renderer.pressStartTime = 0; renderer.pressDuration = 0; renderer.accumulatedRotation = 0; renderer.accumulatedScale = 0; renderer.lastApplyTime = 0; } // 重置拖拽状态(如果存在) if (renderer.isDragging !== undefined) { renderer.isDragging = false; renderer.dragDistance = 0; renderer.dragAngle = 0; renderer.isFirstApply = true; } } } console.log(`🔄 液化管理器状态已恢复(包含完整的数据重置)`); } catch (error) { console.error("恢复液化管理器状态失败:", error); } } /** * 捕获网格状态 * @param {Array} mesh 网格数组 * @returns {Array} 网格状态副本 * @private */ _captureMeshState(mesh) { if (!mesh || !Array.isArray(mesh)) return null; return mesh.map((row) => row.map((point) => ({ x: point.x, y: point.y, originalX: point.originalX, originalY: point.originalY, })) ); } /** * 恢复网格状态 * @param {Array} mesh 目标网格 * @param {Array} meshState 要恢复的网格状态 * @private */ _restoreMeshState(mesh, meshState) { if (!mesh || !meshState || !Array.isArray(mesh) || !Array.isArray(meshState)) return; for (let i = 0; i < Math.min(mesh.length, meshState.length); i++) { for (let j = 0; j < Math.min(mesh[i].length, meshState[i].length); j++) { const point = mesh[i][j]; const statePoint = meshState[i][j]; point.x = statePoint.x; point.y = statePoint.y; point.originalX = statePoint.originalX; point.originalY = statePoint.originalY; } } } /** * 克隆图像数据 * @param {ImageData} imageData 原始图像数据 * @returns {ImageData} 克隆的图像数据 * @private */ _cloneImageData(imageData) { if (!imageData) return null; try { // 使用新的浏览器API直接复制 return new ImageData( new Uint8ClampedArray(imageData.data), imageData.width, imageData.height ); } catch (e) { console.warn("使用备选方法克隆ImageData"); // 备选方法 const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = imageData.width; canvas.height = imageData.height; ctx.putImageData(imageData, 0, 0); return ctx.getImageData(0, 0, imageData.width, imageData.height); } } } /** * 批量液化状态命令 - 用于处理多个对象的液化操作 */ export class BatchLiquifyStateCommand extends Command { /** * 创建批量液化状态命令 * @param {Object} options 配置选项 * @param {Array} options.commands 液化状态命令列表 * @param {Object} options.canvas Fabric.js画布实例 */ constructor(options) { super({ name: options.name || "批量液化操作", description: options.description || `批量液化${options.commands?.length || 0}个对象`, }); this.commands = options.commands || []; this.canvas = options.canvas; this.refManager = getLiquifyReferenceManager(); } /** * 添加液化状态命令 * @param {LiquifyStateCommand} command 液化状态命令 */ addCommand(command) { this.commands.push(command); } /** * 执行批量操作 */ async execute() { const results = []; const updates = []; // 准备批量更新数据 for (const command of this.commands) { if (command.finalImageData && command.objectRefId) { updates.push({ refId: command.objectRefId, imageData: command.finalImageData, }); } } // 执行批量更新 if (updates.length > 0) { const updateResults = await this.refManager.batchUpdate(updates); results.push(...updateResults); } // 更新命令状态 this.commands.forEach((command) => { command.currentState = "final"; }); this.canvas.renderAll(); return results; } /** * 撤销批量操作 */ async undo() { // 逆序撤销 for (let i = this.commands.length - 1; i >= 0; i--) { await this.commands[i].undo(); } this.canvas.renderAll(); return true; } /** * 重做批量操作 */ async redo() { return this.execute(); } /** * 检查批量命令是否有效 * @returns {Boolean} 是否有效 */ isValid() { return this.commands.length > 0 && this.commands.every((cmd) => cmd.isValid()); } /** * 清理所有子命令的资源 */ dispose() { this.commands.forEach((command) => { if (command.dispose) { command.dispose(); } }); } } /** * 序列化fabric对象为JSON * @param {Object} fabricObject fabric对象 * @returns {Object} 序列化后的对象状态 */ export function serializeFabricObject(fabricObject) { if (!fabricObject) { throw new Error("无法序列化:对象为空"); } try { // 使用fabric.js的toObject方法序列化 const serializedObject = fabricObject.toObject([ "id", "objectId", "uid", "layerId", "name", "type", ]); // 记录额外的元数据 const metadata = { timestamp: Date.now(), objectType: fabricObject.type, objectId: fabricObject.id || fabricObject.objectId || fabricObject.uid, layerId: fabricObject.layerId, bounds: fabricObject.getBoundingRect(), }; return { serializedObject, metadata, version: "1.0", }; } catch (error) { console.error("序列化fabric对象失败:", error); throw error; } } /** * 辅助函数:创建液化状态命令 * @param {Object} options 配置选项 * @returns {LiquifyStateCommand} 状态命令实例 */ export function createLiquifyStateCommand(options) { return new LiquifyStateCommand(options); } /** * 辅助函数:创建液化重置命令 * @param {Object} options 配置选项 * @returns {LiquifyResetCommand} 重置命令实例 */ export function createLiquifyResetCommand(options) { return new LiquifyResetCommand(options); } /** * 辅助函数:创建液化变形命令 * @param {Object} options 配置选项 * @returns {LiquifyDeformCommand} 变形命令实例 */ export function createLiquifyDeformCommand(options) { return new LiquifyDeformCommand(options); } /** * 辅助函数:创建复合液化命令 * @param {Object} options 配置选项 * @returns {CompositeLiquifyCommand} 复合命令实例 */ export function createCompositeLiquifyCommand(options) { return new CompositeLiquifyCommand(options); }