diff --git a/README.md b/README.md index aa482a4..6fad53b 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ Release: - Be able to have multiple "current" strokes per player. In case of bad internet this can happen! * Missing features I do not consider bonus + Player pointers - - Player list - - Follow player + + Pretty player pointers + + Player list + + Follow player - Eraser - Line drawing - Follow player (like Ligma) diff --git a/client/aux.js b/client/aux.js index 7b81a18..39acf24 100644 --- a/client/aux.js +++ b/client/aux.js @@ -41,7 +41,12 @@ function event_size(event) { size += 4 * 2; break; } - + + case EVENT.MOVE_CANVAS: { + size += 4 * 2 + 4; + break; + } + case EVENT.LEAVE: case EVENT.CLEAR: { break; @@ -161,12 +166,45 @@ function HTML(html) { return template.content.firstChild; } +function toggle_follow_player(state, player_id) { + document.querySelectorAll('.player-list .player').forEach(p => p.classList.remove('following')); + + if (state.following_player === null) { + state.following_player = player_id; + } else { + if (player_id === state.following_player) { + state.following_player = null; + } else { + state.following_player = player_id; + } + } + + const player_element = document.querySelector(`.player-list .player[data-player-id="${state.following_player}"]`); + if (player_element) player_element.classList.add('following'); + + send_follow(state.following_player); +} + function insert_player_cursor(state, player_id) { const color = random_bright_color_from_seed(parseInt(player_id)); const path_copy = state.cursor_path.cloneNode(); + path_copy.style.fill = color; + const cursor = HTML(``); + const player = HTML(`
`); + + player.style.background = color; + + player.addEventListener('click', () => { + toggle_follow_player(state, player_id); + }); + document.querySelector('.html-hud').appendChild(cursor); + document.querySelector('.player-list').appendChild(player); + + document.querySelector('.player-list').classList.remove('vhide'); + return cursor; } diff --git a/client/client_recv.js b/client/client_recv.js index 5aed22e..f0e4d4c 100644 --- a/client/client_recv.js +++ b/client/client_recv.js @@ -26,6 +26,12 @@ function des_u32(d) { return value; } +function des_s32(d) { + const value = d.view.getInt32(d.offset, true); + d.offset += 4; + return value; +} + function des_f32(d) { const value = d.view.getFloat32(d.offset, true); d.offset += 4; @@ -69,6 +75,13 @@ function des_event(d, state = null) { break; } + case EVENT.MOVE_CANVAS: { + event.offset_x = des_s32(d); + event.offset_y = des_s32(d); + event.zoom = des_f32(d); + break; + } + case EVENT.SET_COLOR: { event.color = des_u32(d); break; @@ -191,6 +204,19 @@ function handle_event(state, context, event, options = {}) { break; } + case EVENT.MOVE_CANVAS: { + // Double-check just in case + // Non-triple equals in on purpose + 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; + need_draw = true; + } + + break; + } + case EVENT.SET_COLOR: { state.players[event.user_id].color = event.color; break; diff --git a/client/client_send.js b/client/client_send.js index e7525d8..8780d45 100644 --- a/client/client_send.js +++ b/client/client_send.js @@ -85,6 +85,13 @@ function ser_event(s, event) { break; } + case EVENT.MOVE_CANVAS: { + ser_u32(s, event.offset_x); + ser_u32(s, event.offset_y); + ser_f32(s, event.zoom); + break; + } + case EVENT.SET_COLOR: { ser_u32(s, event.color); break; @@ -150,8 +157,24 @@ async function send_ack(sn) { } } -async function sync_queue(state) { +async function send_follow(player_id) { + const s = serializer_create(4 + 4); + + player_id = player_id === null ? -1 : player_id; + + ser_u32(s, MESSAGE.FOLLOW); + ser_u32(s, player_id); + + if (config.debug_print) console.debug(`follow ${player_id} out`); + + try { + if (ws) await ws.send(s.buffer); + } catch (e) { + ws.close(); + } +} +async function sync_queue(state) { if (ws === null) { if (config.debug_print) console.debug('socket has closed, stopping SYNs'); return; @@ -326,3 +349,12 @@ function movecursor_event(x, y) { 'y': y, }; } + +function movecanvas_event(state) { + return { + 'type': EVENT.MOVE_CANVAS, + 'offset_x': state.canvas.offset.x, + 'offset_y': state.canvas.offset.y, + 'zoom': state.canvas.zoom, + }; +} diff --git a/client/default.css b/client/default.css index bd9507b..5cf06a9 100644 --- a/client/default.css +++ b/client/default.css @@ -27,6 +27,10 @@ body.offline .main { display: none !important; } +.vhide { + visibility: hidden !important; +} + .flexcol { display: flex; flex-direction: column; @@ -79,7 +83,7 @@ canvas.mousemoving { } .pallete-wrapper, -.sizer-wrapper { +.top-wrapper { position: fixed; top: 0; left: 0; @@ -91,12 +95,47 @@ canvas.mousemoving { transition: var(--transform-amimate); } -.sizer-wrapper { +.top-wrapper { height: unset; width: 100%; flex-direction: row; } +.player-list { + position: absolute; + right: 0; + height: 42px; + padding-left: var(--gap); + padding-right: var(--gap); + background: var(--dark-blue); + display: flex; + gap: var(--gap); + align-items: center; + border-bottom-left-radius: var(--radius); + pointer-events: all; +} + +.player-list .player { + width: 24px; + height: 24px; + border-radius: var(--radius); + display: flex; + justify-content: center; + align-items: center; + border: 2px solid transparent; + box-sizing: border-box; +} + +.player-list .player.following { + border-color: white; +} + +.player-list .player img { + height: 12px; + width: 12px; + filter: invert(100%); +} + .pallete { pointer-events: all; display: grid; @@ -114,7 +153,7 @@ canvas.mousemoving { transform: translateX(-125%); /* to account for a selected color, which is also offset to the right */ } -.sizer-wrapper.hidden { +.top-wrapper.hidden { transform: translateY(-125%); } diff --git a/client/icons/player.svg b/client/icons/player.svg new file mode 100644 index 0000000..01839ed --- /dev/null +++ b/client/icons/player.svg @@ -0,0 +1,57 @@ + + + + diff --git a/client/index.html b/client/index.html index 2723500..e02d380 100644 --- a/client/index.html +++ b/client/index.html @@ -7,22 +7,22 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +