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. 28
      client/webgl_draw.js
  4. 24
      client/webgl_geometry.js

2
README.txt

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

53
client/client_recv.js

@ -367,14 +367,38 @@ function handle_event(state, context, event, options = {}) { @@ -367,14 +367,38 @@ function handle_event(state, context, event, options = {}) {
} else if (other_event.type === EVENT.UNDO) {
// do not undo an undo, we are not Notepad
} 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) {
// TODO
console.log('TODO: undo image move');
other_event.deleted = true;
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;
} else if (other_event.type === EVENT.IMAGE_SCALE) {
// TODO
console.log('TODO: undo image scale');
other_event.deleted = true;
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;
} else if (other_event.type === EVENT.ERASER) {
const stroke = state.events[other_event.stroke_id];
@ -433,6 +457,14 @@ function handle_event(state, context, event, options = {}) { @@ -433,6 +457,14 @@ function handle_event(state, context, event, options = {}) {
if (image) {
// 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.y = event.y;
need_draw = true;
@ -447,6 +479,17 @@ function handle_event(state, context, event, options = {}) { @@ -447,6 +479,17 @@ function handle_event(state, context, event, options = {}) {
const image = get_image(context, image_id);
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});
need_draw = true;
}

28
client/webgl_draw.js

@ -226,20 +226,22 @@ async function draw(state, context, animate, ts) { @@ -226,20 +226,22 @@ async function draw(state, context, animate, ts) {
gl.vertexAttribPointer(locations['a_pos'], 2, gl.FLOAT, false, 2 * 4, 0);
for (const entry of context.images) {
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_translation'], state.canvas.offset.x, state.canvas.offset.y);
gl.uniform1i(locations['u_texture'], 0); // Only 1 active texture for each drawcall
gl.uniform1i(locations['u_solid'], 0);
gl.bindTexture(gl.TEXTURE_2D, entry.texture);
gl.drawArrays(gl.TRIANGLES, offset, 6);
// Highlight active image
if (entry.key === state.active_image) {
gl.uniform1i(locations['u_solid'], 1);
gl.uniform4f(locations['u_color'], 0.133 * 0.5, 0.545 * 0.5, 0.902 * 0.5, 0.5);
if (!entry.deleted) {
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_translation'], state.canvas.offset.x, state.canvas.offset.y);
gl.uniform1i(locations['u_texture'], 0); // Only 1 active texture for each drawcall
gl.uniform1i(locations['u_solid'], 0);
gl.bindTexture(gl.TEXTURE_2D, entry.texture);
gl.drawArrays(gl.TRIANGLES, offset, 6);
// Highlight active image
if (entry.key === state.active_image) {
gl.uniform1i(locations['u_solid'], 1);
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);
}
}
offset += 6;

24
client/webgl_geometry.js

@ -193,6 +193,10 @@ function add_image(context, image_id, bitmap, p, width, height) { @@ -193,6 +193,10 @@ function add_image(context, image_id, bitmap, p, width, height) {
'raw_at': {...p},
'width': width,
'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);
@ -214,10 +218,6 @@ function add_image(context, image_id, bitmap, p, width, height) { @@ -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) {
let new_width, new_height;
@ -250,15 +250,17 @@ function image_at(context, x, y) { @@ -250,15 +250,17 @@ function image_at(context, x, y) {
// Iterate back to front to pick the image at the front first
for (let i = context.images.length - 1; i >= 0; --i) {
const image = context.images[i];
const at = image.at;
const w = image.width;
const h = image.height;
if (!image.deleted) {
const at = image.at;
const w = image.width;
const h = image.height;
const in_x = (at.x <= x && x <= at.x + w) || (at.x + w <= x && x <= at.x);
const in_y = (at.y <= y && y <= at.y + h) || (at.y + h <= y && y <= at.y);
const in_x = (at.x <= x && x <= at.x + w) || (at.x + w <= x && x <= at.x);
const in_y = (at.y <= y && y <= at.y + h) || (at.y + h <= y && y <= at.y);
if (in_x && in_y) {
return image;
if (in_x && in_y) {
return image;
}
}
}

Loading…
Cancel
Save