diff --git a/.gitignore b/.gitignore index 72b65f9..a5a1a12 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ doca.txt data/ client/*.dot server/points.txt +server/scripts.js *.o *.out diff --git a/client/aux.js b/client/aux.js index c3e8ae3..fa95888 100644 --- a/client/aux.js +++ b/client/aux.js @@ -47,6 +47,11 @@ function event_size(event) { break; } + case EVENT.ZOOM_CANVAS: { + size += 4 + 4 * 2; + break; + } + case EVENT.USER_JOINED: case EVENT.LEAVE: case EVENT.CLEAR: { diff --git a/client/client_recv.js b/client/client_recv.js index 76e8d70..b012675 100644 --- a/client/client_recv.js +++ b/client/client_recv.js @@ -85,7 +85,14 @@ function des_event(d, state = null) { case EVENT.MOVE_CANVAS: { event.offset_x = des_s32(d); event.offset_y = des_s32(d); - event.zoom = des_f32(d); + event.zoom_level = des_s32(d); + break; + } + + case EVENT.ZOOM_CANVAS: { + event.zoom_level = des_s32(d); + event.zoom_cx = des_f32(d); + event.zoom_cy = des_f32(d); break; } @@ -221,7 +228,32 @@ function handle_event(state, context, event, options = {}) { if (event.user_id == state.following_player) { state.canvas.offset.x = event.offset_x; state.canvas.offset.y = event.offset_y; - state.canvas.zoom = event.zoom; + + const zoom_level = event.zoom_level; + const dz = (zoom_level > 0 ? config.zoom_delta : -config.zoom_delta); + const zoom = Math.pow(1.0 + dz, Math.abs(zoom_level)) + + state.canvas.zoom_level = zoom_level; + state.canvas.zoom = zoom; + state.canvas.target_zoom = zoom; + + need_draw = true; + } + + break; + } + + case EVENT.ZOOM_CANVAS: { + if (event.user_id == state.following_player) { + const zoom_level = event.zoom_level; + const zoom_center = {'x': event.zoom_cx, 'y': event.zoom_cy}; + const dz = (zoom_level > 0 ? config.zoom_delta : -config.zoom_delta); + const zoom = Math.pow(1.0 + dz, Math.abs(zoom_level)) + + state.canvas.zoom_level = zoom_level; + state.canvas.target_zoom = zoom; + state.canvas.zoom_screenp = canvas_to_screen(state, zoom_center); + need_draw = true; } diff --git a/client/client_send.js b/client/client_send.js index e595d8e..33d9c61 100644 --- a/client/client_send.js +++ b/client/client_send.js @@ -63,6 +63,11 @@ function ser_u32(s, value) { s.offset += 4; } +function ser_s32(s, value) { + s.view.setInt32(s.offset, value, true); + s.offset += 4; +} + function ser_align(s, to) { // TODO: non-stupid version of this while (s.offset % to != 0) { @@ -93,7 +98,14 @@ function ser_event(s, event) { case EVENT.MOVE_CANVAS: { ser_u32(s, event.offset_x); ser_u32(s, event.offset_y); - ser_f32(s, event.zoom); + ser_s32(s, event.zoom_level); + break; + } + + case EVENT.ZOOM_CANVAS: { + ser_s32(s, event.zoom_level); + ser_f32(s, event.zoom_cx); + ser_f32(s, event.zoom_cy); break; } @@ -366,7 +378,16 @@ function movecanvas_event(state) { 'type': EVENT.MOVE_CANVAS, 'offset_x': state.canvas.offset.x, 'offset_y': state.canvas.offset.y, - 'zoom': state.canvas.zoom, + 'zoom_level': state.canvas.zoom_level, + }; +} + +function zoomcanvas_event(state, zoom_cx, zoom_cy) { + return { + 'type': EVENT.ZOOM_CANVAS, + 'zoom_level': state.canvas.zoom_level, + 'zoom_cx': zoom_cx, + 'zoom_cy': zoom_cy, }; } diff --git a/client/index.js b/client/index.js index 69d77e0..1db0161 100644 --- a/client/index.js +++ b/client/index.js @@ -42,10 +42,11 @@ const EVENT = Object.freeze({ SET_WIDTH: 12, CLEAR: 13, // clear predraw events from me (because I started a pan instead of drawing) MOVE_CURSOR: 14, - MOVE_SCREEN: 15, + LEAVE: 16, MOVE_CANVAS: 17, USER_JOINED: 18, + ZOOM_CANVAS: 19, STROKE: 20, RULER: 21, // gets re-written with EVENT.STROKE before sending to server diff --git a/client/webgl_listeners.js b/client/webgl_listeners.js index 56dc268..c6454e1 100644 --- a/client/webgl_listeners.js +++ b/client/webgl_listeners.js @@ -437,6 +437,7 @@ function update_cursor(state) { function wheel(e, state, context) { const screenp = {'x': window.devicePixelRatio * e.clientX, 'y': window.devicePixelRatio * e.clientY}; + const canvasp = screen_to_canvas(state, screenp); const zooming_in = e.deltaY < 0; const zoom_level = zooming_in ? state.canvas.zoom_level + 2 : state.canvas.zoom_level - 2; @@ -454,7 +455,7 @@ function wheel(e, state, context) { toggle_follow_player(state, state.following_player); } - fire_event(state, movecanvas_event(state)); + fire_event(state, zoomcanvas_event(state, canvasp.x, canvasp.y)); schedule_draw(state, context); } diff --git a/server/deserializer.js b/server/deserializer.js index 419030e..e7e2eac 100644 --- a/server/deserializer.js +++ b/server/deserializer.js @@ -26,6 +26,12 @@ export function u32(d) { return value; } +export function s32(d) { + const value = d.view.getInt32(d.offset, true); + d.offset += 4; + return value; +} + export function f32(d) { const value = d.view.getFloat32(d.offset, true); d.offset += 4; @@ -71,7 +77,14 @@ export function event(d) { case EVENT.MOVE_CANVAS: { event.offset_x = u32(d); event.offset_y = u32(d); - event.zoom = f32(d); + event.zoom_level = s32(d); + break; + } + + case EVENT.ZOOM_CANVAS: { + event.zoom_level = s32(d); + event.zoom_cx = f32(d); + event.zoom_cy = f32(d); break; } diff --git a/server/enums.js b/server/enums.js index 97f4c29..8c61987 100644 --- a/server/enums.js +++ b/server/enums.js @@ -10,10 +10,11 @@ export const EVENT = Object.freeze({ SET_WIDTH: 12, CLEAR: 13, MOVE_CURSOR: 14, - MOVE_SCREEN: 15, + LEAVE: 16, MOVE_CANVAS: 17, USER_JOINED: 18, + ZOOM_CANVAS: 19, STROKE: 20, UNDO: 30, diff --git a/server/send.js b/server/send.js index b6e6f9f..bab4b46 100644 --- a/server/send.js +++ b/server/send.js @@ -21,6 +21,11 @@ function event_size(event) { break; } + case EVENT.ZOOM_CANVAS: { + size += 4 + 4 * 2; + break; + } + case EVENT.USER_JOINED: case EVENT.LEAVE: case EVENT.CLEAR: { diff --git a/server/serializer.js b/server/serializer.js index e75e1e2..f43db6a 100644 --- a/server/serializer.js +++ b/server/serializer.js @@ -31,6 +31,11 @@ export function u32(s, value) { s.offset += 4; } +export function s32(s, value) { + s.view.setInt32(s.offset, value, true); + s.offset += 4; +} + export function bytes(s, bytes) { s.strview.set(new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength), s.offset); s.offset += bytes.byteLength; @@ -63,7 +68,14 @@ export function event(s, event) { case EVENT.MOVE_CANVAS: { u32(s, event.offset_x); u32(s, event.offset_y); - f32(s, event.zoom); + s32(s, event.zoom_level); + break; + } + + case EVENT.ZOOM_CANVAS: { + s32(s, event.zoom_level); + f32(s, event.zoom_cx); + f32(s, event.zoom_cy); break; }