Browse Source

Merge scale and move local history, fixing undo for image move/scale

sdf
A.Olokhtonov 2 months ago
parent
commit
fea2874004
  1. 14
      README.txt
  2. 24
      client/client_recv.js
  3. 53
      client/undo.js
  4. 8
      client/webgl_geometry.js
  5. 2
      client/webgl_listeners.js

14
README.txt

@ -16,8 +16,9 @@ Release: @@ -16,8 +16,9 @@ Release:
+ Stroke previews get connected when drawn without panning on touch devices
+ Redraw HTML (cursors) on local canvas moves
+ New strokes dissapear on the HMH desk
+ Undo history of moving and scaling images seems messed up
- Nothing get's drawn if we enable snapping and draw a curve where first and last point match
- Undo history of moving and scaling images seems messed up
- Weird clipping on HMH desk full zoomout after running "benchmark"
- Debug
- Restore ability to limit event range
* Listeners/events/multiplayer
@ -30,6 +31,7 @@ Release: @@ -30,6 +31,7 @@ Release:
+ Be able to have multiple "current" strokes per player. In case of bad internet this can happen!
- Do NOT use session id as player id LUL
- Save events to indexeddb (as some kind of a blob), restore on reconnect and page reload
- Handle out of space
- Local prediction for tools!
- Immediately commit a stroke to the canvas, change order if earlier strokes arrive
- Show my own image immediately, show placeholders while images are loading (add bitmap size to event)
@ -52,12 +54,17 @@ Release: @@ -52,12 +54,17 @@ Release:
- Redo
+ Snapping to grid
- Snapping to other points?
- Color picker should work for ruler
- Show previous color in color picker preview
- Stick picker preview to cursor
* Polish
+ Use typedvector where appropriate
- Show what's happening while the desk is loading (downloading, processing, uploading to gpu)
- Settings panel for config values (including the setting for "offline mode")
- Set up VAOs
- We are calling "geometry_prepare_stroke" twice for some reason
- Replace "geometry_add_dummy_stroke" with something not [so] cursed
- Automatically extract locations from shaders (see nitka project for code examples)
- Presentation / "marketing"
- Title (InfiNotes? MegaDesk?)
- Icon
@ -80,6 +87,11 @@ Bonus: @@ -80,6 +87,11 @@ Bonus:
+ Dots pattern
+ Grid pattern
- Menu option
- Offline mode
- Only one user
- No server, everything applied immediately
- Allow export to file
- Save to browser storage (probaby indexed db + recent events in localstorage)
Bonus-bonus:
- Actually infinite canvas (replace floats with something, some kind of fixed point scheme? chunks? multilevel scheme?)

24
client/client_recv.js

@ -407,16 +407,7 @@ function handle_event(state, context, event, options = {}) { @@ -407,16 +407,7 @@ 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;
push_image_move(image, event.x, event.y);
need_draw = true;
}
@ -429,18 +420,7 @@ function handle_event(state, context, event, options = {}) { @@ -429,18 +420,7 @@ 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});
push_image_scale(image, event.corner, event.x, event.y);
need_draw = true;
}

53
client/undo.js

@ -42,9 +42,7 @@ function undo(state, context, event, options) { @@ -42,9 +42,7 @@ function undo(state, context, event, options) {
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];
pop_image_transform(image);
need_draw = true;
} else {
console.warning('Undo image move for a non-existent image');
@ -56,15 +54,7 @@ function undo(state, context, event, options) { @@ -56,15 +54,7 @@ function undo(state, context, event, options) {
other_event.deleted = true;
const image = get_image(context, other_event.image_id);
if (image !== null) {
image.scale_head -= 4;
// NEXT: merge move and scale. Otherwise we can't know
// that there have been move events inbetween scale
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];
pop_image_transform(image);
need_draw = true;
} else {
console.warning('Undo image scale for a non-existent image');
@ -101,3 +91,42 @@ function undo(state, context, event, options) { @@ -101,3 +91,42 @@ function undo(state, context, event, options) {
function redo() {
console.log('TODO');
}
function push_image_move(image, x, y) {
if (image.transform_head < image.transform_history.length) {
image.transform_history[image.transform_head] = image.at.x;
image.transform_history[image.transform_head + 1] = image.at.y;
image.transform_history[image.transform_head + 2] = image.width;
image.transform_history[image.transform_head + 3] = image.height;
} else {
image.transform_history.push(image.at.x, image.at.y, image.width, image.height);
}
image.at.x = x;
image.at.y = y;
image.transform_head += 4;
}
function push_image_scale(image, corner, x, y) {
if (image.transform_head < image.transform_history.length) {
image.transform_history[image.transform_head] = image.at.x;
image.transform_history[image.transform_head + 1] = image.at.y;
image.transform_history[image.transform_head + 2] = image.width;
image.transform_history[image.transform_head + 3] = image.height;
} else {
image.transform_history.push(image.at.x, image.at.y, image.width, image.height);
}
scale_image(image, corner, {'x': x, 'y': y});
image.transform_head += 4;
}
function pop_image_transform(image, corner, x, y) {
image.transform_head -= 4;
image.at.x = image.transform_history[image.transform_head - 4];
image.at.y = image.transform_history[image.transform_head - 3];
image.width = image.transform_history[image.transform_head - 2];
image.height = image.transform_history[image.transform_head - 1];
}

8
client/webgl_geometry.js

@ -209,10 +209,8 @@ function add_image(context, image_id, bitmap, p, width, height) { @@ -209,10 +209,8 @@ 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,
'transform_history': [ p.x, p.y, width, height ],
'transform_head': 4,
};
context.images.push(entry);
@ -234,7 +232,7 @@ function add_image(context, image_id, bitmap, p, width, height) { @@ -234,7 +232,7 @@ function add_image(context, image_id, bitmap, p, width, height) {
}
}
function scale_image(context, image, corner, canvasp) {
function scale_image(image, corner, canvasp) {
let new_width, new_height;
const old_x2 = image.at.x + image.width;

2
client/webgl_listeners.js

@ -386,7 +386,7 @@ function mousemove(e, state, context) { @@ -386,7 +386,7 @@ function mousemove(e, state, context) {
if (state.imagescaling) {
const image = get_image(context, state.active_image);
scale_image(context, image, state.scaling_corner, canvasp);
scale_image(image, state.scaling_corner, canvasp);
do_draw = true;
}

Loading…
Cancel
Save