microboard-temp 0.13.14 → 0.13.16
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 +197 -0
- package/dist/cjs/index.js +197 -0
- package/dist/cjs/node.js +197 -0
- package/dist/esm/browser.js +197 -0
- package/dist/esm/index.js +197 -0
- package/dist/esm/node.js +197 -0
- package/dist/types/Board.d.ts +6 -0
- package/dist/types/ForceGraph/ForceGraphEngine.d.ts +21 -0
- package/dist/types/Settings.d.ts +5 -0
- package/package.json +1 -1
package/dist/cjs/browser.js
CHANGED
|
@@ -4675,6 +4675,11 @@ var conf = {
|
|
|
4675
4675
|
DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
|
|
4676
4676
|
MAX_CARD_SIZE: 500,
|
|
4677
4677
|
CONNECTOR_ITEM_OFFSET: 20,
|
|
4678
|
+
FG_SPRING_K: 3,
|
|
4679
|
+
FG_TARGET_GAP: 60,
|
|
4680
|
+
FG_REPULSION: 400000,
|
|
4681
|
+
FG_DAMPING: 0.8,
|
|
4682
|
+
FG_SLEEP_THRESHOLD: 0.5,
|
|
4678
4683
|
GRAVITY_G: 80,
|
|
4679
4684
|
GRAVITY_G_CENTER: 120,
|
|
4680
4685
|
GRAVITY_DAMPING: 0.96,
|
|
@@ -54428,6 +54433,8 @@ class GravityEngine {
|
|
|
54428
54433
|
if (this.tickTimer !== null)
|
|
54429
54434
|
return;
|
|
54430
54435
|
for (const item of this.board.items.listAll()) {
|
|
54436
|
+
const pos = item.transformation.getTranslation();
|
|
54437
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
54431
54438
|
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54432
54439
|
}
|
|
54433
54440
|
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
@@ -54442,6 +54449,7 @@ class GravityEngine {
|
|
|
54442
54449
|
clearInterval(this.syncTimer);
|
|
54443
54450
|
this.syncTimer = null;
|
|
54444
54451
|
}
|
|
54452
|
+
this.syncPositions();
|
|
54445
54453
|
this.velocities.clear();
|
|
54446
54454
|
this.lastSyncedPositions.clear();
|
|
54447
54455
|
}
|
|
@@ -54566,6 +54574,176 @@ class GravityEngine {
|
|
|
54566
54574
|
}
|
|
54567
54575
|
}
|
|
54568
54576
|
|
|
54577
|
+
// src/ForceGraph/ForceGraphEngine.ts
|
|
54578
|
+
var EXCLUDED_TYPES = new Set(["Connector", "Comment"]);
|
|
54579
|
+
|
|
54580
|
+
class ForceGraphEngine {
|
|
54581
|
+
board;
|
|
54582
|
+
velocities = new Map;
|
|
54583
|
+
tickTimer = null;
|
|
54584
|
+
syncTimer = null;
|
|
54585
|
+
lastSyncedPositions = new Map;
|
|
54586
|
+
TICK_MS = 33;
|
|
54587
|
+
SYNC_MS = 300;
|
|
54588
|
+
SOFTENING_SQ = 100 * 100;
|
|
54589
|
+
MIN_MOVE_PX = 0.05;
|
|
54590
|
+
constructor(board) {
|
|
54591
|
+
this.board = board;
|
|
54592
|
+
}
|
|
54593
|
+
start() {
|
|
54594
|
+
if (this.tickTimer !== null)
|
|
54595
|
+
return;
|
|
54596
|
+
for (const item of this.getNodes()) {
|
|
54597
|
+
const pos = item.transformation.getTranslation();
|
|
54598
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
54599
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54600
|
+
}
|
|
54601
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54602
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54603
|
+
}
|
|
54604
|
+
stop() {
|
|
54605
|
+
if (this.tickTimer !== null) {
|
|
54606
|
+
clearInterval(this.tickTimer);
|
|
54607
|
+
this.tickTimer = null;
|
|
54608
|
+
}
|
|
54609
|
+
if (this.syncTimer !== null) {
|
|
54610
|
+
clearInterval(this.syncTimer);
|
|
54611
|
+
this.syncTimer = null;
|
|
54612
|
+
}
|
|
54613
|
+
this.syncPositions();
|
|
54614
|
+
this.velocities.clear();
|
|
54615
|
+
this.lastSyncedPositions.clear();
|
|
54616
|
+
}
|
|
54617
|
+
getNodes() {
|
|
54618
|
+
return this.board.items.listAll().filter((item) => !EXCLUDED_TYPES.has(item.itemType) && !item.transformation.isLocked);
|
|
54619
|
+
}
|
|
54620
|
+
getConnectors() {
|
|
54621
|
+
return this.board.items.listAll().filter((item) => item.itemType === "Connector");
|
|
54622
|
+
}
|
|
54623
|
+
tick() {
|
|
54624
|
+
const dt = this.TICK_MS / 1000;
|
|
54625
|
+
const nodes = this.getNodes();
|
|
54626
|
+
if (nodes.length < 2)
|
|
54627
|
+
return;
|
|
54628
|
+
const snapMap = new Map;
|
|
54629
|
+
for (const item of nodes) {
|
|
54630
|
+
const pos = item.transformation.getTranslation();
|
|
54631
|
+
const mbr = item.getMbr();
|
|
54632
|
+
const w = Math.max(mbr.getWidth(), 1);
|
|
54633
|
+
const h2 = Math.max(mbr.getHeight(), 1);
|
|
54634
|
+
snapMap.set(item.getId(), {
|
|
54635
|
+
id: item.getId(),
|
|
54636
|
+
cx: pos.x + w * 0.5,
|
|
54637
|
+
cy: pos.y + h2 * 0.5,
|
|
54638
|
+
w,
|
|
54639
|
+
h: h2
|
|
54640
|
+
});
|
|
54641
|
+
}
|
|
54642
|
+
const snap = Array.from(snapMap.values());
|
|
54643
|
+
const ax = new Map;
|
|
54644
|
+
const ay = new Map;
|
|
54645
|
+
for (const s2 of snap) {
|
|
54646
|
+
ax.set(s2.id, 0);
|
|
54647
|
+
ay.set(s2.id, 0);
|
|
54648
|
+
}
|
|
54649
|
+
for (const connector of this.getConnectors()) {
|
|
54650
|
+
const { startItem, endItem } = connector.getConnectedItems();
|
|
54651
|
+
if (!startItem || !endItem)
|
|
54652
|
+
continue;
|
|
54653
|
+
const s1 = snapMap.get(startItem.getId());
|
|
54654
|
+
const s2 = snapMap.get(endItem.getId());
|
|
54655
|
+
if (!s1 || !s2)
|
|
54656
|
+
continue;
|
|
54657
|
+
const dx = s2.cx - s1.cx;
|
|
54658
|
+
const dy = s2.cy - s1.cy;
|
|
54659
|
+
const dist = Math.sqrt(dx * dx + dy * dy) + 0.001;
|
|
54660
|
+
const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + conf.FG_TARGET_GAP;
|
|
54661
|
+
const stretch = dist - targetDist;
|
|
54662
|
+
const forceMag = stretch * conf.FG_SPRING_K;
|
|
54663
|
+
const fx = dx / dist * forceMag;
|
|
54664
|
+
const fy = dy / dist * forceMag;
|
|
54665
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
|
|
54666
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) + fy);
|
|
54667
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) - fx);
|
|
54668
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) - fy);
|
|
54669
|
+
}
|
|
54670
|
+
for (let i = 0;i < snap.length; i++) {
|
|
54671
|
+
for (let j = i + 1;j < snap.length; j++) {
|
|
54672
|
+
const s1 = snap[i];
|
|
54673
|
+
const s2 = snap[j];
|
|
54674
|
+
const dx = s2.cx - s1.cx;
|
|
54675
|
+
const dy = s2.cy - s1.cy;
|
|
54676
|
+
const distSq = dx * dx + dy * dy + this.SOFTENING_SQ;
|
|
54677
|
+
const repMag = conf.FG_REPULSION / distSq;
|
|
54678
|
+
const fx = dx * repMag;
|
|
54679
|
+
const fy = dy * repMag;
|
|
54680
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) - fx);
|
|
54681
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) - fy);
|
|
54682
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) + fx);
|
|
54683
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) + fy);
|
|
54684
|
+
}
|
|
54685
|
+
}
|
|
54686
|
+
let totalEnergy = 0;
|
|
54687
|
+
for (const item of nodes) {
|
|
54688
|
+
const id = item.getId();
|
|
54689
|
+
if (!this.velocities.has(id)) {
|
|
54690
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54691
|
+
}
|
|
54692
|
+
const vel = this.velocities.get(id);
|
|
54693
|
+
vel.vx = (vel.vx + (ax.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
54694
|
+
vel.vy = (vel.vy + (ay.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
54695
|
+
totalEnergy += vel.vx * vel.vx + vel.vy * vel.vy;
|
|
54696
|
+
const moveX = vel.vx * dt;
|
|
54697
|
+
const moveY = vel.vy * dt;
|
|
54698
|
+
if (Math.abs(moveX) >= this.MIN_MOVE_PX || Math.abs(moveY) >= this.MIN_MOVE_PX) {
|
|
54699
|
+
item.transformation.applyMatrixSilent({
|
|
54700
|
+
translateX: moveX,
|
|
54701
|
+
translateY: moveY,
|
|
54702
|
+
scaleX: 1,
|
|
54703
|
+
scaleY: 1,
|
|
54704
|
+
shearX: 0,
|
|
54705
|
+
shearY: 0
|
|
54706
|
+
});
|
|
54707
|
+
}
|
|
54708
|
+
}
|
|
54709
|
+
if (totalEnergy < conf.FG_SLEEP_THRESHOLD && this.tickTimer !== null) {
|
|
54710
|
+
clearInterval(this.tickTimer);
|
|
54711
|
+
this.tickTimer = null;
|
|
54712
|
+
this.syncPositions();
|
|
54713
|
+
}
|
|
54714
|
+
}
|
|
54715
|
+
syncPositions() {
|
|
54716
|
+
const nodes = this.getNodes();
|
|
54717
|
+
if (nodes.length === 0)
|
|
54718
|
+
return;
|
|
54719
|
+
const movedItems = nodes.map((item) => {
|
|
54720
|
+
const id = item.getId();
|
|
54721
|
+
const pos = item.transformation.getTranslation();
|
|
54722
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54723
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54724
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54725
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54726
|
+
return { id, dx, dy };
|
|
54727
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54728
|
+
if (movedItems.length === 0)
|
|
54729
|
+
return;
|
|
54730
|
+
const operation = {
|
|
54731
|
+
class: "Transformation",
|
|
54732
|
+
method: "applyMatrix",
|
|
54733
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54734
|
+
id,
|
|
54735
|
+
matrix: { translateX: dx, translateY: dy, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
|
|
54736
|
+
}))
|
|
54737
|
+
};
|
|
54738
|
+
this.board.events.emit(operation);
|
|
54739
|
+
}
|
|
54740
|
+
wake() {
|
|
54741
|
+
if (this.tickTimer === null && this.syncTimer !== null) {
|
|
54742
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54743
|
+
}
|
|
54744
|
+
}
|
|
54745
|
+
}
|
|
54746
|
+
|
|
54569
54747
|
// src/Board.ts
|
|
54570
54748
|
class Board {
|
|
54571
54749
|
boardId;
|
|
@@ -55638,6 +55816,25 @@ class Board {
|
|
|
55638
55816
|
isGravityEnabled() {
|
|
55639
55817
|
return this.gravity !== null;
|
|
55640
55818
|
}
|
|
55819
|
+
forceGraph = null;
|
|
55820
|
+
enableForceGraph() {
|
|
55821
|
+
if (this.forceGraph)
|
|
55822
|
+
return;
|
|
55823
|
+
this.forceGraph = new ForceGraphEngine(this);
|
|
55824
|
+
this.forceGraph.start();
|
|
55825
|
+
}
|
|
55826
|
+
disableForceGraph() {
|
|
55827
|
+
if (!this.forceGraph)
|
|
55828
|
+
return;
|
|
55829
|
+
this.forceGraph.stop();
|
|
55830
|
+
this.forceGraph = null;
|
|
55831
|
+
}
|
|
55832
|
+
isForceGraphEnabled() {
|
|
55833
|
+
return this.forceGraph !== null;
|
|
55834
|
+
}
|
|
55835
|
+
wakeForceGraph() {
|
|
55836
|
+
this.forceGraph?.wake();
|
|
55837
|
+
}
|
|
55641
55838
|
}
|
|
55642
55839
|
// src/Events/Merge.ts
|
|
55643
55840
|
var import_slate36 = require("slate");
|
package/dist/cjs/index.js
CHANGED
|
@@ -4675,6 +4675,11 @@ var conf = {
|
|
|
4675
4675
|
DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
|
|
4676
4676
|
MAX_CARD_SIZE: 500,
|
|
4677
4677
|
CONNECTOR_ITEM_OFFSET: 20,
|
|
4678
|
+
FG_SPRING_K: 3,
|
|
4679
|
+
FG_TARGET_GAP: 60,
|
|
4680
|
+
FG_REPULSION: 400000,
|
|
4681
|
+
FG_DAMPING: 0.8,
|
|
4682
|
+
FG_SLEEP_THRESHOLD: 0.5,
|
|
4678
4683
|
GRAVITY_G: 80,
|
|
4679
4684
|
GRAVITY_G_CENTER: 120,
|
|
4680
4685
|
GRAVITY_DAMPING: 0.96,
|
|
@@ -54428,6 +54433,8 @@ class GravityEngine {
|
|
|
54428
54433
|
if (this.tickTimer !== null)
|
|
54429
54434
|
return;
|
|
54430
54435
|
for (const item of this.board.items.listAll()) {
|
|
54436
|
+
const pos = item.transformation.getTranslation();
|
|
54437
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
54431
54438
|
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54432
54439
|
}
|
|
54433
54440
|
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
@@ -54442,6 +54449,7 @@ class GravityEngine {
|
|
|
54442
54449
|
clearInterval(this.syncTimer);
|
|
54443
54450
|
this.syncTimer = null;
|
|
54444
54451
|
}
|
|
54452
|
+
this.syncPositions();
|
|
54445
54453
|
this.velocities.clear();
|
|
54446
54454
|
this.lastSyncedPositions.clear();
|
|
54447
54455
|
}
|
|
@@ -54566,6 +54574,176 @@ class GravityEngine {
|
|
|
54566
54574
|
}
|
|
54567
54575
|
}
|
|
54568
54576
|
|
|
54577
|
+
// src/ForceGraph/ForceGraphEngine.ts
|
|
54578
|
+
var EXCLUDED_TYPES = new Set(["Connector", "Comment"]);
|
|
54579
|
+
|
|
54580
|
+
class ForceGraphEngine {
|
|
54581
|
+
board;
|
|
54582
|
+
velocities = new Map;
|
|
54583
|
+
tickTimer = null;
|
|
54584
|
+
syncTimer = null;
|
|
54585
|
+
lastSyncedPositions = new Map;
|
|
54586
|
+
TICK_MS = 33;
|
|
54587
|
+
SYNC_MS = 300;
|
|
54588
|
+
SOFTENING_SQ = 100 * 100;
|
|
54589
|
+
MIN_MOVE_PX = 0.05;
|
|
54590
|
+
constructor(board) {
|
|
54591
|
+
this.board = board;
|
|
54592
|
+
}
|
|
54593
|
+
start() {
|
|
54594
|
+
if (this.tickTimer !== null)
|
|
54595
|
+
return;
|
|
54596
|
+
for (const item of this.getNodes()) {
|
|
54597
|
+
const pos = item.transformation.getTranslation();
|
|
54598
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
54599
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
54600
|
+
}
|
|
54601
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54602
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
54603
|
+
}
|
|
54604
|
+
stop() {
|
|
54605
|
+
if (this.tickTimer !== null) {
|
|
54606
|
+
clearInterval(this.tickTimer);
|
|
54607
|
+
this.tickTimer = null;
|
|
54608
|
+
}
|
|
54609
|
+
if (this.syncTimer !== null) {
|
|
54610
|
+
clearInterval(this.syncTimer);
|
|
54611
|
+
this.syncTimer = null;
|
|
54612
|
+
}
|
|
54613
|
+
this.syncPositions();
|
|
54614
|
+
this.velocities.clear();
|
|
54615
|
+
this.lastSyncedPositions.clear();
|
|
54616
|
+
}
|
|
54617
|
+
getNodes() {
|
|
54618
|
+
return this.board.items.listAll().filter((item) => !EXCLUDED_TYPES.has(item.itemType) && !item.transformation.isLocked);
|
|
54619
|
+
}
|
|
54620
|
+
getConnectors() {
|
|
54621
|
+
return this.board.items.listAll().filter((item) => item.itemType === "Connector");
|
|
54622
|
+
}
|
|
54623
|
+
tick() {
|
|
54624
|
+
const dt = this.TICK_MS / 1000;
|
|
54625
|
+
const nodes = this.getNodes();
|
|
54626
|
+
if (nodes.length < 2)
|
|
54627
|
+
return;
|
|
54628
|
+
const snapMap = new Map;
|
|
54629
|
+
for (const item of nodes) {
|
|
54630
|
+
const pos = item.transformation.getTranslation();
|
|
54631
|
+
const mbr = item.getMbr();
|
|
54632
|
+
const w = Math.max(mbr.getWidth(), 1);
|
|
54633
|
+
const h2 = Math.max(mbr.getHeight(), 1);
|
|
54634
|
+
snapMap.set(item.getId(), {
|
|
54635
|
+
id: item.getId(),
|
|
54636
|
+
cx: pos.x + w * 0.5,
|
|
54637
|
+
cy: pos.y + h2 * 0.5,
|
|
54638
|
+
w,
|
|
54639
|
+
h: h2
|
|
54640
|
+
});
|
|
54641
|
+
}
|
|
54642
|
+
const snap = Array.from(snapMap.values());
|
|
54643
|
+
const ax = new Map;
|
|
54644
|
+
const ay = new Map;
|
|
54645
|
+
for (const s2 of snap) {
|
|
54646
|
+
ax.set(s2.id, 0);
|
|
54647
|
+
ay.set(s2.id, 0);
|
|
54648
|
+
}
|
|
54649
|
+
for (const connector of this.getConnectors()) {
|
|
54650
|
+
const { startItem, endItem } = connector.getConnectedItems();
|
|
54651
|
+
if (!startItem || !endItem)
|
|
54652
|
+
continue;
|
|
54653
|
+
const s1 = snapMap.get(startItem.getId());
|
|
54654
|
+
const s2 = snapMap.get(endItem.getId());
|
|
54655
|
+
if (!s1 || !s2)
|
|
54656
|
+
continue;
|
|
54657
|
+
const dx = s2.cx - s1.cx;
|
|
54658
|
+
const dy = s2.cy - s1.cy;
|
|
54659
|
+
const dist = Math.sqrt(dx * dx + dy * dy) + 0.001;
|
|
54660
|
+
const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + conf.FG_TARGET_GAP;
|
|
54661
|
+
const stretch = dist - targetDist;
|
|
54662
|
+
const forceMag = stretch * conf.FG_SPRING_K;
|
|
54663
|
+
const fx = dx / dist * forceMag;
|
|
54664
|
+
const fy = dy / dist * forceMag;
|
|
54665
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
|
|
54666
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) + fy);
|
|
54667
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) - fx);
|
|
54668
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) - fy);
|
|
54669
|
+
}
|
|
54670
|
+
for (let i = 0;i < snap.length; i++) {
|
|
54671
|
+
for (let j = i + 1;j < snap.length; j++) {
|
|
54672
|
+
const s1 = snap[i];
|
|
54673
|
+
const s2 = snap[j];
|
|
54674
|
+
const dx = s2.cx - s1.cx;
|
|
54675
|
+
const dy = s2.cy - s1.cy;
|
|
54676
|
+
const distSq = dx * dx + dy * dy + this.SOFTENING_SQ;
|
|
54677
|
+
const repMag = conf.FG_REPULSION / distSq;
|
|
54678
|
+
const fx = dx * repMag;
|
|
54679
|
+
const fy = dy * repMag;
|
|
54680
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) - fx);
|
|
54681
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) - fy);
|
|
54682
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) + fx);
|
|
54683
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) + fy);
|
|
54684
|
+
}
|
|
54685
|
+
}
|
|
54686
|
+
let totalEnergy = 0;
|
|
54687
|
+
for (const item of nodes) {
|
|
54688
|
+
const id = item.getId();
|
|
54689
|
+
if (!this.velocities.has(id)) {
|
|
54690
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
54691
|
+
}
|
|
54692
|
+
const vel = this.velocities.get(id);
|
|
54693
|
+
vel.vx = (vel.vx + (ax.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
54694
|
+
vel.vy = (vel.vy + (ay.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
54695
|
+
totalEnergy += vel.vx * vel.vx + vel.vy * vel.vy;
|
|
54696
|
+
const moveX = vel.vx * dt;
|
|
54697
|
+
const moveY = vel.vy * dt;
|
|
54698
|
+
if (Math.abs(moveX) >= this.MIN_MOVE_PX || Math.abs(moveY) >= this.MIN_MOVE_PX) {
|
|
54699
|
+
item.transformation.applyMatrixSilent({
|
|
54700
|
+
translateX: moveX,
|
|
54701
|
+
translateY: moveY,
|
|
54702
|
+
scaleX: 1,
|
|
54703
|
+
scaleY: 1,
|
|
54704
|
+
shearX: 0,
|
|
54705
|
+
shearY: 0
|
|
54706
|
+
});
|
|
54707
|
+
}
|
|
54708
|
+
}
|
|
54709
|
+
if (totalEnergy < conf.FG_SLEEP_THRESHOLD && this.tickTimer !== null) {
|
|
54710
|
+
clearInterval(this.tickTimer);
|
|
54711
|
+
this.tickTimer = null;
|
|
54712
|
+
this.syncPositions();
|
|
54713
|
+
}
|
|
54714
|
+
}
|
|
54715
|
+
syncPositions() {
|
|
54716
|
+
const nodes = this.getNodes();
|
|
54717
|
+
if (nodes.length === 0)
|
|
54718
|
+
return;
|
|
54719
|
+
const movedItems = nodes.map((item) => {
|
|
54720
|
+
const id = item.getId();
|
|
54721
|
+
const pos = item.transformation.getTranslation();
|
|
54722
|
+
const last = this.lastSyncedPositions.get(id);
|
|
54723
|
+
const dx = last ? pos.x - last.x : 0;
|
|
54724
|
+
const dy = last ? pos.y - last.y : 0;
|
|
54725
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
54726
|
+
return { id, dx, dy };
|
|
54727
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
54728
|
+
if (movedItems.length === 0)
|
|
54729
|
+
return;
|
|
54730
|
+
const operation = {
|
|
54731
|
+
class: "Transformation",
|
|
54732
|
+
method: "applyMatrix",
|
|
54733
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
54734
|
+
id,
|
|
54735
|
+
matrix: { translateX: dx, translateY: dy, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
|
|
54736
|
+
}))
|
|
54737
|
+
};
|
|
54738
|
+
this.board.events.emit(operation);
|
|
54739
|
+
}
|
|
54740
|
+
wake() {
|
|
54741
|
+
if (this.tickTimer === null && this.syncTimer !== null) {
|
|
54742
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
54743
|
+
}
|
|
54744
|
+
}
|
|
54745
|
+
}
|
|
54746
|
+
|
|
54569
54747
|
// src/Board.ts
|
|
54570
54748
|
class Board {
|
|
54571
54749
|
boardId;
|
|
@@ -55638,6 +55816,25 @@ class Board {
|
|
|
55638
55816
|
isGravityEnabled() {
|
|
55639
55817
|
return this.gravity !== null;
|
|
55640
55818
|
}
|
|
55819
|
+
forceGraph = null;
|
|
55820
|
+
enableForceGraph() {
|
|
55821
|
+
if (this.forceGraph)
|
|
55822
|
+
return;
|
|
55823
|
+
this.forceGraph = new ForceGraphEngine(this);
|
|
55824
|
+
this.forceGraph.start();
|
|
55825
|
+
}
|
|
55826
|
+
disableForceGraph() {
|
|
55827
|
+
if (!this.forceGraph)
|
|
55828
|
+
return;
|
|
55829
|
+
this.forceGraph.stop();
|
|
55830
|
+
this.forceGraph = null;
|
|
55831
|
+
}
|
|
55832
|
+
isForceGraphEnabled() {
|
|
55833
|
+
return this.forceGraph !== null;
|
|
55834
|
+
}
|
|
55835
|
+
wakeForceGraph() {
|
|
55836
|
+
this.forceGraph?.wake();
|
|
55837
|
+
}
|
|
55641
55838
|
}
|
|
55642
55839
|
// src/Events/Merge.ts
|
|
55643
55840
|
var import_slate36 = require("slate");
|
package/dist/cjs/node.js
CHANGED
|
@@ -5712,6 +5712,11 @@ var conf = {
|
|
|
5712
5712
|
DEFAULT_GAME_ITEM_DIMENSIONS: { width: 200, height: 200 },
|
|
5713
5713
|
MAX_CARD_SIZE: 500,
|
|
5714
5714
|
CONNECTOR_ITEM_OFFSET: 20,
|
|
5715
|
+
FG_SPRING_K: 3,
|
|
5716
|
+
FG_TARGET_GAP: 60,
|
|
5717
|
+
FG_REPULSION: 400000,
|
|
5718
|
+
FG_DAMPING: 0.8,
|
|
5719
|
+
FG_SLEEP_THRESHOLD: 0.5,
|
|
5715
5720
|
GRAVITY_G: 80,
|
|
5716
5721
|
GRAVITY_G_CENTER: 120,
|
|
5717
5722
|
GRAVITY_DAMPING: 0.96,
|
|
@@ -56901,6 +56906,8 @@ class GravityEngine {
|
|
|
56901
56906
|
if (this.tickTimer !== null)
|
|
56902
56907
|
return;
|
|
56903
56908
|
for (const item of this.board.items.listAll()) {
|
|
56909
|
+
const pos = item.transformation.getTranslation();
|
|
56910
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
56904
56911
|
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
56905
56912
|
}
|
|
56906
56913
|
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
@@ -56915,6 +56922,7 @@ class GravityEngine {
|
|
|
56915
56922
|
clearInterval(this.syncTimer);
|
|
56916
56923
|
this.syncTimer = null;
|
|
56917
56924
|
}
|
|
56925
|
+
this.syncPositions();
|
|
56918
56926
|
this.velocities.clear();
|
|
56919
56927
|
this.lastSyncedPositions.clear();
|
|
56920
56928
|
}
|
|
@@ -57039,6 +57047,176 @@ class GravityEngine {
|
|
|
57039
57047
|
}
|
|
57040
57048
|
}
|
|
57041
57049
|
|
|
57050
|
+
// src/ForceGraph/ForceGraphEngine.ts
|
|
57051
|
+
var EXCLUDED_TYPES = new Set(["Connector", "Comment"]);
|
|
57052
|
+
|
|
57053
|
+
class ForceGraphEngine {
|
|
57054
|
+
board;
|
|
57055
|
+
velocities = new Map;
|
|
57056
|
+
tickTimer = null;
|
|
57057
|
+
syncTimer = null;
|
|
57058
|
+
lastSyncedPositions = new Map;
|
|
57059
|
+
TICK_MS = 33;
|
|
57060
|
+
SYNC_MS = 300;
|
|
57061
|
+
SOFTENING_SQ = 100 * 100;
|
|
57062
|
+
MIN_MOVE_PX = 0.05;
|
|
57063
|
+
constructor(board) {
|
|
57064
|
+
this.board = board;
|
|
57065
|
+
}
|
|
57066
|
+
start() {
|
|
57067
|
+
if (this.tickTimer !== null)
|
|
57068
|
+
return;
|
|
57069
|
+
for (const item of this.getNodes()) {
|
|
57070
|
+
const pos = item.transformation.getTranslation();
|
|
57071
|
+
this.lastSyncedPositions.set(item.getId(), { x: pos.x, y: pos.y });
|
|
57072
|
+
this.velocities.set(item.getId(), { vx: 0, vy: 0 });
|
|
57073
|
+
}
|
|
57074
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
57075
|
+
this.syncTimer = setInterval(() => this.syncPositions(), this.SYNC_MS);
|
|
57076
|
+
}
|
|
57077
|
+
stop() {
|
|
57078
|
+
if (this.tickTimer !== null) {
|
|
57079
|
+
clearInterval(this.tickTimer);
|
|
57080
|
+
this.tickTimer = null;
|
|
57081
|
+
}
|
|
57082
|
+
if (this.syncTimer !== null) {
|
|
57083
|
+
clearInterval(this.syncTimer);
|
|
57084
|
+
this.syncTimer = null;
|
|
57085
|
+
}
|
|
57086
|
+
this.syncPositions();
|
|
57087
|
+
this.velocities.clear();
|
|
57088
|
+
this.lastSyncedPositions.clear();
|
|
57089
|
+
}
|
|
57090
|
+
getNodes() {
|
|
57091
|
+
return this.board.items.listAll().filter((item) => !EXCLUDED_TYPES.has(item.itemType) && !item.transformation.isLocked);
|
|
57092
|
+
}
|
|
57093
|
+
getConnectors() {
|
|
57094
|
+
return this.board.items.listAll().filter((item) => item.itemType === "Connector");
|
|
57095
|
+
}
|
|
57096
|
+
tick() {
|
|
57097
|
+
const dt = this.TICK_MS / 1000;
|
|
57098
|
+
const nodes = this.getNodes();
|
|
57099
|
+
if (nodes.length < 2)
|
|
57100
|
+
return;
|
|
57101
|
+
const snapMap = new Map;
|
|
57102
|
+
for (const item of nodes) {
|
|
57103
|
+
const pos = item.transformation.getTranslation();
|
|
57104
|
+
const mbr = item.getMbr();
|
|
57105
|
+
const w = Math.max(mbr.getWidth(), 1);
|
|
57106
|
+
const h2 = Math.max(mbr.getHeight(), 1);
|
|
57107
|
+
snapMap.set(item.getId(), {
|
|
57108
|
+
id: item.getId(),
|
|
57109
|
+
cx: pos.x + w * 0.5,
|
|
57110
|
+
cy: pos.y + h2 * 0.5,
|
|
57111
|
+
w,
|
|
57112
|
+
h: h2
|
|
57113
|
+
});
|
|
57114
|
+
}
|
|
57115
|
+
const snap = Array.from(snapMap.values());
|
|
57116
|
+
const ax = new Map;
|
|
57117
|
+
const ay = new Map;
|
|
57118
|
+
for (const s2 of snap) {
|
|
57119
|
+
ax.set(s2.id, 0);
|
|
57120
|
+
ay.set(s2.id, 0);
|
|
57121
|
+
}
|
|
57122
|
+
for (const connector of this.getConnectors()) {
|
|
57123
|
+
const { startItem, endItem } = connector.getConnectedItems();
|
|
57124
|
+
if (!startItem || !endItem)
|
|
57125
|
+
continue;
|
|
57126
|
+
const s1 = snapMap.get(startItem.getId());
|
|
57127
|
+
const s2 = snapMap.get(endItem.getId());
|
|
57128
|
+
if (!s1 || !s2)
|
|
57129
|
+
continue;
|
|
57130
|
+
const dx = s2.cx - s1.cx;
|
|
57131
|
+
const dy = s2.cy - s1.cy;
|
|
57132
|
+
const dist = Math.sqrt(dx * dx + dy * dy) + 0.001;
|
|
57133
|
+
const targetDist = (Math.max(s1.w, s1.h) + Math.max(s2.w, s2.h)) * 0.5 + conf.FG_TARGET_GAP;
|
|
57134
|
+
const stretch = dist - targetDist;
|
|
57135
|
+
const forceMag = stretch * conf.FG_SPRING_K;
|
|
57136
|
+
const fx = dx / dist * forceMag;
|
|
57137
|
+
const fy = dy / dist * forceMag;
|
|
57138
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) + fx);
|
|
57139
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) + fy);
|
|
57140
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) - fx);
|
|
57141
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) - fy);
|
|
57142
|
+
}
|
|
57143
|
+
for (let i = 0;i < snap.length; i++) {
|
|
57144
|
+
for (let j = i + 1;j < snap.length; j++) {
|
|
57145
|
+
const s1 = snap[i];
|
|
57146
|
+
const s2 = snap[j];
|
|
57147
|
+
const dx = s2.cx - s1.cx;
|
|
57148
|
+
const dy = s2.cy - s1.cy;
|
|
57149
|
+
const distSq = dx * dx + dy * dy + this.SOFTENING_SQ;
|
|
57150
|
+
const repMag = conf.FG_REPULSION / distSq;
|
|
57151
|
+
const fx = dx * repMag;
|
|
57152
|
+
const fy = dy * repMag;
|
|
57153
|
+
ax.set(s1.id, (ax.get(s1.id) ?? 0) - fx);
|
|
57154
|
+
ay.set(s1.id, (ay.get(s1.id) ?? 0) - fy);
|
|
57155
|
+
ax.set(s2.id, (ax.get(s2.id) ?? 0) + fx);
|
|
57156
|
+
ay.set(s2.id, (ay.get(s2.id) ?? 0) + fy);
|
|
57157
|
+
}
|
|
57158
|
+
}
|
|
57159
|
+
let totalEnergy = 0;
|
|
57160
|
+
for (const item of nodes) {
|
|
57161
|
+
const id = item.getId();
|
|
57162
|
+
if (!this.velocities.has(id)) {
|
|
57163
|
+
this.velocities.set(id, { vx: 0, vy: 0 });
|
|
57164
|
+
}
|
|
57165
|
+
const vel = this.velocities.get(id);
|
|
57166
|
+
vel.vx = (vel.vx + (ax.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
57167
|
+
vel.vy = (vel.vy + (ay.get(id) ?? 0) * dt) * conf.FG_DAMPING;
|
|
57168
|
+
totalEnergy += vel.vx * vel.vx + vel.vy * vel.vy;
|
|
57169
|
+
const moveX = vel.vx * dt;
|
|
57170
|
+
const moveY = vel.vy * dt;
|
|
57171
|
+
if (Math.abs(moveX) >= this.MIN_MOVE_PX || Math.abs(moveY) >= this.MIN_MOVE_PX) {
|
|
57172
|
+
item.transformation.applyMatrixSilent({
|
|
57173
|
+
translateX: moveX,
|
|
57174
|
+
translateY: moveY,
|
|
57175
|
+
scaleX: 1,
|
|
57176
|
+
scaleY: 1,
|
|
57177
|
+
shearX: 0,
|
|
57178
|
+
shearY: 0
|
|
57179
|
+
});
|
|
57180
|
+
}
|
|
57181
|
+
}
|
|
57182
|
+
if (totalEnergy < conf.FG_SLEEP_THRESHOLD && this.tickTimer !== null) {
|
|
57183
|
+
clearInterval(this.tickTimer);
|
|
57184
|
+
this.tickTimer = null;
|
|
57185
|
+
this.syncPositions();
|
|
57186
|
+
}
|
|
57187
|
+
}
|
|
57188
|
+
syncPositions() {
|
|
57189
|
+
const nodes = this.getNodes();
|
|
57190
|
+
if (nodes.length === 0)
|
|
57191
|
+
return;
|
|
57192
|
+
const movedItems = nodes.map((item) => {
|
|
57193
|
+
const id = item.getId();
|
|
57194
|
+
const pos = item.transformation.getTranslation();
|
|
57195
|
+
const last = this.lastSyncedPositions.get(id);
|
|
57196
|
+
const dx = last ? pos.x - last.x : 0;
|
|
57197
|
+
const dy = last ? pos.y - last.y : 0;
|
|
57198
|
+
this.lastSyncedPositions.set(id, { x: pos.x, y: pos.y });
|
|
57199
|
+
return { id, dx, dy };
|
|
57200
|
+
}).filter(({ dx, dy }) => Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5);
|
|
57201
|
+
if (movedItems.length === 0)
|
|
57202
|
+
return;
|
|
57203
|
+
const operation = {
|
|
57204
|
+
class: "Transformation",
|
|
57205
|
+
method: "applyMatrix",
|
|
57206
|
+
items: movedItems.map(({ id, dx, dy }) => ({
|
|
57207
|
+
id,
|
|
57208
|
+
matrix: { translateX: dx, translateY: dy, scaleX: 1, scaleY: 1, shearX: 0, shearY: 0 }
|
|
57209
|
+
}))
|
|
57210
|
+
};
|
|
57211
|
+
this.board.events.emit(operation);
|
|
57212
|
+
}
|
|
57213
|
+
wake() {
|
|
57214
|
+
if (this.tickTimer === null && this.syncTimer !== null) {
|
|
57215
|
+
this.tickTimer = setInterval(() => this.tick(), this.TICK_MS);
|
|
57216
|
+
}
|
|
57217
|
+
}
|
|
57218
|
+
}
|
|
57219
|
+
|
|
57042
57220
|
// src/Board.ts
|
|
57043
57221
|
class Board {
|
|
57044
57222
|
boardId;
|
|
@@ -58111,6 +58289,25 @@ class Board {
|
|
|
58111
58289
|
isGravityEnabled() {
|
|
58112
58290
|
return this.gravity !== null;
|
|
58113
58291
|
}
|
|
58292
|
+
forceGraph = null;
|
|
58293
|
+
enableForceGraph() {
|
|
58294
|
+
if (this.forceGraph)
|
|
58295
|
+
return;
|
|
58296
|
+
this.forceGraph = new ForceGraphEngine(this);
|
|
58297
|
+
this.forceGraph.start();
|
|
58298
|
+
}
|
|
58299
|
+
disableForceGraph() {
|
|
58300
|
+
if (!this.forceGraph)
|
|
58301
|
+
return;
|
|
58302
|
+
this.forceGraph.stop();
|
|
58303
|
+
this.forceGraph = null;
|
|
58304
|
+
}
|
|
58305
|
+
isForceGraphEnabled() {
|
|
58306
|
+
return this.forceGraph !== null;
|
|
58307
|
+
}
|
|
58308
|
+
wakeForceGraph() {
|
|
58309
|
+
this.forceGraph?.wake();
|
|
58310
|
+
}
|
|
58114
58311
|
}
|
|
58115
58312
|
// src/Events/Merge.ts
|
|
58116
58313
|
var import_slate35 = require("slate");
|