microboard-temp 0.11.9 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/browser.js +143 -0
- package/dist/cjs/index.js +143 -0
- package/dist/cjs/node.js +143 -0
- package/dist/esm/browser.js +143 -0
- package/dist/esm/index.js +143 -0
- package/dist/esm/node.js +143 -0
- package/dist/types/Board.d.ts +4 -0
- package/dist/types/Gravity/GravityEngine.d.ts +20 -0
- package/dist/types/Items/Transformation/Transformation.d.ts +1 -0
- package/package.json +1 -1
package/dist/cjs/browser.js
CHANGED
|
@@ -18214,6 +18214,16 @@ class Transformation {
|
|
|
18214
18214
|
shearY: 0
|
|
18215
18215
|
}, timeStamp);
|
|
18216
18216
|
}
|
|
18217
|
+
applyMatrixSilent(matrixData) {
|
|
18218
|
+
this.previous = this._matrix.copy();
|
|
18219
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
18220
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
18221
|
+
this.subject.publish(this, {
|
|
18222
|
+
class: "Transformation",
|
|
18223
|
+
method: "applyMatrix",
|
|
18224
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
18225
|
+
});
|
|
18226
|
+
}
|
|
18217
18227
|
setIsLocked(isLocked, timestamp) {
|
|
18218
18228
|
if (isLocked) {
|
|
18219
18229
|
this.emit({
|
|
@@ -54286,6 +54296,123 @@ class BoardSelection {
|
|
|
54286
54296
|
});
|
|
54287
54297
|
}
|
|
54288
54298
|
}
|
|
54299
|
+
// src/Gravity/GravityEngine.ts
|
|
54300
|
+
class GravityEngine {
|
|
54301
|
+
board;
|
|
54302
|
+
velocities = new Map;
|
|
54303
|
+
tickTimer = null;
|
|
54304
|
+
syncTimer = null;
|
|
54305
|
+
lastSyncedPositions = new Map;
|
|
54306
|
+
G = 500;
|
|
54307
|
+
DAMPING = 0.98;
|
|
54308
|
+
TICK_MS = 33;
|
|
54309
|
+
SYNC_MS = 300;
|
|
54310
|
+
MAX_DISTANCE = 3000;
|
|
54311
|
+
SOFTENING_SQ = 50 * 50;
|
|
54312
|
+
MIN_MOVE_PX = 0.1;
|
|
54313
|
+
constructor(board) {
|
|
54314
|
+
this.board = board;
|
|
54315
|
+
}
|
|
54316
|
+
start() {
|
|
54317
|
+
if (this.tickTimer !== null)
|
|
54318
|
+
return;
|
|
54319
|
+
for (const item of this.board.items.listAll()) {
|
|
54320
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54321
|
+
}
|
|
54322
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54323
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54324
|
+
}
|
|
54325
|
+
stop() {
|
|
54326
|
+
if (this.tickTimer !== null) {
|
|
54327
|
+
clearInterval(this.tickTimer);
|
|
54328
|
+
this.tickTimer = null;
|
|
54329
|
+
}
|
|
54330
|
+
if (this.syncTimer !== null) {
|
|
54331
|
+
clearInterval(this.syncTimer);
|
|
54332
|
+
this.syncTimer = null;
|
|
54333
|
+
}
|
|
54334
|
+
this.velocities.clear();
|
|
54335
|
+
this.lastSyncedPositions.clear();
|
|
54336
|
+
}
|
|
54337
|
+
tick() {
|
|
54338
|
+
const dt = this.TICK_MS / 1000;
|
|
54339
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54340
|
+
if (items.length < 2)
|
|
54341
|
+
return;
|
|
54342
|
+
for (const item of items) {
|
|
54343
|
+
const id = item.getId();
|
|
54344
|
+
if (!this.velocities.has(id)) {
|
|
54345
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54346
|
+
}
|
|
54347
|
+
const vel = this.velocities.get(id);
|
|
54348
|
+
const pos1 = item.transformation.getTranslation();
|
|
54349
|
+
const mbr1 = item.getMbr();
|
|
54350
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
54351
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
54352
|
+
let ax = 0;
|
|
54353
|
+
let ay = 0;
|
|
54354
|
+
for (const other of nearby) {
|
|
54355
|
+
const pos2 = other.transformation.getTranslation();
|
|
54356
|
+
const mbr2 = other.getMbr();
|
|
54357
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
54358
|
+
const dx2 = pos2.x - pos1.x;
|
|
54359
|
+
const dy2 = pos2.y - pos1.y;
|
|
54360
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
54361
|
+
const dist = Math.sqrt(distSq);
|
|
54362
|
+
const acc = this.G * mass2 / distSq;
|
|
54363
|
+
ax += acc * dx2 / dist;
|
|
54364
|
+
ay += acc * dy2 / dist;
|
|
54365
|
+
}
|
|
54366
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
54367
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
54368
|
+
const dx = vel.vx * dt;
|
|
54369
|
+
const dy = vel.vy * dt;
|
|
54370
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
54371
|
+
item.transformation.applyMatrixSilent({
|
|
54372
|
+
translateX: dx,
|
|
54373
|
+
translateY: dy,
|
|
54374
|
+
scaleX: 1,
|
|
54375
|
+
scaleY: 1,
|
|
54376
|
+
shearX: 0,
|
|
54377
|
+
shearY: 0
|
|
54378
|
+
});
|
|
54379
|
+
}
|
|
54380
|
+
}
|
|
54381
|
+
}
|
|
54382
|
+
syncPositions() {
|
|
54383
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54384
|
+
if (items.length === 0)
|
|
54385
|
+
return;
|
|
54386
|
+
const movedItems = items.map((item) => {
|
|
54387
|
+
const id = item.getId();
|
|
54388
|
+
const pos = item.transformation.getTranslation();
|
|
54389
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54390
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54391
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54392
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54393
|
+
return { id, dx, dy };
|
|
54394
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54395
|
+
if (movedItems.length === 0)
|
|
54396
|
+
return;
|
|
54397
|
+
const operation = {
|
|
54398
|
+
class: "Transformation",
|
|
54399
|
+
method: "applyMatrix",
|
|
54400
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54401
|
+
id,
|
|
54402
|
+
matrix: {
|
|
54403
|
+
translateX: dx,
|
|
54404
|
+
translateY: dy,
|
|
54405
|
+
scaleX: 1,
|
|
54406
|
+
scaleY: 1,
|
|
54407
|
+
shearX: 0,
|
|
54408
|
+
shearY: 0
|
|
54409
|
+
}
|
|
54410
|
+
}))
|
|
54411
|
+
};
|
|
54412
|
+
this.board.events.emit(operation);
|
|
54413
|
+
}
|
|
54414
|
+
}
|
|
54415
|
+
|
|
54289
54416
|
// src/Board.ts
|
|
54290
54417
|
class Board {
|
|
54291
54418
|
boardId;
|
|
@@ -55308,6 +55435,22 @@ class Board {
|
|
|
55308
55435
|
this.selection.quickAddButtons.clear();
|
|
55309
55436
|
this.presence.cleanup();
|
|
55310
55437
|
}
|
|
55438
|
+
gravity = null;
|
|
55439
|
+
enableGravity() {
|
|
55440
|
+
if (this.gravity)
|
|
55441
|
+
return;
|
|
55442
|
+
this.gravity = new GravityEngine(this);
|
|
55443
|
+
this.gravity.start();
|
|
55444
|
+
}
|
|
55445
|
+
disableGravity() {
|
|
55446
|
+
if (!this.gravity)
|
|
55447
|
+
return;
|
|
55448
|
+
this.gravity.stop();
|
|
55449
|
+
this.gravity = null;
|
|
55450
|
+
}
|
|
55451
|
+
isGravityEnabled() {
|
|
55452
|
+
return this.gravity !== null;
|
|
55453
|
+
}
|
|
55311
55454
|
}
|
|
55312
55455
|
// src/Events/Merge.ts
|
|
55313
55456
|
var import_slate36 = require("slate");
|
package/dist/cjs/index.js
CHANGED
|
@@ -18214,6 +18214,16 @@ class Transformation {
|
|
|
18214
18214
|
shearY: 0
|
|
18215
18215
|
}, timeStamp);
|
|
18216
18216
|
}
|
|
18217
|
+
applyMatrixSilent(matrixData) {
|
|
18218
|
+
this.previous = this._matrix.copy();
|
|
18219
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
18220
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
18221
|
+
this.subject.publish(this, {
|
|
18222
|
+
class: "Transformation",
|
|
18223
|
+
method: "applyMatrix",
|
|
18224
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
18225
|
+
});
|
|
18226
|
+
}
|
|
18217
18227
|
setIsLocked(isLocked, timestamp) {
|
|
18218
18228
|
if (isLocked) {
|
|
18219
18229
|
this.emit({
|
|
@@ -54286,6 +54296,123 @@ class BoardSelection {
|
|
|
54286
54296
|
});
|
|
54287
54297
|
}
|
|
54288
54298
|
}
|
|
54299
|
+
// src/Gravity/GravityEngine.ts
|
|
54300
|
+
class GravityEngine {
|
|
54301
|
+
board;
|
|
54302
|
+
velocities = new Map;
|
|
54303
|
+
tickTimer = null;
|
|
54304
|
+
syncTimer = null;
|
|
54305
|
+
lastSyncedPositions = new Map;
|
|
54306
|
+
G = 500;
|
|
54307
|
+
DAMPING = 0.98;
|
|
54308
|
+
TICK_MS = 33;
|
|
54309
|
+
SYNC_MS = 300;
|
|
54310
|
+
MAX_DISTANCE = 3000;
|
|
54311
|
+
SOFTENING_SQ = 50 * 50;
|
|
54312
|
+
MIN_MOVE_PX = 0.1;
|
|
54313
|
+
constructor(board) {
|
|
54314
|
+
this.board = board;
|
|
54315
|
+
}
|
|
54316
|
+
start() {
|
|
54317
|
+
if (this.tickTimer !== null)
|
|
54318
|
+
return;
|
|
54319
|
+
for (const item of this.board.items.listAll()) {
|
|
54320
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54321
|
+
}
|
|
54322
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54323
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54324
|
+
}
|
|
54325
|
+
stop() {
|
|
54326
|
+
if (this.tickTimer !== null) {
|
|
54327
|
+
clearInterval(this.tickTimer);
|
|
54328
|
+
this.tickTimer = null;
|
|
54329
|
+
}
|
|
54330
|
+
if (this.syncTimer !== null) {
|
|
54331
|
+
clearInterval(this.syncTimer);
|
|
54332
|
+
this.syncTimer = null;
|
|
54333
|
+
}
|
|
54334
|
+
this.velocities.clear();
|
|
54335
|
+
this.lastSyncedPositions.clear();
|
|
54336
|
+
}
|
|
54337
|
+
tick() {
|
|
54338
|
+
const dt = this.TICK_MS / 1000;
|
|
54339
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54340
|
+
if (items.length < 2)
|
|
54341
|
+
return;
|
|
54342
|
+
for (const item of items) {
|
|
54343
|
+
const id = item.getId();
|
|
54344
|
+
if (!this.velocities.has(id)) {
|
|
54345
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54346
|
+
}
|
|
54347
|
+
const vel = this.velocities.get(id);
|
|
54348
|
+
const pos1 = item.transformation.getTranslation();
|
|
54349
|
+
const mbr1 = item.getMbr();
|
|
54350
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
54351
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
54352
|
+
let ax = 0;
|
|
54353
|
+
let ay = 0;
|
|
54354
|
+
for (const other of nearby) {
|
|
54355
|
+
const pos2 = other.transformation.getTranslation();
|
|
54356
|
+
const mbr2 = other.getMbr();
|
|
54357
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
54358
|
+
const dx2 = pos2.x - pos1.x;
|
|
54359
|
+
const dy2 = pos2.y - pos1.y;
|
|
54360
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
54361
|
+
const dist = Math.sqrt(distSq);
|
|
54362
|
+
const acc = this.G * mass2 / distSq;
|
|
54363
|
+
ax += acc * dx2 / dist;
|
|
54364
|
+
ay += acc * dy2 / dist;
|
|
54365
|
+
}
|
|
54366
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
54367
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
54368
|
+
const dx = vel.vx * dt;
|
|
54369
|
+
const dy = vel.vy * dt;
|
|
54370
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
54371
|
+
item.transformation.applyMatrixSilent({
|
|
54372
|
+
translateX: dx,
|
|
54373
|
+
translateY: dy,
|
|
54374
|
+
scaleX: 1,
|
|
54375
|
+
scaleY: 1,
|
|
54376
|
+
shearX: 0,
|
|
54377
|
+
shearY: 0
|
|
54378
|
+
});
|
|
54379
|
+
}
|
|
54380
|
+
}
|
|
54381
|
+
}
|
|
54382
|
+
syncPositions() {
|
|
54383
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54384
|
+
if (items.length === 0)
|
|
54385
|
+
return;
|
|
54386
|
+
const movedItems = items.map((item) => {
|
|
54387
|
+
const id = item.getId();
|
|
54388
|
+
const pos = item.transformation.getTranslation();
|
|
54389
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54390
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54391
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54392
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54393
|
+
return { id, dx, dy };
|
|
54394
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54395
|
+
if (movedItems.length === 0)
|
|
54396
|
+
return;
|
|
54397
|
+
const operation = {
|
|
54398
|
+
class: "Transformation",
|
|
54399
|
+
method: "applyMatrix",
|
|
54400
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54401
|
+
id,
|
|
54402
|
+
matrix: {
|
|
54403
|
+
translateX: dx,
|
|
54404
|
+
translateY: dy,
|
|
54405
|
+
scaleX: 1,
|
|
54406
|
+
scaleY: 1,
|
|
54407
|
+
shearX: 0,
|
|
54408
|
+
shearY: 0
|
|
54409
|
+
}
|
|
54410
|
+
}))
|
|
54411
|
+
};
|
|
54412
|
+
this.board.events.emit(operation);
|
|
54413
|
+
}
|
|
54414
|
+
}
|
|
54415
|
+
|
|
54289
54416
|
// src/Board.ts
|
|
54290
54417
|
class Board {
|
|
54291
54418
|
boardId;
|
|
@@ -55308,6 +55435,22 @@ class Board {
|
|
|
55308
55435
|
this.selection.quickAddButtons.clear();
|
|
55309
55436
|
this.presence.cleanup();
|
|
55310
55437
|
}
|
|
55438
|
+
gravity = null;
|
|
55439
|
+
enableGravity() {
|
|
55440
|
+
if (this.gravity)
|
|
55441
|
+
return;
|
|
55442
|
+
this.gravity = new GravityEngine(this);
|
|
55443
|
+
this.gravity.start();
|
|
55444
|
+
}
|
|
55445
|
+
disableGravity() {
|
|
55446
|
+
if (!this.gravity)
|
|
55447
|
+
return;
|
|
55448
|
+
this.gravity.stop();
|
|
55449
|
+
this.gravity = null;
|
|
55450
|
+
}
|
|
55451
|
+
isGravityEnabled() {
|
|
55452
|
+
return this.gravity !== null;
|
|
55453
|
+
}
|
|
55311
55454
|
}
|
|
55312
55455
|
// src/Events/Merge.ts
|
|
55313
55456
|
var import_slate36 = require("slate");
|
package/dist/cjs/node.js
CHANGED
|
@@ -20754,6 +20754,16 @@ class Transformation {
|
|
|
20754
20754
|
shearY: 0
|
|
20755
20755
|
}, timeStamp);
|
|
20756
20756
|
}
|
|
20757
|
+
applyMatrixSilent(matrixData) {
|
|
20758
|
+
this.previous = this._matrix.copy();
|
|
20759
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
20760
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
20761
|
+
this.subject.publish(this, {
|
|
20762
|
+
class: "Transformation",
|
|
20763
|
+
method: "applyMatrix",
|
|
20764
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
20765
|
+
});
|
|
20766
|
+
}
|
|
20757
20767
|
setIsLocked(isLocked, timestamp) {
|
|
20758
20768
|
if (isLocked) {
|
|
20759
20769
|
this.emit({
|
|
@@ -56759,6 +56769,123 @@ class BoardSelection {
|
|
|
56759
56769
|
});
|
|
56760
56770
|
}
|
|
56761
56771
|
}
|
|
56772
|
+
// src/Gravity/GravityEngine.ts
|
|
56773
|
+
class GravityEngine {
|
|
56774
|
+
board;
|
|
56775
|
+
velocities = new Map;
|
|
56776
|
+
tickTimer = null;
|
|
56777
|
+
syncTimer = null;
|
|
56778
|
+
lastSyncedPositions = new Map;
|
|
56779
|
+
G = 500;
|
|
56780
|
+
DAMPING = 0.98;
|
|
56781
|
+
TICK_MS = 33;
|
|
56782
|
+
SYNC_MS = 300;
|
|
56783
|
+
MAX_DISTANCE = 3000;
|
|
56784
|
+
SOFTENING_SQ = 50 * 50;
|
|
56785
|
+
MIN_MOVE_PX = 0.1;
|
|
56786
|
+
constructor(board) {
|
|
56787
|
+
this.board = board;
|
|
56788
|
+
}
|
|
56789
|
+
start() {
|
|
56790
|
+
if (this.tickTimer !== null)
|
|
56791
|
+
return;
|
|
56792
|
+
for (const item of this.board.items.listAll()) {
|
|
56793
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
56794
|
+
}
|
|
56795
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
56796
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
56797
|
+
}
|
|
56798
|
+
stop() {
|
|
56799
|
+
if (this.tickTimer !== null) {
|
|
56800
|
+
clearInterval(this.tickTimer);
|
|
56801
|
+
this.tickTimer = null;
|
|
56802
|
+
}
|
|
56803
|
+
if (this.syncTimer !== null) {
|
|
56804
|
+
clearInterval(this.syncTimer);
|
|
56805
|
+
this.syncTimer = null;
|
|
56806
|
+
}
|
|
56807
|
+
this.velocities.clear();
|
|
56808
|
+
this.lastSyncedPositions.clear();
|
|
56809
|
+
}
|
|
56810
|
+
tick() {
|
|
56811
|
+
const dt = this.TICK_MS / 1000;
|
|
56812
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
56813
|
+
if (items.length < 2)
|
|
56814
|
+
return;
|
|
56815
|
+
for (const item of items) {
|
|
56816
|
+
const id = item.getId();
|
|
56817
|
+
if (!this.velocities.has(id)) {
|
|
56818
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
56819
|
+
}
|
|
56820
|
+
const vel = this.velocities.get(id);
|
|
56821
|
+
const pos1 = item.transformation.getTranslation();
|
|
56822
|
+
const mbr1 = item.getMbr();
|
|
56823
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
56824
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
56825
|
+
let ax = 0;
|
|
56826
|
+
let ay = 0;
|
|
56827
|
+
for (const other of nearby) {
|
|
56828
|
+
const pos2 = other.transformation.getTranslation();
|
|
56829
|
+
const mbr2 = other.getMbr();
|
|
56830
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
56831
|
+
const dx2 = pos2.x - pos1.x;
|
|
56832
|
+
const dy2 = pos2.y - pos1.y;
|
|
56833
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
56834
|
+
const dist = Math.sqrt(distSq);
|
|
56835
|
+
const acc = this.G * mass2 / distSq;
|
|
56836
|
+
ax += acc * dx2 / dist;
|
|
56837
|
+
ay += acc * dy2 / dist;
|
|
56838
|
+
}
|
|
56839
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
56840
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
56841
|
+
const dx = vel.vx * dt;
|
|
56842
|
+
const dy = vel.vy * dt;
|
|
56843
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
56844
|
+
item.transformation.applyMatrixSilent({
|
|
56845
|
+
translateX: dx,
|
|
56846
|
+
translateY: dy,
|
|
56847
|
+
scaleX: 1,
|
|
56848
|
+
scaleY: 1,
|
|
56849
|
+
shearX: 0,
|
|
56850
|
+
shearY: 0
|
|
56851
|
+
});
|
|
56852
|
+
}
|
|
56853
|
+
}
|
|
56854
|
+
}
|
|
56855
|
+
syncPositions() {
|
|
56856
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
56857
|
+
if (items.length === 0)
|
|
56858
|
+
return;
|
|
56859
|
+
const movedItems = items.map((item) => {
|
|
56860
|
+
const id = item.getId();
|
|
56861
|
+
const pos = item.transformation.getTranslation();
|
|
56862
|
+
const last = this.lastSyncedPositions.get(id);
|
|
56863
|
+
const dx = last ? pos.x - last.x : 0;
|
|
56864
|
+
const dy = last ? pos.y - last.y : 0;
|
|
56865
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
56866
|
+
return { id, dx, dy };
|
|
56867
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
56868
|
+
if (movedItems.length === 0)
|
|
56869
|
+
return;
|
|
56870
|
+
const operation = {
|
|
56871
|
+
class: "Transformation",
|
|
56872
|
+
method: "applyMatrix",
|
|
56873
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
56874
|
+
id,
|
|
56875
|
+
matrix: {
|
|
56876
|
+
translateX: dx,
|
|
56877
|
+
translateY: dy,
|
|
56878
|
+
scaleX: 1,
|
|
56879
|
+
scaleY: 1,
|
|
56880
|
+
shearX: 0,
|
|
56881
|
+
shearY: 0
|
|
56882
|
+
}
|
|
56883
|
+
}))
|
|
56884
|
+
};
|
|
56885
|
+
this.board.events.emit(operation);
|
|
56886
|
+
}
|
|
56887
|
+
}
|
|
56888
|
+
|
|
56762
56889
|
// src/Board.ts
|
|
56763
56890
|
class Board {
|
|
56764
56891
|
boardId;
|
|
@@ -57781,6 +57908,22 @@ class Board {
|
|
|
57781
57908
|
this.selection.quickAddButtons.clear();
|
|
57782
57909
|
this.presence.cleanup();
|
|
57783
57910
|
}
|
|
57911
|
+
gravity = null;
|
|
57912
|
+
enableGravity() {
|
|
57913
|
+
if (this.gravity)
|
|
57914
|
+
return;
|
|
57915
|
+
this.gravity = new GravityEngine(this);
|
|
57916
|
+
this.gravity.start();
|
|
57917
|
+
}
|
|
57918
|
+
disableGravity() {
|
|
57919
|
+
if (!this.gravity)
|
|
57920
|
+
return;
|
|
57921
|
+
this.gravity.stop();
|
|
57922
|
+
this.gravity = null;
|
|
57923
|
+
}
|
|
57924
|
+
isGravityEnabled() {
|
|
57925
|
+
return this.gravity !== null;
|
|
57926
|
+
}
|
|
57784
57927
|
}
|
|
57785
57928
|
// src/Events/Merge.ts
|
|
57786
57929
|
var import_slate35 = require("slate");
|
package/dist/esm/browser.js
CHANGED
|
@@ -18043,6 +18043,16 @@ class Transformation {
|
|
|
18043
18043
|
shearY: 0
|
|
18044
18044
|
}, timeStamp);
|
|
18045
18045
|
}
|
|
18046
|
+
applyMatrixSilent(matrixData) {
|
|
18047
|
+
this.previous = this._matrix.copy();
|
|
18048
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
18049
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
18050
|
+
this.subject.publish(this, {
|
|
18051
|
+
class: "Transformation",
|
|
18052
|
+
method: "applyMatrix",
|
|
18053
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
18054
|
+
});
|
|
18055
|
+
}
|
|
18046
18056
|
setIsLocked(isLocked, timestamp) {
|
|
18047
18057
|
if (isLocked) {
|
|
18048
18058
|
this.emit({
|
|
@@ -54115,6 +54125,123 @@ class BoardSelection {
|
|
|
54115
54125
|
});
|
|
54116
54126
|
}
|
|
54117
54127
|
}
|
|
54128
|
+
// src/Gravity/GravityEngine.ts
|
|
54129
|
+
class GravityEngine {
|
|
54130
|
+
board;
|
|
54131
|
+
velocities = new Map;
|
|
54132
|
+
tickTimer = null;
|
|
54133
|
+
syncTimer = null;
|
|
54134
|
+
lastSyncedPositions = new Map;
|
|
54135
|
+
G = 500;
|
|
54136
|
+
DAMPING = 0.98;
|
|
54137
|
+
TICK_MS = 33;
|
|
54138
|
+
SYNC_MS = 300;
|
|
54139
|
+
MAX_DISTANCE = 3000;
|
|
54140
|
+
SOFTENING_SQ = 50 * 50;
|
|
54141
|
+
MIN_MOVE_PX = 0.1;
|
|
54142
|
+
constructor(board) {
|
|
54143
|
+
this.board = board;
|
|
54144
|
+
}
|
|
54145
|
+
start() {
|
|
54146
|
+
if (this.tickTimer !== null)
|
|
54147
|
+
return;
|
|
54148
|
+
for (const item of this.board.items.listAll()) {
|
|
54149
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54150
|
+
}
|
|
54151
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54152
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54153
|
+
}
|
|
54154
|
+
stop() {
|
|
54155
|
+
if (this.tickTimer !== null) {
|
|
54156
|
+
clearInterval(this.tickTimer);
|
|
54157
|
+
this.tickTimer = null;
|
|
54158
|
+
}
|
|
54159
|
+
if (this.syncTimer !== null) {
|
|
54160
|
+
clearInterval(this.syncTimer);
|
|
54161
|
+
this.syncTimer = null;
|
|
54162
|
+
}
|
|
54163
|
+
this.velocities.clear();
|
|
54164
|
+
this.lastSyncedPositions.clear();
|
|
54165
|
+
}
|
|
54166
|
+
tick() {
|
|
54167
|
+
const dt = this.TICK_MS / 1000;
|
|
54168
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54169
|
+
if (items.length < 2)
|
|
54170
|
+
return;
|
|
54171
|
+
for (const item of items) {
|
|
54172
|
+
const id = item.getId();
|
|
54173
|
+
if (!this.velocities.has(id)) {
|
|
54174
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54175
|
+
}
|
|
54176
|
+
const vel = this.velocities.get(id);
|
|
54177
|
+
const pos1 = item.transformation.getTranslation();
|
|
54178
|
+
const mbr1 = item.getMbr();
|
|
54179
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
54180
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
54181
|
+
let ax = 0;
|
|
54182
|
+
let ay = 0;
|
|
54183
|
+
for (const other of nearby) {
|
|
54184
|
+
const pos2 = other.transformation.getTranslation();
|
|
54185
|
+
const mbr2 = other.getMbr();
|
|
54186
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
54187
|
+
const dx2 = pos2.x - pos1.x;
|
|
54188
|
+
const dy2 = pos2.y - pos1.y;
|
|
54189
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
54190
|
+
const dist = Math.sqrt(distSq);
|
|
54191
|
+
const acc = this.G * mass2 / distSq;
|
|
54192
|
+
ax += acc * dx2 / dist;
|
|
54193
|
+
ay += acc * dy2 / dist;
|
|
54194
|
+
}
|
|
54195
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
54196
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
54197
|
+
const dx = vel.vx * dt;
|
|
54198
|
+
const dy = vel.vy * dt;
|
|
54199
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
54200
|
+
item.transformation.applyMatrixSilent({
|
|
54201
|
+
translateX: dx,
|
|
54202
|
+
translateY: dy,
|
|
54203
|
+
scaleX: 1,
|
|
54204
|
+
scaleY: 1,
|
|
54205
|
+
shearX: 0,
|
|
54206
|
+
shearY: 0
|
|
54207
|
+
});
|
|
54208
|
+
}
|
|
54209
|
+
}
|
|
54210
|
+
}
|
|
54211
|
+
syncPositions() {
|
|
54212
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54213
|
+
if (items.length === 0)
|
|
54214
|
+
return;
|
|
54215
|
+
const movedItems = items.map((item) => {
|
|
54216
|
+
const id = item.getId();
|
|
54217
|
+
const pos = item.transformation.getTranslation();
|
|
54218
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54219
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54220
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54221
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54222
|
+
return { id, dx, dy };
|
|
54223
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54224
|
+
if (movedItems.length === 0)
|
|
54225
|
+
return;
|
|
54226
|
+
const operation = {
|
|
54227
|
+
class: "Transformation",
|
|
54228
|
+
method: "applyMatrix",
|
|
54229
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54230
|
+
id,
|
|
54231
|
+
matrix: {
|
|
54232
|
+
translateX: dx,
|
|
54233
|
+
translateY: dy,
|
|
54234
|
+
scaleX: 1,
|
|
54235
|
+
scaleY: 1,
|
|
54236
|
+
shearX: 0,
|
|
54237
|
+
shearY: 0
|
|
54238
|
+
}
|
|
54239
|
+
}))
|
|
54240
|
+
};
|
|
54241
|
+
this.board.events.emit(operation);
|
|
54242
|
+
}
|
|
54243
|
+
}
|
|
54244
|
+
|
|
54118
54245
|
// src/Board.ts
|
|
54119
54246
|
class Board {
|
|
54120
54247
|
boardId;
|
|
@@ -55137,6 +55264,22 @@ class Board {
|
|
|
55137
55264
|
this.selection.quickAddButtons.clear();
|
|
55138
55265
|
this.presence.cleanup();
|
|
55139
55266
|
}
|
|
55267
|
+
gravity = null;
|
|
55268
|
+
enableGravity() {
|
|
55269
|
+
if (this.gravity)
|
|
55270
|
+
return;
|
|
55271
|
+
this.gravity = new GravityEngine(this);
|
|
55272
|
+
this.gravity.start();
|
|
55273
|
+
}
|
|
55274
|
+
disableGravity() {
|
|
55275
|
+
if (!this.gravity)
|
|
55276
|
+
return;
|
|
55277
|
+
this.gravity.stop();
|
|
55278
|
+
this.gravity = null;
|
|
55279
|
+
}
|
|
55280
|
+
isGravityEnabled() {
|
|
55281
|
+
return this.gravity !== null;
|
|
55282
|
+
}
|
|
55140
55283
|
}
|
|
55141
55284
|
// src/Events/Merge.ts
|
|
55142
55285
|
import { Path as Path15 } from "slate";
|
package/dist/esm/index.js
CHANGED
|
@@ -18036,6 +18036,16 @@ class Transformation {
|
|
|
18036
18036
|
shearY: 0
|
|
18037
18037
|
}, timeStamp);
|
|
18038
18038
|
}
|
|
18039
|
+
applyMatrixSilent(matrixData) {
|
|
18040
|
+
this.previous = this._matrix.copy();
|
|
18041
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
18042
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
18043
|
+
this.subject.publish(this, {
|
|
18044
|
+
class: "Transformation",
|
|
18045
|
+
method: "applyMatrix",
|
|
18046
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
18047
|
+
});
|
|
18048
|
+
}
|
|
18039
18049
|
setIsLocked(isLocked, timestamp) {
|
|
18040
18050
|
if (isLocked) {
|
|
18041
18051
|
this.emit({
|
|
@@ -54108,6 +54118,123 @@ class BoardSelection {
|
|
|
54108
54118
|
});
|
|
54109
54119
|
}
|
|
54110
54120
|
}
|
|
54121
|
+
// src/Gravity/GravityEngine.ts
|
|
54122
|
+
class GravityEngine {
|
|
54123
|
+
board;
|
|
54124
|
+
velocities = new Map;
|
|
54125
|
+
tickTimer = null;
|
|
54126
|
+
syncTimer = null;
|
|
54127
|
+
lastSyncedPositions = new Map;
|
|
54128
|
+
G = 500;
|
|
54129
|
+
DAMPING = 0.98;
|
|
54130
|
+
TICK_MS = 33;
|
|
54131
|
+
SYNC_MS = 300;
|
|
54132
|
+
MAX_DISTANCE = 3000;
|
|
54133
|
+
SOFTENING_SQ = 50 * 50;
|
|
54134
|
+
MIN_MOVE_PX = 0.1;
|
|
54135
|
+
constructor(board) {
|
|
54136
|
+
this.board = board;
|
|
54137
|
+
}
|
|
54138
|
+
start() {
|
|
54139
|
+
if (this.tickTimer !== null)
|
|
54140
|
+
return;
|
|
54141
|
+
for (const item of this.board.items.listAll()) {
|
|
54142
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54143
|
+
}
|
|
54144
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54145
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54146
|
+
}
|
|
54147
|
+
stop() {
|
|
54148
|
+
if (this.tickTimer !== null) {
|
|
54149
|
+
clearInterval(this.tickTimer);
|
|
54150
|
+
this.tickTimer = null;
|
|
54151
|
+
}
|
|
54152
|
+
if (this.syncTimer !== null) {
|
|
54153
|
+
clearInterval(this.syncTimer);
|
|
54154
|
+
this.syncTimer = null;
|
|
54155
|
+
}
|
|
54156
|
+
this.velocities.clear();
|
|
54157
|
+
this.lastSyncedPositions.clear();
|
|
54158
|
+
}
|
|
54159
|
+
tick() {
|
|
54160
|
+
const dt = this.TICK_MS / 1000;
|
|
54161
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54162
|
+
if (items.length < 2)
|
|
54163
|
+
return;
|
|
54164
|
+
for (const item of items) {
|
|
54165
|
+
const id = item.getId();
|
|
54166
|
+
if (!this.velocities.has(id)) {
|
|
54167
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54168
|
+
}
|
|
54169
|
+
const vel = this.velocities.get(id);
|
|
54170
|
+
const pos1 = item.transformation.getTranslation();
|
|
54171
|
+
const mbr1 = item.getMbr();
|
|
54172
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
54173
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
54174
|
+
let ax = 0;
|
|
54175
|
+
let ay = 0;
|
|
54176
|
+
for (const other of nearby) {
|
|
54177
|
+
const pos2 = other.transformation.getTranslation();
|
|
54178
|
+
const mbr2 = other.getMbr();
|
|
54179
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
54180
|
+
const dx2 = pos2.x - pos1.x;
|
|
54181
|
+
const dy2 = pos2.y - pos1.y;
|
|
54182
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
54183
|
+
const dist = Math.sqrt(distSq);
|
|
54184
|
+
const acc = this.G * mass2 / distSq;
|
|
54185
|
+
ax += acc * dx2 / dist;
|
|
54186
|
+
ay += acc * dy2 / dist;
|
|
54187
|
+
}
|
|
54188
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
54189
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
54190
|
+
const dx = vel.vx * dt;
|
|
54191
|
+
const dy = vel.vy * dt;
|
|
54192
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
54193
|
+
item.transformation.applyMatrixSilent({
|
|
54194
|
+
translateX: dx,
|
|
54195
|
+
translateY: dy,
|
|
54196
|
+
scaleX: 1,
|
|
54197
|
+
scaleY: 1,
|
|
54198
|
+
shearX: 0,
|
|
54199
|
+
shearY: 0
|
|
54200
|
+
});
|
|
54201
|
+
}
|
|
54202
|
+
}
|
|
54203
|
+
}
|
|
54204
|
+
syncPositions() {
|
|
54205
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
54206
|
+
if (items.length === 0)
|
|
54207
|
+
return;
|
|
54208
|
+
const movedItems = items.map((item) => {
|
|
54209
|
+
const id = item.getId();
|
|
54210
|
+
const pos = item.transformation.getTranslation();
|
|
54211
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54212
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54213
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54214
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54215
|
+
return { id, dx, dy };
|
|
54216
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54217
|
+
if (movedItems.length === 0)
|
|
54218
|
+
return;
|
|
54219
|
+
const operation = {
|
|
54220
|
+
class: "Transformation",
|
|
54221
|
+
method: "applyMatrix",
|
|
54222
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54223
|
+
id,
|
|
54224
|
+
matrix: {
|
|
54225
|
+
translateX: dx,
|
|
54226
|
+
translateY: dy,
|
|
54227
|
+
scaleX: 1,
|
|
54228
|
+
scaleY: 1,
|
|
54229
|
+
shearX: 0,
|
|
54230
|
+
shearY: 0
|
|
54231
|
+
}
|
|
54232
|
+
}))
|
|
54233
|
+
};
|
|
54234
|
+
this.board.events.emit(operation);
|
|
54235
|
+
}
|
|
54236
|
+
}
|
|
54237
|
+
|
|
54111
54238
|
// src/Board.ts
|
|
54112
54239
|
class Board {
|
|
54113
54240
|
boardId;
|
|
@@ -55130,6 +55257,22 @@ class Board {
|
|
|
55130
55257
|
this.selection.quickAddButtons.clear();
|
|
55131
55258
|
this.presence.cleanup();
|
|
55132
55259
|
}
|
|
55260
|
+
gravity = null;
|
|
55261
|
+
enableGravity() {
|
|
55262
|
+
if (this.gravity)
|
|
55263
|
+
return;
|
|
55264
|
+
this.gravity = new GravityEngine(this);
|
|
55265
|
+
this.gravity.start();
|
|
55266
|
+
}
|
|
55267
|
+
disableGravity() {
|
|
55268
|
+
if (!this.gravity)
|
|
55269
|
+
return;
|
|
55270
|
+
this.gravity.stop();
|
|
55271
|
+
this.gravity = null;
|
|
55272
|
+
}
|
|
55273
|
+
isGravityEnabled() {
|
|
55274
|
+
return this.gravity !== null;
|
|
55275
|
+
}
|
|
55133
55276
|
}
|
|
55134
55277
|
// src/Events/Merge.ts
|
|
55135
55278
|
import { Path as Path15 } from "slate";
|
package/dist/esm/node.js
CHANGED
|
@@ -20571,6 +20571,16 @@ class Transformation {
|
|
|
20571
20571
|
shearY: 0
|
|
20572
20572
|
}, timeStamp);
|
|
20573
20573
|
}
|
|
20574
|
+
applyMatrixSilent(matrixData) {
|
|
20575
|
+
this.previous = this._matrix.copy();
|
|
20576
|
+
this._matrix.scale(matrixData.scaleX, matrixData.scaleY);
|
|
20577
|
+
this._matrix.translate(matrixData.translateX, matrixData.translateY);
|
|
20578
|
+
this.subject.publish(this, {
|
|
20579
|
+
class: "Transformation",
|
|
20580
|
+
method: "applyMatrix",
|
|
20581
|
+
items: [{ id: this.id, matrix: matrixData }]
|
|
20582
|
+
});
|
|
20583
|
+
}
|
|
20574
20584
|
setIsLocked(isLocked, timestamp) {
|
|
20575
20585
|
if (isLocked) {
|
|
20576
20586
|
this.emit({
|
|
@@ -56576,6 +56586,123 @@ class BoardSelection {
|
|
|
56576
56586
|
});
|
|
56577
56587
|
}
|
|
56578
56588
|
}
|
|
56589
|
+
// src/Gravity/GravityEngine.ts
|
|
56590
|
+
class GravityEngine {
|
|
56591
|
+
board;
|
|
56592
|
+
velocities = new Map;
|
|
56593
|
+
tickTimer = null;
|
|
56594
|
+
syncTimer = null;
|
|
56595
|
+
lastSyncedPositions = new Map;
|
|
56596
|
+
G = 500;
|
|
56597
|
+
DAMPING = 0.98;
|
|
56598
|
+
TICK_MS = 33;
|
|
56599
|
+
SYNC_MS = 300;
|
|
56600
|
+
MAX_DISTANCE = 3000;
|
|
56601
|
+
SOFTENING_SQ = 50 * 50;
|
|
56602
|
+
MIN_MOVE_PX = 0.1;
|
|
56603
|
+
constructor(board) {
|
|
56604
|
+
this.board = board;
|
|
56605
|
+
}
|
|
56606
|
+
start() {
|
|
56607
|
+
if (this.tickTimer !== null)
|
|
56608
|
+
return;
|
|
56609
|
+
for (const item of this.board.items.listAll()) {
|
|
56610
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
56611
|
+
}
|
|
56612
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
56613
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
56614
|
+
}
|
|
56615
|
+
stop() {
|
|
56616
|
+
if (this.tickTimer !== null) {
|
|
56617
|
+
clearInterval(this.tickTimer);
|
|
56618
|
+
this.tickTimer = null;
|
|
56619
|
+
}
|
|
56620
|
+
if (this.syncTimer !== null) {
|
|
56621
|
+
clearInterval(this.syncTimer);
|
|
56622
|
+
this.syncTimer = null;
|
|
56623
|
+
}
|
|
56624
|
+
this.velocities.clear();
|
|
56625
|
+
this.lastSyncedPositions.clear();
|
|
56626
|
+
}
|
|
56627
|
+
tick() {
|
|
56628
|
+
const dt = this.TICK_MS / 1000;
|
|
56629
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
56630
|
+
if (items.length < 2)
|
|
56631
|
+
return;
|
|
56632
|
+
for (const item of items) {
|
|
56633
|
+
const id = item.getId();
|
|
56634
|
+
if (!this.velocities.has(id)) {
|
|
56635
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
56636
|
+
}
|
|
56637
|
+
const vel = this.velocities.get(id);
|
|
56638
|
+
const pos1 = item.transformation.getTranslation();
|
|
56639
|
+
const mbr1 = item.getMbr();
|
|
56640
|
+
const mass1 = mbr1.getWidth() * mbr1.getHeight();
|
|
56641
|
+
const nearby = this.board.items.getEnclosedOrCrossed(pos1.x - this.MAX_DISTANCE, pos1.y - this.MAX_DISTANCE, pos1.x + this.MAX_DISTANCE * 2, pos1.y + this.MAX_DISTANCE * 2).filter((other) => other.getId() !== id);
|
|
56642
|
+
let ax = 0;
|
|
56643
|
+
let ay = 0;
|
|
56644
|
+
for (const other of nearby) {
|
|
56645
|
+
const pos2 = other.transformation.getTranslation();
|
|
56646
|
+
const mbr2 = other.getMbr();
|
|
56647
|
+
const mass2 = mbr2.getWidth() * mbr2.getHeight();
|
|
56648
|
+
const dx2 = pos2.x - pos1.x;
|
|
56649
|
+
const dy2 = pos2.y - pos1.y;
|
|
56650
|
+
const distSq = dx2 * dx2 + dy2 * dy2 + this.SOFTENING_SQ;
|
|
56651
|
+
const dist = Math.sqrt(distSq);
|
|
56652
|
+
const acc = this.G * mass2 / distSq;
|
|
56653
|
+
ax += acc * dx2 / dist;
|
|
56654
|
+
ay += acc * dy2 / dist;
|
|
56655
|
+
}
|
|
56656
|
+
vel.vx = (vel.vx + ax * dt) * this.DAMPING;
|
|
56657
|
+
vel.vy = (vel.vy + ay * dt) * this.DAMPING;
|
|
56658
|
+
const dx = vel.vx * dt;
|
|
56659
|
+
const dy = vel.vy * dt;
|
|
56660
|
+
if (Math.abs(dx) >= this.MIN_MOVE_PX || Math.abs(dy) >= this.MIN_MOVE_PX) {
|
|
56661
|
+
item.transformation.applyMatrixSilent({
|
|
56662
|
+
translateX: dx,
|
|
56663
|
+
translateY: dy,
|
|
56664
|
+
scaleX: 1,
|
|
56665
|
+
scaleY: 1,
|
|
56666
|
+
shearX: 0,
|
|
56667
|
+
shearY: 0
|
|
56668
|
+
});
|
|
56669
|
+
}
|
|
56670
|
+
}
|
|
56671
|
+
}
|
|
56672
|
+
syncPositions() {
|
|
56673
|
+
const items = this.board.items.listAll().filter((item) => !item.transformation.isLocked);
|
|
56674
|
+
if (items.length === 0)
|
|
56675
|
+
return;
|
|
56676
|
+
const movedItems = items.map((item) => {
|
|
56677
|
+
const id = item.getId();
|
|
56678
|
+
const pos = item.transformation.getTranslation();
|
|
56679
|
+
const last = this.lastSyncedPositions.get(id);
|
|
56680
|
+
const dx = last ? pos.x - last.x : 0;
|
|
56681
|
+
const dy = last ? pos.y - last.y : 0;
|
|
56682
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
56683
|
+
return { id, dx, dy };
|
|
56684
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
56685
|
+
if (movedItems.length === 0)
|
|
56686
|
+
return;
|
|
56687
|
+
const operation = {
|
|
56688
|
+
class: "Transformation",
|
|
56689
|
+
method: "applyMatrix",
|
|
56690
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
56691
|
+
id,
|
|
56692
|
+
matrix: {
|
|
56693
|
+
translateX: dx,
|
|
56694
|
+
translateY: dy,
|
|
56695
|
+
scaleX: 1,
|
|
56696
|
+
scaleY: 1,
|
|
56697
|
+
shearX: 0,
|
|
56698
|
+
shearY: 0
|
|
56699
|
+
}
|
|
56700
|
+
}))
|
|
56701
|
+
};
|
|
56702
|
+
this.board.events.emit(operation);
|
|
56703
|
+
}
|
|
56704
|
+
}
|
|
56705
|
+
|
|
56579
56706
|
// src/Board.ts
|
|
56580
56707
|
class Board {
|
|
56581
56708
|
boardId;
|
|
@@ -57598,6 +57725,22 @@ class Board {
|
|
|
57598
57725
|
this.selection.quickAddButtons.clear();
|
|
57599
57726
|
this.presence.cleanup();
|
|
57600
57727
|
}
|
|
57728
|
+
gravity = null;
|
|
57729
|
+
enableGravity() {
|
|
57730
|
+
if (this.gravity)
|
|
57731
|
+
return;
|
|
57732
|
+
this.gravity = new GravityEngine(this);
|
|
57733
|
+
this.gravity.start();
|
|
57734
|
+
}
|
|
57735
|
+
disableGravity() {
|
|
57736
|
+
if (!this.gravity)
|
|
57737
|
+
return;
|
|
57738
|
+
this.gravity.stop();
|
|
57739
|
+
this.gravity = null;
|
|
57740
|
+
}
|
|
57741
|
+
isGravityEnabled() {
|
|
57742
|
+
return this.gravity !== null;
|
|
57743
|
+
}
|
|
57601
57744
|
}
|
|
57602
57745
|
// src/Events/Merge.ts
|
|
57603
57746
|
import { Path as Path14 } from "slate";
|
package/dist/types/Board.d.ts
CHANGED
|
@@ -133,6 +133,10 @@ export declare class Board {
|
|
|
133
133
|
setIsOpen(isOpen: boolean): void;
|
|
134
134
|
getIsOpen(): boolean;
|
|
135
135
|
cleanup(): void;
|
|
136
|
+
private gravity;
|
|
137
|
+
enableGravity(): void;
|
|
138
|
+
disableGravity(): void;
|
|
139
|
+
isGravityEnabled(): boolean;
|
|
136
140
|
}
|
|
137
141
|
export interface BoardSnapshot {
|
|
138
142
|
items: (ItemData & {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Board } from '../Board';
|
|
2
|
+
export declare class GravityEngine {
|
|
3
|
+
private board;
|
|
4
|
+
private velocities;
|
|
5
|
+
private tickTimer;
|
|
6
|
+
private syncTimer;
|
|
7
|
+
private lastSyncedPositions;
|
|
8
|
+
readonly G = 500;
|
|
9
|
+
readonly DAMPING = 0.98;
|
|
10
|
+
readonly TICK_MS = 33;
|
|
11
|
+
readonly SYNC_MS = 300;
|
|
12
|
+
readonly MAX_DISTANCE = 3000;
|
|
13
|
+
readonly SOFTENING_SQ: number;
|
|
14
|
+
readonly MIN_MOVE_PX = 0.1;
|
|
15
|
+
constructor(board: Board);
|
|
16
|
+
start(): void;
|
|
17
|
+
stop(): void;
|
|
18
|
+
private tick;
|
|
19
|
+
private syncPositions;
|
|
20
|
+
}
|
|
@@ -61,6 +61,7 @@ export declare class Transformation {
|
|
|
61
61
|
rotateBy(degree: number, timeStamp?: number): void;
|
|
62
62
|
scaleToRelativeTo(x: number, y: number, _point: Point, timeStamp?: number): void;
|
|
63
63
|
scaleByRelativeTo(x: number, y: number, point: Point, timeStamp?: number): void;
|
|
64
|
+
applyMatrixSilent(matrixData: MatrixData): void;
|
|
64
65
|
setIsLocked(isLocked: boolean, timestamp?: number): void;
|
|
65
66
|
apply(op: Operation): void;
|
|
66
67
|
/** @deprecated Only for replaying legacy events. Do not call directly. */
|