add very basic undo/redo for move/scale/rotate
This commit is contained in:
parent
bf51d56bb5
commit
d9037c67ff
9 changed files with 204 additions and 5 deletions
156
src/kiri/do.js
Normal file
156
src/kiri/do.js
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/** Copyright Stewart Allen <sa@grid.space> -- All Rights Reserved */
|
||||
|
||||
kiri.load(function(API) {
|
||||
let stack = [];
|
||||
let stpos = 0;
|
||||
|
||||
let event = API.event;
|
||||
let moved = {x:0, y:0};
|
||||
let msgid;
|
||||
|
||||
event.on("init-done", () => {
|
||||
$('undo').onclick = undo;
|
||||
$('redo').onclick = redo;
|
||||
});
|
||||
|
||||
let undo = API.doit.undo = function() {
|
||||
if (stpos) {
|
||||
action(stack[--stpos].undo);
|
||||
} else {
|
||||
message('nothing to undo');
|
||||
}
|
||||
};
|
||||
|
||||
let redo = API.doit.redo = function() {
|
||||
if (stpos < stack.length) {
|
||||
action(stack[stpos++].redo);
|
||||
} else {
|
||||
message('nothing to redo');
|
||||
}
|
||||
};
|
||||
|
||||
let clear = API.doit.clear = function() {
|
||||
stack = [];
|
||||
stpos = 0;
|
||||
moved = {x:0, y:0};
|
||||
updateButtons();
|
||||
};
|
||||
|
||||
function updateButtons() {
|
||||
$('doit').style.display = stack.length ? '' : 'none';
|
||||
$('undo').disabled = stpos === 0;
|
||||
$('redo').disabled = stpos == stack.length;
|
||||
}
|
||||
|
||||
function message(txt) {
|
||||
if (msgid) {
|
||||
API.hide.alert(msgid);
|
||||
}
|
||||
msgid = API.show.alert(txt);
|
||||
}
|
||||
|
||||
function action(rec) {
|
||||
switch (rec.type) {
|
||||
case 'move':
|
||||
for (let w of rec.widgets) {
|
||||
w._move(rec.dist.x, rec.dist.y, 0);
|
||||
}
|
||||
break;
|
||||
case 'rotate':
|
||||
for (let w of rec.widgets) {
|
||||
w.rotate(rec.x, rec.y, rec.z);
|
||||
}
|
||||
break;
|
||||
case 'scale':
|
||||
for (let w of rec.widgets) {
|
||||
w._scale(rec.x, rec.y, rec.z);
|
||||
}
|
||||
API.selection.update_info();
|
||||
break;
|
||||
}
|
||||
API.space.update();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
function pushActions(ur) {
|
||||
stack.length = stpos++;
|
||||
stack.push(ur);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
event.on([
|
||||
'platform.layout',
|
||||
'widget.add',
|
||||
'widget.delete'
|
||||
], (widget) => {
|
||||
clear();
|
||||
});
|
||||
|
||||
// selection event (store position)
|
||||
event.on('widget.rotate', (rec) => {
|
||||
let type = "rotate";
|
||||
let {widget, x, y, z} = rec;
|
||||
if (!(x || y || z)) {
|
||||
return;
|
||||
}
|
||||
pushActions({
|
||||
redo: {
|
||||
type,
|
||||
widgets: [ widget ],
|
||||
x, y, z
|
||||
},
|
||||
undo: {
|
||||
type,
|
||||
widgets: [ widget ],
|
||||
x: -x, y: -y, z: -z
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
event.on('selection.scale', (rec) => {
|
||||
let [x, y, z] = rec;
|
||||
// ignore scale close to 1
|
||||
if (Math.abs(1 - (x * y * z)) < 0.0001) {
|
||||
return;
|
||||
}
|
||||
let widgets = API.selection.widgets();
|
||||
let type = "scale";
|
||||
pushActions({
|
||||
redo: {
|
||||
type,
|
||||
widgets,
|
||||
x, y, z
|
||||
},
|
||||
undo: {
|
||||
type,
|
||||
widgets,
|
||||
x: 1/x, y: 1/y, z: 1/z
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// selection moved (accumulator)
|
||||
event.on('selection.drag', (delta) => {
|
||||
moved.x += delta.x;
|
||||
moved.y += delta.y;
|
||||
});
|
||||
|
||||
// move complete (store updated position)
|
||||
event.on('mouse.drag.done', () => {
|
||||
let widgets = API.selection.widgets();
|
||||
let type = "move";
|
||||
pushActions({
|
||||
redo: {
|
||||
type,
|
||||
widgets,
|
||||
dist: moved
|
||||
},
|
||||
undo: {
|
||||
type,
|
||||
widgets,
|
||||
dist: {x: -moved.x, y: -moved.y}
|
||||
}
|
||||
});
|
||||
moved = {x:0, y:0};
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue