js-draw 0.1.12 → 0.2.0
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/.eslintrc.js +1 -0
- package/.firebaserc +5 -0
- package/.github/workflows/firebase-hosting-merge.yml +25 -0
- package/.github/workflows/firebase-hosting-pull-request.yml +22 -0
- package/.github/workflows/github-pages.yml +52 -0
- package/CHANGELOG.md +6 -0
- package/README.md +11 -6
- package/dist/bundle.js +1 -1
- package/dist/src/Color4.d.ts +19 -0
- package/dist/src/Color4.js +24 -3
- package/dist/src/Editor.d.ts +129 -2
- package/dist/src/Editor.js +94 -17
- package/dist/src/EditorImage.d.ts +7 -2
- package/dist/src/EditorImage.js +41 -25
- package/dist/src/EventDispatcher.d.ts +18 -0
- package/dist/src/EventDispatcher.js +19 -4
- package/dist/src/Pointer.js +3 -2
- package/dist/src/UndoRedoHistory.js +15 -2
- package/dist/src/Viewport.js +4 -1
- package/dist/src/bundle/bundled.d.ts +1 -2
- package/dist/src/bundle/bundled.js +1 -2
- package/dist/src/commands/Duplicate.d.ts +1 -1
- package/dist/src/commands/Duplicate.js +3 -4
- package/dist/src/commands/Erase.d.ts +1 -1
- package/dist/src/commands/Erase.js +6 -5
- package/dist/src/commands/SerializableCommand.d.ts +4 -5
- package/dist/src/commands/SerializableCommand.js +12 -4
- package/dist/src/commands/invertCommand.d.ts +4 -0
- package/dist/src/commands/invertCommand.js +44 -0
- package/dist/src/commands/lib.d.ts +6 -0
- package/dist/src/commands/lib.js +6 -0
- package/dist/src/commands/localization.d.ts +1 -0
- package/dist/src/commands/localization.js +1 -0
- package/dist/src/components/AbstractComponent.d.ts +13 -8
- package/dist/src/components/AbstractComponent.js +26 -15
- package/dist/src/components/SVGGlobalAttributesObject.d.ts +1 -1
- package/dist/src/components/SVGGlobalAttributesObject.js +7 -1
- package/dist/src/components/Stroke.d.ts +12 -2
- package/dist/src/components/Stroke.js +10 -7
- package/dist/src/components/Text.d.ts +2 -2
- package/dist/src/components/Text.js +6 -6
- package/dist/src/components/UnknownSVGObject.d.ts +1 -1
- package/dist/src/components/UnknownSVGObject.js +6 -1
- package/dist/src/components/lib.d.ts +4 -0
- package/dist/src/components/lib.js +4 -0
- package/dist/src/lib.d.ts +25 -0
- package/dist/src/lib.js +25 -0
- package/dist/src/math/Mat33.d.ts +47 -1
- package/dist/src/math/Mat33.js +48 -20
- package/dist/src/math/Path.js +3 -3
- package/dist/src/math/Rect2.d.ts +2 -2
- package/dist/src/math/Vec3.d.ts +62 -0
- package/dist/src/math/Vec3.js +62 -14
- package/dist/src/math/lib.d.ts +7 -0
- package/dist/src/math/lib.js +7 -0
- package/dist/src/math/rounding.js +1 -0
- package/dist/src/rendering/Display.d.ts +44 -0
- package/dist/src/rendering/Display.js +45 -6
- package/dist/src/rendering/caching/CacheRecord.d.ts +1 -0
- package/dist/src/rendering/caching/CacheRecord.js +3 -0
- package/dist/src/rendering/caching/CacheRecordManager.d.ts +4 -3
- package/dist/src/rendering/caching/CacheRecordManager.js +16 -4
- package/dist/src/rendering/caching/RenderingCache.d.ts +2 -3
- package/dist/src/rendering/caching/RenderingCache.js +9 -10
- package/dist/src/rendering/caching/types.d.ts +1 -3
- package/dist/src/rendering/renderers/CanvasRenderer.js +1 -1
- package/dist/src/toolbar/HTMLToolbar.js +1 -0
- package/dist/src/toolbar/makeColorInput.js +1 -1
- package/dist/src/toolbar/widgets/PenWidget.js +1 -0
- package/dist/src/tools/Pen.d.ts +1 -2
- package/dist/src/tools/Pen.js +8 -1
- package/dist/src/tools/PipetteTool.js +1 -0
- package/dist/src/tools/SelectionTool.js +45 -22
- package/dist/src/types.d.ts +17 -6
- package/dist/src/types.js +7 -5
- package/firebase.json +16 -0
- package/package.json +118 -101
- package/src/Color4.ts +23 -2
- package/src/Editor.ts +147 -25
- package/src/EditorImage.ts +45 -27
- package/src/EventDispatcher.ts +21 -6
- package/src/Pointer.ts +3 -2
- package/src/UndoRedoHistory.ts +18 -2
- package/src/Viewport.ts +5 -2
- package/src/bundle/bundled.ts +1 -2
- package/src/commands/Duplicate.ts +3 -4
- package/src/commands/Erase.ts +6 -5
- package/src/commands/SerializableCommand.ts +17 -9
- package/src/commands/invertCommand.ts +51 -0
- package/src/commands/lib.ts +14 -0
- package/src/commands/localization.ts +2 -0
- package/src/components/AbstractComponent.ts +31 -20
- package/src/components/SVGGlobalAttributesObject.ts +8 -1
- package/src/components/Stroke.test.ts +1 -1
- package/src/components/Stroke.ts +11 -7
- package/src/components/Text.ts +6 -7
- package/src/components/UnknownSVGObject.ts +7 -1
- package/src/components/lib.ts +9 -0
- package/src/lib.ts +28 -0
- package/src/math/Mat33.ts +48 -20
- package/src/math/Path.ts +3 -3
- package/src/math/Rect2.ts +2 -2
- package/src/math/Vec3.ts +62 -14
- package/src/math/lib.ts +15 -0
- package/src/math/rounding.ts +2 -0
- package/src/rendering/Display.ts +46 -6
- package/src/rendering/caching/CacheRecord.test.ts +1 -1
- package/src/rendering/caching/CacheRecord.ts +4 -0
- package/src/rendering/caching/CacheRecordManager.ts +33 -7
- package/src/rendering/caching/RenderingCache.ts +10 -15
- package/src/rendering/caching/types.ts +1 -6
- package/src/rendering/renderers/CanvasRenderer.ts +1 -1
- package/src/toolbar/HTMLToolbar.ts +1 -0
- package/src/toolbar/makeColorInput.ts +1 -1
- package/src/toolbar/widgets/PenWidget.ts +2 -0
- package/src/tools/PanZoom.ts +0 -1
- package/src/tools/Pen.ts +11 -2
- package/src/tools/PipetteTool.ts +2 -0
- package/src/tools/SelectionTool.ts +46 -18
- package/src/types.ts +19 -3
- package/tsconfig.json +4 -1
- package/typedoc.json +20 -0
@@ -1,3 +1,17 @@
|
|
1
|
+
/**
|
2
|
+
* Handles `HTMLCanvasElement`s (or other drawing surfaces if being used) used to display the editor's contents.
|
3
|
+
*
|
4
|
+
* @example
|
5
|
+
* ```
|
6
|
+
* const editor = new Editor(document.body);
|
7
|
+
* const w = editor.display.width;
|
8
|
+
* const h = editor.display.height;
|
9
|
+
* const center = Vec2.of(w / 2, h / 2);
|
10
|
+
* const colorAtCenter = editor.display.getColorAt(center);
|
11
|
+
* ```
|
12
|
+
*
|
13
|
+
* @packageDocumentation
|
14
|
+
*/
|
1
15
|
import CanvasRenderer from './renderers/CanvasRenderer';
|
2
16
|
import { EditorEventType } from '../types';
|
3
17
|
import DummyRenderer from './renderers/DummyRenderer';
|
@@ -12,10 +26,15 @@ export var RenderingMode;
|
|
12
26
|
// SVGRenderer is not supported by the main display
|
13
27
|
})(RenderingMode || (RenderingMode = {}));
|
14
28
|
export default class Display {
|
29
|
+
/** @internal */
|
15
30
|
constructor(editor, mode, parent) {
|
16
31
|
this.editor = editor;
|
17
32
|
this.parent = parent;
|
18
33
|
this.textRerenderOutput = null;
|
34
|
+
/**
|
35
|
+
* @returns the color at the given point on the dry ink renderer, or `null` if `screenPos`
|
36
|
+
* is not on the display.
|
37
|
+
*/
|
19
38
|
this.getColorAt = (_screenPos) => {
|
20
39
|
return null;
|
21
40
|
};
|
@@ -52,7 +71,7 @@ export default class Display {
|
|
52
71
|
return this.dryInkRenderer.canRenderFromWithoutDataLoss(renderer);
|
53
72
|
},
|
54
73
|
blockResolution: cacheBlockResolution,
|
55
|
-
cacheSize: 500 * 500 * 4 *
|
74
|
+
cacheSize: 500 * 500 * 4 * 150,
|
56
75
|
maxScale: 1.5,
|
57
76
|
minComponentsPerCache: 45,
|
58
77
|
minComponentsToUseCache: 105,
|
@@ -65,15 +84,18 @@ export default class Display {
|
|
65
84
|
(_a = this.resizeSurfacesCallback) === null || _a === void 0 ? void 0 : _a.call(this);
|
66
85
|
});
|
67
86
|
}
|
68
|
-
|
69
|
-
|
70
|
-
|
87
|
+
/**
|
88
|
+
* @returns the visible width of the display (e.g. how much
|
89
|
+
* space the display's element takes up in the x direction
|
90
|
+
* in the DOM).
|
91
|
+
*/
|
71
92
|
get width() {
|
72
93
|
return this.dryInkRenderer.displaySize().x;
|
73
94
|
}
|
74
95
|
get height() {
|
75
96
|
return this.dryInkRenderer.displaySize().y;
|
76
97
|
}
|
98
|
+
/** @internal */
|
77
99
|
getCache() {
|
78
100
|
return this.cache;
|
79
101
|
}
|
@@ -135,6 +157,10 @@ export default class Display {
|
|
135
157
|
textRendererOutputContainer.replaceChildren(rerenderButton, this.textRerenderOutput);
|
136
158
|
this.editor.createHTMLOverlay(textRendererOutputContainer);
|
137
159
|
}
|
160
|
+
/**
|
161
|
+
* Rerenders the text-based display.
|
162
|
+
* The text-based display is intended for screen readers and can be navigated to by pressing `tab`.
|
163
|
+
*/
|
138
164
|
rerenderAsText() {
|
139
165
|
this.textRenderer.clear();
|
140
166
|
this.editor.image.render(this.textRenderer, this.editor.viewport);
|
@@ -142,7 +168,11 @@ export default class Display {
|
|
142
168
|
this.textRerenderOutput.innerText = this.textRenderer.getDescription();
|
143
169
|
}
|
144
170
|
}
|
145
|
-
|
171
|
+
/**
|
172
|
+
* Clears the drawing surfaces and otherwise prepares for a rerender.
|
173
|
+
*
|
174
|
+
* @returns the dry ink renderer.
|
175
|
+
*/
|
146
176
|
startRerender() {
|
147
177
|
var _a;
|
148
178
|
(_a = this.resizeSurfacesCallback) === null || _a === void 0 ? void 0 : _a.call(this);
|
@@ -150,16 +180,25 @@ export default class Display {
|
|
150
180
|
this.dryInkRenderer.clear();
|
151
181
|
return this.dryInkRenderer;
|
152
182
|
}
|
183
|
+
/**
|
184
|
+
* If `draftMode`, the dry ink renderer is configured to render
|
185
|
+
* low-quality output.
|
186
|
+
*/
|
153
187
|
setDraftMode(draftMode) {
|
154
188
|
this.dryInkRenderer.setDraftMode(draftMode);
|
155
189
|
}
|
190
|
+
/** @internal */
|
156
191
|
getDryInkRenderer() {
|
157
192
|
return this.dryInkRenderer;
|
158
193
|
}
|
194
|
+
/**
|
195
|
+
* @returns The renderer used for showing action previews (e.g. an unfinished stroke).
|
196
|
+
* The `wetInkRenderer`'s surface is stacked above the `dryInkRenderer`'s.
|
197
|
+
*/
|
159
198
|
getWetInkRenderer() {
|
160
199
|
return this.wetInkRenderer;
|
161
200
|
}
|
162
|
-
|
201
|
+
/** Re-renders the contents of the wetInkRenderer onto the dryInkRenderer. */
|
163
202
|
flatten() {
|
164
203
|
var _a;
|
165
204
|
(_a = this.flattenCallback) === null || _a === void 0 ? void 0 : _a.call(this);
|
@@ -8,6 +8,7 @@ export default class CacheRecord {
|
|
8
8
|
private renderer;
|
9
9
|
private lastUsedCycle;
|
10
10
|
private allocd;
|
11
|
+
allocCount: number;
|
11
12
|
constructor(onBeforeDeallocCallback: BeforeDeallocCallback | null, cacheState: CacheState);
|
12
13
|
startRender(): AbstractRenderer;
|
13
14
|
dealloc(): void;
|
@@ -6,6 +6,8 @@ export default class CacheRecord {
|
|
6
6
|
this.onBeforeDeallocCallback = onBeforeDeallocCallback;
|
7
7
|
this.cacheState = cacheState;
|
8
8
|
this.allocd = false;
|
9
|
+
// For debugging
|
10
|
+
this.allocCount = 0;
|
9
11
|
this.renderer = cacheState.props.createRenderer();
|
10
12
|
this.lastUsedCycle = -1;
|
11
13
|
this.allocd = true;
|
@@ -34,6 +36,7 @@ export default class CacheRecord {
|
|
34
36
|
this.allocd = true;
|
35
37
|
this.onBeforeDeallocCallback = newDeallocCallback;
|
36
38
|
this.lastUsedCycle = this.cacheState.currentRenderingCycle;
|
39
|
+
this.allocCount++;
|
37
40
|
}
|
38
41
|
getLastUsedCycle() {
|
39
42
|
return this.lastUsedCycle;
|
@@ -1,11 +1,12 @@
|
|
1
|
-
import { BeforeDeallocCallback,
|
1
|
+
import { BeforeDeallocCallback, CacheProps, CacheState } from './types';
|
2
2
|
import CacheRecord from './CacheRecord';
|
3
3
|
import Rect2 from '../../math/Rect2';
|
4
4
|
export declare class CacheRecordManager {
|
5
|
-
private readonly cacheState;
|
6
5
|
private cacheRecords;
|
7
6
|
private maxCanvases;
|
8
|
-
|
7
|
+
private cacheState;
|
8
|
+
constructor(cacheProps: CacheProps);
|
9
|
+
setSharedState(state: CacheState): void;
|
9
10
|
allocCanvas(drawTo: Rect2, onDealloc: BeforeDeallocCallback): CacheRecord;
|
10
11
|
private getLeastRecentlyUsedRecord;
|
11
12
|
}
|
@@ -1,25 +1,37 @@
|
|
1
1
|
import CacheRecord from './CacheRecord';
|
2
|
+
const debugMode = false;
|
2
3
|
export class CacheRecordManager {
|
3
|
-
constructor(
|
4
|
-
this.cacheState = cacheState;
|
4
|
+
constructor(cacheProps) {
|
5
5
|
// Fixed-size array: Cache blocks are assigned indicies into [cachedCanvases].
|
6
6
|
this.cacheRecords = [];
|
7
|
-
const cacheProps = cacheState.props;
|
8
7
|
this.maxCanvases = Math.ceil(
|
9
8
|
// Assuming four components per pixel:
|
10
9
|
cacheProps.cacheSize / 4 / cacheProps.blockResolution.x / cacheProps.blockResolution.y);
|
11
10
|
}
|
11
|
+
setSharedState(state) {
|
12
|
+
this.cacheState = state;
|
13
|
+
}
|
12
14
|
allocCanvas(drawTo, onDealloc) {
|
13
15
|
if (this.cacheRecords.length < this.maxCanvases) {
|
14
|
-
const record = new CacheRecord(onDealloc,
|
16
|
+
const record = new CacheRecord(onDealloc, this.cacheState);
|
15
17
|
record.setRenderingRegion(drawTo);
|
16
18
|
this.cacheRecords.push(record);
|
19
|
+
if (debugMode) {
|
20
|
+
console.log('[Cache] Cache spaces used: ', this.cacheRecords.length, ' of ', this.maxCanvases);
|
21
|
+
}
|
17
22
|
return record;
|
18
23
|
}
|
19
24
|
else {
|
20
25
|
const lru = this.getLeastRecentlyUsedRecord();
|
26
|
+
if (debugMode) {
|
27
|
+
console.log('[Cache] Re-alloc. Times allocated: ', lru.allocCount, '\nLast used cycle: ', lru.getLastUsedCycle(), '\nCurrent cycle: ', this.cacheState.currentRenderingCycle);
|
28
|
+
}
|
21
29
|
lru.realloc(onDealloc);
|
22
30
|
lru.setRenderingRegion(drawTo);
|
31
|
+
if (debugMode) {
|
32
|
+
console.log('[Cache] Now re-alloc\'d. Last used cycle: ', lru.getLastUsedCycle());
|
33
|
+
console.assert(lru['cacheState'] === this.cacheState, '[Cache] Unequal cache states! cacheState should be a shared object!');
|
34
|
+
}
|
23
35
|
return lru;
|
24
36
|
}
|
25
37
|
}
|
@@ -1,12 +1,11 @@
|
|
1
1
|
import { ImageNode } from '../../EditorImage';
|
2
2
|
import Viewport from '../../Viewport';
|
3
3
|
import AbstractRenderer from '../renderers/AbstractRenderer';
|
4
|
-
import { CacheProps
|
4
|
+
import { CacheProps } from './types';
|
5
5
|
export default class RenderingCache {
|
6
|
-
private
|
6
|
+
private sharedState;
|
7
7
|
private recordManager;
|
8
8
|
private rootNode;
|
9
9
|
constructor(cacheProps: CacheProps);
|
10
|
-
getSharedState(): CacheState;
|
11
10
|
render(screenRenderer: AbstractRenderer, image: ImageNode, viewport: Viewport): void;
|
12
11
|
}
|
@@ -3,36 +3,35 @@ import RenderingCacheNode from './RenderingCacheNode';
|
|
3
3
|
import { CacheRecordManager } from './CacheRecordManager';
|
4
4
|
export default class RenderingCache {
|
5
5
|
constructor(cacheProps) {
|
6
|
-
this.
|
6
|
+
this.recordManager = new CacheRecordManager(cacheProps);
|
7
|
+
this.sharedState = {
|
7
8
|
props: cacheProps,
|
8
9
|
currentRenderingCycle: 0,
|
10
|
+
recordManager: this.recordManager,
|
9
11
|
};
|
10
|
-
this.recordManager
|
11
|
-
}
|
12
|
-
getSharedState() {
|
13
|
-
return Object.assign(Object.assign({}, this.partialSharedState), { recordManager: this.recordManager });
|
12
|
+
this.recordManager.setSharedState(this.sharedState);
|
14
13
|
}
|
15
14
|
render(screenRenderer, image, viewport) {
|
16
15
|
var _a;
|
17
16
|
const visibleRect = viewport.visibleRect;
|
18
|
-
this.
|
17
|
+
this.sharedState.currentRenderingCycle++;
|
19
18
|
// If we can't use the cache,
|
20
|
-
if (!this.
|
19
|
+
if (!this.sharedState.props.isOfCorrectType(screenRenderer)) {
|
21
20
|
image.render(screenRenderer, visibleRect);
|
22
21
|
return;
|
23
22
|
}
|
24
23
|
if (!this.rootNode) {
|
25
24
|
// Adjust the node so that it has the correct aspect ratio
|
26
|
-
const res = this.
|
25
|
+
const res = this.sharedState.props.blockResolution;
|
27
26
|
const topLeft = visibleRect.topLeft;
|
28
|
-
this.rootNode = new RenderingCacheNode(new Rect2(topLeft.x, topLeft.y, res.x, res.y), this.
|
27
|
+
this.rootNode = new RenderingCacheNode(new Rect2(topLeft.x, topLeft.y, res.x, res.y), this.sharedState);
|
29
28
|
}
|
30
29
|
while (!this.rootNode.region.containsRect(visibleRect)) {
|
31
30
|
this.rootNode = this.rootNode.generateParent();
|
32
31
|
}
|
33
32
|
this.rootNode = (_a = this.rootNode.smallestChildContaining(visibleRect)) !== null && _a !== void 0 ? _a : this.rootNode;
|
34
33
|
const visibleLeaves = image.getLeavesIntersectingRegion(viewport.visibleRect, rect => screenRenderer.isTooSmallToRender(rect));
|
35
|
-
if (visibleLeaves.length > this.
|
34
|
+
if (visibleLeaves.length > this.sharedState.props.minComponentsToUseCache) {
|
36
35
|
this.rootNode.renderItems(screenRenderer, [image], viewport);
|
37
36
|
}
|
38
37
|
else {
|
@@ -12,10 +12,8 @@ export interface CacheProps {
|
|
12
12
|
minComponentsPerCache: number;
|
13
13
|
minComponentsToUseCache: number;
|
14
14
|
}
|
15
|
-
export interface
|
15
|
+
export interface CacheState {
|
16
16
|
currentRenderingCycle: number;
|
17
17
|
props: CacheProps;
|
18
|
-
}
|
19
|
-
export interface CacheState extends PartialCacheState {
|
20
18
|
recordManager: CacheRecordManager;
|
21
19
|
}
|
@@ -2,7 +2,7 @@ import Color4 from '../Color4';
|
|
2
2
|
import { ToolType } from '../tools/ToolController';
|
3
3
|
import { EditorEventType } from '../types';
|
4
4
|
import { makePipetteIcon } from './icons';
|
5
|
-
// Returns [ input, container ].
|
5
|
+
// Returns [ color input, input container ].
|
6
6
|
export const makeColorInput = (editor, onColorChange) => {
|
7
7
|
const colorInputContainer = document.createElement('span');
|
8
8
|
const colorInput = document.createElement('input');
|
@@ -1,3 +1,4 @@
|
|
1
|
+
// @internal @packageDocumentation
|
1
2
|
import { makeArrowBuilder } from '../../components/builders/ArrowBuilder';
|
2
3
|
import { makeFreehandLineBuilder } from '../../components/builders/FreehandLineBuilder';
|
3
4
|
import { makeLineBuilder } from '../../components/builders/LineBuilder';
|
package/dist/src/tools/Pen.d.ts
CHANGED
@@ -4,7 +4,7 @@ import { PointerEvt } from '../types';
|
|
4
4
|
import BaseTool from './BaseTool';
|
5
5
|
import { ToolType } from './ToolController';
|
6
6
|
import { ComponentBuilderFactory } from '../components/builders/types';
|
7
|
-
interface PenStyle {
|
7
|
+
export interface PenStyle {
|
8
8
|
color: Color4;
|
9
9
|
thickness: number;
|
10
10
|
}
|
@@ -32,4 +32,3 @@ export default class Pen extends BaseTool {
|
|
32
32
|
getColor(): Color4;
|
33
33
|
getStrokeFactory(): ComponentBuilderFactory;
|
34
34
|
}
|
35
|
-
export {};
|
package/dist/src/tools/Pen.js
CHANGED
@@ -20,7 +20,14 @@ export default class Pen extends BaseTool {
|
|
20
20
|
getStrokePoint(pointer) {
|
21
21
|
var _a;
|
22
22
|
const minPressure = 0.3;
|
23
|
-
|
23
|
+
let pressure = Math.max((_a = pointer.pressure) !== null && _a !== void 0 ? _a : 1.0, minPressure);
|
24
|
+
if (!isFinite(pressure)) {
|
25
|
+
console.warn('Non-finite pressure!', pointer);
|
26
|
+
pressure = minPressure;
|
27
|
+
}
|
28
|
+
console.assert(isFinite(pointer.canvasPos.length()), 'Non-finite canvas position!');
|
29
|
+
console.assert(isFinite(pointer.screenPos.length()), 'Non-finite screen position!');
|
30
|
+
console.assert(isFinite(pointer.timeStamp), 'Non-finite timeStamp on pointer!');
|
24
31
|
return {
|
25
32
|
pos: pointer.canvasPos,
|
26
33
|
width: pressure * this.getPressureMultiplier(),
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8
8
|
});
|
9
9
|
};
|
10
|
-
|
10
|
+
var _a;
|
11
11
|
import Duplicate from '../commands/Duplicate';
|
12
12
|
import Erase from '../commands/Erase';
|
13
13
|
import Mat33 from '../math/Mat33';
|
@@ -18,6 +18,7 @@ import { EditorEventType } from '../types';
|
|
18
18
|
import Viewport from '../Viewport';
|
19
19
|
import BaseTool from './BaseTool';
|
20
20
|
import { ToolType } from './ToolController';
|
21
|
+
import SerializableCommand from '../commands/SerializableCommand';
|
21
22
|
const handleScreenSize = 30;
|
22
23
|
const styles = `
|
23
24
|
.handleOverlay {
|
@@ -118,6 +119,7 @@ const makeDraggable = (element, onDrag, onDragEnd) => {
|
|
118
119
|
};
|
119
120
|
// Maximum number of strokes to transform without a re-render.
|
120
121
|
const updateChunkSize = 100;
|
122
|
+
// @internal
|
121
123
|
class Selection {
|
122
124
|
constructor(startPoint, editor) {
|
123
125
|
this.startPoint = startPoint;
|
@@ -228,7 +230,7 @@ class Selection {
|
|
228
230
|
this.transform = Mat33.identity;
|
229
231
|
this.region = this.region.transformedBoundingBox(inverseTransform);
|
230
232
|
// Make the commands undo-able
|
231
|
-
this.editor.dispatch(new Selection.ApplyTransformationCommand(this, currentTransfmCommands, fullTransform,
|
233
|
+
this.editor.dispatch(new Selection.ApplyTransformationCommand(this, currentTransfmCommands, fullTransform, deltaBoxRotation));
|
232
234
|
}
|
233
235
|
// Preview the effects of the current transformation on the selection
|
234
236
|
previewTransformCmds() {
|
@@ -352,36 +354,57 @@ class Selection {
|
|
352
354
|
return new Duplicate(this.selectedElems);
|
353
355
|
}
|
354
356
|
}
|
355
|
-
|
356
|
-
|
357
|
-
|
357
|
+
_a = Selection;
|
358
|
+
(() => {
|
359
|
+
SerializableCommand.register('selection-tool-transform', (json, editor) => {
|
360
|
+
// The selection box is lost when serializing/deserializing. No need to store box rotation
|
361
|
+
const guiBoxRotation = 0;
|
362
|
+
const fullTransform = new Mat33(...json.transform);
|
363
|
+
const commands = json.commands.map(data => SerializableCommand.deserialize(data, editor));
|
364
|
+
return new _a.ApplyTransformationCommand(null, commands, fullTransform, guiBoxRotation);
|
365
|
+
});
|
366
|
+
})();
|
367
|
+
Selection.ApplyTransformationCommand = class extends SerializableCommand {
|
368
|
+
constructor(selection, currentTransfmCommands, fullTransform, deltaBoxRotation) {
|
369
|
+
super('selection-tool-transform');
|
358
370
|
this.selection = selection;
|
359
371
|
this.currentTransfmCommands = currentTransfmCommands;
|
360
372
|
this.fullTransform = fullTransform;
|
361
|
-
this.inverseTransform = inverseTransform;
|
362
373
|
this.deltaBoxRotation = deltaBoxRotation;
|
363
374
|
}
|
364
375
|
apply(editor) {
|
376
|
+
var _b, _c;
|
365
377
|
return __awaiter(this, void 0, void 0, function* () {
|
366
378
|
// Approximate the new selection
|
367
|
-
|
368
|
-
|
369
|
-
|
379
|
+
if (this.selection) {
|
380
|
+
this.selection.region = this.selection.region.transformedBoundingBox(this.fullTransform);
|
381
|
+
this.selection.boxRotation += this.deltaBoxRotation;
|
382
|
+
this.selection.updateUI();
|
383
|
+
}
|
370
384
|
yield editor.asyncApplyCommands(this.currentTransfmCommands, updateChunkSize);
|
371
|
-
this.selection.recomputeRegion();
|
372
|
-
this.selection.updateUI();
|
385
|
+
(_b = this.selection) === null || _b === void 0 ? void 0 : _b.recomputeRegion();
|
386
|
+
(_c = this.selection) === null || _c === void 0 ? void 0 : _c.updateUI();
|
373
387
|
});
|
374
388
|
}
|
375
389
|
unapply(editor) {
|
390
|
+
var _b, _c;
|
376
391
|
return __awaiter(this, void 0, void 0, function* () {
|
377
|
-
|
378
|
-
|
379
|
-
|
392
|
+
if (this.selection) {
|
393
|
+
this.selection.region = this.selection.region.transformedBoundingBox(this.fullTransform.inverse());
|
394
|
+
this.selection.boxRotation -= this.deltaBoxRotation;
|
395
|
+
this.selection.updateUI();
|
396
|
+
}
|
380
397
|
yield editor.asyncUnapplyCommands(this.currentTransfmCommands, updateChunkSize);
|
381
|
-
this.selection.recomputeRegion();
|
382
|
-
this.selection.updateUI();
|
398
|
+
(_b = this.selection) === null || _b === void 0 ? void 0 : _b.recomputeRegion();
|
399
|
+
(_c = this.selection) === null || _c === void 0 ? void 0 : _c.updateUI();
|
383
400
|
});
|
384
401
|
}
|
402
|
+
serializeToJSON() {
|
403
|
+
return {
|
404
|
+
commands: this.currentTransfmCommands.map(command => command.serialize()),
|
405
|
+
transform: this.fullTransform.toArray(),
|
406
|
+
};
|
407
|
+
}
|
385
408
|
description(_editor, localizationTable) {
|
386
409
|
return localizationTable.transformedElements(this.currentTransfmCommands.length);
|
387
410
|
}
|
@@ -397,9 +420,9 @@ export default class SelectionTool extends BaseTool {
|
|
397
420
|
this.handleOverlay.style.display = 'none';
|
398
421
|
this.handleOverlay.classList.add('handleOverlay');
|
399
422
|
editor.notifier.on(EditorEventType.ViewportChanged, _data => {
|
400
|
-
var
|
401
|
-
(
|
402
|
-
(
|
423
|
+
var _b, _c;
|
424
|
+
(_b = this.selectionBox) === null || _b === void 0 ? void 0 : _b.recomputeRegion();
|
425
|
+
(_c = this.selectionBox) === null || _c === void 0 ? void 0 : _c.updateUI();
|
403
426
|
});
|
404
427
|
this.editor.handleKeyEventsFrom(this.handleOverlay);
|
405
428
|
}
|
@@ -447,11 +470,11 @@ export default class SelectionTool extends BaseTool {
|
|
447
470
|
this.onGestureEnd();
|
448
471
|
}
|
449
472
|
onGestureCancel() {
|
450
|
-
var
|
473
|
+
var _b, _c;
|
451
474
|
// Revert to the previous selection, if any.
|
452
|
-
(
|
475
|
+
(_b = this.selectionBox) === null || _b === void 0 ? void 0 : _b.cancelSelection();
|
453
476
|
this.selectionBox = this.prevSelectionBox;
|
454
|
-
(
|
477
|
+
(_c = this.selectionBox) === null || _c === void 0 ? void 0 : _c.appendBackgroundBoxTo(this.handleOverlay);
|
455
478
|
}
|
456
479
|
onKeyPress(event) {
|
457
480
|
let rotationSteps = 0;
|
package/dist/src/types.d.ts
CHANGED
@@ -7,6 +7,7 @@ import AbstractComponent from './components/AbstractComponent';
|
|
7
7
|
import Rect2 from './math/Rect2';
|
8
8
|
import Pointer from './Pointer';
|
9
9
|
import Color4 from './Color4';
|
10
|
+
import Command from './commands/Command';
|
10
11
|
export interface PointerEvtListener {
|
11
12
|
onPointerDown(event: PointerEvt): boolean;
|
12
13
|
onPointerMove(event: PointerEvt): void;
|
@@ -61,11 +62,13 @@ export declare enum EditorEventType {
|
|
61
62
|
ToolDisabled = 1,
|
62
63
|
ToolUpdated = 2,
|
63
64
|
UndoRedoStackUpdated = 3,
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
CommandDone = 4,
|
66
|
+
CommandUndone = 5,
|
67
|
+
ObjectAdded = 6,
|
68
|
+
ViewportChanged = 7,
|
69
|
+
DisplayResized = 8,
|
70
|
+
ColorPickerToggled = 9,
|
71
|
+
ColorPickerColorSelected = 10
|
69
72
|
}
|
70
73
|
declare type EditorToolEventType = EditorEventType.ToolEnabled | EditorEventType.ToolDisabled | EditorEventType.ToolUpdated;
|
71
74
|
export interface EditorToolEvent {
|
@@ -90,6 +93,14 @@ export interface EditorUndoStackUpdated {
|
|
90
93
|
readonly undoStackSize: number;
|
91
94
|
readonly redoStackSize: number;
|
92
95
|
}
|
96
|
+
export interface CommandDoneEvent {
|
97
|
+
readonly kind: EditorEventType.CommandDone;
|
98
|
+
readonly command: Command;
|
99
|
+
}
|
100
|
+
export interface CommandUndoneEvent {
|
101
|
+
readonly kind: EditorEventType.CommandUndone;
|
102
|
+
readonly command: Command;
|
103
|
+
}
|
93
104
|
export interface ColorPickerToggled {
|
94
105
|
readonly kind: EditorEventType.ColorPickerToggled;
|
95
106
|
readonly open: boolean;
|
@@ -98,7 +109,7 @@ export interface ColorPickerColorSelected {
|
|
98
109
|
readonly kind: EditorEventType.ColorPickerColorSelected;
|
99
110
|
readonly color: Color4;
|
100
111
|
}
|
101
|
-
export declare type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | ColorPickerToggled | ColorPickerColorSelected;
|
112
|
+
export declare type EditorEventDataType = EditorToolEvent | EditorObjectEvent | EditorViewportChangedEvent | DisplayResizedEvent | EditorUndoStackUpdated | CommandDoneEvent | CommandUndoneEvent | ColorPickerToggled | ColorPickerColorSelected;
|
102
113
|
export declare type OnProgressListener = (amountProcessed: number, totalToProcess: number) => Promise<void> | null;
|
103
114
|
export declare type ComponentAddedListener = (component: AbstractComponent) => void;
|
104
115
|
export declare type OnDetermineExportRectListener = (exportRect: Rect2) => void;
|
package/dist/src/types.js
CHANGED
@@ -15,9 +15,11 @@ export var EditorEventType;
|
|
15
15
|
EditorEventType[EditorEventType["ToolDisabled"] = 1] = "ToolDisabled";
|
16
16
|
EditorEventType[EditorEventType["ToolUpdated"] = 2] = "ToolUpdated";
|
17
17
|
EditorEventType[EditorEventType["UndoRedoStackUpdated"] = 3] = "UndoRedoStackUpdated";
|
18
|
-
EditorEventType[EditorEventType["
|
19
|
-
EditorEventType[EditorEventType["
|
20
|
-
EditorEventType[EditorEventType["
|
21
|
-
EditorEventType[EditorEventType["
|
22
|
-
EditorEventType[EditorEventType["
|
18
|
+
EditorEventType[EditorEventType["CommandDone"] = 4] = "CommandDone";
|
19
|
+
EditorEventType[EditorEventType["CommandUndone"] = 5] = "CommandUndone";
|
20
|
+
EditorEventType[EditorEventType["ObjectAdded"] = 6] = "ObjectAdded";
|
21
|
+
EditorEventType[EditorEventType["ViewportChanged"] = 7] = "ViewportChanged";
|
22
|
+
EditorEventType[EditorEventType["DisplayResized"] = 8] = "DisplayResized";
|
23
|
+
EditorEventType[EditorEventType["ColorPickerToggled"] = 9] = "ColorPickerToggled";
|
24
|
+
EditorEventType[EditorEventType["ColorPickerColorSelected"] = 10] = "ColorPickerColorSelected";
|
23
25
|
})(EditorEventType || (EditorEventType = {}));
|