Browse Source

Clean up image move/scale logic a little bit. Remove obsolete cursor.js file

ssao
A.Olokhtonov 5 months ago
parent
commit
45bac3395a
  1. 9
      client/client_recv.js
  2. 327
      client/cursor.js
  3. 6
      client/index.js
  4. 6
      client/webgl_draw.js
  5. 2
      client/webgl_geometry.js
  6. 58
      client/webgl_listeners.js

9
client/client_recv.js

@ -392,13 +392,12 @@ function handle_event(state, context, event, options = {}) { @@ -392,13 +392,12 @@ function handle_event(state, context, event, options = {}) {
// Already moved due to local prediction
if (event.user_id !== state.me) {
const image_id = event.image_id;
const image_event = find_image(state, image_id);
const image = get_image(context, image_id);
if (image_event) {
if (image) {
// if (config.debug_print) console.debug('move image', image_id, 'to', image_event.x, image_event.y);
image_event.x = event.x;
image_event.y = event.y;
move_image(context, image_event);
image.at.x = event.x;
image.at.y = event.y;
need_draw = true;
}
}

327
client/cursor.js

@ -1,327 +0,0 @@ @@ -1,327 +0,0 @@
function on_down(e) {
const x = Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom);
const y = Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom);
// Scroll wheel (mouse button 3)
if (e.button === 1) {
// storage.state.moving = true;
// storage.state.mousedown = true;
return;
}
// Right mouse button
if (e.button === 2) {
const image_hit = image_at(x, y);
activate_image(image_hit);
e.preventDefault();
return;
}
// Left mouse button
if (e.button === 0) {
const image_hit = image_at(context, x, y);
if (elements.active_image !== null && image_hit !== null) {
const image_id = image_hit.getAttribute('data-image-id');
const image_position = storage.images[image_id];
storage.state.moving_image = true;
storage.moving_image_original_x = image_position.x;
storage.moving_image_original_y = image_position.y;
return;
}
if (storage.state.moving) {
storage.state.mousedown = true;
return;
}
storage.state.drawing = true;
if (storage.ctx1.lineWidth !== storage.cursor.width) {
storage.ctx1.lineWidth = storage.cursor.width;
}
storage.cursor.x = x;
storage.cursor.y = y;
if (storage.tools.active === 'pencil') {
const predraw = predraw_event(x, y);
storage.current_stroke.push(predraw);
fire_event(predraw);
} else if (storage.tools.active === 'ruler') {
storage.ruler_origin.x = x;
storage.ruler_origin.y = y;
}
}
}
function on_move(e) {
const last_x = storage.cursor.x;
const last_y = storage.cursor.y;
const x = storage.cursor.x = Math.max(Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom), 0);
const y = storage.cursor.y = Math.max(Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom), 0);
const old_offset_x = storage.canvas.offset_x;
const old_offset_y = storage.canvas.offset_y;
if (elements.active_image && storage.state.moving_image) {
const dx = Math.round(e.movementX / storage.canvas.zoom);
const dy = Math.round(e.movementY / storage.canvas.zoom);
const image_id = elements.active_image.getAttribute('data-image-id');
const ix = storage.images[image_id].x += dx;
const iy = storage.images[image_id].y += dy;
elements.active_image.style.transform = `translate(${ix}px, ${iy}px)`;
return;
}
if (storage.state.drawing) {
if (storage.tools.active === 'pencil') {
const width = storage.cursor.width;
storage.ctx1.beginPath();
storage.ctx1.moveTo(last_x, last_y);
storage.ctx1.lineTo(x, y);
storage.ctx1.stroke();
const predraw = predraw_event(x, y);
storage.current_stroke.push(predraw);
fire_event(predraw);
} else if (storage.tools.active === 'eraser') {
const erased = strokes_intersect_line(last_x, last_y, x, y);
storage.erased.push(...erased);
if (erased.length > 0) {
for (const other_event of storage.events) {
for (const stroke_id of erased) {
if (stroke_id === other_event.stroke_id) {
if (!other_event.deleted) {
other_event.deleted = true;
const stats = stroke_stats(other_event.points, storage.cursor.width);
redraw_region(stats.bbox);
}
}
}
}
}
} else if (storage.tools.active === 'ruler') {
const old_ruler = [
{'x': storage.ruler_origin.x, 'y': storage.ruler_origin.y},
{'x': last_x, 'y': last_y}
];
const stats = stroke_stats(old_ruler, storage.cursor.width);
const bbox = stats.bbox;
storage.ctx1.clearRect(bbox.xmin, bbox.ymin, bbox.xmax - bbox.xmin, bbox.ymax - bbox.ymin);
storage.ctx1.beginPath();
storage.ctx1.moveTo(storage.ruler_origin.x, storage.ruler_origin.y);
storage.ctx1.lineTo(x, y);
storage.ctx1.stroke();
} else {
console.error('fuck');
}
} else if (storage.state.moving && storage.state.mousedown) {
storage.canvas.offset_x -= e.movementX;
storage.canvas.offset_y -= e.movementY;
if (storage.canvas.offset_x !== old_offset_x || storage.canvas.offset_y !== old_offset_y) {
move_canvas();
}
// if (storage.canvas.offset_x > storage.canvas.max_scroll_x) storage.canvas.offset_x = storage.canvas.max_scroll_x;
// if (storage.canvas.offset_x < 0) storage.canvas.offset_x = 0;
// if (storage.canvas.offset_y > storage.canvas.max_scroll_y) storage.canvas.offset_y = storage.canvas.max_scroll_y;
// if (storage.canvas.offset_y < 0) storage.canvas.offset_y = 0;
}
e.preventDefault();
}
async function on_up(e) {
if (storage.state.moving_image && e.button === 0) {
storage.state.moving_image = false;
const image_id = elements.active_image.getAttribute('data-image-id');
const position = storage.images[image_id];
// Store delta instead of new position for easy undo
const event = image_move_event(image_id, position.x - storage.moving_image_original_x, position.y - storage.moving_image_original_y);
await queue_event(event);
storage.moving_image_original_x = null;
storage.moving_image_original_y = null;
return;
}
if (storage.state.moving && (e.button === 1 || e.button === 0)) {
storage.state.mousedown = false;
if (!storage.state.spacedown) {
storage.state.moving = false;
return;
}
}
if (storage.state.drawing && e.button === 0) {
if (storage.tools.active === 'pencil') {
const event = stroke_event();
storage.current_stroke = [];
await queue_event(event);
} else if (storage.tools.active === 'eraser') {
const events = eraser_events();
storage.erased = [];
if (events.length > 0) {
for (const event of events) {
await queue_event(event);
}
}
} else if (storage.tools.active === 'ruler') {
const event = ruler_event(storage.cursor.x, storage.cursor.y);
await queue_event(event);
} else {
console.error('fuck');
}
storage.state.drawing = false;
return;
}
}
function on_keydown(e) {
if (e.code === 'Space' && !storage.state.drawing) {
storage.state.moving = true;
storage.state.spacedown = true;
return;
}
if (e.code === 'KeyZ' && e.ctrlKey) {
undo();
return;
}
}
function on_keyup(e) {
if (e.code === 'Space' && storage.state.moving) {
storage.state.moving = false;
storage.state.spacedown = false;
}
}
function on_leave(e) {
// TODO: broken when "moving"
if (storage.state.moving) {
storage.state.moving = false;
storage.state.holding = false;
return;
}
}
function on_resize(e) {
const width = window.innerWidth;
const height = window.innerHeight;
elements.canvas0.width = elements.canvas1.width = width;
elements.canvas0.height = elements.canvas1.height = height;
storage.ctx1.lineJoin = storage.ctx1.lineCap = storage.ctx0.lineJoin = storage.ctx0.lineCap = 'round';
storage.ctx1.lineWidth = storage.ctx0.lineWidth = storage.cursor.width;
redraw_region({'xmin': 0, 'xmax': width, 'ymin': 0, 'ymax': width});
// storage.canvas.max_scroll_x = storage.canvas.width - window.innerWidth;
// storage.canvas.max_scroll_y = storage.canvas.height - window.innerHeight;
}
async function on_drop(e) {
e.preventDefault();
const file = e.dataTransfer.files[0];
const bitmap = await createImageBitmap(file);
const x = storage.cursor.x - Math.round(bitmap.width / 2);
const y = storage.cursor.y - Math.round(bitmap.height / 2);
// storage.ctx0.drawImage(bitmap, x, y);
const form_data = new FormData();
form_data.append('file', file);
const resp = await fetch(`/api/image?deskId=${storage.desk_id}`, {
method: 'post',
body: form_data,
})
if (resp.ok) {
const image_id = await resp.text();
const event = image_event(image_id, x, y);
await queue_event(event);
}
return false;
}
function on_wheel(e) {
return;
const x = Math.round((e.clientX + storage.canvas.offset_x) / storage.canvas.zoom);
const y = Math.round((e.clientY + storage.canvas.offset_y) / storage.canvas.zoom);
const dz = (e.deltaY < 0 ? 0.1 : -0.1);
storage.canvas.zoom += dz;
if (storage.canvas.zoom > storage.max_zoom) {
storage.canvas.zoom = storage.max_zoom;
return;
}
if (storage.canvas.zoom < storage.min_zoom) {
storage.canvas.zoom = storage.min_zoom;
return;
}
const zoom_offset_x = Math.round(dz * x);
const zoom_offset_y = Math.round(dz * y);
storage.canvas.offset_x += zoom_offset_x;
storage.canvas.offset_y += zoom_offset_y;
move_canvas();
}
function cancel(e) {
e.preventDefault();
return false;
}
function update_brush() {
elements.brush_preview.classList.remove('dhide');
const color = elements.brush_color.value;
const width = elements.brush_width.value;
storage.cursor.color = color;
storage.cursor.width = width;
const x = Math.round(storage.cursor.x - width / 2);
const y = Math.round(storage.cursor.y - width / 2);
elements.brush_preview.style.transform = `translate(${x}px, ${y}px)`;
elements.brush_preview.style.width = width + 'px';
elements.brush_preview.style.height = width + 'px';
elements.brush_preview.style.background = color;
if (storage.timers.brush_preview) {
clearTimeout(storage.timers.brush_preview);
}
storage.timers.brush_preview = setTimeout(() => {
elements.brush_preview.classList.add('dhide');
}, 1000);
}

6
client/index.js

@ -177,9 +177,10 @@ async function main() { @@ -177,9 +177,10 @@ async function main() {
'colorpicking': false,
'zooming': false,
'zoomdown': false,
'imagemoving': false,
'imagescaling': false,
'moving_image': null,
'scaling_image': null,
'active_image': null,
'scaling_corner': null,
'current_strokes': {},
@ -271,7 +272,6 @@ async function main() { @@ -271,7 +272,6 @@ async function main() {
'bgcolor': {'r': 1.0, 'g': 1.0, 'b': 1.0},
'gpu_timer_ext': null,
'active_image': null,
'last_frame_ts': 0,
'last_frame_dt': 0,
};

6
client/webgl_draw.js

@ -236,7 +236,7 @@ async function draw(state, context, animate, ts) { @@ -236,7 +236,7 @@ async function draw(state, context, animate, ts) {
gl.drawArrays(gl.TRIANGLES, offset, 6);
// Highlight active image
if (entry.key === context.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);
@ -361,8 +361,8 @@ async function draw(state, context, animate, ts) { @@ -361,8 +361,8 @@ async function draw(state, context, animate, ts) {
}
// HUD: resize handles, etc
if (context.active_image !== null) {
const handles = geometry_generate_handles(state, context, context.active_image);
if (state.active_image !== null) {
const handles = geometry_generate_handles(state, context, state.active_image);
const ui_segments = 7 * 4 - 1; // each square = 4, each line = 1, square->line = 1, line->square = 1
gl.bindBuffer(gl.ARRAY_BUFFER, buffers['b_instance']);

2
client/webgl_geometry.js

@ -218,7 +218,7 @@ function add_image(context, image_id, bitmap, p) { @@ -218,7 +218,7 @@ function add_image(context, image_id, bitmap, p) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, bitmap);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}

58
client/webgl_listeners.js

@ -209,7 +209,7 @@ function mousedown(e, state, context) { @@ -209,7 +209,7 @@ function mousedown(e, state, context) {
geometry_add_point(state, context, state.me, canvasp);
state.drawing = true;
context.active_image = null;
state.active_image = null;
schedule_draw(state, context);
} else if (state.tools.active === 'ruler') {
@ -217,14 +217,17 @@ function mousedown(e, state, context) { @@ -217,14 +217,17 @@ function mousedown(e, state, context) {
} else if (state.tools.active === 'eraser') {
state.erasing = true;
} else if (state.tools.active === 'pointer') {
state.scaling_image = null;
state.imagescaling = false;
state.imagemoving = false;
if (context.active_image !== null) {
// Resize image?
const image = get_image(context, context.active_image);
corner = image_corner(state, image, canvasp);
if (state.active_image !== null) {
// Check for resize first, because it supports
// clicking slightly outside of the image
const image = get_image(context, state.active_image);
const corner = image_corner(state, image, canvasp);
if (corner !== null) {
state.scaling_image = image.key;
// Resize
state.imagescaling = true;
state.scaling_corner = corner;
document.querySelector('canvas').classList.remove('resize-topleft');
@ -238,15 +241,15 @@ function mousedown(e, state, context) { @@ -238,15 +241,15 @@ function mousedown(e, state, context) {
}
}
if (state.scaling_image === null) {
// Select/move image?
const image_event = image_at(context, canvasp.x, canvasp.y);
if (image_event) {
context.active_image = image_event.key;
state.moving_image = image_event.key;
// Only do picking logic if we haven't started imagescaling already
if (!state.imagescaling) {
const image = image_at(context, canvasp.x, canvasp.y);
if (image !== null) {
state.active_image = image.key;
// Allow immediately moving
state.imagemoving = true;
} else {
context.active_image = null;
state.active_image = null;
}
}
@ -276,8 +279,8 @@ function mousemove(e, state, context) { @@ -276,8 +279,8 @@ function mousemove(e, state, context) {
const canvasp = screen_to_canvas(state, screenp);
if (state.tools.active === 'pointer') {
if (context.active_image !== null) {
const image = get_image(context, context.active_image);
if (state.active_image !== null) {
const image = get_image(context, state.active_image);
const corner = image_corner(state, image, canvasp);
if (state.scaling_corner === null) {
@ -350,14 +353,14 @@ function mousemove(e, state, context) { @@ -350,14 +353,14 @@ function mousemove(e, state, context) {
do_draw = true;
}
if (state.scaling_image) {
const image = get_image(context, state.scaling_image);
if (state.imagescaling) {
const image = get_image(context, state.active_image);
scale_image(context, image, state.scaling_corner, canvasp);
do_draw = true;
}
if (state.moving_image) {
const image = get_image(context, state.moving_image);
if (state.imagemoving) {
const image = get_image(context, state.active_image);
if (image !== null) {
const dx = e.movementX / state.canvas.zoom;
@ -366,8 +369,6 @@ function mousemove(e, state, context) { @@ -366,8 +369,6 @@ function mousemove(e, state, context) {
image.at.x += dx;
image.at.y += dy;
//move_image(context, state.moving_image);
do_draw = true;
}
}
@ -412,15 +413,16 @@ function mouseup(e, state, context) { @@ -412,15 +413,16 @@ function mouseup(e, state, context) {
return;
}
if (state.moving_image) {
if (state.imagemoving) {
state.imagemoving = false;
const image = get_image(context, state.active_image);
queue_event(state, image_move_event(state.active_image, image.at.x, image.at.y));
schedule_draw(state, context);
//queue_event(state, image_move_event(context.active_image, state.moving_image.x, state.moving_image.y));
state.moving_image = null;
return;
}
if (state.scaling_image) {
state.scaling_image = null;
if (state.imagescaling) {
state.imagescaling = false;
state.scaling_corner = null;
return;
}

Loading…
Cancel
Save