kritzel-react 0.1.30 → 0.1.32
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/kritzel-react/lib/components/stencil-generated/components.js +122 -0
- package/dist/kritzel-react/lib/index.js +2 -0
- package/dist/kritzel-stencil/src/classes/core/core.class.js +797 -0
- package/dist/kritzel-stencil/src/classes/core/reviver.class.js +97 -0
- package/dist/kritzel-stencil/src/classes/core/store.class.js +153 -0
- package/dist/kritzel-stencil/src/classes/core/viewport.class.js +311 -0
- package/dist/kritzel-stencil/src/classes/core/workspace.class.js +34 -0
- package/dist/kritzel-stencil/src/classes/handlers/base.handler.js +6 -0
- package/dist/kritzel-stencil/src/classes/handlers/context-menu.handler.js +63 -0
- package/dist/kritzel-stencil/src/classes/handlers/hover.handler.js +18 -0
- package/dist/kritzel-stencil/src/classes/handlers/key.handler.js +76 -0
- package/dist/kritzel-stencil/src/classes/handlers/line-handle.handler.js +382 -0
- package/dist/kritzel-stencil/src/classes/handlers/move.handler.js +213 -0
- package/dist/kritzel-stencil/src/classes/handlers/resize.handler.js +205 -0
- package/dist/kritzel-stencil/src/classes/handlers/rotation.handler.js +117 -0
- package/dist/kritzel-stencil/src/classes/handlers/selection.handler.js +313 -0
- package/dist/kritzel-stencil/src/classes/managers/anchor.manager.js +1056 -0
- package/dist/kritzel-stencil/src/classes/managers/cursor.manager.js +117 -0
- package/dist/kritzel-stencil/src/classes/managers/theme.manager.js +103 -0
- package/dist/kritzel-stencil/src/classes/objects/base-object.class.js +249 -0
- package/dist/kritzel-stencil/src/classes/objects/custom-element.class.js +60 -0
- package/dist/kritzel-stencil/src/classes/objects/group.class.js +407 -0
- package/dist/kritzel-stencil/src/classes/objects/image.class.js +55 -0
- package/dist/kritzel-stencil/src/classes/objects/line.class.js +608 -0
- package/dist/kritzel-stencil/src/classes/objects/path.class.js +401 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-box.class.js +21 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-group.class.js +409 -0
- package/dist/kritzel-stencil/src/classes/objects/shape.class.js +412 -0
- package/dist/kritzel-stencil/src/classes/objects/text.class.js +292 -0
- package/dist/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.js +101 -0
- package/dist/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.js +241 -0
- package/dist/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.js +43 -0
- package/dist/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.js +98 -0
- package/dist/kritzel-stencil/src/classes/registries/icon-registry.class.js +66 -0
- package/dist/kritzel-stencil/src/classes/registries/tool.registry.js +21 -0
- package/dist/kritzel-stencil/src/classes/structures/app-state-map.structure.js +212 -0
- package/dist/kritzel-stencil/src/classes/structures/object-map.structure.js +414 -0
- package/dist/kritzel-stencil/src/classes/structures/quadtree.structure.js +151 -0
- package/dist/kritzel-stencil/src/classes/tools/base-tool.class.js +36 -0
- package/dist/kritzel-stencil/src/classes/tools/brush-tool.class.js +161 -0
- package/dist/kritzel-stencil/src/classes/tools/eraser-tool.class.js +85 -0
- package/dist/kritzel-stencil/src/classes/tools/image-tool.class.js +83 -0
- package/dist/kritzel-stencil/src/classes/tools/line-tool.class.js +187 -0
- package/dist/kritzel-stencil/src/classes/tools/selection-tool.class.js +429 -0
- package/dist/kritzel-stencil/src/classes/tools/shape-tool.class.js +196 -0
- package/dist/kritzel-stencil/src/classes/tools/text-tool.class.js +100 -0
- package/dist/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.js +1343 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.js +46 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.js +312 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.js +60 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.js +105 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +53 -0
- package/dist/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.js +137 -0
- package/dist/kritzel-stencil/src/configs/default-brush-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-engine-config.js +63 -0
- package/dist/kritzel-stencil/src/configs/default-line-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-sync.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-text-tool.config.js +7 -0
- package/dist/kritzel-stencil/src/constants/color-palette.constants.js +37 -0
- package/dist/kritzel-stencil/src/constants/engine.constants.js +2 -0
- package/dist/kritzel-stencil/src/enums/event-button.enum.js +6 -0
- package/dist/kritzel-stencil/src/enums/handle-type.enum.js +7 -0
- package/dist/kritzel-stencil/src/enums/shape-type.enum.js +6 -0
- package/dist/kritzel-stencil/src/helpers/class.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/color.helper.js +106 -0
- package/dist/kritzel-stencil/src/helpers/cursor.helper.js +57 -0
- package/dist/kritzel-stencil/src/helpers/devices.helper.js +28 -0
- package/dist/kritzel-stencil/src/helpers/event.helper.js +58 -0
- package/dist/kritzel-stencil/src/helpers/geometry.helper.js +149 -0
- package/dist/kritzel-stencil/src/helpers/keyboard.helper.js +51 -0
- package/dist/kritzel-stencil/src/helpers/math.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/object.helper.js +11 -0
- package/dist/kritzel-stencil/src/helpers/theme.helper.js +69 -0
- package/dist/kritzel-stencil/src/index.js +41 -0
- package/dist/kritzel-stencil/src/interfaces/anchor.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/arrow-head.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/bounding-box.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/clonable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/context-menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/debug-info.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/dialog.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/displayable-shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/engine-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/line-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/master-detail.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/object.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/path-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/point.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/polygon.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/serializable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/settings.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-provider.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/theme.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/toolbar-control.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/undo-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/themes/dark-theme.js +198 -0
- package/dist/kritzel-stencil/src/themes/light-theme.js +199 -0
- package/dist/kritzel-stencil/src/types/shortcut.type.js +1 -0
- package/dist/kritzel-stencil/src/types/state.types.js +1 -0
- package/dist/types/kritzel-react/lib/components/stencil-generated/components.d.ts +74 -0
- package/dist/types/kritzel-react/lib/index.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/classes/core/core.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/core/reviver.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/core/store.class.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/classes/core/viewport.class.d.ts +48 -0
- package/dist/types/kritzel-stencil/src/classes/core/workspace.class.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/base.handler.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/context-menu.handler.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/hover.handler.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/key.handler.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/line-handle.handler.d.ts +34 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/move.handler.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/resize.handler.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/rotation.handler.d.ts +12 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/selection.handler.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/classes/managers/anchor.manager.d.ts +180 -0
- package/dist/types/kritzel-stencil/src/classes/managers/cursor.manager.d.ts +43 -0
- package/dist/types/kritzel-stencil/src/classes/managers/theme.manager.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/objects/base-object.class.d.ts +76 -0
- package/dist/types/kritzel-stencil/src/classes/objects/custom-element.class.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/classes/objects/group.class.d.ts +97 -0
- package/dist/types/kritzel-stencil/src/classes/objects/image.class.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/classes/objects/line.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/objects/path.class.d.ts +62 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-box.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-group.class.d.ts +67 -0
- package/dist/types/kritzel-stencil/src/classes/objects/shape.class.d.ts +124 -0
- package/dist/types/kritzel-stencil/src/classes/objects/text.class.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.d.ts +18 -0
- package/dist/types/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.d.ts +120 -0
- package/dist/types/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.d.ts +52 -0
- package/dist/types/kritzel-stencil/src/classes/registries/icon-registry.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/registries/tool.registry.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/structures/app-state-map.structure.d.ts +31 -0
- package/dist/types/kritzel-stencil/src/classes/structures/object-map.structure.d.ts +63 -0
- package/dist/types/kritzel-stencil/src/classes/structures/quadtree.structure.d.ts +36 -0
- package/dist/types/kritzel-stencil/src/classes/tools/base-tool.class.d.ts +20 -0
- package/dist/types/kritzel-stencil/src/classes/tools/brush-tool.class.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/classes/tools/eraser-tool.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/tools/image-tool.class.d.ts +15 -0
- package/dist/types/kritzel-stencil/src/classes/tools/line-tool.class.d.ts +19 -0
- package/dist/types/kritzel-stencil/src/classes/tools/selection-tool.class.d.ts +54 -0
- package/dist/types/kritzel-stencil/src/classes/tools/shape-tool.class.d.ts +39 -0
- package/dist/types/kritzel-stencil/src/classes/tools/text-tool.class.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.d.ts +111 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +46 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/configs/default-brush-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-engine-config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-line-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-sync.config.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/configs/default-text-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/constants/color-palette.constants.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/constants/engine.constants.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/enums/event-button.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/enums/handle-type.enum.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/helpers/class.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/color.helper.d.ts +33 -0
- package/dist/types/kritzel-stencil/src/helpers/cursor.helper.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/helpers/devices.helper.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/helpers/event.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/geometry.helper.d.ts +38 -0
- package/dist/types/kritzel-stencil/src/helpers/keyboard.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/math.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/object.helper.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/helpers/theme.helper.d.ts +41 -0
- package/dist/types/kritzel-stencil/src/index.d.ts +42 -0
- package/dist/types/kritzel-stencil/src/interfaces/anchor.interface.d.ts +137 -0
- package/dist/types/kritzel-stencil/src/interfaces/arrow-head.interface.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/interfaces/bounding-box.interface.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/interfaces/clonable.interface.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/interfaces/context-menu-item.interface.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/interfaces/debug-info.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/dialog.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/displayable-shortcut.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/engine-state.interface.d.ts +73 -0
- package/dist/types/kritzel-stencil/src/interfaces/line-options.interface.d.ts +23 -0
- package/dist/types/kritzel-stencil/src/interfaces/master-detail.interface.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/interfaces/menu-item.interface.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/interfaces/object.interface.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/interfaces/path-options.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/point.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/polygon.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/serializable.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/settings.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/shortcut.interface.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-config.interface.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-provider.interface.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/interfaces/theme.interface.d.ts +330 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool-config.interface.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/toolbar-control.interface.d.ts +58 -0
- package/dist/types/kritzel-stencil/src/interfaces/undo-state.interface.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/themes/dark-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/themes/light-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/types/shortcut.type.d.ts +1 -0
- package/dist/types/kritzel-stencil/src/types/state.types.d.ts +3 -0
- package/package.json +2 -2
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import * as Y from 'yjs';
|
|
11
|
+
import { KritzelReviver } from '../core/reviver.class';
|
|
12
|
+
import { KritzelSelectionBox } from '../objects/selection-box.class';
|
|
13
|
+
import { KritzelSelectionGroup } from '../objects/selection-group.class';
|
|
14
|
+
import { DEFAULT_SYNC_CONFIG } from '../../configs/default-sync.config';
|
|
15
|
+
import { KritzelQuadtree } from './quadtree.structure';
|
|
16
|
+
export class KritzelObjectMap {
|
|
17
|
+
get isReady() {
|
|
18
|
+
return this._isReady;
|
|
19
|
+
}
|
|
20
|
+
get undoManager() {
|
|
21
|
+
return this._undoManager;
|
|
22
|
+
}
|
|
23
|
+
get workspaceId() {
|
|
24
|
+
return this._workspaceId;
|
|
25
|
+
}
|
|
26
|
+
get undoState() {
|
|
27
|
+
return {
|
|
28
|
+
canUndo: this._undoManager ? this._undoManager.canUndo() : false,
|
|
29
|
+
canRedo: this._undoManager ? this._undoManager.canRedo() : false,
|
|
30
|
+
undoStackSize: this._undoManager ? this._undoManager.undoStack.length : 0,
|
|
31
|
+
redoStackSize: this._undoManager ? this._undoManager.redoStack.length : 0,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
get totalCount() {
|
|
35
|
+
return this.quadtree.size;
|
|
36
|
+
}
|
|
37
|
+
constructor() {
|
|
38
|
+
this._ydoc = null;
|
|
39
|
+
this._objectsMap = null;
|
|
40
|
+
this._providers = [];
|
|
41
|
+
this._undoManager = null;
|
|
42
|
+
this._reviver = null;
|
|
43
|
+
this._core = null;
|
|
44
|
+
this._workspaceId = null;
|
|
45
|
+
this._isReady = false;
|
|
46
|
+
this._temporaryItemsCount = 0;
|
|
47
|
+
// Store observer/listener references for cleanup
|
|
48
|
+
this._objectsObserver = null;
|
|
49
|
+
this._stackItemAddedHandler = null;
|
|
50
|
+
this._stackItemPoppedHandler = null;
|
|
51
|
+
this.quadtree = new KritzelQuadtree({
|
|
52
|
+
x: -Infinity,
|
|
53
|
+
y: -Infinity,
|
|
54
|
+
z: 0,
|
|
55
|
+
width: Infinity,
|
|
56
|
+
height: Infinity,
|
|
57
|
+
}, 8);
|
|
58
|
+
}
|
|
59
|
+
initialize(core, workspaceId, config) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
this._core = core;
|
|
62
|
+
this._workspaceId = workspaceId;
|
|
63
|
+
this._reviver = new KritzelReviver(core);
|
|
64
|
+
// Create a dedicated Y.Doc for this workspace
|
|
65
|
+
this._ydoc = new Y.Doc();
|
|
66
|
+
this._objectsMap = this._ydoc.getMap('objects');
|
|
67
|
+
const docName = `kritzel-workspace-${workspaceId}`;
|
|
68
|
+
const finalConfig = config !== null && config !== void 0 ? config : DEFAULT_SYNC_CONFIG;
|
|
69
|
+
// Instantiate providers from configuration
|
|
70
|
+
for (const providerConfig of finalConfig.providers) {
|
|
71
|
+
let provider;
|
|
72
|
+
// Check if it's a class constructor or a factory
|
|
73
|
+
if (typeof providerConfig === 'function') {
|
|
74
|
+
// It's a class constructor
|
|
75
|
+
provider = new providerConfig(docName, this._ydoc);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
// It's a factory with a create method
|
|
79
|
+
provider = providerConfig.create(docName, this._ydoc);
|
|
80
|
+
}
|
|
81
|
+
this._providers.push(provider);
|
|
82
|
+
}
|
|
83
|
+
// Set up undo/redo manager for this workspace
|
|
84
|
+
this._undoManager = new Y.UndoManager([this._objectsMap], {
|
|
85
|
+
captureTimeout: 200,
|
|
86
|
+
trackedOrigins: new Set(['local', 'temporary']),
|
|
87
|
+
ignoreRemoteMapChanges: true,
|
|
88
|
+
});
|
|
89
|
+
// Store handler references for cleanup
|
|
90
|
+
this._stackItemAddedHandler = event => {
|
|
91
|
+
if (event.type === 'undo') {
|
|
92
|
+
// Track if this was a temporary item
|
|
93
|
+
if (event.origin === 'temporary') {
|
|
94
|
+
this._temporaryItemsCount++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
this._stackItemPoppedHandler = event => {
|
|
99
|
+
if (event.type === 'undo') {
|
|
100
|
+
// Reduce temporary count when items are undone
|
|
101
|
+
if (event.origin === 'temporary' && this._temporaryItemsCount > 0) {
|
|
102
|
+
this._temporaryItemsCount--;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
this._undoManager.on('stack-item-added', this._stackItemAddedHandler);
|
|
107
|
+
this._undoManager.on('stack-item-popped', this._stackItemPoppedHandler);
|
|
108
|
+
// Observe changes to objects and sync with application state
|
|
109
|
+
this._objectsObserver = event => {
|
|
110
|
+
this.handleObjectsChange(event);
|
|
111
|
+
};
|
|
112
|
+
this._objectsMap.observe(this._objectsObserver);
|
|
113
|
+
// Connect all providers in parallel
|
|
114
|
+
yield Promise.all(this._providers.map(p => p.connect()));
|
|
115
|
+
this._isReady = true;
|
|
116
|
+
// Load objects from Yjs
|
|
117
|
+
this.loadFromYjs();
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
handleObjectsChange(event) {
|
|
121
|
+
var _a, _b, _c;
|
|
122
|
+
// Skip Map updates for local changes (already done), but still trigger re-render
|
|
123
|
+
// 'temporary' is also a local change that shouldn't be re-deserialized
|
|
124
|
+
if (event.transaction.origin === 'local' || event.transaction.origin === 'temporary') {
|
|
125
|
+
(_a = this._core) === null || _a === void 0 ? void 0 : _a.rerender();
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const changedKeys = Array.from(event.keysChanged);
|
|
129
|
+
const objectsToUpdate = [];
|
|
130
|
+
const selectionGroupsToUpdate = [];
|
|
131
|
+
const objectsToDelete = [];
|
|
132
|
+
changedKeys.forEach(key => {
|
|
133
|
+
const change = event.changes.keys.get(key);
|
|
134
|
+
if (change && change.action === 'delete') {
|
|
135
|
+
objectsToDelete.push(key);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const serialized = this._objectsMap.get(key);
|
|
139
|
+
if (serialized) {
|
|
140
|
+
const object = this._reviver.revive(serialized);
|
|
141
|
+
// Separate SelectionGroups to process them after regular objects
|
|
142
|
+
if (object instanceof KritzelSelectionGroup) {
|
|
143
|
+
selectionGroupsToUpdate.push(object);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
objectsToUpdate.push(object);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
// Delete objects from local map
|
|
152
|
+
objectsToDelete.forEach(objectId => {
|
|
153
|
+
this.quadtree.remove(o => o.id === objectId);
|
|
154
|
+
});
|
|
155
|
+
// First, update or insert regular objects
|
|
156
|
+
objectsToUpdate.forEach(object => {
|
|
157
|
+
const existed = this.quadtree.filter(o => o.id === object.id).length > 0;
|
|
158
|
+
if (existed) {
|
|
159
|
+
this.quadtree.update(object);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.quadtree.insert(object);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
// Then, update or insert SelectionGroups
|
|
166
|
+
const updatedSelectionGroupIds = new Set();
|
|
167
|
+
selectionGroupsToUpdate.forEach(object => {
|
|
168
|
+
const existed = this.quadtree.filter(o => o.id === object.id).length > 0;
|
|
169
|
+
if (existed) {
|
|
170
|
+
this.quadtree.update(object);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
this.quadtree.insert(object);
|
|
174
|
+
}
|
|
175
|
+
updatedSelectionGroupIds.add(object.id);
|
|
176
|
+
// After undo/redo, the SelectionGroup's dimensions may be stale because:
|
|
177
|
+
// 1. The serialized state contains the old bounding box
|
|
178
|
+
// 2. The child objects have been reverted to their previous positions
|
|
179
|
+
// We need to invalidate the cache and recalculate dimensions
|
|
180
|
+
// skipPersist=true prevents creating new undo entries
|
|
181
|
+
object.invalidateObjectsCache();
|
|
182
|
+
object.refreshObjectDimensions(undefined, true);
|
|
183
|
+
object.captureUnchangedSnapshots();
|
|
184
|
+
// Update quadtree again with corrected dimensions
|
|
185
|
+
this.quadtree.update(object);
|
|
186
|
+
});
|
|
187
|
+
// If regular objects were changed but their SelectionGroup wasn't explicitly updated,
|
|
188
|
+
// we still need to refresh that SelectionGroup's dimensions
|
|
189
|
+
if (objectsToUpdate.length > 0 || objectsToDelete.length > 0) {
|
|
190
|
+
const changedObjectIds = new Set([
|
|
191
|
+
...objectsToUpdate.map(o => o.id),
|
|
192
|
+
...objectsToDelete
|
|
193
|
+
]);
|
|
194
|
+
// Find any existing SelectionGroups that contain changed objects
|
|
195
|
+
const existingSelectionGroups = this.quadtree.filter(o => o instanceof KritzelSelectionGroup && !updatedSelectionGroupIds.has(o.id));
|
|
196
|
+
for (const selectionGroup of existingSelectionGroups) {
|
|
197
|
+
const hasChangedChildren = selectionGroup.objectIds.some(id => changedObjectIds.has(id));
|
|
198
|
+
if (hasChangedChildren) {
|
|
199
|
+
selectionGroup.invalidateObjectsCache();
|
|
200
|
+
selectionGroup.refreshObjectDimensions(undefined, true);
|
|
201
|
+
selectionGroup.captureUnchangedSnapshots();
|
|
202
|
+
// Update quadtree with corrected dimensions
|
|
203
|
+
this.quadtree.update(selectionGroup);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Invalidate the store's selection cache so it fetches the updated SelectionGroup
|
|
208
|
+
(_b = this._core) === null || _b === void 0 ? void 0 : _b.store.invalidateSelectionCache();
|
|
209
|
+
(_c = this._core) === null || _c === void 0 ? void 0 : _c.rerender();
|
|
210
|
+
}
|
|
211
|
+
transaction(callback) {
|
|
212
|
+
if (this._ydoc) {
|
|
213
|
+
this._ydoc.transact(callback, 'local');
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
loadFromYjs() {
|
|
217
|
+
if (!this._objectsMap || !this._reviver) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
this.quadtree.reset();
|
|
221
|
+
this._objectsMap.forEach(serialized => {
|
|
222
|
+
const object = this._reviver.revive(serialized);
|
|
223
|
+
this.quadtree.insert(object);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
reset() {
|
|
227
|
+
this.quadtree.reset();
|
|
228
|
+
this._ydoc.transact(() => {
|
|
229
|
+
this._objectsMap.clear();
|
|
230
|
+
}, 'local');
|
|
231
|
+
}
|
|
232
|
+
insert(object) {
|
|
233
|
+
if (!object.id) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
this.quadtree.insert(object);
|
|
237
|
+
if (this._objectsMap && this.isPersistable(object)) {
|
|
238
|
+
const serialized = object.serialize();
|
|
239
|
+
this._ydoc.transact(() => {
|
|
240
|
+
this._objectsMap.set(object.id, serialized);
|
|
241
|
+
}, 'local');
|
|
242
|
+
}
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
update(object, options = {}) {
|
|
246
|
+
if (!object.id) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
const existed = this.quadtree.filter(o => o.id === object.id).length > 0;
|
|
250
|
+
if (!existed) {
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
this.quadtree.update(object);
|
|
254
|
+
if (this._objectsMap && this.isPersistable(object)) {
|
|
255
|
+
const serialized = object.serialize();
|
|
256
|
+
const origin = options.temporary ? 'temporary' : 'local';
|
|
257
|
+
this._ydoc.transact(() => {
|
|
258
|
+
this._objectsMap.set(object.id, serialized);
|
|
259
|
+
}, origin);
|
|
260
|
+
}
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
remove(predicate) {
|
|
264
|
+
const objectsToRemove = this.quadtree.filter(predicate);
|
|
265
|
+
for (const object of objectsToRemove) {
|
|
266
|
+
this.quadtree.remove(o => o.id === object.id);
|
|
267
|
+
if (this._objectsMap && this.isPersistable(object)) {
|
|
268
|
+
this._ydoc.transact(() => {
|
|
269
|
+
this._objectsMap.delete(object.id);
|
|
270
|
+
}, 'local');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
filter(predicate) {
|
|
275
|
+
return this.quadtree.filter(predicate);
|
|
276
|
+
}
|
|
277
|
+
allObjects() {
|
|
278
|
+
return this.quadtree.allObjects();
|
|
279
|
+
}
|
|
280
|
+
query(range) {
|
|
281
|
+
return this.quadtree.query(range);
|
|
282
|
+
}
|
|
283
|
+
isPersistable(object) {
|
|
284
|
+
if (object instanceof KritzelSelectionBox) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
undo() {
|
|
290
|
+
if (this._undoManager && this._undoManager.canUndo()) {
|
|
291
|
+
this._undoManager.undo();
|
|
292
|
+
this._core.engine.emitObjectsChange();
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
redo() {
|
|
296
|
+
if (this._undoManager && this._undoManager.canRedo()) {
|
|
297
|
+
this._undoManager.redo();
|
|
298
|
+
this._core.engine.emitObjectsChange();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
canUndo() {
|
|
302
|
+
return this._undoManager ? this._undoManager.canUndo() : false;
|
|
303
|
+
}
|
|
304
|
+
canRedo() {
|
|
305
|
+
return this._undoManager ? this._undoManager.canRedo() : false;
|
|
306
|
+
}
|
|
307
|
+
clearHistory() {
|
|
308
|
+
if (this._undoManager) {
|
|
309
|
+
this._undoManager.clear();
|
|
310
|
+
this._temporaryItemsCount = 0;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Consolidates all temporary items in the undo stack into a single undo item.
|
|
315
|
+
* Call this when you want to merge multiple temporary changes (e.g., keystrokes) into one.
|
|
316
|
+
*/
|
|
317
|
+
consolidateTemporaryItems() {
|
|
318
|
+
if (!this._undoManager || this._temporaryItemsCount === 0) {
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
// Get current stack length
|
|
322
|
+
const stackLength = this._undoManager.undoStack.length;
|
|
323
|
+
if (stackLength === 0) {
|
|
324
|
+
this._temporaryItemsCount = 0;
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
// Stop tracking temporarily
|
|
328
|
+
this._undoManager.stopCapturing();
|
|
329
|
+
// The temporary items should be at the end of the stack
|
|
330
|
+
// We'll need to undo them all, then redo as a single transaction
|
|
331
|
+
const itemsToConsolidate = Math.min(this._temporaryItemsCount, stackLength);
|
|
332
|
+
if (itemsToConsolidate > 1) {
|
|
333
|
+
// Store the current state before undoing
|
|
334
|
+
const undoneItems = [];
|
|
335
|
+
// Undo all temporary items
|
|
336
|
+
for (let i = 0; i < itemsToConsolidate; i++) {
|
|
337
|
+
if (this._undoManager.canUndo()) {
|
|
338
|
+
undoneItems.push(this._undoManager.undoStack[this._undoManager.undoStack.length - 1]);
|
|
339
|
+
this._undoManager.undo();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// Now redo them all as a single 'local' transaction
|
|
343
|
+
// This will consolidate them into one undo item
|
|
344
|
+
this._ydoc.transact(() => {
|
|
345
|
+
for (let i = itemsToConsolidate - 1; i >= 0; i--) {
|
|
346
|
+
if (this._undoManager.canRedo()) {
|
|
347
|
+
this._undoManager.redo();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}, 'local');
|
|
351
|
+
}
|
|
352
|
+
else if (itemsToConsolidate === 1) {
|
|
353
|
+
// If only one temporary item, just change its origin to 'local'
|
|
354
|
+
// This is implicit - next transaction will be separate
|
|
355
|
+
}
|
|
356
|
+
this._temporaryItemsCount = 0;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Removes all temporary items from the undo stack without consolidating them.
|
|
360
|
+
* Use this to discard temporary changes completely.
|
|
361
|
+
*/
|
|
362
|
+
clearTemporaryItems() {
|
|
363
|
+
if (!this._undoManager || this._temporaryItemsCount === 0) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const stackLength = this._undoManager.undoStack.length;
|
|
367
|
+
const itemsToRemove = Math.min(this._temporaryItemsCount, stackLength);
|
|
368
|
+
// Remove items from the end of the stack
|
|
369
|
+
for (let i = 0; i < itemsToRemove; i++) {
|
|
370
|
+
if (this._undoManager.undoStack.length > 0) {
|
|
371
|
+
this._undoManager.undoStack.pop();
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
this._temporaryItemsCount = 0;
|
|
375
|
+
}
|
|
376
|
+
destroy() {
|
|
377
|
+
// Unobserve the objects map
|
|
378
|
+
if (this._objectsMap && this._objectsObserver) {
|
|
379
|
+
this._objectsMap.unobserve(this._objectsObserver);
|
|
380
|
+
this._objectsObserver = null;
|
|
381
|
+
}
|
|
382
|
+
// Remove undo manager event listeners
|
|
383
|
+
if (this._undoManager) {
|
|
384
|
+
if (this._stackItemAddedHandler) {
|
|
385
|
+
this._undoManager.off('stack-item-added', this._stackItemAddedHandler);
|
|
386
|
+
this._stackItemAddedHandler = null;
|
|
387
|
+
}
|
|
388
|
+
if (this._stackItemPoppedHandler) {
|
|
389
|
+
this._undoManager.off('stack-item-popped', this._stackItemPoppedHandler);
|
|
390
|
+
this._stackItemPoppedHandler = null;
|
|
391
|
+
}
|
|
392
|
+
this._undoManager.destroy();
|
|
393
|
+
this._undoManager = null;
|
|
394
|
+
}
|
|
395
|
+
// Reset quadtree
|
|
396
|
+
this.quadtree.reset();
|
|
397
|
+
// Destroy providers
|
|
398
|
+
this._providers.forEach(p => p.destroy());
|
|
399
|
+
this._providers = [];
|
|
400
|
+
// Clear object map reference
|
|
401
|
+
this._objectsMap = null;
|
|
402
|
+
// Destroy Y.Doc
|
|
403
|
+
if (this._ydoc) {
|
|
404
|
+
this._ydoc.destroy();
|
|
405
|
+
this._ydoc = null;
|
|
406
|
+
}
|
|
407
|
+
// Clear remaining references
|
|
408
|
+
this._core = null;
|
|
409
|
+
this._reviver = null;
|
|
410
|
+
this._workspaceId = null;
|
|
411
|
+
this._isReady = false;
|
|
412
|
+
this._temporaryItemsCount = 0;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
export class KritzelQuadtree {
|
|
2
|
+
/** Total number of objects in the quadtree (O(1) access) */
|
|
3
|
+
get size() {
|
|
4
|
+
return this._size;
|
|
5
|
+
}
|
|
6
|
+
constructor(bounds, capacity = 16) {
|
|
7
|
+
this.objects = [];
|
|
8
|
+
this.children = null;
|
|
9
|
+
this._size = 0;
|
|
10
|
+
this.bounds = bounds;
|
|
11
|
+
this.capacity = capacity;
|
|
12
|
+
}
|
|
13
|
+
reset() {
|
|
14
|
+
this.objects = [];
|
|
15
|
+
this.children = null;
|
|
16
|
+
this._size = 0;
|
|
17
|
+
}
|
|
18
|
+
insert(object) {
|
|
19
|
+
if (!this.intersects(object.rotatedBoundingBox, this.bounds)) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (this.objects.length < this.capacity && this.children === null) {
|
|
23
|
+
this.objects.push(object);
|
|
24
|
+
this._size++;
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (this.children === null) {
|
|
28
|
+
this.subdivide();
|
|
29
|
+
}
|
|
30
|
+
for (const child of this.children) {
|
|
31
|
+
if (child.insert(object)) {
|
|
32
|
+
this._size++;
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
update(object) {
|
|
39
|
+
const index = this.objects.findIndex(o => o.id === object.id);
|
|
40
|
+
if (index !== -1) {
|
|
41
|
+
this.objects[index] = object;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
if (this.children !== null) {
|
|
45
|
+
for (const child of this.children) {
|
|
46
|
+
if (child.update(object)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
remove(predicate) {
|
|
54
|
+
let removed = 0;
|
|
55
|
+
const index = this.objects.findIndex(o => predicate(o));
|
|
56
|
+
if (index !== -1) {
|
|
57
|
+
this.objects.splice(index, 1);
|
|
58
|
+
removed++;
|
|
59
|
+
}
|
|
60
|
+
if (this.children !== null) {
|
|
61
|
+
for (const child of this.children) {
|
|
62
|
+
removed += child.remove(predicate);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
this._size -= removed;
|
|
66
|
+
return removed;
|
|
67
|
+
}
|
|
68
|
+
query(range) {
|
|
69
|
+
const results = [];
|
|
70
|
+
this._queryInto(range, results);
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Internal method that collects query results into a pre-allocated array.
|
|
75
|
+
* Avoids creating intermediate arrays from spread operators.
|
|
76
|
+
*/
|
|
77
|
+
_queryInto(range, results) {
|
|
78
|
+
if (!this.intersects(range, this.bounds)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
for (const object of this.objects) {
|
|
82
|
+
if (this.intersects(object.rotatedBoundingBox, range)) {
|
|
83
|
+
results.push(object);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (this.children !== null) {
|
|
87
|
+
for (const child of this.children) {
|
|
88
|
+
child._queryInto(range, results);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
filter(predicate) {
|
|
93
|
+
const results = [];
|
|
94
|
+
this._filterInto(predicate, results);
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Internal method that collects filter results into a pre-allocated array.
|
|
99
|
+
* Avoids creating intermediate arrays from spread operators.
|
|
100
|
+
*/
|
|
101
|
+
_filterInto(predicate, results) {
|
|
102
|
+
for (const obj of this.objects) {
|
|
103
|
+
if (predicate(obj)) {
|
|
104
|
+
results.push(obj);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (this.children !== null) {
|
|
108
|
+
for (const child of this.children) {
|
|
109
|
+
child._filterInto(predicate, results);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
allObjects() {
|
|
114
|
+
const results = [];
|
|
115
|
+
this._collectAllInto(results);
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Internal method that collects all objects into a pre-allocated array.
|
|
120
|
+
* Avoids creating intermediate arrays from spread operators.
|
|
121
|
+
*/
|
|
122
|
+
_collectAllInto(results) {
|
|
123
|
+
for (const obj of this.objects) {
|
|
124
|
+
results.push(obj);
|
|
125
|
+
}
|
|
126
|
+
if (this.children !== null) {
|
|
127
|
+
for (const child of this.children) {
|
|
128
|
+
child._collectAllInto(results);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
subdivide() {
|
|
133
|
+
const { x, y, z, width, height } = this.bounds;
|
|
134
|
+
const halfWidth = width / 2;
|
|
135
|
+
const halfHeight = height / 2;
|
|
136
|
+
// Create 4 quadrants: NW, NE, SW, SE
|
|
137
|
+
this.children = [
|
|
138
|
+
new KritzelQuadtree({ x, y, z, width: halfWidth, height: halfHeight }, this.capacity), // Northwest
|
|
139
|
+
new KritzelQuadtree({ x: x + halfWidth, y, z, width: halfWidth, height: halfHeight }, this.capacity), // Northeast
|
|
140
|
+
new KritzelQuadtree({ x, y: y + halfHeight, z, width: halfWidth, height: halfHeight }, this.capacity), // Southwest
|
|
141
|
+
new KritzelQuadtree({ x: x + halfWidth, y: y + halfHeight, z, width: halfWidth, height: halfHeight }, this.capacity), // Southeast
|
|
142
|
+
];
|
|
143
|
+
}
|
|
144
|
+
intersects(a, b) {
|
|
145
|
+
return !(a.x >= b.x + b.width || // a is completely to the right of b
|
|
146
|
+
a.x + a.width <= b.x || // a is completely to the left of b
|
|
147
|
+
a.y >= b.y + b.height || // a is completely below b
|
|
148
|
+
a.y + a.height <= b.y // a is completely above b
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export class KritzelBaseTool {
|
|
2
|
+
constructor(core) {
|
|
3
|
+
this.__class__ = this.constructor.name;
|
|
4
|
+
this.name = 'base-tool';
|
|
5
|
+
this._core = core;
|
|
6
|
+
void this._core; // Avoid unused variable warning
|
|
7
|
+
}
|
|
8
|
+
onActivate() {
|
|
9
|
+
// default implementation
|
|
10
|
+
}
|
|
11
|
+
onDeactivate() {
|
|
12
|
+
// default implementation
|
|
13
|
+
}
|
|
14
|
+
handlePointerDown(_event) {
|
|
15
|
+
// default implementation
|
|
16
|
+
}
|
|
17
|
+
handlePointerMove(_event) {
|
|
18
|
+
// default implementation
|
|
19
|
+
}
|
|
20
|
+
handlePointerUp(_event) {
|
|
21
|
+
// default implementation
|
|
22
|
+
}
|
|
23
|
+
handleWheel(_event) {
|
|
24
|
+
// default implementation
|
|
25
|
+
}
|
|
26
|
+
serialize() {
|
|
27
|
+
return {
|
|
28
|
+
__class__: this.__class__,
|
|
29
|
+
name: this.name,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
deserialize(object) {
|
|
33
|
+
Object.assign(this, object);
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
}
|