fix undo/redo for scale/rotate/move
This commit is contained in:
parent
4e1cacc805
commit
be8247c1a6
3 changed files with 84 additions and 48 deletions
|
|
@ -255,8 +255,7 @@ const selection = {
|
||||||
|
|
||||||
scale(dx = 0, dy = 0, dz = 0) {
|
scale(dx = 0, dy = 0, dz = 0) {
|
||||||
for (let s of selection.groups()) {
|
for (let s of selection.groups()) {
|
||||||
let { x, y, z } = s.scale();
|
s.scale(dx, dy, dz);
|
||||||
s.scale(x * dx, y * dy, z * dz);
|
|
||||||
}
|
}
|
||||||
broker.publish('scale', { set: selection.groups(), dx, dy, dz });
|
broker.publish('scale', { set: selection.groups(), dx, dy, dz });
|
||||||
return selection;
|
return selection;
|
||||||
|
|
@ -1480,7 +1479,7 @@ let dbug = self.dbug = self.dbug || {
|
||||||
const api = {
|
const api = {
|
||||||
init() {
|
init() {
|
||||||
// publish messages when api functions are called
|
// publish messages when api functions are called
|
||||||
// broker.wrapObject(selection, 'selection');
|
broker.wrapObject(selection, 'selection');
|
||||||
// broker.wrapObject(model, 'model');
|
// broker.wrapObject(model, 'model');
|
||||||
// broker.wrapObject(group, 'group');
|
// broker.wrapObject(group, 'group');
|
||||||
|
|
||||||
|
|
@ -1519,8 +1518,12 @@ const api = {
|
||||||
},
|
},
|
||||||
|
|
||||||
history: {
|
history: {
|
||||||
undo() { history.undo() },
|
undo() {
|
||||||
redo() { history.redo() }
|
history.undo();
|
||||||
|
},
|
||||||
|
redo() {
|
||||||
|
history.redo();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// @param object {THREE.Object3D | THREE.Object3D[] | Point}
|
// @param object {THREE.Object3D | THREE.Object3D[] | Point}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ const isDebug = api.isDebug;
|
||||||
|
|
||||||
let call = broker.send;
|
let call = broker.send;
|
||||||
let rad = 180 / Math.PI;
|
let rad = 180 / Math.PI;
|
||||||
|
let deg = Math.PI / 180;
|
||||||
let und = undefined;
|
let und = undefined;
|
||||||
|
|
||||||
broker.listeners({
|
broker.listeners({
|
||||||
|
|
@ -765,23 +766,14 @@ function ui_build() {
|
||||||
function field_edit(title, set, opt = {}) {
|
function field_edit(title, set, opt = {}) {
|
||||||
return function(ev) {
|
return function(ev) {
|
||||||
let floor = api.prefs.map.space.floor !== false;
|
let floor = api.prefs.map.space.floor !== false;
|
||||||
let value = ev.target.innerText;
|
let value = parseFloat(ev.target.innerText);
|
||||||
let onclick = (ev) => {
|
let onclick = (ev) => {
|
||||||
let tempval = parseFloat($('tempval').value);
|
let tempval = parseFloat($('tempval').value);
|
||||||
api.modal.hide(modal.info.cancelled);
|
api.modal.hide(modal.info.cancelled);
|
||||||
if (modal.info.cancelled) {
|
if (modal.info.cancelled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (opt.sketch) {
|
set(tempval, value);
|
||||||
defer_selection();
|
|
||||||
return set(tempval, value);
|
|
||||||
}
|
|
||||||
for (let g of api.selection.groups()) {
|
|
||||||
set(g, tempval, value);
|
|
||||||
if (floor && opt.floor !== false) {
|
|
||||||
g.floor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer_selection();
|
defer_selection();
|
||||||
};
|
};
|
||||||
let onkeydown = (ev) => {
|
let onkeydown = (ev) => {
|
||||||
|
|
@ -988,39 +980,39 @@ function ui_build() {
|
||||||
// bind rotation editable fields
|
// bind rotation editable fields
|
||||||
let { group_val_X_rot, group_val_Y_rot, group_val_Z_rot } = bound;
|
let { group_val_X_rot, group_val_Y_rot, group_val_Z_rot } = bound;
|
||||||
editable(group_val_X_rot, group_val_Y_rot, group_val_Z_rot);
|
editable(group_val_X_rot, group_val_Y_rot, group_val_Z_rot);
|
||||||
group_val_X_rot.onclick = field_edit('x rotation', (group, val) => {
|
group_val_X_rot.onclick = field_edit('x rotation', (val) => {
|
||||||
group.rotate(val,0,0);
|
selection.rotate(val * deg,0,0);
|
||||||
});
|
});
|
||||||
group_val_Y_rot.onclick = field_edit('y rotation', (group, val) => {
|
group_val_Y_rot.onclick = field_edit('y rotation', (val) => {
|
||||||
group.rotate(0,val,0);
|
selection.rotate(0,val * deg,0);
|
||||||
});
|
});
|
||||||
group_val_Z_rot.onclick = field_edit('z rotation', (group, val) => {
|
group_val_Z_rot.onclick = field_edit('z rotation', (val) => {
|
||||||
group.rotate(0,0,val);
|
selection.rotate(0,0,val * deg);
|
||||||
});
|
});
|
||||||
|
|
||||||
// bind position editable fields
|
// bind position editable fields
|
||||||
let { group_val_X_pos, group_val_Y_pos, group_val_Z_pos } = bound;
|
let { group_val_X_pos, group_val_Y_pos, group_val_Z_pos } = bound;
|
||||||
editable(group_val_X_pos, group_val_Y_pos, group_val_Z_pos);
|
editable(group_val_X_pos, group_val_Y_pos, group_val_Z_pos);
|
||||||
group_val_X_pos.onclick = field_edit('x position', (group, val) => {
|
group_val_X_pos.onclick = field_edit('x position', (val) => {
|
||||||
selection.move_models(val,0,0);
|
selection.move_models(val,0,0);
|
||||||
}, { floor: false });
|
}, { floor: false });
|
||||||
group_val_Y_pos.onclick = field_edit('y position', (group, val) => {
|
group_val_Y_pos.onclick = field_edit('y position', (val) => {
|
||||||
selection.move_models(0,val,0);
|
selection.move_models(0,val,0);
|
||||||
}, { floor: false });
|
}, { floor: false });
|
||||||
group_val_Z_pos.onclick = field_edit('z position', (group, val) => {
|
group_val_Z_pos.onclick = field_edit('z position', (val) => {
|
||||||
selection.move_models(0,0,val);
|
selection.move_models(0,0,val);
|
||||||
}, { floor: false });
|
}, { floor: false });
|
||||||
|
|
||||||
// bind center editable fields
|
// bind center editable fields
|
||||||
let { span_val_X_center, span_val_Y_center, span_val_Z_center } = bound;
|
let { span_val_X_center, span_val_Y_center, span_val_Z_center } = bound;
|
||||||
editable(span_val_X_center, span_val_Y_center, span_val_Z_center);
|
editable(span_val_X_center, span_val_Y_center, span_val_Z_center);
|
||||||
span_val_X_center.onclick = field_edit('x center', (group, val, oval) => {
|
span_val_X_center.onclick = field_edit('x center', (val, oval) => {
|
||||||
selection.move_models(val - parseFloat(oval),0,0);
|
selection.move_models(val - parseFloat(oval),0,0);
|
||||||
});
|
});
|
||||||
span_val_Y_center.onclick = field_edit('y center', (group, val, oval) => {
|
span_val_Y_center.onclick = field_edit('y center', (val, oval) => {
|
||||||
selection.move_models(0,val - parseFloat(oval),0);
|
selection.move_models(0,val - parseFloat(oval),0);
|
||||||
});
|
});
|
||||||
span_val_Z_center.onclick = field_edit('z center', (group, val, oval) => {
|
span_val_Z_center.onclick = field_edit('z center', (val, oval) => {
|
||||||
selection.move_models(0,0,val - parseFloat(oval));
|
selection.move_models(0,0,val - parseFloat(oval));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1046,28 +1038,28 @@ function ui_build() {
|
||||||
};
|
};
|
||||||
editable(lbl);
|
editable(lbl);
|
||||||
});
|
});
|
||||||
span_val_X_size.onclick = field_edit('x size', (group, val, oval) => {
|
span_val_X_size.onclick = field_edit('x size', (val, oval) => {
|
||||||
let rel = val / parseFloat(oval);
|
let rel = val / oval;
|
||||||
if (axgrp.X) {
|
if (axgrp.X) {
|
||||||
group.scale(rel, axgrp.Y ? rel : 1, axgrp.Z ? rel : 1);
|
selection.scale(rel, axgrp.Y ? rel : 1, axgrp.Z ? rel : 1);
|
||||||
} else {
|
} else {
|
||||||
group.scale(rel, 1, 1);
|
selection.scale(rel, 1, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
span_val_Y_size.onclick = field_edit('y size', (group, val, oval) => {
|
span_val_Y_size.onclick = field_edit('y size', (val, oval) => {
|
||||||
let rel = val / parseFloat(oval);
|
let rel = val / oval;
|
||||||
if (axgrp.Y) {
|
if (axgrp.Y) {
|
||||||
group.scale(axgrp.X ? rel : 1, rel, axgrp.Z ? rel : 1);
|
selection.scale(axgrp.X ? rel : 1, rel, axgrp.Z ? rel : 1);
|
||||||
} else {
|
} else {
|
||||||
group.scale(1, rel, 1);
|
selection.scale(1, rel, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
span_val_Z_size.onclick = field_edit('z size', (group, val, oval) => {
|
span_val_Z_size.onclick = field_edit('z size', (val, oval) => {
|
||||||
let rel = val / parseFloat(oval);
|
let rel = val / oval;
|
||||||
if (axgrp.Z) {
|
if (axgrp.Z) {
|
||||||
group.scale(axgrp.X ? rel : 1, axgrp.Y ? rel : 1, rel);
|
selection.scale(axgrp.X ? rel : 1, axgrp.Y ? rel : 1, rel);
|
||||||
} else {
|
} else {
|
||||||
group.scale(1, 1, rel);
|
selection.scale(1, 1, rel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1098,11 +1090,13 @@ function ui_build() {
|
||||||
|
|
||||||
// listen for api calls
|
// listen for api calls
|
||||||
// create a deferred wrapper to merge multiple rapid events
|
// create a deferred wrapper to merge multiple rapid events
|
||||||
let defer_all = util.deferWrap(update_all);
|
const defer_all = util.deferWrap(update_all);
|
||||||
let defer_selector = util.deferWrap(update_selector);
|
const defer_selector = util.deferWrap(update_selector);
|
||||||
let defer_selection = util.deferWrap(update_selection);
|
const defer_selection = util.deferWrap(update_selection);
|
||||||
|
|
||||||
broker.listeners({
|
broker.listeners({
|
||||||
|
history_undo: defer_all,
|
||||||
|
history_redo: defer_all,
|
||||||
model_add: defer_all,
|
model_add: defer_all,
|
||||||
group_add: defer_all,
|
group_add: defer_all,
|
||||||
model_remove: defer_all,
|
model_remove: defer_all,
|
||||||
|
|
@ -1117,4 +1111,4 @@ function ui_build() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export { api };
|
export { };
|
||||||
|
|
|
||||||
|
|
@ -29,15 +29,30 @@ class History {
|
||||||
},
|
},
|
||||||
|
|
||||||
move(data) {
|
move(data) {
|
||||||
console.log('move', data);
|
const { set, dx, dy, dz } = data;
|
||||||
|
this.push('move', {
|
||||||
|
set, dx: -dx, dy: -dy, dz: -dz
|
||||||
|
}, {
|
||||||
|
set, dx, dy, dz
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
rotate(data) {
|
rotate(data) {
|
||||||
console.log('rotate', data);
|
const { set, dx, dy, dz } = data;
|
||||||
|
this.push('rotate', {
|
||||||
|
set, dx: -dx, dy: -dy, dz: -dz
|
||||||
|
}, {
|
||||||
|
set, dx, dy, dz
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
scale(data) {
|
scale(data) {
|
||||||
console.log('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);
|
}, this);
|
||||||
|
|
@ -64,11 +79,33 @@ class History {
|
||||||
|
|
||||||
do(type, data) {
|
do(type, data) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'position':
|
case 'move': {
|
||||||
|
let { set, dx, dy, dz } = data;
|
||||||
|
for (let grp of set) {
|
||||||
|
grp.move(dx, dy, dz);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'position': {
|
||||||
for (let { model, pos } of data) {
|
for (let { model, pos } of data) {
|
||||||
model.position(...pos);
|
model.position(...pos);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
console.warn(`invalid record type: ${type}`);
|
console.warn(`invalid record type: ${type}`);
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +115,7 @@ class History {
|
||||||
if (this.#pos >= 0) {
|
if (this.#pos >= 0) {
|
||||||
const rec = this.#stack[this.#pos--];
|
const rec = this.#stack[this.#pos--];
|
||||||
this.do(rec.type, rec.undo);
|
this.do(rec.type, rec.undo);
|
||||||
|
broker.publish("history_undo", rec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,6 +123,7 @@ class History {
|
||||||
if (this.#stack.length && this.#pos >= -1 && this.#pos < this.#stack.length - 1) {
|
if (this.#stack.length && this.#pos >= -1 && this.#pos < this.#stack.length - 1) {
|
||||||
const rec = this.#stack[++this.#pos];
|
const rec = this.#stack[++this.#pos];
|
||||||
this.do(rec.type, rec.redo);
|
this.do(rec.type, rec.redo);
|
||||||
|
broker.publish("history_redo", rec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue