@tldraw/editor 4.3.0 → 4.4.0-canary.09e80a09d230
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/README.md +1 -1
- package/dist-cjs/index.d.ts +180 -11
- package/dist-cjs/index.js +3 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/LiveCollaborators.js +14 -24
- package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +201 -0
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +7 -0
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +30 -16
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +3 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +13 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +58 -6
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +13 -21
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +378 -89
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +180 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -3
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +29 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +29 -0
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/options.js +1 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/collaboratorState.js +42 -0
- package/dist-cjs/lib/utils/collaboratorState.js.map +7 -0
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +180 -11
- package/dist-esm/index.mjs +3 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/LiveCollaborators.mjs +17 -24
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +181 -0
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +7 -0
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +30 -16
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +3 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +13 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +58 -6
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +13 -21
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +378 -89
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +160 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -3
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +29 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +33 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +1 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/collaboratorState.mjs +22 -0
- package/dist-esm/lib/utils/collaboratorState.mjs.map +7 -0
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +6 -0
- package/package.json +10 -8
- package/src/index.ts +3 -0
- package/src/lib/components/LiveCollaborators.tsx +26 -37
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +244 -0
- package/src/lib/components/default-components/DefaultCanvas.tsx +16 -6
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +6 -1
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +16 -1
- package/src/lib/config/TLUserPreferences.test.ts +1 -0
- package/src/lib/config/TLUserPreferences.ts +8 -0
- package/src/lib/editor/Editor.ts +84 -6
- package/src/lib/editor/derivations/notVisibleShapes.ts +15 -41
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +491 -106
- package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
- package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +214 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +24 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +8 -0
- package/src/lib/editor/shapes/ShapeUtil.ts +44 -0
- package/src/lib/hooks/usePeerIds.ts +46 -1
- package/src/lib/options.ts +7 -0
- package/src/lib/utils/collaboratorState.ts +54 -0
- package/src/version.ts +3 -3
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -621
|
@@ -23,33 +23,25 @@ __export(notVisibleShapes_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(notVisibleShapes_exports);
|
|
24
24
|
var import_state = require("@tldraw/state");
|
|
25
25
|
function notVisibleShapes(editor) {
|
|
26
|
-
return (0, import_state.computed)("notVisibleShapes", function
|
|
27
|
-
const
|
|
28
|
-
const nextValue = /* @__PURE__ */ new Set();
|
|
26
|
+
return (0, import_state.computed)("notVisibleShapes", function(prevValue) {
|
|
27
|
+
const allShapeIds = editor.getCurrentPageShapeIds();
|
|
29
28
|
const viewportPageBounds = editor.getViewportPageBounds();
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
continue;
|
|
29
|
+
const visibleIds = editor.getShapeIdsInsideBounds(viewportPageBounds);
|
|
30
|
+
const nextValue = /* @__PURE__ */ new Set();
|
|
31
|
+
for (const id of allShapeIds) {
|
|
32
|
+
if (!visibleIds.has(id)) {
|
|
33
|
+
const shape = editor.getShape(id);
|
|
34
|
+
if (!shape) continue;
|
|
35
|
+
const canCull = editor.getShapeUtil(shape.type).canCull(shape);
|
|
36
|
+
if (!canCull) continue;
|
|
37
|
+
nextValue.add(id);
|
|
38
38
|
}
|
|
39
|
-
const shape = editor.getShape(id);
|
|
40
|
-
if (!shape) continue;
|
|
41
|
-
const canCull = editor.getShapeUtil(shape.type).canCull(shape);
|
|
42
|
-
if (!canCull) continue;
|
|
43
|
-
nextValue.add(id);
|
|
44
39
|
}
|
|
45
|
-
if ((0, import_state.isUninitialized)(prevValue)) {
|
|
40
|
+
if ((0, import_state.isUninitialized)(prevValue) || prevValue.size !== nextValue.size) {
|
|
46
41
|
return nextValue;
|
|
47
42
|
}
|
|
48
|
-
if (prevValue.size !== nextValue.size) return nextValue;
|
|
49
43
|
for (const prev of prevValue) {
|
|
50
|
-
if (!nextValue.has(prev))
|
|
51
|
-
return nextValue;
|
|
52
|
-
}
|
|
44
|
+
if (!nextValue.has(prev)) return nextValue;
|
|
53
45
|
}
|
|
54
46
|
return prevValue;
|
|
55
47
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/editor/derivations/notVisibleShapes.ts"],
|
|
4
|
-
"sourcesContent": ["import { computed, isUninitialized } from '@tldraw/state'\nimport { TLShapeId } from '@tldraw/tlschema'\nimport { Editor } from '../Editor'\n\n/**\n * Non visible shapes are shapes outside of the viewport page bounds.\n *\n * @param editor - Instance of the tldraw Editor.\n * @returns Incremental derivation of non visible shapes.\n */\nexport function notVisibleShapes(editor: Editor) {\n\treturn computed<Set<TLShapeId>>('notVisibleShapes', function
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0C;AAUnC,SAAS,iBAAiB,QAAgB;AAChD,aAAO,uBAAyB,oBAAoB,
|
|
4
|
+
"sourcesContent": ["import { computed, isUninitialized } from '@tldraw/state'\nimport { TLShapeId } from '@tldraw/tlschema'\nimport { Editor } from '../Editor'\n\n/**\n * Non visible shapes are shapes outside of the viewport page bounds.\n *\n * @param editor - Instance of the tldraw Editor.\n * @returns Incremental derivation of non visible shapes.\n */\nexport function notVisibleShapes(editor: Editor) {\n\treturn computed<Set<TLShapeId>>('notVisibleShapes', function (prevValue) {\n\t\tconst allShapeIds = editor.getCurrentPageShapeIds()\n\t\tconst viewportPageBounds = editor.getViewportPageBounds()\n\t\tconst visibleIds = editor.getShapeIdsInsideBounds(viewportPageBounds)\n\n\t\tconst nextValue = new Set<TLShapeId>()\n\n\t\t// Non-visible shapes are all shapes minus visible shapes\n\t\tfor (const id of allShapeIds) {\n\t\t\tif (!visibleIds.has(id)) {\n\t\t\t\tconst shape = editor.getShape(id)\n\t\t\t\tif (!shape) continue\n\n\t\t\t\tconst canCull = editor.getShapeUtil(shape.type).canCull(shape)\n\t\t\t\tif (!canCull) continue\n\n\t\t\t\tnextValue.add(id)\n\t\t\t}\n\t\t}\n\n\t\tif (isUninitialized(prevValue) || prevValue.size !== nextValue.size) {\n\t\t\treturn nextValue\n\t\t}\n\n\t\tfor (const prev of prevValue) {\n\t\t\tif (!nextValue.has(prev)) return nextValue\n\t\t}\n\n\t\treturn prevValue\n\t})\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0C;AAUnC,SAAS,iBAAiB,QAAgB;AAChD,aAAO,uBAAyB,oBAAoB,SAAU,WAAW;AACxE,UAAM,cAAc,OAAO,uBAAuB;AAClD,UAAM,qBAAqB,OAAO,sBAAsB;AACxD,UAAM,aAAa,OAAO,wBAAwB,kBAAkB;AAEpE,UAAM,YAAY,oBAAI,IAAe;AAGrC,eAAW,MAAM,aAAa;AAC7B,UAAI,CAAC,WAAW,IAAI,EAAE,GAAG;AACxB,cAAM,QAAQ,OAAO,SAAS,EAAE;AAChC,YAAI,CAAC,MAAO;AAEZ,cAAM,UAAU,OAAO,aAAa,MAAM,IAAI,EAAE,QAAQ,KAAK;AAC7D,YAAI,CAAC,QAAS;AAEd,kBAAU,IAAI,EAAE;AAAA,MACjB;AAAA,IACD;AAEA,YAAI,8BAAgB,SAAS,KAAK,UAAU,SAAS,UAAU,MAAM;AACpE,aAAO;AAAA,IACR;AAEA,eAAW,QAAQ,WAAW;AAC7B,UAAI,CAAC,UAAU,IAAI,IAAI,EAAG,QAAO;AAAA,IAClC;AAEA,WAAO;AAAA,EACR,CAAC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,13 +27,53 @@ class ScribbleManager {
|
|
|
27
27
|
constructor(editor) {
|
|
28
28
|
this.editor = editor;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
sessions = /* @__PURE__ */ new Map();
|
|
31
|
+
// ==================== SESSION API ====================
|
|
32
|
+
/**
|
|
33
|
+
* Start a new session for grouping scribbles.
|
|
34
|
+
* Returns a session ID that can be used with other session methods.
|
|
35
|
+
*
|
|
36
|
+
* @param options - Session configuration
|
|
37
|
+
* @returns Session ID
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
startSession(options = {}) {
|
|
41
|
+
const id = options.id ?? (0, import_utils.uniqueId)();
|
|
42
|
+
const session = {
|
|
34
43
|
id,
|
|
44
|
+
items: [],
|
|
45
|
+
state: "active",
|
|
46
|
+
options: {
|
|
47
|
+
selfConsume: options.selfConsume ?? true,
|
|
48
|
+
idleTimeoutMs: options.idleTimeoutMs ?? 0,
|
|
49
|
+
fadeMode: options.fadeMode ?? "individual",
|
|
50
|
+
fadeEasing: options.fadeEasing ?? (options.fadeMode === "grouped" ? "ease-in" : "linear"),
|
|
51
|
+
fadeDurationMs: options.fadeDurationMs ?? this.editor.options.laserFadeoutMs
|
|
52
|
+
},
|
|
53
|
+
fadeElapsed: 0,
|
|
54
|
+
totalPointsAtFadeStart: 0
|
|
55
|
+
};
|
|
56
|
+
this.sessions.set(id, session);
|
|
57
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
58
|
+
this.resetIdleTimeout(session);
|
|
59
|
+
}
|
|
60
|
+
return id;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Add a scribble to a session.
|
|
64
|
+
*
|
|
65
|
+
* @param sessionId - The session ID
|
|
66
|
+
* @param scribble - Partial scribble properties
|
|
67
|
+
* @param scribbleId - Optional scribble ID
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
addScribbleToSession(sessionId, scribble, scribbleId = (0, import_utils.uniqueId)()) {
|
|
71
|
+
const session = this.sessions.get(sessionId);
|
|
72
|
+
if (!session) throw Error(`Session ${sessionId} not found`);
|
|
73
|
+
const item = {
|
|
74
|
+
id: scribbleId,
|
|
35
75
|
scribble: {
|
|
36
|
-
id,
|
|
76
|
+
id: scribbleId,
|
|
37
77
|
size: 20,
|
|
38
78
|
color: "accent",
|
|
39
79
|
opacity: 0.8,
|
|
@@ -49,43 +89,187 @@ class ScribbleManager {
|
|
|
49
89
|
prev: null,
|
|
50
90
|
next: null
|
|
51
91
|
};
|
|
52
|
-
|
|
92
|
+
session.items.push(item);
|
|
93
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
94
|
+
this.resetIdleTimeout(session);
|
|
95
|
+
}
|
|
53
96
|
return item;
|
|
54
97
|
}
|
|
55
|
-
reset() {
|
|
56
|
-
this.editor.updateInstanceState({ scribbles: [] });
|
|
57
|
-
this.scribbleItems.clear();
|
|
58
|
-
}
|
|
59
98
|
/**
|
|
60
|
-
*
|
|
99
|
+
* Add a point to a scribble in a session.
|
|
61
100
|
*
|
|
101
|
+
* @param sessionId - The session ID
|
|
102
|
+
* @param scribbleId - The scribble ID
|
|
103
|
+
* @param x - X coordinate
|
|
104
|
+
* @param y - Y coordinate
|
|
105
|
+
* @param z - Z coordinate (pressure)
|
|
62
106
|
* @public
|
|
63
107
|
*/
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
if (!
|
|
67
|
-
item
|
|
68
|
-
item
|
|
108
|
+
addPointToSession(sessionId, scribbleId, x, y, z = 0.5) {
|
|
109
|
+
const session = this.sessions.get(sessionId);
|
|
110
|
+
if (!session) throw Error(`Session ${sessionId} not found`);
|
|
111
|
+
const item = session.items.find((i) => i.id === scribbleId);
|
|
112
|
+
if (!item) throw Error(`Scribble ${scribbleId} not found in session ${sessionId}`);
|
|
113
|
+
const point = { x, y, z };
|
|
114
|
+
if (!item.prev || import_Vec.Vec.Dist(item.prev, point) >= 1) {
|
|
115
|
+
item.next = point;
|
|
116
|
+
}
|
|
117
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
118
|
+
this.resetIdleTimeout(session);
|
|
119
|
+
}
|
|
69
120
|
return item;
|
|
70
121
|
}
|
|
71
122
|
/**
|
|
72
|
-
*
|
|
123
|
+
* Extend a session, resetting its idle timeout.
|
|
73
124
|
*
|
|
74
|
-
* @param
|
|
75
|
-
* @
|
|
76
|
-
|
|
77
|
-
|
|
125
|
+
* @param sessionId - The session ID
|
|
126
|
+
* @public
|
|
127
|
+
*/
|
|
128
|
+
extendSession(sessionId) {
|
|
129
|
+
const session = this.sessions.get(sessionId);
|
|
130
|
+
if (!session) return;
|
|
131
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
132
|
+
this.resetIdleTimeout(session);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Stop a session, triggering fade-out.
|
|
137
|
+
*
|
|
138
|
+
* @param sessionId - The session ID
|
|
139
|
+
* @public
|
|
140
|
+
*/
|
|
141
|
+
stopSession(sessionId) {
|
|
142
|
+
const session = this.sessions.get(sessionId);
|
|
143
|
+
if (!session || session.state !== "active") return;
|
|
144
|
+
this.clearIdleTimeout(session);
|
|
145
|
+
session.state = "stopping";
|
|
146
|
+
if (session.options.fadeMode === "grouped") {
|
|
147
|
+
session.totalPointsAtFadeStart = session.items.reduce(
|
|
148
|
+
(sum, item) => sum + item.scribble.points.length,
|
|
149
|
+
0
|
|
150
|
+
);
|
|
151
|
+
session.fadeElapsed = 0;
|
|
152
|
+
for (const item of session.items) {
|
|
153
|
+
item.scribble.state = "stopping";
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
for (const item of session.items) {
|
|
157
|
+
item.delayRemaining = Math.min(item.delayRemaining, 200);
|
|
158
|
+
item.scribble.state = "stopping";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Clear all scribbles in a session immediately.
|
|
164
|
+
*
|
|
165
|
+
* @param sessionId - The session ID
|
|
166
|
+
* @public
|
|
167
|
+
*/
|
|
168
|
+
clearSession(sessionId) {
|
|
169
|
+
const session = this.sessions.get(sessionId);
|
|
170
|
+
if (!session) return;
|
|
171
|
+
this.clearIdleTimeout(session);
|
|
172
|
+
for (const item of session.items) {
|
|
173
|
+
item.scribble.points.length = 0;
|
|
174
|
+
}
|
|
175
|
+
session.state = "complete";
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Check if a session is active.
|
|
179
|
+
*
|
|
180
|
+
* @param sessionId - The session ID
|
|
181
|
+
* @public
|
|
182
|
+
*/
|
|
183
|
+
isSessionActive(sessionId) {
|
|
184
|
+
const session = this.sessions.get(sessionId);
|
|
185
|
+
return session?.state === "active";
|
|
186
|
+
}
|
|
187
|
+
// ==================== SIMPLE API (for eraser, select, etc.) ====================
|
|
188
|
+
/**
|
|
189
|
+
* Add a scribble using the default self-consuming behavior.
|
|
190
|
+
* Creates an implicit session for the scribble.
|
|
191
|
+
*
|
|
192
|
+
* @param scribble - Partial scribble properties
|
|
193
|
+
* @param id - Optional scribble id
|
|
194
|
+
* @returns The created scribble item
|
|
195
|
+
* @public
|
|
196
|
+
*/
|
|
197
|
+
addScribble(scribble, id = (0, import_utils.uniqueId)()) {
|
|
198
|
+
const sessionId = this.startSession();
|
|
199
|
+
return this.addScribbleToSession(sessionId, scribble, id);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Add a point to a scribble. Searches all sessions.
|
|
203
|
+
*
|
|
204
|
+
* @param id - The scribble id
|
|
205
|
+
* @param x - X coordinate
|
|
206
|
+
* @param y - Y coordinate
|
|
207
|
+
* @param z - Z coordinate (pressure)
|
|
78
208
|
* @public
|
|
79
209
|
*/
|
|
80
210
|
addPoint(id, x, y, z = 0.5) {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
211
|
+
for (const session of this.sessions.values()) {
|
|
212
|
+
const item = session.items.find((i) => i.id === id);
|
|
213
|
+
if (item) {
|
|
214
|
+
const point = { x, y, z };
|
|
215
|
+
if (!item.prev || import_Vec.Vec.Dist(item.prev, point) >= 1) {
|
|
216
|
+
item.next = point;
|
|
217
|
+
}
|
|
218
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
219
|
+
this.resetIdleTimeout(session);
|
|
220
|
+
}
|
|
221
|
+
return item;
|
|
222
|
+
}
|
|
87
223
|
}
|
|
88
|
-
|
|
224
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Mark a scribble as complete (done being drawn but not yet fading).
|
|
228
|
+
* Searches all sessions.
|
|
229
|
+
*
|
|
230
|
+
* @param id - The scribble id
|
|
231
|
+
* @public
|
|
232
|
+
*/
|
|
233
|
+
complete(id) {
|
|
234
|
+
for (const session of this.sessions.values()) {
|
|
235
|
+
const item = session.items.find((i) => i.id === id);
|
|
236
|
+
if (item) {
|
|
237
|
+
if (item.scribble.state === "starting" || item.scribble.state === "active") {
|
|
238
|
+
item.scribble.state = "complete";
|
|
239
|
+
}
|
|
240
|
+
return item;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Stop a scribble. Searches all sessions.
|
|
247
|
+
*
|
|
248
|
+
* @param id - The scribble id
|
|
249
|
+
* @public
|
|
250
|
+
*/
|
|
251
|
+
stop(id) {
|
|
252
|
+
for (const session of this.sessions.values()) {
|
|
253
|
+
const item = session.items.find((i) => i.id === id);
|
|
254
|
+
if (item) {
|
|
255
|
+
item.delayRemaining = Math.min(item.delayRemaining, 200);
|
|
256
|
+
item.scribble.state = "stopping";
|
|
257
|
+
return item;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Stop and remove all sessions.
|
|
264
|
+
*
|
|
265
|
+
* @public
|
|
266
|
+
*/
|
|
267
|
+
reset() {
|
|
268
|
+
for (const session of this.sessions.values()) {
|
|
269
|
+
this.clearIdleTimeout(session);
|
|
270
|
+
}
|
|
271
|
+
this.sessions.clear();
|
|
272
|
+
this.editor.updateInstanceState({ scribbles: [] });
|
|
89
273
|
}
|
|
90
274
|
/**
|
|
91
275
|
* Update on each animation frame.
|
|
@@ -94,77 +278,182 @@ class ScribbleManager {
|
|
|
94
278
|
* @public
|
|
95
279
|
*/
|
|
96
280
|
tick(elapsed) {
|
|
97
|
-
|
|
281
|
+
const currentScribbles = this.editor.getInstanceState().scribbles;
|
|
282
|
+
if (this.sessions.size === 0 && currentScribbles.length === 0) return;
|
|
98
283
|
this.editor.run(() => {
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (item.scribble.points.length > 8) {
|
|
107
|
-
item.scribble.state = "active";
|
|
108
|
-
}
|
|
109
|
-
return;
|
|
284
|
+
for (const session of this.sessions.values()) {
|
|
285
|
+
this.tickSession(session, elapsed);
|
|
286
|
+
}
|
|
287
|
+
for (const [id, session] of this.sessions) {
|
|
288
|
+
if (session.state === "complete") {
|
|
289
|
+
this.clearIdleTimeout(session);
|
|
290
|
+
this.sessions.delete(id);
|
|
110
291
|
}
|
|
111
|
-
|
|
112
|
-
|
|
292
|
+
}
|
|
293
|
+
const scribbles = [];
|
|
294
|
+
for (const session of this.sessions.values()) {
|
|
295
|
+
for (const item of session.items) {
|
|
296
|
+
if (item.scribble.points.length > 0) {
|
|
297
|
+
scribbles.push({
|
|
298
|
+
...item.scribble,
|
|
299
|
+
points: [...item.scribble.points]
|
|
300
|
+
});
|
|
301
|
+
}
|
|
113
302
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
303
|
+
}
|
|
304
|
+
this.editor.updateInstanceState({ scribbles });
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
// ==================== PRIVATE HELPERS ====================
|
|
308
|
+
resetIdleTimeout(session) {
|
|
309
|
+
this.clearIdleTimeout(session);
|
|
310
|
+
session.idleTimeoutHandle = this.editor.timers.setTimeout(() => {
|
|
311
|
+
this.stopSession(session.id);
|
|
312
|
+
}, session.options.idleTimeoutMs);
|
|
313
|
+
}
|
|
314
|
+
clearIdleTimeout(session) {
|
|
315
|
+
if (session.idleTimeoutHandle !== void 0) {
|
|
316
|
+
clearTimeout(session.idleTimeoutHandle);
|
|
317
|
+
session.idleTimeoutHandle = void 0;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
tickSession(session, elapsed) {
|
|
321
|
+
if (session.state === "complete") return;
|
|
322
|
+
if (session.state === "stopping" && session.options.fadeMode === "grouped") {
|
|
323
|
+
this.tickGroupedFade(session, elapsed);
|
|
324
|
+
} else {
|
|
325
|
+
this.tickSessionItems(session, elapsed);
|
|
326
|
+
}
|
|
327
|
+
const hasContent = session.items.some((item) => item.scribble.points.length > 0);
|
|
328
|
+
if (!hasContent && (session.state === "stopping" || session.items.length === 0)) {
|
|
329
|
+
session.state = "complete";
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
tickSessionItems(session, elapsed) {
|
|
333
|
+
for (const item of session.items) {
|
|
334
|
+
const shouldSelfConsume = session.options.selfConsume || session.state === "stopping" || item.scribble.state === "stopping";
|
|
335
|
+
if (shouldSelfConsume) {
|
|
336
|
+
this.tickSelfConsumingItem(item, elapsed);
|
|
337
|
+
} else {
|
|
338
|
+
this.tickPersistentItem(item);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (session.options.fadeMode === "individual") {
|
|
342
|
+
for (let i = session.items.length - 1; i >= 0; i--) {
|
|
343
|
+
if (session.items[i].scribble.points.length === 0) {
|
|
344
|
+
session.items.splice(i, 1);
|
|
117
345
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
tickPersistentItem(item) {
|
|
350
|
+
const { scribble } = item;
|
|
351
|
+
if (scribble.state === "starting") {
|
|
352
|
+
const { next, prev } = item;
|
|
353
|
+
if (next && next !== prev) {
|
|
354
|
+
item.prev = next;
|
|
355
|
+
scribble.points.push(next);
|
|
356
|
+
}
|
|
357
|
+
if (scribble.points.length > 8) {
|
|
358
|
+
scribble.state = "active";
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (scribble.state === "active") {
|
|
363
|
+
const { next, prev } = item;
|
|
364
|
+
if (next && next !== prev) {
|
|
365
|
+
item.prev = next;
|
|
366
|
+
scribble.points.push(next);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
tickSelfConsumingItem(item, elapsed) {
|
|
371
|
+
const { scribble } = item;
|
|
372
|
+
if (scribble.state === "starting") {
|
|
373
|
+
const { next: next2, prev: prev2 } = item;
|
|
374
|
+
if (next2 && next2 !== prev2) {
|
|
375
|
+
item.prev = next2;
|
|
376
|
+
scribble.points.push(next2);
|
|
377
|
+
}
|
|
378
|
+
if (scribble.points.length > 8) {
|
|
379
|
+
scribble.state = "active";
|
|
380
|
+
}
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (item.delayRemaining > 0) {
|
|
384
|
+
item.delayRemaining = Math.max(0, item.delayRemaining - elapsed);
|
|
385
|
+
}
|
|
386
|
+
item.timeoutMs += elapsed;
|
|
387
|
+
if (item.timeoutMs >= 16) {
|
|
388
|
+
item.timeoutMs = 0;
|
|
389
|
+
}
|
|
390
|
+
const { delayRemaining, timeoutMs, prev, next } = item;
|
|
391
|
+
switch (scribble.state) {
|
|
392
|
+
case "active": {
|
|
393
|
+
if (next && next !== prev) {
|
|
394
|
+
item.prev = next;
|
|
395
|
+
scribble.points.push(next);
|
|
396
|
+
if (delayRemaining === 0 && scribble.points.length > 8) {
|
|
397
|
+
scribble.points.shift();
|
|
398
|
+
}
|
|
399
|
+
} else {
|
|
400
|
+
if (timeoutMs === 0) {
|
|
401
|
+
if (scribble.points.length > 1) {
|
|
402
|
+
scribble.points.shift();
|
|
129
403
|
} else {
|
|
130
|
-
|
|
131
|
-
if (scribble.points.length > 1) {
|
|
132
|
-
scribble.points.shift();
|
|
133
|
-
} else {
|
|
134
|
-
item.delayRemaining = scribble.delay;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
404
|
+
item.delayRemaining = scribble.delay;
|
|
137
405
|
}
|
|
138
|
-
break;
|
|
139
406
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
scribble.size = Math.max(1, scribble.size * (1 - scribble.shrink));
|
|
149
|
-
}
|
|
150
|
-
scribble.points.shift();
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
break;
|
|
407
|
+
}
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
case "stopping": {
|
|
411
|
+
if (delayRemaining === 0 && timeoutMs === 0) {
|
|
412
|
+
if (scribble.points.length <= 1) {
|
|
413
|
+
scribble.points.length = 0;
|
|
414
|
+
return;
|
|
154
415
|
}
|
|
155
|
-
|
|
156
|
-
|
|
416
|
+
if (scribble.shrink) {
|
|
417
|
+
scribble.size = Math.max(1, scribble.size * (1 - scribble.shrink));
|
|
157
418
|
}
|
|
419
|
+
scribble.points.shift();
|
|
158
420
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
421
|
+
break;
|
|
422
|
+
}
|
|
423
|
+
case "paused": {
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
tickGroupedFade(session, elapsed) {
|
|
429
|
+
session.fadeElapsed += elapsed;
|
|
430
|
+
let remainingPoints = 0;
|
|
431
|
+
for (const item of session.items) {
|
|
432
|
+
remainingPoints += item.scribble.points.length;
|
|
433
|
+
}
|
|
434
|
+
if (remainingPoints === 0) return;
|
|
435
|
+
if (session.fadeElapsed >= session.options.fadeDurationMs) {
|
|
436
|
+
for (const item of session.items) {
|
|
437
|
+
item.scribble.points.length = 0;
|
|
438
|
+
}
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const progress = session.fadeElapsed / session.options.fadeDurationMs;
|
|
442
|
+
const easedProgress = session.options.fadeEasing === "ease-in" ? progress * progress : progress;
|
|
443
|
+
const targetRemoved = Math.floor(easedProgress * session.totalPointsAtFadeStart);
|
|
444
|
+
const actuallyRemoved = session.totalPointsAtFadeStart - remainingPoints;
|
|
445
|
+
const pointsToRemove = Math.max(1, targetRemoved - actuallyRemoved);
|
|
446
|
+
let removed = 0;
|
|
447
|
+
let itemIndex = 0;
|
|
448
|
+
while (removed < pointsToRemove && itemIndex < session.items.length) {
|
|
449
|
+
const item = session.items[itemIndex];
|
|
450
|
+
if (item.scribble.points.length > 0) {
|
|
451
|
+
item.scribble.points.shift();
|
|
452
|
+
removed++;
|
|
453
|
+
} else {
|
|
454
|
+
itemIndex++;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
168
457
|
}
|
|
169
458
|
}
|
|
170
459
|
//# sourceMappingURL=ScribbleManager.js.map
|