TransformUnRedo.js 4.96 KB
import { EventDispatcher } from 'three';
import Undoredo from './Undoredo';

class MeshStatus {
    constructor({
        name = null,
        matrix = null,
        rotateCenter = null,
        finalRotateAngle = null,
        BoxHelper = null,
        allMesh = []
    }) {
        this.name = name;
        this.matrix = matrix;
        this.rotateCenter = rotateCenter;
        this.finalRotateAngle = finalRotateAngle;
        this.BoxHelper = BoxHelper;
        this.allMesh = allMesh;
    }
}

class TransformUnRedo extends Undoredo {
    constructor({ scene }) {
        super();
        this.scene = scene;
        this.eventDispatcher = new EventDispatcher();
        this.addEvents();
    }

    addEvents = () => {
        document.addEventListener('keydown', this.keydown);
    };

    removeEvents = () => {
        document.removeEventListener('keydown', this.keydown);
    };

    keydown = (e) => {
        if (e.ctrlKey) {
            switch (e.key) {
                case 'z':
                case 'Z':
                    this.doUndo();
                    break;
                case 'y':
                case 'Y':
                    this.doRedo();
                    break;
                default:
                    break;
            }
        }
    };

    getSelectedMeshes = () => {
        if (!this.scene) return [];
        return this.scene.children.filter((el) => el.name.includes('active:') && el.isMesh /*&& el.selected*/);
    };

    register = () => {
        const current_status = this.getCurrentStatus();
        if (current_status.length > 0) {
            this.currentStatusPush(current_status);
        }
        return {
            isCanUndo: this.isUndo(),
            isCanRedo: this.isRedo()
        };
    };

    doUndo = () => {
        const status = this.undo();
        if (status.length > 0) {
            const current_status = this.getCurrentStatus();
            this.redoPush(current_status);
            this.update(status, {
                isCanUndo: this.isUndo(),
                isCanRedo: this.isRedo()
            });
        }
    };

    doRedo = () => {
        const status = this.redo();
        if (status.length > 0) {
            const current_status = this.getCurrentStatus();
            this.undoPush(current_status);
            this.update(status, {
                isCanUndo: this.isUndo(),
                isCanRedo: this.isRedo()
            });
        }
    };

    getCurrentStatus = () => {
        const status = [];
        // const meshes = this.getSelectedMeshes();
        const allMesh = this.scene.children.filter((mesh) => mesh.name.includes('active:') && mesh.isMesh);
        allMesh.forEach((el) => {
            if (el.name && el.matrix && el.rotateCenter) {
                status.push(
                    new MeshStatus({
                        name: el.name,
                        matrix: el.matrix.clone(),
                        rotateCenter: el.rotateCenter.clone(),
                        finalRotateAngle: { ...el.finalRotateAngle },
                        BoxHelper: el.BoxHelper,
                        allMesh
                    })
                );
            }
        });
        if (allMesh.length === 0) {
            status.push(
                new MeshStatus({
                    name: null,
                    matrix: null,
                    rotateCenter: null,
                    finalRotateAngle: null,
                    BoxHelper: null,
                    allMesh: []
                })
            );
        }
        return status;
    };

    update = (status, UnRedoEnabled) => {
        const sceneMesh = this.scene.children.filter((el) => el.name.includes('active:') && el.isMesh);
        status.forEach((el) => {
            const { name, matrix, rotateCenter, finalRotateAngle, allMesh, BoxHelper } = el;
            const mesh = sceneMesh.find((object) => object.name === name);
            if (mesh && mesh.matrix && mesh.matrix !== matrix) {
                mesh.matrix.copy(matrix);
                mesh.rotateCenter.copy(rotateCenter);
                mesh.finalRotateAngle = finalRotateAngle;
                mesh.BoxHelper = BoxHelper;
            }
            if (sceneMesh.length > allMesh.length) {
                this.eventDispatcher.dispatchEvent({
                    type: 'removeMeshOnScene',
                    message: { sceneMesh, allMesh }
                });
            } else {
                const objects = allMesh.filter((element) => element.name === name);
                if (objects.length > 0) {
                    objects.forEach((object) => {
                        object.BoxHelper = BoxHelper;
                    });
                }
                this.eventDispatcher.dispatchEvent({
                    type: 'addMeshToScene',
                    message: { allMesh }
                });
            }
        });
        this.eventDispatcher.dispatchEvent({
            type: 'update',
            message: { UnRedoEnabled }
        });
    };
}

export default TransformUnRedo;