144 lines
3.8 KiB
JavaScript
144 lines
3.8 KiB
JavaScript
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
|
|
|
import { broker } from "../moto/broker.js";
|
|
import { target } from "./sketch.js";
|
|
|
|
class History {
|
|
#pos = -1;
|
|
#stack = [];
|
|
#offset; // store final drag move
|
|
#target; // store sketch drag target
|
|
#tracking = false;
|
|
|
|
constructor() {
|
|
broker.subscribe({
|
|
|
|
app_ready() {
|
|
this.#tracking = true
|
|
},
|
|
|
|
drag_start(selected) {},
|
|
|
|
drag(opt) {
|
|
this.#target = target();
|
|
this.#offset = opt.offset;
|
|
},
|
|
|
|
drag_end(selected) {
|
|
// console.log({
|
|
// drag_end: selected,
|
|
// offset: this.#offset,
|
|
// target: this.#target
|
|
// });
|
|
const { x, y, z } = this.#offset;
|
|
broker.publish('move', {
|
|
target: this.#target,
|
|
set: selected,
|
|
dx: x,
|
|
dy: y,
|
|
dz: z
|
|
});
|
|
},
|
|
|
|
move(data) {
|
|
const { target, set, dx, dy, dz } = data;
|
|
this.push('move', {
|
|
set, dx: -dx, dy: -dy, dz: -dz, target
|
|
}, {
|
|
set, dx, dy, dz, target
|
|
});
|
|
},
|
|
|
|
rotate(data) {
|
|
const { set, dx, dy, dz } = data;
|
|
this.push('rotate', {
|
|
set, dx: -dx, dy: -dy, dz: -dz
|
|
}, {
|
|
set, dx, dy, dz
|
|
});
|
|
},
|
|
|
|
scale(data) {
|
|
const { set, dx, dy, dz } = data;
|
|
this.push('scale', {
|
|
set, dx: 1/dx, dy: 1/dy, dz: 1/dz
|
|
}, {
|
|
set, dx, dy, dz
|
|
});
|
|
},
|
|
|
|
}, this);
|
|
}
|
|
|
|
push(type, undo, redo) {
|
|
this.#stack.length = ++this.#pos;
|
|
this.#stack.push({
|
|
type,
|
|
undo,
|
|
redo
|
|
});
|
|
}
|
|
|
|
// update(redo, undo) {
|
|
// let peek = this.#stack.peek();
|
|
// if (peek) {
|
|
// Object.assign(peek, {
|
|
// redo: redo || peek.redo,
|
|
// undo: undo || peek.undo
|
|
// });
|
|
// }
|
|
// }
|
|
|
|
do(type, data) {
|
|
// console.log({ type, data });
|
|
switch (type) {
|
|
case 'move': {
|
|
let { set, dx, dy, dz, target } = data;
|
|
for (let grp of set) {
|
|
grp.move(dx, dy, dz, target);
|
|
}
|
|
break;
|
|
}
|
|
// case 'position': {
|
|
// for (let { model, pos } of data) {
|
|
// model.position(...pos);
|
|
// }
|
|
// break;
|
|
// }
|
|
case 'rotate': {
|
|
let { set, dx, dy, dz } = data;
|
|
for (let grp of set) {
|
|
grp.rotate(dx, dy, dz);
|
|
}
|
|
break;
|
|
}
|
|
case 'scale': {
|
|
let { set, dx, dy, dz } = data;
|
|
for (let grp of set) {
|
|
grp.scale(dx, dy, dz);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
console.warn(`invalid record type: ${type}`);
|
|
}
|
|
}
|
|
|
|
undo() {
|
|
if (this.#pos >= 0) {
|
|
const rec = this.#stack[this.#pos--];
|
|
this.do(rec.type, rec.undo);
|
|
broker.publish("history_undo", rec);
|
|
}
|
|
}
|
|
|
|
redo() {
|
|
if (this.#stack.length && this.#pos >= -1 && this.#pos < this.#stack.length - 1) {
|
|
const rec = this.#stack[++this.#pos];
|
|
this.do(rec.type, rec.redo);
|
|
broker.publish("history_redo", rec);
|
|
}
|
|
}
|
|
}
|
|
|
|
export const history = new History();
|