Browse Source

Undo for all available actions

sdf
A.Olokhtonov 2 months ago
parent
commit
bdc3bdc9a1
  1. 2
      README.txt
  2. 53
      client/client_recv.js
  3. 2
      client/webgl_draw.js
  4. 10
      client/webgl_geometry.js

2
README.txt

@ -46,7 +46,7 @@ Release:
- Alignment (horizontal, vertical, diagonal, etc) - Alignment (horizontal, vertical, diagonal, etc)
+ Undo + Undo
+ Undo for eraser + Undo for eraser
- Undo for images (add, move, scale) + Undo for images (add, move, scale)
- Redo - Redo
+ Snapping to grid + Snapping to grid
- Snapping to other points? - Snapping to other points?

53
client/client_recv.js

@ -367,14 +367,38 @@ function handle_event(state, context, event, options = {}) {
} else if (other_event.type === EVENT.UNDO) { } else if (other_event.type === EVENT.UNDO) {
// do not undo an undo, we are not Notepad // do not undo an undo, we are not Notepad
} else if (other_event.type === EVENT.IMAGE) { } else if (other_event.type === EVENT.IMAGE) {
console.log('TODO: undo image'); other_event.deleted = true;
const image = get_image(context, other_event.image_id);
if (image !== null) {
image.deleted = true;
}
need_draw = true;
break;
} else if (other_event.type === EVENT.IMAGE_MOVE) { } else if (other_event.type === EVENT.IMAGE_MOVE) {
// TODO other_event.deleted = true;
console.log('TODO: undo image move'); const image = get_image(context, other_event.image_id);
if (image !== null) {
image.move_head -= 2;
image.at.x = image.move_history[image.move_head - 2];
image.at.y = image.move_history[image.move_head - 1];
need_draw = true;
} else {
console.warning('Undo image move for a non-existent image');
}
break; break;
} else if (other_event.type === EVENT.IMAGE_SCALE) { } else if (other_event.type === EVENT.IMAGE_SCALE) {
// TODO other_event.deleted = true;
console.log('TODO: undo image scale'); const image = get_image(context, other_event.image_id);
if (image !== null) {
image.scale_head -= 4;
image.at.x = image.scale_history[image.scale_head - 4];
image.at.y = image.scale_history[image.scale_head - 3];
image.width = image.scale_history[image.scale_head - 2];
image.height = image.scale_history[image.scale_head - 1];
need_draw = true;
} else {
console.warning('Undo image scale for a non-existent image');
}
break; break;
} else if (other_event.type === EVENT.ERASER) { } else if (other_event.type === EVENT.ERASER) {
const stroke = state.events[other_event.stroke_id]; const stroke = state.events[other_event.stroke_id];
@ -433,6 +457,14 @@ function handle_event(state, context, event, options = {}) {
if (image) { if (image) {
// if (config.debug_print) console.debug('move image', image_id, 'to', image_event.x, image_event.y); // if (config.debug_print) console.debug('move image', image_id, 'to', image_event.x, image_event.y);
if (image.move_head < image.move_history.length) {
image.move_history[image.move_head] = event.x;
image.move_history[image.move_head + 1] = event.y;
} else {
image.move_history.push(event.x, event.y);
}
image.move_head += 2;
image.at.x = event.x; image.at.x = event.x;
image.at.y = event.y; image.at.y = event.y;
need_draw = true; need_draw = true;
@ -447,6 +479,17 @@ function handle_event(state, context, event, options = {}) {
const image = get_image(context, image_id); const image = get_image(context, image_id);
if (image !== null) { if (image !== null) {
if (image.scale_head < image.scale_history.length) {
image.scale_history[image.scale_head] = image.at.x;
image.scale_history[image.scale_head + 1] = image.at.y;
image.scale_history[image.scale_head + 2] = image.width;
image.scale_history[image.scale_head + 3] = image.height;
} else {
image.scale_history.push(image.at.x, image.at.y, image.width, image.height);
}
image.scale_head += 4;
scale_image(context, image, event.corner, {'x': event.x, 'y': event.y}); scale_image(context, image, event.corner, {'x': event.x, 'y': event.y});
need_draw = true; need_draw = true;
} }

2
client/webgl_draw.js

@ -226,6 +226,7 @@ async function draw(state, context, animate, ts) {
gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, 0); gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, 0);
for (const entry of context.images) { for (const entry of context.images) {
if (!entry.deleted) {
gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height); gl.uniform2f(locations['u_res'], context.canvas.width, context.canvas.height);
gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom); gl.uniform2f(locations['u_scale'], state.canvas.zoom, state.canvas.zoom);
gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y); gl.uniform2f(locations['u_translation'], state.canvas.offset.x, state.canvas.offset.y);
@ -241,6 +242,7 @@ async function draw(state, context, animate, ts) {
gl.uniform4f(locations['u_color'], 0.133 * 0.5, 0.545 * 0.5, 0.902 * 0.5, 0.5); gl.uniform4f(locations['u_color'], 0.133 * 0.5, 0.545 * 0.5, 0.902 * 0.5, 0.5);
gl.drawArrays(gl.TRIANGLES, offset, 6); gl.drawArrays(gl.TRIANGLES, offset, 6);
} }
}
offset += 6; offset += 6;
} }

10
client/webgl_geometry.js

@ -193,6 +193,10 @@ function add_image(context, image_id, bitmap, p, width, height) {
'raw_at': {...p}, 'raw_at': {...p},
'width': width, 'width': width,
'height': height, 'height': height,
'move_history': [ p.x, p.y ],
'scale_history': [ p.x, p.y, width, height ],
'move_head': 2,
'scale_head': 4,
}; };
context.images.push(entry); context.images.push(entry);
@ -214,10 +218,6 @@ function add_image(context, image_id, bitmap, p, width, height) {
} }
} }
function move_image(context, image, dx, dy) {
consol.error('wtf is this');
}
function scale_image(context, image, corner, canvasp) { function scale_image(context, image, corner, canvasp) {
let new_width, new_height; let new_width, new_height;
@ -250,6 +250,7 @@ function image_at(context, x, y) {
// Iterate back to front to pick the image at the front first // Iterate back to front to pick the image at the front first
for (let i = context.images.length - 1; i >= 0; --i) { for (let i = context.images.length - 1; i >= 0; --i) {
const image = context.images[i]; const image = context.images[i];
if (!image.deleted) {
const at = image.at; const at = image.at;
const w = image.width; const w = image.width;
const h = image.height; const h = image.height;
@ -261,6 +262,7 @@ function image_at(context, x, y) {
return image; return image;
} }
} }
}
return null; return null;
} }

Loading…
Cancel
Save