Browse Source

Better draw->move cancellation. Instead of not registering short strokes, cancel them for all users if we registered a second finger during the time window.

ssao
A.Olokhtonov 1 year ago
parent
commit
14faef4146
  1. 4
      client/aux.js
  2. 9
      client/client_recv.js
  3. 10
      client/client_send.js
  4. 24
      client/index.html
  5. 3
      client/index.js
  6. 1
      client/webgl_geometry.js
  7. 45
      client/webgl_listeners.js
  8. 4
      server/deserializer.js
  9. 1
      server/enums.js
  10. 4
      server/send.js
  11. 4
      server/serializer.js

4
client/aux.js

@ -41,6 +41,10 @@ function event_size(event) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
size += 4; size += 4;
break; break;

9
client/client_recv.js

@ -57,6 +57,10 @@ function des_event(d) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
event.color = des_u32(d); event.color = des_u32(d);
break; break;
@ -150,6 +154,11 @@ function handle_event(state, context, event) {
break; break;
} }
case EVENT.CLEAR: {
geometry_clear_player(state, context, event.user_id);
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
state.players[event.user_id].color = event.color; state.players[event.user_id].color = event.color;
break; break;

10
client/client_send.js

@ -57,6 +57,10 @@ function ser_event(s, event) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
ser_u32(s, event.color); ser_u32(s, event.color);
break; break;
@ -285,3 +289,9 @@ function stroke_event(state) {
'color': stroke.color, 'color': stroke.color,
}; };
} }
function clear_event(state) {
return {
'type': EVENT.CLEAR
};
}

24
client/index.html

@ -7,20 +7,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="shortcut icon" href="icons/favicon.svg" id="favicon"> <link rel="shortcut icon" href="icons/favicon.svg" id="favicon">
<link rel="stylesheet" type="text/css" href="default.css?v=50"> <link rel="stylesheet" type="text/css" href="default.css?v=57">
<script type="text/javascript" src="aux.js?v=50"></script> <script type="text/javascript" src="aux.js?v=57"></script>
<script type="text/javascript" src="math.js?v=50"></script> <script type="text/javascript" src="math.js?v=57"></script>
<script type="text/javascript" src="tools.js?v=50"></script> <script type="text/javascript" src="tools.js?v=57"></script>
<script type="text/javascript" src="webgl_geometry.js?v=50"></script> <script type="text/javascript" src="webgl_geometry.js?v=57"></script>
<script type="text/javascript" src="webgl_shaders.js?v=50"></script> <script type="text/javascript" src="webgl_shaders.js?v=57"></script>
<script type="text/javascript" src="webgl_listeners.js?v=50"></script> <script type="text/javascript" src="webgl_listeners.js?v=57"></script>
<script type="text/javascript" src="webgl_draw.js?v=50"></script> <script type="text/javascript" src="webgl_draw.js?v=57"></script>
<script type="text/javascript" src="index.js?v=50"></script> <script type="text/javascript" src="index.js?v=57"></script>
<script type="text/javascript" src="client_send.js?v=50"></script> <script type="text/javascript" src="client_send.js?v=57"></script>
<script type="text/javascript" src="client_recv.js?v=50"></script> <script type="text/javascript" src="client_recv.js?v=57"></script>
<script type="text/javascript" src="websocket.js?v=50"></script> <script type="text/javascript" src="websocket.js?v=57"></script>
</head> </head>
<body> <body>
<div class="main"> <div class="main">

3
client/index.js

@ -25,9 +25,10 @@ const EVENT = Object.freeze({
PREDRAW: 10, PREDRAW: 10,
SET_COLOR: 11, SET_COLOR: 11,
SET_WIDTH: 12, SET_WIDTH: 12,
CLEAR: 13, // clear predraw events from me (because I started a pan instead of drawing)
STROKE: 20, STROKE: 20,
RULER: 21, /* gets re-written with EVENT.STROKE before sending to server */ RULER: 21, // gets re-written with EVENT.STROKE before sending to server
UNDO: 30, UNDO: 30,
REDO: 31, REDO: 31,

1
client/webgl_geometry.js

@ -169,6 +169,7 @@ function geometry_clear_player(state, context, player_id) {
if (!state.online) return; if (!state.online) return;
state.players[player_id].points.length = 0; state.players[player_id].points.length = 0;
recompute_dynamic_data(state, context); recompute_dynamic_data(state, context);
schedule_draw(state, context);
} }
function add_image(context, image_id, bitmap, p) { function add_image(context, image_id, bitmap, p) {

45
client/webgl_listeners.js

@ -252,14 +252,9 @@ function wheel(e, state, context) {
schedule_draw(state, context); schedule_draw(state, context);
} }
function touchstart(e, state) { function touchstart(e, state, context) {
e.preventDefault(); e.preventDefault();
if (state.touch.drawing) {
// Ingore subsequent touches if we are already drawing
return;
}
// First finger(s) down? // First finger(s) down?
if (state.touch.ids.length === 0) { if (state.touch.ids.length === 0) {
if (e.changedTouches.length === 1) { if (e.changedTouches.length === 1) {
@ -269,6 +264,7 @@ function touchstart(e, state) {
state.touch.moves = 0; state.touch.moves = 0;
state.touch.buffered.length = 0; state.touch.buffered.length = 0;
state.touch.ids.push(e.changedTouches[0].identifier); state.touch.ids.push(e.changedTouches[0].identifier);
state.touch.drawing = true;
setTimeout(() => { setTimeout(() => {
state.touch.waiting_for_second_finger = false; state.touch.waiting_for_second_finger = false;
@ -283,6 +279,9 @@ function touchstart(e, state) {
// There are touches already // There are touches already
if (state.touch.waiting_for_second_finger) { if (state.touch.waiting_for_second_finger) {
if (e.changedTouches.length === 1) { if (e.changedTouches.length === 1) {
geometry_clear_player(state, context, state.me); // Hide predraws of this stroke that is not means to be
fire_event(state, clear_event(state)); // Tell others to hide predraws of this stroke
state.touch.ids.push(e.changedTouches[0].identifier); state.touch.ids.push(e.changedTouches[0].identifier);
for (const touch of e.touches) { for (const touch of e.touches) {
@ -317,35 +316,17 @@ function touchmove(e, state, context) {
return; return;
} }
if (!state.touch.drawing) { state.touch.moves += 1;
// Buffer this move
state.touch.moves += 1;
if (state.touch.moves > config.buffer_first_touchmoves) { if (state.touch.moves > config.buffer_first_touchmoves) {
// Start drawing, no more waiting // At this point touch with second finger will NOT start a pan
state.touch.waiting_for_second_finger = false; state.touch.waiting_for_second_finger = false;
state.touch.drawing = true; }
} else {
state.touch.buffered.push(canvasp);
}
} else {
// Handle buffered moves
if (state.touch.buffered.length > 0) {
geometry_clear_player(state, context, state.me);
for (const p of state.touch.buffered) {
geometry_add_point(state, context, state.me, p);
fire_event(state, predraw_event(p.x, p.y));
}
state.touch.buffered.length = 0;
}
geometry_add_point(state, context, state.me, canvasp); geometry_add_point(state, context, state.me, canvasp);
fire_event(state, predraw_event(canvasp.x, canvasp.y)); fire_event(state, predraw_event(canvasp.x, canvasp.y));
schedule_draw(state, context); schedule_draw(state, context);
}
return; return;
} }

4
server/deserializer.js

@ -56,6 +56,10 @@ export function event(d) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
event.color = u32(d); event.color = u32(d);
break; break;

1
server/enums.js

@ -8,6 +8,7 @@ export const EVENT = Object.freeze({
PREDRAW: 10, PREDRAW: 10,
SET_COLOR: 11, SET_COLOR: 11,
SET_WIDTH: 12, SET_WIDTH: 12,
CLEAR: 13,
STROKE: 20, STROKE: 20,
UNDO: 30, UNDO: 30,
REDO: 31, REDO: 31,

4
server/send.js

@ -15,6 +15,10 @@ function event_size(event) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
size += 4; size += 4;
break; break;

4
server/serializer.js

@ -47,6 +47,10 @@ export function event(s, event) {
break; break;
} }
case EVENT.CLEAR: {
break;
}
case EVENT.SET_COLOR: { case EVENT.SET_COLOR: {
u32(s, event.color); u32(s, event.color);
break; break;

Loading…
Cancel
Save